xref: /onnv-gate/usr/src/lib/libcmd/common/id.c (revision 12068:08a39a083754)
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