1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1992-2008 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 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 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 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 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