/*********************************************************************** * * * This software is part of the ast package * * Copyright (c) 1992-2011 AT&T Intellectual Property * * and is licensed under the * * Common Public License, Version 1.0 * * by AT&T Intellectual Property * * * * A copy of the License is available at * * http://www.opensource.org/licenses/cpl1.0.txt * * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * * * * Information and Software Systems Research * * AT&T Research * * Florham Park NJ * * * * Glenn Fowler * * David Korn * * * ***********************************************************************/ #pragma prototyped /* * David Korn * Glenn Fowler * AT&T Research * * id */ static const char usage[] = "[-?\n@(#)$Id: id (AT&T Research) 2004-06-11 $\n]" USAGE_LICENSE "[+NAME?id - return user identity]" "[+DESCRIPTION?If no \auser\a operand is specified \bid\b writes user and " "group IDs and the corresponding user and group names of the " "invoking process to standard output. If the effective and " "real IDs do not match, both are written. Any supplementary " "groups the current process belongs to will also be written.]" "[+?If a \auser\a operand is specified and the process has permission, " "the user and group IDs and any supplementary group IDs of the " "selected user will be written to standard output.]" "[+?If any options are specified, then only a portion of the information " "is written.]" "[n:name?Write the name instead of the numeric ID.]" "[r:real?Writes real ID instead of the effective ID.]" "[[a?This option is ignored.]" "[g:group?Writes only the group ID.]" "[u:user?Writes only the user ID.]" "[G:groups?Writes only the supplementary group IDs.]" "[s:fair-share?Writes fair share scheduler IDs and groups on systems that " "support fair share scheduling.]" "\n" "\n[user]\n" "\n" "[+EXIT STATUS?]{" "[+0?Successful completion.]" "[+>0?An error occurred.]" "}" "[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\b(2)]" ; #include #include "FEATURE/ids" #include #include #if _lib_fsid #if _lib_getfsgid && ( _sys_fss || _hdr_fsg ) #define fss_grp fs_grp #define fss_id fs_id #define fss_mem fs_mem #define fss_passwd fs_passwd #define fss_shares fs_shares #if _sys_fss #include #endif #if _hdr_fsg #include #endif #if !_lib_isfsg && !defined(isfsg) #define isfsg(p) (!(p)->fs_id&&!(p)->fs_shares&&(!(p)->fs_passwd||!*(p)->fs_passwd)) #endif #else #undef _lib_fsid #endif #endif #define power2(n) (!((n)&((n)-1))) #define GG_FLAG (1<<0) #define G_FLAG (1<<1) #define N_FLAG (1<<2) #define R_FLAG (1<<3) #define U_FLAG (1<<4) #define S_FLAG (1<<5) #define O_FLAG (1<<6) #define X_FLAG (1<<7) #if _lib_fsid static void getfsids(Sfio_t* sp, const char* name, int flags, register int lastchar) { register struct fsg* fs; register char* s; register char** p; char** x; if (lastchar) { if (flags & O_FLAG) flags = 1; else flags = 0; } else if (flags & N_FLAG) flags = 1; else flags = -1; setfsgent(); while (fs = getfsgnam(name)) if (!isfsg(fs)) { if (p = fs->fs_mem) { if (flags > 0) x = 0; else { register char** q; register char* t; register int n; n = 0; q = p; while (s = *q++) n += strlen(s) + 1; if (!(x = newof(0, char*, q - p, n))) break; s = (char*)(x + (q - p)); q = x; while (t = *p++) { *q++ = s; while (*s++ = *t++); } *q = 0; p = x; } while (s = *p++) { if (lastchar == '=') { lastchar = ','; sfputr(sp, " fsid=", -1); } else if (!lastchar) lastchar = ' '; else sfputc(sp, lastchar); if (flags > 0) sfprintf(sp, "%s", s); else { setfsgent(); while (fs = getfsgnam(s)) if (isfsg(fs)) { if (flags < 0) sfprintf(sp, "%u", fs->fs_id); else sfprintf(sp, "%u(%s)", fs->fs_id, s); break; } } } if (x) free(x); } break; } endfsgent(); if (lastchar == ' ') sfputc(sp, '\n'); } #endif static void putid(Sfio_t* sp, int flags, const char* label, const char* name, long number) { sfprintf(sp, "%s=", label); if (flags & O_FLAG) { if (name) sfputr(sp, name, -1); else sfprintf(sp, "%lu", number); } else { sfprintf(sp, "%u", number); if (name) sfprintf(sp, "(%s)", name); } } static int getids(Sfio_t* sp, const char* name, register int flags) { register struct passwd* pw; register struct group* grp; register int i; register int j; register int k; #if _lib_fsid register struct fsg* fs; const char* fs_name; int fs_id; #endif char** p; char* s; int lastchar; int ngroups = 0; const char* gname; uid_t user; uid_t euid; gid_t group; gid_t egid; static gid_t* groups; if (flags & GG_FLAG) { static int maxgroups; /* * get supplemental groups if required */ if (!maxgroups) { /* * first time */ if ((maxgroups = getgroups(0, groups)) <= 0) maxgroups = NGROUPS_MAX; if (!(groups = newof(0, gid_t, maxgroups + 1, 0))) error(ERROR_exit(1), "out of space [group array]"); } ngroups = getgroups(maxgroups, groups); for (i = j = 0; i < ngroups; i++) { for (k = 0; k < j && groups[k] != groups[i]; k++); if (k >= j) groups[j++] = groups[i]; } ngroups = j; } if (name) { flags |= X_FLAG; if (!(flags & N_FLAG) || (flags & (G_FLAG|GG_FLAG))) { if (!(pw = getpwnam(name))) { user = strtol(name, &s, 0); if (*s || !(pw = getpwuid(user))) error(ERROR_exit(1), "%s: name not found", name); name = pw->pw_name; } user = pw->pw_uid; group = pw->pw_gid; } #if _lib_fsid if (!(flags & N_FLAG) || (flags & S_FLAG)) { setfsgent(); do { if (!(fs = getfsgnam(name))) error(ERROR_exit(1), "%u: fss name not found", name); } while (isfsg(fs)); fs_id = fs->fs_id; } #endif } else { if (flags & G_FLAG) group = (flags & R_FLAG) ? getgid() : getegid(); if (flags & (GG_FLAG|N_FLAG|U_FLAG)) user = (flags & R_FLAG) ? getuid() : geteuid(); #if _lib_fsid if (flags & S_FLAG) fs_id = fsid(0); #endif if (flags & N_FLAG) name = (pw = getpwuid(user)) ? pw->pw_name : (char*)0; } if (ngroups == 1 && groups[0] == group) ngroups = 0; if ((flags & N_FLAG) && (flags & G_FLAG)) gname = (grp = getgrgid(group)) ? grp->gr_name : (char*)0; #if _lib_fsid if ((flags & N_FLAG) && (flags & S_FLAG)) { setfsgent(); fs_name = (fs = getfsgid(fs_id)) ? fs->fs_grp : (char*)0; } #endif if ((flags & (U_FLAG|G_FLAG|S_FLAG)) == (U_FLAG|G_FLAG|S_FLAG)) { putid(sp, flags, "uid", name, user); putid(sp, flags, " gid", gname, group); if ((flags & X_FLAG) && name) { #if _lib_getgrent #if _lib_setgrent setgrent(); #endif lastchar = '='; while (grp = getgrent()) if (p = grp->gr_mem) while (s = *p++) if (streq(s, name)) { if (lastchar == '=') sfputr(sp, " groups", -1); sfputc(sp, lastchar); lastchar = ','; if (flags & O_FLAG) sfprintf(sp, "%s", grp->gr_name); else sfprintf(sp, "%u(%s)", grp->gr_gid, grp->gr_name); } #if _lib_endgrent endgrent(); #endif #endif #if _lib_fsid getfsids(sp, name, flags, '='); #endif } else { if ((euid = geteuid()) != user) putid(sp, flags, " euid", (pw = getpwuid(euid)) ? pw->pw_name : (char*)0, euid); if ((egid = getegid()) != group) putid(sp, flags, " egid", (grp = getgrgid(egid)) ? grp->gr_name : (char*)0, egid); if (ngroups > 0) { sfputr(sp, " groups", -1); lastchar = '='; for (i = 0; i < ngroups; i++) { group = groups[i]; sfputc(sp, lastchar); if (grp = getgrgid(group)) { if (flags & O_FLAG) sfprintf(sp, "%s", grp->gr_name); else sfprintf(sp, "%u(%s)", group, grp->gr_name); } else sfprintf(sp, "%u", group); lastchar = ','; } } #if _lib_fsid putid(sp, flags, " fsid", fs_name, fs_id); #endif } sfputc(sp,'\n'); return(0); } if (flags & U_FLAG) { if ((flags & N_FLAG) && name) sfputr(sp, name, '\n'); else sfprintf(sp, "%u\n", user); } else if (flags & G_FLAG) { if ((flags & N_FLAG) && gname) sfputr(sp, gname, '\n'); else sfprintf(sp, "%u\n", group); } else if (flags & GG_FLAG) { if ((flags & X_FLAG) && name) { #if _lib_getgrent #if _lib_setgrent setgrent(); #endif i = 0; while (grp = getgrent()) if (p = grp->gr_mem) while (s = *p++) if (streq(s, name)) { if (i++) sfputc(sp, ' '); if (flags & N_FLAG) sfprintf(sp, "%s", grp->gr_name); else sfprintf(sp, "%u", grp->gr_gid); } #if _lib_endgrent endgrent(); #endif if (i) sfputc(sp, '\n'); #endif } else if (ngroups > 0) { for (i = 0;;) { group = groups[i]; if ((flags & N_FLAG) && (grp = getgrgid(group))) sfprintf(sp, "%s", grp->gr_name); else sfprintf(sp, "%u", group); if (++i >= ngroups) break; sfputc(sp, ' '); } sfputc(sp, '\n'); } } #if _lib_fsid else if (flags & S_FLAG) { if ((flags & X_FLAG) && name) getfsids(sp, name, flags, 0); else if ((flags & N_FLAG) && fs_name) sfputr(sp, fs_name, '\n'); else sfprintf(sp, "%u\n", fs_id); } #endif return(0); } int b_id(int argc, char *argv[], void* context) { register int flags = 0; register int n; cmdinit(argc, argv, context, ERROR_CATALOG, 0); for (;;) { switch (optget(argv, usage)) { case 'a': continue; case 'G': flags |= GG_FLAG; continue; case 'g': flags |= G_FLAG; continue; case 'n': flags |= N_FLAG; continue; case 'r': flags |= R_FLAG; continue; case 's': flags |= S_FLAG; continue; case 'u': flags |= U_FLAG; continue; case ':': error(2, "%s", opt_info.arg); break; case '?': error(ERROR_usage(2), "%s", opt_info.arg); break; } break; } argv += opt_info.index; argc -= opt_info.index; n = (flags & (GG_FLAG|G_FLAG|S_FLAG|U_FLAG)); if (!power2(n)) error(2, "incompatible options selected"); if (error_info.errors || argc > 1) error(ERROR_usage(2), "%s", optusage(NiL)); if (!(flags & ~(N_FLAG|R_FLAG))) { if (flags & N_FLAG) flags |= O_FLAG; flags |= (U_FLAG|G_FLAG|N_FLAG|R_FLAG|S_FLAG|GG_FLAG); } error_info.errors = getids(sfstdout, *argv, flags); return(error_info.errors); }