1/*********************************************************************** 2* * 3* This software is part of the ast package * 4* Copyright (c) 1992-2011 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 30static const char usage[] = 31"[-?\n@(#)$Id: id (AT&T Research) 2004-06-11 $\n]" 32USAGE_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 102static void 103getfsids(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 177static void 178putid(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 193static int 194getids(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 418int 419b_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 for (;;) 426 { 427 switch (optget(argv, usage)) 428 { 429 case 'a': 430 continue; 431 case 'G': 432 flags |= GG_FLAG; 433 continue; 434 case 'g': 435 flags |= G_FLAG; 436 continue; 437 case 'n': 438 flags |= N_FLAG; 439 continue; 440 case 'r': 441 flags |= R_FLAG; 442 continue; 443 case 's': 444 flags |= S_FLAG; 445 continue; 446 case 'u': 447 flags |= U_FLAG; 448 continue; 449 case ':': 450 error(2, "%s", opt_info.arg); 451 break; 452 case '?': 453 error(ERROR_usage(2), "%s", opt_info.arg); 454 break; 455 } 456 break; 457 } 458 argv += opt_info.index; 459 argc -= opt_info.index; 460 n = (flags & (GG_FLAG|G_FLAG|S_FLAG|U_FLAG)); 461 if (!power2(n)) 462 error(2, "incompatible options selected"); 463 if (error_info.errors || argc > 1) 464 error(ERROR_usage(2), "%s", optusage(NiL)); 465 if (!(flags & ~(N_FLAG|R_FLAG))) 466 { 467 if (flags & N_FLAG) flags |= O_FLAG; 468 flags |= (U_FLAG|G_FLAG|N_FLAG|R_FLAG|S_FLAG|GG_FLAG); 469 } 470 error_info.errors = getids(sfstdout, *argv, flags); 471 return(error_info.errors); 472} 473