1/* id.c - print real and effective user and group IDs
2 *
3 * Copyright 2012 Sony Network Entertainment, Inc.
4 *
5 * by Tim Bird <tim.bird@am.sony.com>
6 *
7 * See http://opengroup.org/onlinepubs/9699919799/utilities/id.html
8
9USE_ID(NEWTOY(id, ">1"USE_ID_SELINUX("Z")"nGgru[!"USE_ID_SELINUX("Z")"Ggu]", TOYFLAG_USR|TOYFLAG_BIN))
10USE_GROUPS(NEWTOY(groups, NULL, TOYFLAG_USR|TOYFLAG_BIN))
11USE_LOGNAME(NEWTOY(logname, ">0", TOYFLAG_USR|TOYFLAG_BIN))
12USE_WHOAMI(OLDTOY(whoami, logname, TOYFLAG_USR|TOYFLAG_BIN))
13
14config ID
15  bool "id"
16  default y
17  help
18    usage: id [-nGgru]
19
20    Print user and group ID.
21
22    -n	print names instead of numeric IDs (to be used with -Ggu)
23    -G	Show only the group IDs
24    -g	Show only the effective group ID
25    -r	Show real ID instead of effective ID
26    -u	Show only the effective user ID
27
28config ID_SELINUX
29  bool
30  default y
31  depends on ID && TOYBOX_SELINUX
32  help
33    usage: id [-Z]
34
35    -Z Show only SELinux context
36
37config GROUPS
38  bool "groups"
39  default y
40  help
41    usage: groups [user]
42
43    Print the groups a user is in.
44
45config LOGNAME
46  bool "logname"
47  default y
48  help
49    usage: logname
50
51    Print the current user name.
52
53config WHOAMI
54  bool "whoami"
55  default y
56  help
57    usage: whoami
58
59    Print the current user name.
60*/
61
62#define FOR_id
63#include "toys.h"
64
65GLOBALS(
66  int do_u, do_n, do_G, do_Z, is_groups;
67)
68
69static void s_or_u(char *s, unsigned u, int done)
70{
71  if (TT.do_n) printf("%s", s);
72  else printf("%u", u);
73  if (done) {
74    xputc('\n');
75    exit(0);
76  }
77}
78
79static void showid(char *header, unsigned u, char *s)
80{
81  printf("%s%u(%s)", header, u, s);
82}
83
84void do_id(char *username)
85{
86  int flags, i, ngroups;
87  struct passwd *pw;
88  struct group *grp;
89  uid_t uid = getuid(), euid = geteuid();
90  gid_t gid = getgid(), egid = getegid(), *groups;
91
92  flags = toys.optflags;
93
94  // check if a username is given
95  if (username) {
96    pw = xgetpwnam(username);
97    uid = euid = pw->pw_uid;
98    gid = egid = pw->pw_gid;
99    if (TT.is_groups) printf("%s : ", pw->pw_name);
100  }
101
102  i = flags & FLAG_r;
103  pw = xgetpwuid(i ? uid : euid);
104  if (TT.do_u) s_or_u(pw->pw_name, pw->pw_uid, 1);
105
106  grp = xgetgrgid(i ? gid : egid);
107  if (flags & FLAG_g) s_or_u(grp->gr_name, grp->gr_gid, 1);
108
109  if (!TT.do_G && !TT.do_Z) {
110    showid("uid=", pw->pw_uid, pw->pw_name);
111    showid(" gid=", grp->gr_gid, grp->gr_name);
112
113    if (!i) {
114      if (uid != euid) {
115        pw = xgetpwuid(euid);
116        showid(" euid=", pw->pw_uid, pw->pw_name);
117      }
118      if (gid != egid) {
119        grp = xgetgrgid(egid);
120        showid(" egid=", grp->gr_gid, grp->gr_name);
121      }
122    }
123
124    showid(" groups=", grp->gr_gid, grp->gr_name);
125  }
126
127  if (!TT.do_Z) {
128    groups = (gid_t *)toybuf;
129    i = sizeof(toybuf)/sizeof(gid_t);
130    ngroups = username ? getgrouplist(username, gid, groups, &i)
131      : getgroups(i, groups);
132    if (ngroups<0) perror_exit(0);
133
134    int show_separator = !TT.do_G;
135    for (i = 0; i<ngroups; i++) {
136      if (show_separator) xputc(TT.do_G ? ' ' : ',');
137      show_separator = 1;
138      if (!(grp = getgrgid(groups[i]))) perror_msg(0);
139      else if (TT.do_G) s_or_u(grp->gr_name, grp->gr_gid, 0);
140      else if (grp->gr_gid != egid) showid("", grp->gr_gid, grp->gr_name);
141      else show_separator = 0; // Because we didn't show anything this time.
142    }
143    if (TT.do_G) {
144      xputc('\n');
145      exit(0);
146    }
147  }
148
149  if (CFG_TOYBOX_SELINUX) {
150    char *context = NULL;
151
152    if (is_selinux_enabled() < 1) {
153      if (TT.do_Z)
154        error_exit("SELinux disabled");
155    } else if (getcon(&context) == 0) {
156      if (!TT.do_Z) xputc(' ');
157      printf("context=%s", context);
158    }
159    if (CFG_TOYBOX_FREE) free(context);
160  }
161
162  xputc('\n');
163}
164
165void id_main(void)
166{
167  // FLAG macros can be 0 if "id" command not enabled, so snapshot them here.
168  if (FLAG_u) TT.do_u |= toys.optflags & FLAG_u;
169  if (FLAG_n) TT.do_n |= toys.optflags & FLAG_n;
170  if (FLAG_G) TT.do_G |= toys.optflags & FLAG_G;
171  if (FLAG_Z) TT.do_Z |= toys.optflags & FLAG_Z;
172
173  if (toys.optc) while(*toys.optargs) do_id(*toys.optargs++);
174  else do_id(NULL);
175}
176
177void groups_main(void)
178{
179  TT.is_groups = 1;
180  TT.do_G = TT.do_n = 1;
181  id_main();
182}
183
184void logname_main(void)
185{
186  TT.do_u = TT.do_n = 1;
187  id_main();
188}
189