xref: /titanic_51/usr/src/lib/libcmd/common/id.c (revision da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968)
1*da2e3ebdSchin /***********************************************************************
2*da2e3ebdSchin *                                                                      *
3*da2e3ebdSchin *               This software is part of the ast package               *
4*da2e3ebdSchin *           Copyright (c) 1992-2007 AT&T Knowledge Ventures            *
5*da2e3ebdSchin *                      and is licensed under the                       *
6*da2e3ebdSchin *                  Common Public License, Version 1.0                  *
7*da2e3ebdSchin *                      by AT&T Knowledge Ventures                      *
8*da2e3ebdSchin *                                                                      *
9*da2e3ebdSchin *                A copy of the License is available at                 *
10*da2e3ebdSchin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*da2e3ebdSchin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*da2e3ebdSchin *                                                                      *
13*da2e3ebdSchin *              Information and Software Systems Research               *
14*da2e3ebdSchin *                            AT&T Research                             *
15*da2e3ebdSchin *                           Florham Park NJ                            *
16*da2e3ebdSchin *                                                                      *
17*da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18*da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
19*da2e3ebdSchin *                                                                      *
20*da2e3ebdSchin ***********************************************************************/
21*da2e3ebdSchin #pragma prototyped
22*da2e3ebdSchin /*
23*da2e3ebdSchin  * David Korn
24*da2e3ebdSchin  * Glenn Fowler
25*da2e3ebdSchin  * AT&T Research
26*da2e3ebdSchin  *
27*da2e3ebdSchin  * id
28*da2e3ebdSchin  */
29*da2e3ebdSchin 
30*da2e3ebdSchin static const char usage[] =
31*da2e3ebdSchin "[-?\n@(#)$Id: id (AT&T Research) 2004-06-11 $\n]"
32*da2e3ebdSchin USAGE_LICENSE
33*da2e3ebdSchin "[+NAME?id - return user identity]"
34*da2e3ebdSchin "[+DESCRIPTION?If no \auser\a operand is specified \bid\b writes user and "
35*da2e3ebdSchin 	"group IDs and the corresponding user and group names of the "
36*da2e3ebdSchin 	"invoking process to standard output.  If the effective and "
37*da2e3ebdSchin 	"real IDs do not match, both are written.  Any supplementary "
38*da2e3ebdSchin 	"groups the current process belongs to will also be written.]"
39*da2e3ebdSchin "[+?If a \auser\a operand is specified and the process has permission, "
40*da2e3ebdSchin 	"the user and group IDs and any supplementary group IDs of the "
41*da2e3ebdSchin 	"selected user will be written to standard output.]"
42*da2e3ebdSchin "[+?If any options are specified, then only a portion of the information "
43*da2e3ebdSchin 	"is written.]"
44*da2e3ebdSchin "[n:name?Write the name instead of the numeric ID.]"
45*da2e3ebdSchin "[r:real?Writes real ID instead of the effective ID.]"
46*da2e3ebdSchin "[[a?This option is ignored.]"
47*da2e3ebdSchin "[g:group?Writes only the group ID.]"
48*da2e3ebdSchin "[u:user?Writes only the user ID.]"
49*da2e3ebdSchin "[G:groups?Writes only the supplementary group IDs.]"
50*da2e3ebdSchin "[s:fair-share?Writes fair share scheduler IDs and groups on systems that "
51*da2e3ebdSchin 	"support fair share scheduling.]"
52*da2e3ebdSchin "\n"
53*da2e3ebdSchin "\n[user]\n"
54*da2e3ebdSchin "\n"
55*da2e3ebdSchin "[+EXIT STATUS?]{"
56*da2e3ebdSchin         "[+0?Successful completion.]"
57*da2e3ebdSchin         "[+>0?An error occurred.]"
58*da2e3ebdSchin "}"
59*da2e3ebdSchin "[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\b(2)]"
60*da2e3ebdSchin ;
61*da2e3ebdSchin 
62*da2e3ebdSchin #include <cmd.h>
63*da2e3ebdSchin 
64*da2e3ebdSchin #include "FEATURE/ids"
65*da2e3ebdSchin 
66*da2e3ebdSchin #include <grp.h>
67*da2e3ebdSchin #include <pwd.h>
68*da2e3ebdSchin 
69*da2e3ebdSchin #if _lib_fsid
70*da2e3ebdSchin #if _lib_getfsgid && ( _sys_fss || _hdr_fsg )
71*da2e3ebdSchin #define fss_grp		fs_grp
72*da2e3ebdSchin #define fss_id		fs_id
73*da2e3ebdSchin #define fss_mem		fs_mem
74*da2e3ebdSchin #define fss_passwd	fs_passwd
75*da2e3ebdSchin #define fss_shares	fs_shares
76*da2e3ebdSchin #if _sys_fss
77*da2e3ebdSchin #include <sys/fss.h>
78*da2e3ebdSchin #endif
79*da2e3ebdSchin #if _hdr_fsg
80*da2e3ebdSchin #include <fsg.h>
81*da2e3ebdSchin #endif
82*da2e3ebdSchin #if !_lib_isfsg && !defined(isfsg)
83*da2e3ebdSchin #define isfsg(p)	(!(p)->fs_id&&!(p)->fs_shares&&(!(p)->fs_passwd||!*(p)->fs_passwd))
84*da2e3ebdSchin #endif
85*da2e3ebdSchin #else
86*da2e3ebdSchin #undef _lib_fsid
87*da2e3ebdSchin #endif
88*da2e3ebdSchin #endif
89*da2e3ebdSchin 
90*da2e3ebdSchin #define power2(n)	(!((n)&((n)-1)))
91*da2e3ebdSchin 
92*da2e3ebdSchin #define GG_FLAG		(1<<0)
93*da2e3ebdSchin #define G_FLAG		(1<<1)
94*da2e3ebdSchin #define N_FLAG		(1<<2)
95*da2e3ebdSchin #define R_FLAG		(1<<3)
96*da2e3ebdSchin #define U_FLAG		(1<<4)
97*da2e3ebdSchin #define S_FLAG		(1<<5)
98*da2e3ebdSchin #define O_FLAG		(1<<6)
99*da2e3ebdSchin #define X_FLAG		(1<<7)
100*da2e3ebdSchin 
101*da2e3ebdSchin #if _lib_fsid
102*da2e3ebdSchin static void
103*da2e3ebdSchin getfsids(Sfio_t* sp, const char* name, int flags, register int lastchar)
104*da2e3ebdSchin {
105*da2e3ebdSchin 	register struct fsg*	fs;
106*da2e3ebdSchin 	register char*		s;
107*da2e3ebdSchin 	register char**		p;
108*da2e3ebdSchin 	char**			x;
109*da2e3ebdSchin 
110*da2e3ebdSchin 	if (lastchar)
111*da2e3ebdSchin 	{
112*da2e3ebdSchin 		if (flags & O_FLAG) flags = 1;
113*da2e3ebdSchin 		else flags = 0;
114*da2e3ebdSchin 	}
115*da2e3ebdSchin 	else if (flags & N_FLAG) flags = 1;
116*da2e3ebdSchin 	else flags = -1;
117*da2e3ebdSchin 	setfsgent();
118*da2e3ebdSchin 	while (fs = getfsgnam(name))
119*da2e3ebdSchin 		if (!isfsg(fs))
120*da2e3ebdSchin 		{
121*da2e3ebdSchin 			if (p = fs->fs_mem)
122*da2e3ebdSchin 			{
123*da2e3ebdSchin 				if (flags > 0) x = 0;
124*da2e3ebdSchin 				else
125*da2e3ebdSchin 				{
126*da2e3ebdSchin 					register char**		q;
127*da2e3ebdSchin 					register char*		t;
128*da2e3ebdSchin 					register int		n;
129*da2e3ebdSchin 
130*da2e3ebdSchin 					n = 0;
131*da2e3ebdSchin 					q = p;
132*da2e3ebdSchin 					while (s = *q++)
133*da2e3ebdSchin 						n += strlen(s) + 1;
134*da2e3ebdSchin 					if (!(x = newof(0, char*, q - p, n)))
135*da2e3ebdSchin 						break;
136*da2e3ebdSchin 					s = (char*)(x + (q - p));
137*da2e3ebdSchin 					q = x;
138*da2e3ebdSchin 					while (t = *p++)
139*da2e3ebdSchin 					{
140*da2e3ebdSchin 						*q++ = s;
141*da2e3ebdSchin 						while (*s++ = *t++);
142*da2e3ebdSchin 					}
143*da2e3ebdSchin 					*q = 0;
144*da2e3ebdSchin 					p = x;
145*da2e3ebdSchin 				}
146*da2e3ebdSchin 				while (s = *p++)
147*da2e3ebdSchin 				{
148*da2e3ebdSchin 					if (lastchar == '=')
149*da2e3ebdSchin 					{
150*da2e3ebdSchin 						lastchar = ',';
151*da2e3ebdSchin 						sfputr(sp, " fsid=", -1);
152*da2e3ebdSchin 					}
153*da2e3ebdSchin 					else if (!lastchar) lastchar = ' ';
154*da2e3ebdSchin 					else sfputc(sp, lastchar);
155*da2e3ebdSchin 					if (flags > 0) sfprintf(sp, "%s", s);
156*da2e3ebdSchin 					else
157*da2e3ebdSchin 					{
158*da2e3ebdSchin 						setfsgent();
159*da2e3ebdSchin 						while (fs = getfsgnam(s))
160*da2e3ebdSchin 							if (isfsg(fs))
161*da2e3ebdSchin 							{
162*da2e3ebdSchin 								if (flags < 0) sfprintf(sp, "%u", fs->fs_id);
163*da2e3ebdSchin 								else sfprintf(sp, "%u(%s)", fs->fs_id, s);
164*da2e3ebdSchin 								break;
165*da2e3ebdSchin 							}
166*da2e3ebdSchin 					}
167*da2e3ebdSchin 				}
168*da2e3ebdSchin 				if (x) free(x);
169*da2e3ebdSchin 			}
170*da2e3ebdSchin 			break;
171*da2e3ebdSchin 		}
172*da2e3ebdSchin 	endfsgent();
173*da2e3ebdSchin 	if (lastchar == ' ') sfputc(sp, '\n');
174*da2e3ebdSchin }
175*da2e3ebdSchin #endif
176*da2e3ebdSchin 
177*da2e3ebdSchin static void
178*da2e3ebdSchin putid(Sfio_t* sp, int flags, const char* label, const char* name, long number)
179*da2e3ebdSchin {
180*da2e3ebdSchin 	sfprintf(sp, "%s=", label);
181*da2e3ebdSchin 	if (flags & O_FLAG)
182*da2e3ebdSchin 	{
183*da2e3ebdSchin 		if (name) sfputr(sp, name, -1);
184*da2e3ebdSchin 		else sfprintf(sp, "%lu", number);
185*da2e3ebdSchin 	}
186*da2e3ebdSchin 	else
187*da2e3ebdSchin 	{
188*da2e3ebdSchin 		sfprintf(sp, "%u", number);
189*da2e3ebdSchin 		if (name) sfprintf(sp, "(%s)", name);
190*da2e3ebdSchin 	}
191*da2e3ebdSchin }
192*da2e3ebdSchin 
193*da2e3ebdSchin static int
194*da2e3ebdSchin getids(Sfio_t* sp, const char* name, register int flags)
195*da2e3ebdSchin {
196*da2e3ebdSchin 	register struct passwd*	pw;
197*da2e3ebdSchin 	register struct group*	grp;
198*da2e3ebdSchin 	register int		i;
199*da2e3ebdSchin 	register int		j;
200*da2e3ebdSchin 	register int		k;
201*da2e3ebdSchin #if _lib_fsid
202*da2e3ebdSchin 	register struct fsg*	fs;
203*da2e3ebdSchin 	const char*		fs_name;
204*da2e3ebdSchin 	int			fs_id;
205*da2e3ebdSchin #endif
206*da2e3ebdSchin 	char**			p;
207*da2e3ebdSchin 	char*			s;
208*da2e3ebdSchin 	int			lastchar;
209*da2e3ebdSchin 	int			ngroups = 0;
210*da2e3ebdSchin 	const char*		gname;
211*da2e3ebdSchin 	uid_t			user;
212*da2e3ebdSchin 	uid_t			euid;
213*da2e3ebdSchin 	gid_t			group;
214*da2e3ebdSchin 	gid_t			egid;
215*da2e3ebdSchin 
216*da2e3ebdSchin 	static gid_t*		groups;
217*da2e3ebdSchin 
218*da2e3ebdSchin 	if (flags & GG_FLAG)
219*da2e3ebdSchin 	{
220*da2e3ebdSchin 		static int	maxgroups;
221*da2e3ebdSchin 
222*da2e3ebdSchin 		/*
223*da2e3ebdSchin 		 * get supplemental groups if required
224*da2e3ebdSchin 		 */
225*da2e3ebdSchin 
226*da2e3ebdSchin 		if (!maxgroups)
227*da2e3ebdSchin 		{
228*da2e3ebdSchin 			/*
229*da2e3ebdSchin 			 * first time
230*da2e3ebdSchin 			 */
231*da2e3ebdSchin 
232*da2e3ebdSchin 			if ((maxgroups = getgroups(0, groups)) <= 0)
233*da2e3ebdSchin 				maxgroups = NGROUPS_MAX;
234*da2e3ebdSchin 			if (!(groups = newof(0, gid_t, maxgroups + 1, 0)))
235*da2e3ebdSchin 				error(ERROR_exit(1), "out of space [group array]");
236*da2e3ebdSchin 		}
237*da2e3ebdSchin 		ngroups = getgroups(maxgroups, groups);
238*da2e3ebdSchin 		for (i = j = 0; i < ngroups; i++)
239*da2e3ebdSchin 		{
240*da2e3ebdSchin 			for (k = 0; k < j && groups[k] != groups[i]; k++);
241*da2e3ebdSchin 			if (k >= j) groups[j++] = groups[i];
242*da2e3ebdSchin 		}
243*da2e3ebdSchin 		ngroups = j;
244*da2e3ebdSchin 	}
245*da2e3ebdSchin 	if (name)
246*da2e3ebdSchin 	{
247*da2e3ebdSchin 		flags |= X_FLAG;
248*da2e3ebdSchin 		if (!(flags & N_FLAG) || (flags & (G_FLAG|GG_FLAG)))
249*da2e3ebdSchin 		{
250*da2e3ebdSchin 			if (!(pw = getpwnam(name)))
251*da2e3ebdSchin 			{
252*da2e3ebdSchin 				user = strtol(name, &s, 0);
253*da2e3ebdSchin 				if (*s || !(pw = getpwuid(user)))
254*da2e3ebdSchin 					error(ERROR_exit(1), "%s: name not found", name);
255*da2e3ebdSchin 				name = pw->pw_name;
256*da2e3ebdSchin 			}
257*da2e3ebdSchin 			user = pw->pw_uid;
258*da2e3ebdSchin 			group = pw->pw_gid;
259*da2e3ebdSchin 		}
260*da2e3ebdSchin #if _lib_fsid
261*da2e3ebdSchin 		if (!(flags & N_FLAG) || (flags & S_FLAG))
262*da2e3ebdSchin 		{
263*da2e3ebdSchin 			setfsgent();
264*da2e3ebdSchin 			do
265*da2e3ebdSchin                         {
266*da2e3ebdSchin                                 if (!(fs = getfsgnam(name)))
267*da2e3ebdSchin                                         error(ERROR_exit(1), "%u: fss name not found", name);
268*da2e3ebdSchin                         } while (isfsg(fs));
269*da2e3ebdSchin                         fs_id = fs->fs_id;
270*da2e3ebdSchin 		}
271*da2e3ebdSchin #endif
272*da2e3ebdSchin 	}
273*da2e3ebdSchin 	else
274*da2e3ebdSchin 	{
275*da2e3ebdSchin 		if (flags & G_FLAG)
276*da2e3ebdSchin 			group = (flags & R_FLAG) ? getgid() : getegid();
277*da2e3ebdSchin 		if (flags & (GG_FLAG|N_FLAG|U_FLAG))
278*da2e3ebdSchin 			user = (flags & R_FLAG) ? getuid() : geteuid();
279*da2e3ebdSchin #if _lib_fsid
280*da2e3ebdSchin 		if (flags & S_FLAG)
281*da2e3ebdSchin 			fs_id = fsid(0);
282*da2e3ebdSchin #endif
283*da2e3ebdSchin 		if (flags & N_FLAG)
284*da2e3ebdSchin 			name = (pw = getpwuid(user)) ? pw->pw_name : (char*)0;
285*da2e3ebdSchin 	}
286*da2e3ebdSchin 	if (ngroups == 1 && groups[0] == group)
287*da2e3ebdSchin 		ngroups = 0;
288*da2e3ebdSchin 	if ((flags & N_FLAG) && (flags & G_FLAG))
289*da2e3ebdSchin 		gname = (grp = getgrgid(group)) ? grp->gr_name : (char*)0;
290*da2e3ebdSchin #if _lib_fsid
291*da2e3ebdSchin 	if ((flags & N_FLAG) && (flags & S_FLAG))
292*da2e3ebdSchin 	{
293*da2e3ebdSchin 		setfsgent();
294*da2e3ebdSchin 		fs_name = (fs = getfsgid(fs_id)) ? fs->fs_grp : (char*)0;
295*da2e3ebdSchin 	}
296*da2e3ebdSchin #endif
297*da2e3ebdSchin 	if ((flags & (U_FLAG|G_FLAG|S_FLAG)) == (U_FLAG|G_FLAG|S_FLAG))
298*da2e3ebdSchin 	{
299*da2e3ebdSchin 		putid(sp, flags, "uid", name, user);
300*da2e3ebdSchin 		putid(sp, flags, " gid", gname, group);
301*da2e3ebdSchin 		if ((flags & X_FLAG) && name)
302*da2e3ebdSchin 		{
303*da2e3ebdSchin #if _lib_getgrent
304*da2e3ebdSchin #if _lib_setgrent
305*da2e3ebdSchin 			setgrent();
306*da2e3ebdSchin #endif
307*da2e3ebdSchin 			lastchar = '=';
308*da2e3ebdSchin 			while (grp = getgrent())
309*da2e3ebdSchin 				if (p = grp->gr_mem)
310*da2e3ebdSchin 					while (s = *p++)
311*da2e3ebdSchin 						if (streq(s, name))
312*da2e3ebdSchin 						{
313*da2e3ebdSchin 							if (lastchar == '=')
314*da2e3ebdSchin 								sfputr(sp, " groups", -1);
315*da2e3ebdSchin 							sfputc(sp, lastchar);
316*da2e3ebdSchin 							lastchar = ',';
317*da2e3ebdSchin 							if (flags & O_FLAG)
318*da2e3ebdSchin 								sfprintf(sp, "%s", grp->gr_name);
319*da2e3ebdSchin 							else sfprintf(sp, "%u(%s)", grp->gr_gid, grp->gr_name);
320*da2e3ebdSchin 						}
321*da2e3ebdSchin #if _lib_endgrent
322*da2e3ebdSchin 			endgrent();
323*da2e3ebdSchin #endif
324*da2e3ebdSchin #endif
325*da2e3ebdSchin #if _lib_fsid
326*da2e3ebdSchin 			getfsids(sp, name, flags, '=');
327*da2e3ebdSchin #endif
328*da2e3ebdSchin 		}
329*da2e3ebdSchin 		else
330*da2e3ebdSchin 		{
331*da2e3ebdSchin 			if ((euid = geteuid()) != user)
332*da2e3ebdSchin 				putid(sp, flags, " euid", (pw = getpwuid(euid)) ? pw->pw_name : (char*)0, euid);
333*da2e3ebdSchin 			if ((egid = getegid()) != group)
334*da2e3ebdSchin 				putid(sp, flags, " egid", (grp = getgrgid(egid)) ? grp->gr_name : (char*)0, egid);
335*da2e3ebdSchin 			if (ngroups > 0)
336*da2e3ebdSchin 			{
337*da2e3ebdSchin 				sfputr(sp, " groups", -1);
338*da2e3ebdSchin 				lastchar = '=';
339*da2e3ebdSchin 				for (i = 0; i < ngroups; i++)
340*da2e3ebdSchin 				{
341*da2e3ebdSchin 					group = groups[i];
342*da2e3ebdSchin 					sfputc(sp, lastchar);
343*da2e3ebdSchin 					if (grp = getgrgid(group))
344*da2e3ebdSchin 					{
345*da2e3ebdSchin 						if (flags & O_FLAG) sfprintf(sp, "%s", grp->gr_name);
346*da2e3ebdSchin 						else sfprintf(sp, "%u(%s)", group, grp->gr_name);
347*da2e3ebdSchin 					}
348*da2e3ebdSchin 					else sfprintf(sp, "%u", group);
349*da2e3ebdSchin 					lastchar = ',';
350*da2e3ebdSchin 				}
351*da2e3ebdSchin 			}
352*da2e3ebdSchin #if _lib_fsid
353*da2e3ebdSchin 			putid(sp, flags, " fsid", fs_name, fs_id);
354*da2e3ebdSchin #endif
355*da2e3ebdSchin 		}
356*da2e3ebdSchin 		sfputc(sp,'\n');
357*da2e3ebdSchin 		return(0);
358*da2e3ebdSchin 	}
359*da2e3ebdSchin 	if (flags & U_FLAG)
360*da2e3ebdSchin 	{
361*da2e3ebdSchin 		if ((flags & N_FLAG) && name) sfputr(sp, name, '\n');
362*da2e3ebdSchin 		else sfprintf(sp, "%u\n", user);
363*da2e3ebdSchin 	}
364*da2e3ebdSchin 	else if (flags & G_FLAG)
365*da2e3ebdSchin 	{
366*da2e3ebdSchin 		if ((flags & N_FLAG) && gname) sfputr(sp, gname, '\n');
367*da2e3ebdSchin 		else sfprintf(sp, "%u\n", group);
368*da2e3ebdSchin 	}
369*da2e3ebdSchin 	else if (flags & GG_FLAG)
370*da2e3ebdSchin 	{
371*da2e3ebdSchin 		if ((flags & X_FLAG) && name)
372*da2e3ebdSchin 		{
373*da2e3ebdSchin #if _lib_getgrent
374*da2e3ebdSchin #if _lib_setgrent
375*da2e3ebdSchin 			setgrent();
376*da2e3ebdSchin #endif
377*da2e3ebdSchin 			i = 0;
378*da2e3ebdSchin 			while (grp = getgrent())
379*da2e3ebdSchin 				if (p = grp->gr_mem)
380*da2e3ebdSchin 					while (s = *p++)
381*da2e3ebdSchin 						if (streq(s, name))
382*da2e3ebdSchin 						{
383*da2e3ebdSchin 							if (i++) sfputc(sp, ' ');
384*da2e3ebdSchin 							if (flags & N_FLAG) sfprintf(sp, "%s", grp->gr_name);
385*da2e3ebdSchin 							else sfprintf(sp, "%u", grp->gr_gid);
386*da2e3ebdSchin 						}
387*da2e3ebdSchin #if _lib_endgrent
388*da2e3ebdSchin 			endgrent();
389*da2e3ebdSchin #endif
390*da2e3ebdSchin 			if (i) sfputc(sp, '\n');
391*da2e3ebdSchin #endif
392*da2e3ebdSchin 		}
393*da2e3ebdSchin 		else if (ngroups > 0)
394*da2e3ebdSchin 		{
395*da2e3ebdSchin 			for (i = 0;;)
396*da2e3ebdSchin 			{
397*da2e3ebdSchin 				group = groups[i];
398*da2e3ebdSchin 				if ((flags & N_FLAG) && (grp = getgrgid(group)))
399*da2e3ebdSchin 					sfprintf(sp, "%s", grp->gr_name);
400*da2e3ebdSchin 				else sfprintf(sp, "%u", group);
401*da2e3ebdSchin 				if (++i >= ngroups) break;
402*da2e3ebdSchin 				sfputc(sp, ' ');
403*da2e3ebdSchin 			}
404*da2e3ebdSchin 			sfputc(sp, '\n');
405*da2e3ebdSchin 		}
406*da2e3ebdSchin 	}
407*da2e3ebdSchin #if _lib_fsid
408*da2e3ebdSchin 	else if (flags & S_FLAG)
409*da2e3ebdSchin 	{
410*da2e3ebdSchin 		if ((flags & X_FLAG) && name) getfsids(sp, name, flags, 0);
411*da2e3ebdSchin 		else if ((flags & N_FLAG) && fs_name) sfputr(sp, fs_name, '\n');
412*da2e3ebdSchin 		else sfprintf(sp, "%u\n", fs_id);
413*da2e3ebdSchin 	}
414*da2e3ebdSchin #endif
415*da2e3ebdSchin 	return(0);
416*da2e3ebdSchin }
417*da2e3ebdSchin 
418*da2e3ebdSchin int
419*da2e3ebdSchin b_id(int argc, char *argv[], void* context)
420*da2e3ebdSchin {
421*da2e3ebdSchin 	register int	flags = 0;
422*da2e3ebdSchin 	register int	n;
423*da2e3ebdSchin 
424*da2e3ebdSchin 	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
425*da2e3ebdSchin 	while (n = optget(argv, usage)) switch (n)
426*da2e3ebdSchin 	{
427*da2e3ebdSchin 	case 'a':
428*da2e3ebdSchin 		break;
429*da2e3ebdSchin 	case 'G':
430*da2e3ebdSchin 		flags |= GG_FLAG;
431*da2e3ebdSchin 		break;
432*da2e3ebdSchin 	case 'g':
433*da2e3ebdSchin 		flags |= G_FLAG;
434*da2e3ebdSchin 		break;
435*da2e3ebdSchin 	case 'n':
436*da2e3ebdSchin 		flags |= N_FLAG;
437*da2e3ebdSchin 		break;
438*da2e3ebdSchin 	case 'r':
439*da2e3ebdSchin 		flags |= R_FLAG;
440*da2e3ebdSchin 		break;
441*da2e3ebdSchin 	case 's':
442*da2e3ebdSchin 		flags |= S_FLAG;
443*da2e3ebdSchin 		break;
444*da2e3ebdSchin 	case 'u':
445*da2e3ebdSchin 		flags |= U_FLAG;
446*da2e3ebdSchin 		break;
447*da2e3ebdSchin 	case ':':
448*da2e3ebdSchin 		error(2, "%s", opt_info.arg);
449*da2e3ebdSchin 		break;
450*da2e3ebdSchin 	case '?':
451*da2e3ebdSchin 		error(ERROR_usage(2), "%s", opt_info.arg);
452*da2e3ebdSchin 		break;
453*da2e3ebdSchin 	}
454*da2e3ebdSchin 	argv += opt_info.index;
455*da2e3ebdSchin 	argc -= opt_info.index;
456*da2e3ebdSchin 	n = (flags & (GG_FLAG|G_FLAG|S_FLAG|U_FLAG));
457*da2e3ebdSchin 	if (!power2(n))
458*da2e3ebdSchin 		error(2, "incompatible options selected");
459*da2e3ebdSchin 	if (error_info.errors || argc > 1)
460*da2e3ebdSchin 		error(ERROR_usage(2), "%s", optusage(NiL));
461*da2e3ebdSchin 	if (!(flags & ~(N_FLAG|R_FLAG)))
462*da2e3ebdSchin 	{
463*da2e3ebdSchin 		if (flags & N_FLAG) flags |= O_FLAG;
464*da2e3ebdSchin 		flags |= (U_FLAG|G_FLAG|N_FLAG|R_FLAG|S_FLAG|GG_FLAG);
465*da2e3ebdSchin 	}
466*da2e3ebdSchin 	error_info.errors = getids(sfstdout, *argv, flags);
467*da2e3ebdSchin 	return(error_info.errors);
468*da2e3ebdSchin }
469