14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1992-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * Glenn Fowler <gsf@research.att.com> *
184887Schin * David Korn <dgk@research.att.com> *
194887Schin * *
204887Schin ***********************************************************************/
214887Schin #pragma prototyped
224887Schin /*
234887Schin * David Korn
244887Schin * Glenn Fowler
254887Schin * AT&T Research
264887Schin *
274887Schin * id
284887Schin */
294887Schin
304887Schin static const char usage[] =
314887Schin "[-?\n@(#)$Id: id (AT&T Research) 2004-06-11 $\n]"
324887Schin USAGE_LICENSE
334887Schin "[+NAME?id - return user identity]"
344887Schin "[+DESCRIPTION?If no \auser\a operand is specified \bid\b writes user and "
354887Schin "group IDs and the corresponding user and group names of the "
364887Schin "invoking process to standard output. If the effective and "
374887Schin "real IDs do not match, both are written. Any supplementary "
384887Schin "groups the current process belongs to will also be written.]"
394887Schin "[+?If a \auser\a operand is specified and the process has permission, "
404887Schin "the user and group IDs and any supplementary group IDs of the "
414887Schin "selected user will be written to standard output.]"
424887Schin "[+?If any options are specified, then only a portion of the information "
434887Schin "is written.]"
444887Schin "[n:name?Write the name instead of the numeric ID.]"
454887Schin "[r:real?Writes real ID instead of the effective ID.]"
464887Schin "[[a?This option is ignored.]"
474887Schin "[g:group?Writes only the group ID.]"
484887Schin "[u:user?Writes only the user ID.]"
494887Schin "[G:groups?Writes only the supplementary group IDs.]"
504887Schin "[s:fair-share?Writes fair share scheduler IDs and groups on systems that "
514887Schin "support fair share scheduling.]"
524887Schin "\n"
534887Schin "\n[user]\n"
544887Schin "\n"
554887Schin "[+EXIT STATUS?]{"
564887Schin "[+0?Successful completion.]"
574887Schin "[+>0?An error occurred.]"
584887Schin "}"
594887Schin "[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\b(2)]"
604887Schin ;
614887Schin
624887Schin #include <cmd.h>
634887Schin
644887Schin #include "FEATURE/ids"
654887Schin
664887Schin #include <grp.h>
674887Schin #include <pwd.h>
684887Schin
694887Schin #if _lib_fsid
704887Schin #if _lib_getfsgid && ( _sys_fss || _hdr_fsg )
714887Schin #define fss_grp fs_grp
724887Schin #define fss_id fs_id
734887Schin #define fss_mem fs_mem
744887Schin #define fss_passwd fs_passwd
754887Schin #define fss_shares fs_shares
764887Schin #if _sys_fss
774887Schin #include <sys/fss.h>
784887Schin #endif
794887Schin #if _hdr_fsg
804887Schin #include <fsg.h>
814887Schin #endif
824887Schin #if !_lib_isfsg && !defined(isfsg)
834887Schin #define isfsg(p) (!(p)->fs_id&&!(p)->fs_shares&&(!(p)->fs_passwd||!*(p)->fs_passwd))
844887Schin #endif
854887Schin #else
864887Schin #undef _lib_fsid
874887Schin #endif
884887Schin #endif
894887Schin
904887Schin #define power2(n) (!((n)&((n)-1)))
914887Schin
924887Schin #define GG_FLAG (1<<0)
934887Schin #define G_FLAG (1<<1)
944887Schin #define N_FLAG (1<<2)
954887Schin #define R_FLAG (1<<3)
964887Schin #define U_FLAG (1<<4)
974887Schin #define S_FLAG (1<<5)
984887Schin #define O_FLAG (1<<6)
994887Schin #define X_FLAG (1<<7)
1004887Schin
1014887Schin #if _lib_fsid
1024887Schin static void
getfsids(Sfio_t * sp,const char * name,int flags,register int lastchar)1034887Schin getfsids(Sfio_t* sp, const char* name, int flags, register int lastchar)
1044887Schin {
1054887Schin register struct fsg* fs;
1064887Schin register char* s;
1074887Schin register char** p;
1084887Schin char** x;
1094887Schin
1104887Schin if (lastchar)
1114887Schin {
1124887Schin if (flags & O_FLAG) flags = 1;
1134887Schin else flags = 0;
1144887Schin }
1154887Schin else if (flags & N_FLAG) flags = 1;
1164887Schin else flags = -1;
1174887Schin setfsgent();
1184887Schin while (fs = getfsgnam(name))
1194887Schin if (!isfsg(fs))
1204887Schin {
1214887Schin if (p = fs->fs_mem)
1224887Schin {
1234887Schin if (flags > 0) x = 0;
1244887Schin else
1254887Schin {
1264887Schin register char** q;
1274887Schin register char* t;
1284887Schin register int n;
1294887Schin
1304887Schin n = 0;
1314887Schin q = p;
1324887Schin while (s = *q++)
1334887Schin n += strlen(s) + 1;
1344887Schin if (!(x = newof(0, char*, q - p, n)))
1354887Schin break;
1364887Schin s = (char*)(x + (q - p));
1374887Schin q = x;
1384887Schin while (t = *p++)
1394887Schin {
1404887Schin *q++ = s;
1414887Schin while (*s++ = *t++);
1424887Schin }
1434887Schin *q = 0;
1444887Schin p = x;
1454887Schin }
1464887Schin while (s = *p++)
1474887Schin {
1484887Schin if (lastchar == '=')
1494887Schin {
1504887Schin lastchar = ',';
1514887Schin sfputr(sp, " fsid=", -1);
1524887Schin }
1534887Schin else if (!lastchar) lastchar = ' ';
1544887Schin else sfputc(sp, lastchar);
1554887Schin if (flags > 0) sfprintf(sp, "%s", s);
1564887Schin else
1574887Schin {
1584887Schin setfsgent();
1594887Schin while (fs = getfsgnam(s))
1604887Schin if (isfsg(fs))
1614887Schin {
1624887Schin if (flags < 0) sfprintf(sp, "%u", fs->fs_id);
1634887Schin else sfprintf(sp, "%u(%s)", fs->fs_id, s);
1644887Schin break;
1654887Schin }
1664887Schin }
1674887Schin }
1684887Schin if (x) free(x);
1694887Schin }
1704887Schin break;
1714887Schin }
1724887Schin endfsgent();
1734887Schin if (lastchar == ' ') sfputc(sp, '\n');
1744887Schin }
1754887Schin #endif
1764887Schin
1774887Schin static void
putid(Sfio_t * sp,int flags,const char * label,const char * name,long number)1784887Schin putid(Sfio_t* sp, int flags, const char* label, const char* name, long number)
1794887Schin {
1804887Schin sfprintf(sp, "%s=", label);
1814887Schin if (flags & O_FLAG)
1824887Schin {
1834887Schin if (name) sfputr(sp, name, -1);
1844887Schin else sfprintf(sp, "%lu", number);
1854887Schin }
1864887Schin else
1874887Schin {
1884887Schin sfprintf(sp, "%u", number);
1894887Schin if (name) sfprintf(sp, "(%s)", name);
1904887Schin }
1914887Schin }
1924887Schin
1934887Schin static int
getids(Sfio_t * sp,const char * name,register int flags)1944887Schin getids(Sfio_t* sp, const char* name, register int flags)
1954887Schin {
1964887Schin register struct passwd* pw;
1974887Schin register struct group* grp;
1984887Schin register int i;
1994887Schin register int j;
2004887Schin register int k;
2014887Schin #if _lib_fsid
2024887Schin register struct fsg* fs;
2034887Schin const char* fs_name;
2044887Schin int fs_id;
2054887Schin #endif
2064887Schin char** p;
2074887Schin char* s;
2084887Schin int lastchar;
2094887Schin int ngroups = 0;
2104887Schin const char* gname;
2114887Schin uid_t user;
2124887Schin uid_t euid;
2134887Schin gid_t group;
2144887Schin gid_t egid;
2154887Schin
2164887Schin static gid_t* groups;
2174887Schin
2184887Schin if (flags & GG_FLAG)
2194887Schin {
2204887Schin static int maxgroups;
2214887Schin
2224887Schin /*
2234887Schin * get supplemental groups if required
2244887Schin */
2254887Schin
2264887Schin if (!maxgroups)
2274887Schin {
2284887Schin /*
2294887Schin * first time
2304887Schin */
2314887Schin
2324887Schin if ((maxgroups = getgroups(0, groups)) <= 0)
2334887Schin maxgroups = NGROUPS_MAX;
2344887Schin if (!(groups = newof(0, gid_t, maxgroups + 1, 0)))
2354887Schin error(ERROR_exit(1), "out of space [group array]");
2364887Schin }
2374887Schin ngroups = getgroups(maxgroups, groups);
2384887Schin for (i = j = 0; i < ngroups; i++)
2394887Schin {
2404887Schin for (k = 0; k < j && groups[k] != groups[i]; k++);
2414887Schin if (k >= j) groups[j++] = groups[i];
2424887Schin }
2434887Schin ngroups = j;
2444887Schin }
2454887Schin if (name)
2464887Schin {
2474887Schin flags |= X_FLAG;
2484887Schin if (!(flags & N_FLAG) || (flags & (G_FLAG|GG_FLAG)))
2494887Schin {
2504887Schin if (!(pw = getpwnam(name)))
2514887Schin {
2524887Schin user = strtol(name, &s, 0);
2534887Schin if (*s || !(pw = getpwuid(user)))
2544887Schin error(ERROR_exit(1), "%s: name not found", name);
2554887Schin name = pw->pw_name;
2564887Schin }
2574887Schin user = pw->pw_uid;
2584887Schin group = pw->pw_gid;
2594887Schin }
2604887Schin #if _lib_fsid
2614887Schin if (!(flags & N_FLAG) || (flags & S_FLAG))
2624887Schin {
2634887Schin setfsgent();
2644887Schin do
2654887Schin {
2664887Schin if (!(fs = getfsgnam(name)))
2674887Schin error(ERROR_exit(1), "%u: fss name not found", name);
2684887Schin } while (isfsg(fs));
2694887Schin fs_id = fs->fs_id;
2704887Schin }
2714887Schin #endif
2724887Schin }
2734887Schin else
2744887Schin {
2754887Schin if (flags & G_FLAG)
2764887Schin group = (flags & R_FLAG) ? getgid() : getegid();
2774887Schin if (flags & (GG_FLAG|N_FLAG|U_FLAG))
2784887Schin user = (flags & R_FLAG) ? getuid() : geteuid();
2794887Schin #if _lib_fsid
2804887Schin if (flags & S_FLAG)
2814887Schin fs_id = fsid(0);
2824887Schin #endif
2834887Schin if (flags & N_FLAG)
2844887Schin name = (pw = getpwuid(user)) ? pw->pw_name : (char*)0;
2854887Schin }
2864887Schin if (ngroups == 1 && groups[0] == group)
2874887Schin ngroups = 0;
2884887Schin if ((flags & N_FLAG) && (flags & G_FLAG))
2894887Schin gname = (grp = getgrgid(group)) ? grp->gr_name : (char*)0;
2904887Schin #if _lib_fsid
2914887Schin if ((flags & N_FLAG) && (flags & S_FLAG))
2924887Schin {
2934887Schin setfsgent();
2944887Schin fs_name = (fs = getfsgid(fs_id)) ? fs->fs_grp : (char*)0;
2954887Schin }
2964887Schin #endif
2974887Schin if ((flags & (U_FLAG|G_FLAG|S_FLAG)) == (U_FLAG|G_FLAG|S_FLAG))
2984887Schin {
2994887Schin putid(sp, flags, "uid", name, user);
3004887Schin putid(sp, flags, " gid", gname, group);
3014887Schin if ((flags & X_FLAG) && name)
3024887Schin {
3034887Schin #if _lib_getgrent
3044887Schin #if _lib_setgrent
3054887Schin setgrent();
3064887Schin #endif
3074887Schin lastchar = '=';
3084887Schin while (grp = getgrent())
3094887Schin if (p = grp->gr_mem)
3104887Schin while (s = *p++)
3114887Schin if (streq(s, name))
3124887Schin {
3134887Schin if (lastchar == '=')
3144887Schin sfputr(sp, " groups", -1);
3154887Schin sfputc(sp, lastchar);
3164887Schin lastchar = ',';
3174887Schin if (flags & O_FLAG)
3184887Schin sfprintf(sp, "%s", grp->gr_name);
3194887Schin else sfprintf(sp, "%u(%s)", grp->gr_gid, grp->gr_name);
3204887Schin }
3214887Schin #if _lib_endgrent
3224887Schin endgrent();
3234887Schin #endif
3244887Schin #endif
3254887Schin #if _lib_fsid
3264887Schin getfsids(sp, name, flags, '=');
3274887Schin #endif
3284887Schin }
3294887Schin else
3304887Schin {
3314887Schin if ((euid = geteuid()) != user)
3324887Schin putid(sp, flags, " euid", (pw = getpwuid(euid)) ? pw->pw_name : (char*)0, euid);
3334887Schin if ((egid = getegid()) != group)
3344887Schin putid(sp, flags, " egid", (grp = getgrgid(egid)) ? grp->gr_name : (char*)0, egid);
3354887Schin if (ngroups > 0)
3364887Schin {
3374887Schin sfputr(sp, " groups", -1);
3384887Schin lastchar = '=';
3394887Schin for (i = 0; i < ngroups; i++)
3404887Schin {
3414887Schin group = groups[i];
3424887Schin sfputc(sp, lastchar);
3434887Schin if (grp = getgrgid(group))
3444887Schin {
3454887Schin if (flags & O_FLAG) sfprintf(sp, "%s", grp->gr_name);
3464887Schin else sfprintf(sp, "%u(%s)", group, grp->gr_name);
3474887Schin }
3484887Schin else sfprintf(sp, "%u", group);
3494887Schin lastchar = ',';
3504887Schin }
3514887Schin }
3524887Schin #if _lib_fsid
3534887Schin putid(sp, flags, " fsid", fs_name, fs_id);
3544887Schin #endif
3554887Schin }
3564887Schin sfputc(sp,'\n');
3574887Schin return(0);
3584887Schin }
3594887Schin if (flags & U_FLAG)
3604887Schin {
3614887Schin if ((flags & N_FLAG) && name) sfputr(sp, name, '\n');
3624887Schin else sfprintf(sp, "%u\n", user);
3634887Schin }
3644887Schin else if (flags & G_FLAG)
3654887Schin {
3664887Schin if ((flags & N_FLAG) && gname) sfputr(sp, gname, '\n');
3674887Schin else sfprintf(sp, "%u\n", group);
3684887Schin }
3694887Schin else if (flags & GG_FLAG)
3704887Schin {
3714887Schin if ((flags & X_FLAG) && name)
3724887Schin {
3734887Schin #if _lib_getgrent
3744887Schin #if _lib_setgrent
3754887Schin setgrent();
3764887Schin #endif
3774887Schin i = 0;
3784887Schin while (grp = getgrent())
3794887Schin if (p = grp->gr_mem)
3804887Schin while (s = *p++)
3814887Schin if (streq(s, name))
3824887Schin {
3834887Schin if (i++) sfputc(sp, ' ');
3844887Schin if (flags & N_FLAG) sfprintf(sp, "%s", grp->gr_name);
3854887Schin else sfprintf(sp, "%u", grp->gr_gid);
3864887Schin }
3874887Schin #if _lib_endgrent
3884887Schin endgrent();
3894887Schin #endif
3904887Schin if (i) sfputc(sp, '\n');
3914887Schin #endif
3924887Schin }
3934887Schin else if (ngroups > 0)
3944887Schin {
3954887Schin for (i = 0;;)
3964887Schin {
3974887Schin group = groups[i];
3984887Schin if ((flags & N_FLAG) && (grp = getgrgid(group)))
3994887Schin sfprintf(sp, "%s", grp->gr_name);
4004887Schin else sfprintf(sp, "%u", group);
4014887Schin if (++i >= ngroups) break;
4024887Schin sfputc(sp, ' ');
4034887Schin }
4044887Schin sfputc(sp, '\n');
4054887Schin }
4064887Schin }
4074887Schin #if _lib_fsid
4084887Schin else if (flags & S_FLAG)
4094887Schin {
4104887Schin if ((flags & X_FLAG) && name) getfsids(sp, name, flags, 0);
4114887Schin else if ((flags & N_FLAG) && fs_name) sfputr(sp, fs_name, '\n');
4124887Schin else sfprintf(sp, "%u\n", fs_id);
4134887Schin }
4144887Schin #endif
4154887Schin return(0);
4164887Schin }
4174887Schin
4184887Schin int
b_id(int argc,char * argv[],void * context)4194887Schin b_id(int argc, char *argv[], void* context)
4204887Schin {
4214887Schin register int flags = 0;
4224887Schin register int n;
4234887Schin
4244887Schin cmdinit(argc, argv, context, ERROR_CATALOG, 0);
4254887Schin while (n = optget(argv, usage)) switch (n)
4264887Schin {
4274887Schin case 'a':
4284887Schin break;
4294887Schin case 'G':
4304887Schin flags |= GG_FLAG;
4314887Schin break;
4324887Schin case 'g':
4334887Schin flags |= G_FLAG;
4344887Schin break;
4354887Schin case 'n':
4364887Schin flags |= N_FLAG;
4374887Schin break;
4384887Schin case 'r':
4394887Schin flags |= R_FLAG;
4404887Schin break;
4414887Schin case 's':
4424887Schin flags |= S_FLAG;
4434887Schin break;
4444887Schin case 'u':
4454887Schin flags |= U_FLAG;
4464887Schin break;
4474887Schin case ':':
4484887Schin error(2, "%s", opt_info.arg);
4494887Schin break;
4504887Schin case '?':
4514887Schin error(ERROR_usage(2), "%s", opt_info.arg);
4524887Schin break;
4534887Schin }
4544887Schin argv += opt_info.index;
4554887Schin argc -= opt_info.index;
4564887Schin n = (flags & (GG_FLAG|G_FLAG|S_FLAG|U_FLAG));
4574887Schin if (!power2(n))
4584887Schin error(2, "incompatible options selected");
4594887Schin if (error_info.errors || argc > 1)
4604887Schin error(ERROR_usage(2), "%s", optusage(NiL));
4614887Schin if (!(flags & ~(N_FLAG|R_FLAG)))
4624887Schin {
4634887Schin if (flags & N_FLAG) flags |= O_FLAG;
4644887Schin flags |= (U_FLAG|G_FLAG|N_FLAG|R_FLAG|S_FLAG|GG_FLAG);
4654887Schin }
4664887Schin error_info.errors = getids(sfstdout, *argv, flags);
4674887Schin return(error_info.errors);
4684887Schin }
469