/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include #include #include #include #include #include #include #include #include #include #define PWNULL ((struct passwd *)0) #define GRNULL ((struct group *)0) typedef enum TYPE { UID, EUID, GID, EGID, SGID } TYPE; typedef enum PRINT { CURR, /* Print uid/gid only */ ALLGROUPS, /* Print all groups */ GROUP, /* Print only group */ USER /* Print only uid */ } PRINT; static PRINT mode = CURR; static int usage(void); static void puid(uid_t); static void pgid(gid_t); static void prid(TYPE, uid_t); static int getusergroups(int, gid_t *, char *, gid_t); static int nflag = 0; /* Output names, not numbers */ static int rflag = 0; /* Output real, not effective IDs */ static char stdbuf[BUFSIZ]; int main(int argc, char *argv[]) { gid_t *idp; uid_t uid, euid; gid_t gid, egid, prgid; int c, aflag = 0, project_flag = 0; struct passwd *pwp; int i, j; int groupmax = sysconf(_SC_NGROUPS_MAX); gid_t *groupids = alloca(groupmax * sizeof (gid_t)); struct group *gr; char *user = NULL; (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ #define TEXT_DOMAIN "SYS_TEST" #endif (void) textdomain(TEXT_DOMAIN); while ((c = getopt(argc, argv, "Ggunarp")) != EOF) { switch (c) { case 'G': if (mode != CURR) return (usage()); mode = ALLGROUPS; break; case 'g': if (mode != CURR) return (usage()); mode = GROUP; break; case 'a': aflag++; break; case 'n': nflag++; break; case 'r': rflag++; break; case 'u': if (mode != CURR) return (usage()); mode = USER; break; case 'p': if (mode != CURR) return (usage()); project_flag++; break; case '?': return (usage()); } } setbuf(stdout, stdbuf); argc -= optind-1; argv += optind-1; /* -n and -r must be combined with one of -[Ggu] */ /* -r cannot be combined with -G */ /* -a and -p cannot be combined with -[Ggu] */ if ((mode == CURR && (nflag || rflag)) || (mode == ALLGROUPS && rflag) || (argc != 1 && argc != 2) || (mode != CURR && (project_flag || aflag))) return (usage()); if (argc == 2) { if ((pwp = getpwnam(argv[1])) == PWNULL) { (void) fprintf(stderr, gettext("id: invalid user name: \"%s\"\n"), argv[1]); return (1); } user = argv[1]; uid = euid = pwp->pw_uid; prgid = gid = egid = pwp->pw_gid; } else { uid = getuid(); gid = getgid(); euid = geteuid(); egid = getegid(); } if (mode != CURR) { if (!rflag) { uid = euid; gid = egid; } if (mode == USER) puid(uid); else if (mode == GROUP) pgid(gid); else if (mode == ALLGROUPS) { pgid(gid); if (user) i = getusergroups(groupmax, groupids, user, prgid); else i = getgroups(groupmax, groupids); if (i == -1) perror("getgroups"); else if (i > 0) { for (j = 0; j < i; ++j) { if ((gid = groupids[j]) == egid) continue; (void) putchar(' '); pgid(gid); } } } (void) putchar('\n'); } else { prid(UID, uid); prid(GID, gid); if (uid != euid) prid(EUID, euid); if (gid != egid) prid(EGID, egid); if (aflag) { if (user) i = getusergroups(groupmax, groupids, user, prgid); else i = getgroups(groupmax, groupids); if (i == -1) perror("getgroups"); else if (i > 0) { (void) printf(" groups="); for (idp = groupids; i--; idp++) { (void) printf("%u", *idp); if (gr = getgrgid(*idp)) (void) printf("(%s)", gr->gr_name); if (i) (void) putchar(','); } } } #ifdef XPG4 /* * POSIX requires us to show all supplementary groups * groups other than the effective group already listed. * * This differs from -a above, because -a always shows * all groups including the effective group in the group= * line. * * It would be simpler if SunOS could just adopt this * POSIX behavior, as it is so incredibly close to the * the norm already. * * Then the magic -a flag could just indicate whether or * not we are suppressing the effective group id. */ else { if (user) i = getusergroups(groupmax, groupids, user, prgid); else i = getgroups(groupmax, groupids); if (i == -1) perror("getgroups"); else if (i > 1) { (void) printf(" groups="); for (idp = groupids; i--; idp++) { if (*idp == egid) continue; (void) printf("%u", *idp); if (gr = getgrgid(*idp)) (void) printf("(%s)", gr->gr_name); if (i) (void) putchar(','); } } } #endif if (project_flag) { struct project proj; void *projbuf; projid_t curprojid = getprojid(); if ((projbuf = malloc(PROJECT_BUFSZ)) == NULL) { (void) fprintf(stderr, "unable to allocate " "memory\n"); return (2); } if (user) { if (getdefaultproj(user, &proj, projbuf, PROJECT_BUFSZ) != NULL) (void) printf(" projid=%d(%s)", (int)proj.pj_projid, proj.pj_name); else /* * This can only happen if project * "default" has been removed from * /etc/project file or the whole * project database file was removed. */ (void) printf(" projid=(NONE)"); } else { if (getprojbyid(curprojid, &proj, projbuf, PROJECT_BUFSZ) == NULL) (void) printf(" projid=%d", (int)curprojid); else (void) printf(" projid=%d(%s)", (int)curprojid, proj.pj_name); } free(projbuf); } (void) putchar('\n'); } return (0); } static int usage() { (void) fprintf(stderr, gettext( "Usage: id [-ap] [user]\n" " id -G [-n] [user]\n" " id -g [-nr] [user]\n" " id -u [-nr] [user]\n")); return (2); } static void puid(uid_t uid) { struct passwd *pw; if (nflag && (pw = getpwuid(uid)) != PWNULL) (void) printf("%s", pw->pw_name); else (void) printf("%u", uid); } static void pgid(gid_t gid) { struct group *gr; if (nflag && (gr = getgrgid(gid)) != GRNULL) (void) printf("%s", gr->gr_name); else (void) printf("%u", gid); } static void prid(TYPE how, uid_t id) { char *s; switch ((int)how) { case UID: s = "uid"; break; case EUID: s = " euid"; break; case GID: s = " gid"; break; case EGID: s = " egid"; break; } if (s != NULL) (void) printf("%s=", s); (void) printf("%u", id); switch ((int)how) { case UID: case EUID: { struct passwd *pwp; if ((pwp = getpwuid(id)) != PWNULL) (void) printf("(%s)", pwp->pw_name); } break; case GID: case EGID: { struct group *grp; if ((grp = getgrgid(id)) != GRNULL) (void) printf("(%s)", grp->gr_name); } break; } } /* * Get the supplementary group affiliation for the user */ static int getusergroups(gidsetsize, grouplist, user, prgid) int gidsetsize; gid_t *grouplist; char *user; gid_t prgid; { struct group *group; char **gr_mem; int ngroups = 0; setgrent(); while ((ngroups < gidsetsize) && ((group = getgrent()) != NULL)) for (gr_mem = group->gr_mem; *gr_mem; gr_mem++) if (strcmp(user, *gr_mem) == 0) { if (gidsetsize) grouplist[ngroups] = group->gr_gid; ngroups++; } endgrent(); if (gidsetsize && !ngroups) grouplist[ngroups++] = prgid; return (ngroups); }