1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 30 /* All Rights Reserved */ 31 32 33 #include <locale.h> 34 #include <stdio.h> 35 #include <pwd.h> 36 #include <grp.h> 37 #include <sys/param.h> 38 #include <unistd.h> 39 #include <string.h> 40 #include <project.h> 41 #include <stdlib.h> 42 43 #define PWNULL ((struct passwd *)0) 44 #define GRNULL ((struct group *)0) 45 46 typedef enum TYPE { 47 UID, EUID, GID, EGID, SGID 48 } TYPE; 49 50 typedef enum PRINT { 51 CURR, /* Print uid/gid only */ 52 ALLGROUPS, /* Print all groups */ 53 GROUP, /* Print only group */ 54 USER /* Print only uid */ 55 } PRINT; 56 static PRINT mode = CURR; 57 58 static int usage(void); 59 static void puid(uid_t); 60 static void pgid(gid_t); 61 static void prid(TYPE, uid_t); 62 static int getusergroups(int, gid_t *, char *, gid_t); 63 64 static int nflag = 0; /* Output names, not numbers */ 65 static int rflag = 0; /* Output real, not effective IDs */ 66 static char stdbuf[BUFSIZ]; 67 68 int 69 main(int argc, char *argv[]) 70 { 71 gid_t *idp; 72 uid_t uid, euid; 73 gid_t gid, egid, prgid; 74 int c, aflag = 0, project_flag = 0; 75 struct passwd *pwp; 76 int i, j; 77 gid_t groupids[NGROUPS_UMAX]; 78 struct group *gr; 79 char *user = NULL; 80 81 (void) setlocale(LC_ALL, ""); 82 83 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 84 #define TEXT_DOMAIN "SYS_TEST" 85 #endif 86 (void) textdomain(TEXT_DOMAIN); 87 #ifdef XPG4 88 while ((c = getopt(argc, argv, "Ggunrp")) != EOF) { 89 #else 90 while ((c = getopt(argc, argv, "ap")) != EOF) { 91 #endif 92 switch (c) { 93 case 'G': 94 if (mode != CURR) 95 return (usage()); 96 mode = ALLGROUPS; 97 break; 98 99 case 'g': 100 if (mode != CURR) 101 return (usage()); 102 mode = GROUP; 103 break; 104 105 #ifndef XPG4 106 case 'a': 107 aflag++; 108 break; 109 #endif 110 111 case 'n': 112 nflag++; 113 break; 114 115 case 'r': 116 rflag++; 117 break; 118 119 case 'u': 120 if (mode != CURR) 121 return (usage()); 122 mode = USER; 123 break; 124 125 case 'p': 126 if (mode != CURR) 127 return (usage()); 128 project_flag++; 129 break; 130 131 case '?': 132 return (usage()); 133 } 134 } 135 setbuf(stdout, stdbuf); 136 argc -= optind-1; 137 argv += optind-1; 138 139 /* -n and -r must be combined with one of -[Ggu] */ 140 /* -r cannot be combined with -G */ 141 142 if ((mode == CURR && (nflag || rflag)) || 143 (mode == ALLGROUPS && rflag) || 144 (argc != 1 && argc != 2)) 145 return (usage()); 146 if (argc == 2) { 147 if ((pwp = getpwnam(argv[1])) == PWNULL) { 148 (void) fprintf(stderr, 149 gettext("id: invalid user name: \"%s\"\n"), 150 argv[1]); 151 return (1); 152 } 153 user = argv[1]; 154 uid = euid = pwp->pw_uid; 155 prgid = gid = egid = pwp->pw_gid; 156 } else { 157 uid = getuid(); 158 gid = getgid(); 159 euid = geteuid(); 160 egid = getegid(); 161 } 162 163 if (mode != CURR) { 164 if (!rflag) { 165 uid = euid; 166 gid = egid; 167 } 168 if (mode == USER) 169 puid(uid); 170 else if (mode == GROUP) 171 pgid(gid); 172 else if (mode == ALLGROUPS) { 173 pgid(gid); 174 if (user) 175 i = getusergroups(NGROUPS_UMAX, groupids, user, 176 prgid); 177 else 178 i = getgroups(NGROUPS_UMAX, groupids); 179 if (i == -1) 180 perror("getgroups"); 181 else if (i > 0) { 182 for (j = 0; j < i; ++j) { 183 if ((gid = groupids[j]) == egid) 184 continue; 185 (void) putchar(' '); 186 pgid(gid); 187 } 188 } 189 } 190 (void) putchar('\n'); 191 } else { 192 prid(UID, uid); 193 prid(GID, gid); 194 if (uid != euid) 195 prid(EUID, euid); 196 if (gid != egid) 197 prid(EGID, egid); 198 #ifndef XPG4 199 if (aflag) { 200 if (user) 201 i = getusergroups(NGROUPS_UMAX, groupids, user, 202 prgid); 203 else 204 i = getgroups(NGROUPS_UMAX, groupids); 205 if (i == -1) 206 perror("getgroups"); 207 else if (i > 0) { 208 (void) printf(" groups="); 209 for (idp = groupids; i--; idp++) { 210 (void) printf("%d", (int)*idp); 211 if (gr = getgrgid(*idp)) 212 (void) printf("(%s)", 213 gr->gr_name); 214 if (i) 215 (void) putchar(','); 216 } 217 } 218 } 219 #else 220 if (user) 221 i = getusergroups(NGROUPS_UMAX, groupids, user, prgid); 222 else 223 i = getgroups(NGROUPS_UMAX, groupids); 224 if (i == -1) 225 perror("getgroups"); 226 else if (i > 1) { 227 (void) printf(" groups="); 228 for (idp = groupids; i--; idp++) { 229 if (*idp == egid) 230 continue; 231 (void) printf("%d", (int)*idp); 232 if (gr = getgrgid(*idp)) 233 (void) printf("(%s)", gr->gr_name); 234 if (i) 235 (void) putchar(','); 236 } 237 } 238 #endif 239 if (project_flag) { 240 struct project proj; 241 void *projbuf; 242 projid_t curprojid = getprojid(); 243 244 if ((projbuf = malloc(PROJECT_BUFSZ)) == NULL) { 245 (void) fprintf(stderr, "unable to allocate " 246 "memory\n"); 247 return (2); 248 } 249 250 if (user) { 251 if (getdefaultproj(user, &proj, projbuf, 252 PROJECT_BUFSZ) != NULL) 253 (void) printf(" projid=%d(%s)", 254 (int)proj.pj_projid, proj.pj_name); 255 else 256 /* 257 * This can only happen if project 258 * "default" has been removed from 259 * /etc/project file or the whole 260 * project database file was removed. 261 */ 262 (void) printf(" projid=(NONE)"); 263 } else { 264 if (getprojbyid(curprojid, &proj, projbuf, 265 PROJECT_BUFSZ) == NULL) 266 (void) printf(" projid=%d", 267 (int)curprojid); 268 else 269 (void) printf(" projid=%d(%s)", 270 (int)curprojid, proj.pj_name); 271 } 272 free(projbuf); 273 } 274 (void) putchar('\n'); 275 } 276 return (0); 277 } 278 279 static int 280 usage() 281 { 282 #ifdef XPG4 283 (void) fprintf(stderr, gettext( 284 "Usage: id [-p] [user]\n" 285 " id -G [-n] [user]\n" 286 " id -g [-nr] [user]\n" 287 " id -u [-nr] [user]\n")); 288 #else 289 (void) fprintf(stderr, gettext("Usage: id [-ap] [user]\n")); 290 #endif 291 return (2); 292 } 293 294 static void 295 puid(uid_t uid) 296 { 297 struct passwd *pw; 298 299 if (nflag && (pw = getpwuid(uid)) != PWNULL) 300 (void) printf("%s", pw->pw_name); 301 else 302 (void) printf("%u", (int)uid); 303 } 304 305 static void 306 pgid(gid_t gid) 307 { 308 struct group *gr; 309 310 if (nflag && (gr = getgrgid(gid)) != GRNULL) 311 (void) printf("%s", gr->gr_name); 312 else 313 (void) printf("%u", (int)gid); 314 } 315 316 static void 317 prid(TYPE how, uid_t id) 318 { 319 char *s; 320 321 switch ((int)how) { 322 case UID: 323 s = "uid"; 324 break; 325 326 case EUID: 327 s = " euid"; 328 break; 329 330 case GID: 331 s = " gid"; 332 break; 333 334 case EGID: 335 s = " egid"; 336 break; 337 338 } 339 if (s != NULL) 340 (void) printf("%s=", s); 341 (void) printf("%u", (int)id); 342 switch ((int)how) { 343 case UID: 344 case EUID: 345 { 346 struct passwd *pwp; 347 348 if ((pwp = getpwuid(id)) != PWNULL) 349 (void) printf("(%s)", pwp->pw_name); 350 351 } 352 break; 353 case GID: 354 case EGID: 355 { 356 struct group *grp; 357 358 if ((grp = getgrgid(id)) != GRNULL) 359 (void) printf("(%s)", grp->gr_name); 360 } 361 break; 362 } 363 } 364 365 /* 366 * Get the supplementary group affiliation for the user 367 */ 368 static int getusergroups(gidsetsize, grouplist, user, prgid) 369 int gidsetsize; 370 gid_t *grouplist; 371 char *user; 372 gid_t prgid; 373 { 374 struct group *group; 375 char **gr_mem; 376 int ngroups = 0; 377 378 setgrent(); 379 while ((ngroups < gidsetsize) && ((group = getgrent()) != NULL)) 380 for (gr_mem = group->gr_mem; *gr_mem; gr_mem++) 381 if (strcmp(user, *gr_mem) == 0) { 382 if (gidsetsize) 383 grouplist[ngroups] = group->gr_gid; 384 ngroups++; 385 } 386 endgrent(); 387 if (gidsetsize && !ngroups) 388 grouplist[ngroups++] = prgid; 389 return (ngroups); 390 } 391