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