diff options
Diffstat (limited to 'usr/src/lib/libcmd/common/id.c')
-rw-r--r-- | usr/src/lib/libcmd/common/id.c | 468 |
1 files changed, 468 insertions, 0 deletions
diff --git a/usr/src/lib/libcmd/common/id.c b/usr/src/lib/libcmd/common/id.c new file mode 100644 index 0000000000..b880659ad5 --- /dev/null +++ b/usr/src/lib/libcmd/common/id.c @@ -0,0 +1,468 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1992-2007 AT&T Knowledge Ventures * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Knowledge Ventures * +* * +* 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 <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* * +***********************************************************************/ +#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 <cmd.h> + +#include "FEATURE/ids" + +#include <grp.h> +#include <pwd.h> + +#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 <sys/fss.h> +#endif +#if _hdr_fsg +#include <fsg.h> +#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); + while (n = optget(argv, usage)) switch (n) + { + case 'a': + break; + case 'G': + flags |= GG_FLAG; + break; + case 'g': + flags |= G_FLAG; + break; + case 'n': + flags |= N_FLAG; + break; + case 'r': + flags |= R_FLAG; + break; + case 's': + flags |= S_FLAG; + break; + case 'u': + flags |= U_FLAG; + break; + case ':': + error(2, "%s", opt_info.arg); + break; + case '?': + error(ERROR_usage(2), "%s", opt_info.arg); + 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); +} |