1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1992-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * *
20 ***********************************************************************/
21 #pragma prototyped
22 /*
23 * David Korn
24 * Glenn Fowler
25 * AT&T Research
26 *
27 * id
28 */
29
30 static const char usage[] =
31 "[-?\n@(#)$Id: id (AT&T Research) 2004-06-11 $\n]"
32 USAGE_LICENSE
33 "[+NAME?id - return user identity]"
34 "[+DESCRIPTION?If no \auser\a operand is specified \bid\b writes user and "
35 "group IDs and the corresponding user and group names of the "
36 "invoking process to standard output. If the effective and "
37 "real IDs do not match, both are written. Any supplementary "
38 "groups the current process belongs to will also be written.]"
39 "[+?If a \auser\a operand is specified and the process has permission, "
40 "the user and group IDs and any supplementary group IDs of the "
41 "selected user will be written to standard output.]"
42 "[+?If any options are specified, then only a portion of the information "
43 "is written.]"
44 "[n:name?Write the name instead of the numeric ID.]"
45 "[r:real?Writes real ID instead of the effective ID.]"
46 "[[a?This option is ignored.]"
47 "[g:group?Writes only the group ID.]"
48 "[u:user?Writes only the user ID.]"
49 "[G:groups?Writes only the supplementary group IDs.]"
50 "[s:fair-share?Writes fair share scheduler IDs and groups on systems that "
51 "support fair share scheduling.]"
52 "\n"
53 "\n[user]\n"
54 "\n"
55 "[+EXIT STATUS?]{"
56 "[+0?Successful completion.]"
57 "[+>0?An error occurred.]"
58 "}"
59 "[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\b(2)]"
60 ;
61
62 #include <cmd.h>
63
64 #include "FEATURE/ids"
65
66 #include <grp.h>
67 #include <pwd.h>
68
69 #if _lib_fsid
70 #if _lib_getfsgid && ( _sys_fss || _hdr_fsg )
71 #define fss_grp fs_grp
72 #define fss_id fs_id
73 #define fss_mem fs_mem
74 #define fss_passwd fs_passwd
75 #define fss_shares fs_shares
76 #if _sys_fss
77 #include <sys/fss.h>
78 #endif
79 #if _hdr_fsg
80 #include <fsg.h>
81 #endif
82 #if !_lib_isfsg && !defined(isfsg)
83 #define isfsg(p) (!(p)->fs_id&&!(p)->fs_shares&&(!(p)->fs_passwd||!*(p)->fs_passwd))
84 #endif
85 #else
86 #undef _lib_fsid
87 #endif
88 #endif
89
90 #define power2(n) (!((n)&((n)-1)))
91
92 #define GG_FLAG (1<<0)
93 #define G_FLAG (1<<1)
94 #define N_FLAG (1<<2)
95 #define R_FLAG (1<<3)
96 #define U_FLAG (1<<4)
97 #define S_FLAG (1<<5)
98 #define O_FLAG (1<<6)
99 #define X_FLAG (1<<7)
100
101 #if _lib_fsid
102 static void
getfsids(Sfio_t * sp,const char * name,int flags,register int lastchar)103 getfsids(Sfio_t* sp, const char* name, int flags, register int lastchar)
104 {
105 register struct fsg* fs;
106 register char* s;
107 register char** p;
108 char** x;
109
110 if (lastchar)
111 {
112 if (flags & O_FLAG) flags = 1;
113 else flags = 0;
114 }
115 else if (flags & N_FLAG) flags = 1;
116 else flags = -1;
117 setfsgent();
118 while (fs = getfsgnam(name))
119 if (!isfsg(fs))
120 {
121 if (p = fs->fs_mem)
122 {
123 if (flags > 0) x = 0;
124 else
125 {
126 register char** q;
127 register char* t;
128 register int n;
129
130 n = 0;
131 q = p;
132 while (s = *q++)
133 n += strlen(s) + 1;
134 if (!(x = newof(0, char*, q - p, n)))
135 break;
136 s = (char*)(x + (q - p));
137 q = x;
138 while (t = *p++)
139 {
140 *q++ = s;
141 while (*s++ = *t++);
142 }
143 *q = 0;
144 p = x;
145 }
146 while (s = *p++)
147 {
148 if (lastchar == '=')
149 {
150 lastchar = ',';
151 sfputr(sp, " fsid=", -1);
152 }
153 else if (!lastchar) lastchar = ' ';
154 else sfputc(sp, lastchar);
155 if (flags > 0) sfprintf(sp, "%s", s);
156 else
157 {
158 setfsgent();
159 while (fs = getfsgnam(s))
160 if (isfsg(fs))
161 {
162 if (flags < 0) sfprintf(sp, "%u", fs->fs_id);
163 else sfprintf(sp, "%u(%s)", fs->fs_id, s);
164 break;
165 }
166 }
167 }
168 if (x) free(x);
169 }
170 break;
171 }
172 endfsgent();
173 if (lastchar == ' ') sfputc(sp, '\n');
174 }
175 #endif
176
177 static void
putid(Sfio_t * sp,int flags,const char * label,const char * name,long number)178 putid(Sfio_t* sp, int flags, const char* label, const char* name, long number)
179 {
180 sfprintf(sp, "%s=", label);
181 if (flags & O_FLAG)
182 {
183 if (name) sfputr(sp, name, -1);
184 else sfprintf(sp, "%lu", number);
185 }
186 else
187 {
188 sfprintf(sp, "%u", number);
189 if (name) sfprintf(sp, "(%s)", name);
190 }
191 }
192
193 static int
getids(Sfio_t * sp,const char * name,register int flags)194 getids(Sfio_t* sp, const char* name, register int flags)
195 {
196 register struct passwd* pw;
197 register struct group* grp;
198 register int i;
199 register int j;
200 register int k;
201 #if _lib_fsid
202 register struct fsg* fs;
203 const char* fs_name;
204 int fs_id;
205 #endif
206 char** p;
207 char* s;
208 int lastchar;
209 int ngroups = 0;
210 const char* gname;
211 uid_t user;
212 uid_t euid;
213 gid_t group;
214 gid_t egid;
215
216 static gid_t* groups;
217
218 if (flags & GG_FLAG)
219 {
220 static int maxgroups;
221
222 /*
223 * get supplemental groups if required
224 */
225
226 if (!maxgroups)
227 {
228 /*
229 * first time
230 */
231
232 if ((maxgroups = getgroups(0, groups)) <= 0)
233 maxgroups = NGROUPS_MAX;
234 if (!(groups = newof(0, gid_t, maxgroups + 1, 0)))
235 error(ERROR_exit(1), "out of space [group array]");
236 }
237 ngroups = getgroups(maxgroups, groups);
238 for (i = j = 0; i < ngroups; i++)
239 {
240 for (k = 0; k < j && groups[k] != groups[i]; k++);
241 if (k >= j) groups[j++] = groups[i];
242 }
243 ngroups = j;
244 }
245 if (name)
246 {
247 flags |= X_FLAG;
248 if (!(flags & N_FLAG) || (flags & (G_FLAG|GG_FLAG)))
249 {
250 if (!(pw = getpwnam(name)))
251 {
252 user = strtol(name, &s, 0);
253 if (*s || !(pw = getpwuid(user)))
254 error(ERROR_exit(1), "%s: name not found", name);
255 name = pw->pw_name;
256 }
257 user = pw->pw_uid;
258 group = pw->pw_gid;
259 }
260 #if _lib_fsid
261 if (!(flags & N_FLAG) || (flags & S_FLAG))
262 {
263 setfsgent();
264 do
265 {
266 if (!(fs = getfsgnam(name)))
267 error(ERROR_exit(1), "%u: fss name not found", name);
268 } while (isfsg(fs));
269 fs_id = fs->fs_id;
270 }
271 #endif
272 }
273 else
274 {
275 if (flags & G_FLAG)
276 group = (flags & R_FLAG) ? getgid() : getegid();
277 if (flags & (GG_FLAG|N_FLAG|U_FLAG))
278 user = (flags & R_FLAG) ? getuid() : geteuid();
279 #if _lib_fsid
280 if (flags & S_FLAG)
281 fs_id = fsid(0);
282 #endif
283 if (flags & N_FLAG)
284 name = (pw = getpwuid(user)) ? pw->pw_name : (char*)0;
285 }
286 if (ngroups == 1 && groups[0] == group)
287 ngroups = 0;
288 if ((flags & N_FLAG) && (flags & G_FLAG))
289 gname = (grp = getgrgid(group)) ? grp->gr_name : (char*)0;
290 #if _lib_fsid
291 if ((flags & N_FLAG) && (flags & S_FLAG))
292 {
293 setfsgent();
294 fs_name = (fs = getfsgid(fs_id)) ? fs->fs_grp : (char*)0;
295 }
296 #endif
297 if ((flags & (U_FLAG|G_FLAG|S_FLAG)) == (U_FLAG|G_FLAG|S_FLAG))
298 {
299 putid(sp, flags, "uid", name, user);
300 putid(sp, flags, " gid", gname, group);
301 if ((flags & X_FLAG) && name)
302 {
303 #if _lib_getgrent
304 #if _lib_setgrent
305 setgrent();
306 #endif
307 lastchar = '=';
308 while (grp = getgrent())
309 if (p = grp->gr_mem)
310 while (s = *p++)
311 if (streq(s, name))
312 {
313 if (lastchar == '=')
314 sfputr(sp, " groups", -1);
315 sfputc(sp, lastchar);
316 lastchar = ',';
317 if (flags & O_FLAG)
318 sfprintf(sp, "%s", grp->gr_name);
319 else sfprintf(sp, "%u(%s)", grp->gr_gid, grp->gr_name);
320 }
321 #if _lib_endgrent
322 endgrent();
323 #endif
324 #endif
325 #if _lib_fsid
326 getfsids(sp, name, flags, '=');
327 #endif
328 }
329 else
330 {
331 if ((euid = geteuid()) != user)
332 putid(sp, flags, " euid", (pw = getpwuid(euid)) ? pw->pw_name : (char*)0, euid);
333 if ((egid = getegid()) != group)
334 putid(sp, flags, " egid", (grp = getgrgid(egid)) ? grp->gr_name : (char*)0, egid);
335 if (ngroups > 0)
336 {
337 sfputr(sp, " groups", -1);
338 lastchar = '=';
339 for (i = 0; i < ngroups; i++)
340 {
341 group = groups[i];
342 sfputc(sp, lastchar);
343 if (grp = getgrgid(group))
344 {
345 if (flags & O_FLAG) sfprintf(sp, "%s", grp->gr_name);
346 else sfprintf(sp, "%u(%s)", group, grp->gr_name);
347 }
348 else sfprintf(sp, "%u", group);
349 lastchar = ',';
350 }
351 }
352 #if _lib_fsid
353 putid(sp, flags, " fsid", fs_name, fs_id);
354 #endif
355 }
356 sfputc(sp,'\n');
357 return(0);
358 }
359 if (flags & U_FLAG)
360 {
361 if ((flags & N_FLAG) && name) sfputr(sp, name, '\n');
362 else sfprintf(sp, "%u\n", user);
363 }
364 else if (flags & G_FLAG)
365 {
366 if ((flags & N_FLAG) && gname) sfputr(sp, gname, '\n');
367 else sfprintf(sp, "%u\n", group);
368 }
369 else if (flags & GG_FLAG)
370 {
371 if ((flags & X_FLAG) && name)
372 {
373 #if _lib_getgrent
374 #if _lib_setgrent
375 setgrent();
376 #endif
377 i = 0;
378 while (grp = getgrent())
379 if (p = grp->gr_mem)
380 while (s = *p++)
381 if (streq(s, name))
382 {
383 if (i++) sfputc(sp, ' ');
384 if (flags & N_FLAG) sfprintf(sp, "%s", grp->gr_name);
385 else sfprintf(sp, "%u", grp->gr_gid);
386 }
387 #if _lib_endgrent
388 endgrent();
389 #endif
390 if (i) sfputc(sp, '\n');
391 #endif
392 }
393 else if (ngroups > 0)
394 {
395 for (i = 0;;)
396 {
397 group = groups[i];
398 if ((flags & N_FLAG) && (grp = getgrgid(group)))
399 sfprintf(sp, "%s", grp->gr_name);
400 else sfprintf(sp, "%u", group);
401 if (++i >= ngroups) break;
402 sfputc(sp, ' ');
403 }
404 sfputc(sp, '\n');
405 }
406 }
407 #if _lib_fsid
408 else if (flags & S_FLAG)
409 {
410 if ((flags & X_FLAG) && name) getfsids(sp, name, flags, 0);
411 else if ((flags & N_FLAG) && fs_name) sfputr(sp, fs_name, '\n');
412 else sfprintf(sp, "%u\n", fs_id);
413 }
414 #endif
415 return(0);
416 }
417
418 int
b_id(int argc,char * argv[],void * context)419 b_id(int argc, char *argv[], void* context)
420 {
421 register int flags = 0;
422 register int n;
423
424 cmdinit(argc, argv, context, ERROR_CATALOG, 0);
425 while (n = optget(argv, usage)) switch (n)
426 {
427 case 'a':
428 break;
429 case 'G':
430 flags |= GG_FLAG;
431 break;
432 case 'g':
433 flags |= G_FLAG;
434 break;
435 case 'n':
436 flags |= N_FLAG;
437 break;
438 case 'r':
439 flags |= R_FLAG;
440 break;
441 case 's':
442 flags |= S_FLAG;
443 break;
444 case 'u':
445 flags |= U_FLAG;
446 break;
447 case ':':
448 error(2, "%s", opt_info.arg);
449 break;
450 case '?':
451 error(ERROR_usage(2), "%s", opt_info.arg);
452 break;
453 }
454 argv += opt_info.index;
455 argc -= opt_info.index;
456 n = (flags & (GG_FLAG|G_FLAG|S_FLAG|U_FLAG));
457 if (!power2(n))
458 error(2, "incompatible options selected");
459 if (error_info.errors || argc > 1)
460 error(ERROR_usage(2), "%s", optusage(NiL));
461 if (!(flags & ~(N_FLAG|R_FLAG)))
462 {
463 if (flags & N_FLAG) flags |= O_FLAG;
464 flags |= (U_FLAG|G_FLAG|N_FLAG|R_FLAG|S_FLAG|GG_FLAG);
465 }
466 error_info.errors = getids(sfstdout, *argv, flags);
467 return(error_info.errors);
468 }
469