1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1992-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
20 ***********************************************************************/
30 static const char usage
[] =
31 "[-?\n@(#)$Id: id (AT&T Research) 2004-06-11 $\n]"
33 "[+NAME?id - return user identity]"
34 "[+DESCRIPTION?If no \auser\a operand is specified \bid\b writes user and "
35 "group IDs and the corresponding user and group names of the "
36 "invoking process to standard output. If the effective and "
37 "real IDs do not match, both are written. Any supplementary "
38 "groups the current process belongs to will also be written.]"
39 "[+?If a \auser\a operand is specified and the process has permission, "
40 "the user and group IDs and any supplementary group IDs of the "
41 "selected user will be written to standard output.]"
42 "[+?If any options are specified, then only a portion of the information "
44 "[n:name?Write the name instead of the numeric ID.]"
45 "[r:real?Writes real ID instead of the effective ID.]"
46 "[[a?This option is ignored.]"
47 "[g:group?Writes only the group ID.]"
48 "[u:user?Writes only the user ID.]"
49 "[G:groups?Writes only the supplementary group IDs.]"
50 "[s:fair-share?Writes fair share scheduler IDs and groups on systems that "
51 "support fair share scheduling.]"
56 "[+0?Successful completion.]"
57 "[+>0?An error occurred.]"
59 "[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\b(2)]"
64 #include "FEATURE/ids"
70 #if _lib_getfsgid && ( _sys_fss || _hdr_fsg )
71 #define fss_grp fs_grp
73 #define fss_mem fs_mem
74 #define fss_passwd fs_passwd
75 #define fss_shares fs_shares
82 #if !_lib_isfsg && !defined(isfsg)
83 #define isfsg(p) (!(p)->fs_id&&!(p)->fs_shares&&(!(p)->fs_passwd||!*(p)->fs_passwd))
90 #define power2(n) (!((n)&((n)-1)))
92 #define GG_FLAG (1<<0)
103 getfsids(Sfio_t
* sp
, const char* name
, int flags
, register int lastchar
)
105 register struct fsg
* fs
;
112 if (flags
& O_FLAG
) flags
= 1;
115 else if (flags
& N_FLAG
) flags
= 1;
118 while (fs
= getfsgnam(name
))
123 if (flags
> 0) x
= 0;
134 if (!(x
= newof(0, char*, q
- p
, n
)))
136 s
= (char*)(x
+ (q
- p
));
151 sfputr(sp
, " fsid=", -1);
153 else if (!lastchar
) lastchar
= ' ';
154 else sfputc(sp
, lastchar
);
155 if (flags
> 0) sfprintf(sp
, "%s", s
);
159 while (fs
= getfsgnam(s
))
162 if (flags
< 0) sfprintf(sp
, "%u", fs
->fs_id
);
163 else sfprintf(sp
, "%u(%s)", fs
->fs_id
, s
);
173 if (lastchar
== ' ') sfputc(sp
, '\n');
178 putid(Sfio_t
* sp
, int flags
, const char* label
, const char* name
, long number
)
180 sfprintf(sp
, "%s=", label
);
183 if (name
) sfputr(sp
, name
, -1);
184 else sfprintf(sp
, "%lu", number
);
188 sfprintf(sp
, "%u", number
);
189 if (name
) sfprintf(sp
, "(%s)", name
);
194 getids(Sfio_t
* sp
, const char* name
, register int flags
)
196 register struct passwd
* pw
;
197 register struct group
* grp
;
202 register struct fsg
* fs
;
216 static gid_t
* groups
;
220 static int maxgroups
;
223 * get supplemental groups if required
232 if ((maxgroups
= getgroups(0, groups
)) <= 0)
233 maxgroups
= NGROUPS_MAX
;
234 if (!(groups
= newof(0, gid_t
, maxgroups
+ 1, 0)))
235 error(ERROR_exit(1), "out of space [group array]");
237 ngroups
= getgroups(maxgroups
, groups
);
238 for (i
= j
= 0; i
< ngroups
; i
++)
240 for (k
= 0; k
< j
&& groups
[k
] != groups
[i
]; k
++);
241 if (k
>= j
) groups
[j
++] = groups
[i
];
248 if (!(flags
& N_FLAG
) || (flags
& (G_FLAG
|GG_FLAG
)))
250 if (!(pw
= getpwnam(name
)))
252 user
= strtol(name
, &s
, 0);
253 if (*s
|| !(pw
= getpwuid(user
)))
254 error(ERROR_exit(1), "%s: name not found", name
);
261 if (!(flags
& N_FLAG
) || (flags
& S_FLAG
))
266 if (!(fs
= getfsgnam(name
)))
267 error(ERROR_exit(1), "%u: fss name not found", name
);
276 group
= (flags
& R_FLAG
) ? getgid() : getegid();
277 if (flags
& (GG_FLAG
|N_FLAG
|U_FLAG
))
278 user
= (flags
& R_FLAG
) ? getuid() : geteuid();
284 name
= (pw
= getpwuid(user
)) ? pw
->pw_name
: (char*)0;
286 if (ngroups
== 1 && groups
[0] == group
)
288 if ((flags
& N_FLAG
) && (flags
& G_FLAG
))
289 gname
= (grp
= getgrgid(group
)) ? grp
->gr_name
: (char*)0;
291 if ((flags
& N_FLAG
) && (flags
& S_FLAG
))
294 fs_name
= (fs
= getfsgid(fs_id
)) ? fs
->fs_grp
: (char*)0;
297 if ((flags
& (U_FLAG
|G_FLAG
|S_FLAG
)) == (U_FLAG
|G_FLAG
|S_FLAG
))
299 putid(sp
, flags
, "uid", name
, user
);
300 putid(sp
, flags
, " gid", gname
, group
);
301 if ((flags
& X_FLAG
) && name
)
308 while (grp
= getgrent())
314 sfputr(sp
, " groups", -1);
315 sfputc(sp
, lastchar
);
318 sfprintf(sp
, "%s", grp
->gr_name
);
319 else sfprintf(sp
, "%u(%s)", grp
->gr_gid
, grp
->gr_name
);
326 getfsids(sp
, name
, flags
, '=');
331 if ((euid
= geteuid()) != user
)
332 putid(sp
, flags
, " euid", (pw
= getpwuid(euid
)) ? pw
->pw_name
: (char*)0, euid
);
333 if ((egid
= getegid()) != group
)
334 putid(sp
, flags
, " egid", (grp
= getgrgid(egid
)) ? grp
->gr_name
: (char*)0, egid
);
337 sfputr(sp
, " groups", -1);
339 for (i
= 0; i
< ngroups
; i
++)
342 sfputc(sp
, lastchar
);
343 if (grp
= getgrgid(group
))
345 if (flags
& O_FLAG
) sfprintf(sp
, "%s", grp
->gr_name
);
346 else sfprintf(sp
, "%u(%s)", group
, grp
->gr_name
);
348 else sfprintf(sp
, "%u", group
);
353 putid(sp
, flags
, " fsid", fs_name
, fs_id
);
361 if ((flags
& N_FLAG
) && name
) sfputr(sp
, name
, '\n');
362 else sfprintf(sp
, "%u\n", user
);
364 else if (flags
& G_FLAG
)
366 if ((flags
& N_FLAG
) && gname
) sfputr(sp
, gname
, '\n');
367 else sfprintf(sp
, "%u\n", group
);
369 else if (flags
& GG_FLAG
)
371 if ((flags
& X_FLAG
) && name
)
378 while (grp
= getgrent())
383 if (i
++) sfputc(sp
, ' ');
384 if (flags
& N_FLAG
) sfprintf(sp
, "%s", grp
->gr_name
);
385 else sfprintf(sp
, "%u", grp
->gr_gid
);
390 if (i
) sfputc(sp
, '\n');
393 else if (ngroups
> 0)
398 if ((flags
& N_FLAG
) && (grp
= getgrgid(group
)))
399 sfprintf(sp
, "%s", grp
->gr_name
);
400 else sfprintf(sp
, "%u", group
);
401 if (++i
>= ngroups
) break;
408 else if (flags
& S_FLAG
)
410 if ((flags
& X_FLAG
) && name
) getfsids(sp
, name
, flags
, 0);
411 else if ((flags
& N_FLAG
) && fs_name
) sfputr(sp
, fs_name
, '\n');
412 else sfprintf(sp
, "%u\n", fs_id
);
419 b_id(int argc
, char *argv
[], void* context
)
421 register int flags
= 0;
424 cmdinit(argc
, argv
, context
, ERROR_CATALOG
, 0);
425 while (n
= optget(argv
, usage
)) switch (n
)
448 error(2, "%s", opt_info
.arg
);
451 error(ERROR_usage(2), "%s", opt_info
.arg
);
454 argv
+= opt_info
.index
;
455 argc
-= opt_info
.index
;
456 n
= (flags
& (GG_FLAG
|G_FLAG
|S_FLAG
|U_FLAG
));
458 error(2, "incompatible options selected");
459 if (error_info
.errors
|| argc
> 1)
460 error(ERROR_usage(2), "%s", optusage(NiL
));
461 if (!(flags
& ~(N_FLAG
|R_FLAG
)))
463 if (flags
& N_FLAG
) flags
|= O_FLAG
;
464 flags
|= (U_FLAG
|G_FLAG
|N_FLAG
|R_FLAG
|S_FLAG
|GG_FLAG
);
466 error_info
.errors
= getids(sfstdout
, *argv
, flags
);
467 return(error_info
.errors
);