945190d7c1c17a212a34e597ad4225abb06ac515
[platform/upstream/bash.git] / examples / loadables / id.c
1 /*
2  * id - POSIX.2 user identity
3  *
4  * (INCOMPLETE -- supplementary groups for other users not yet done)
5  *
6  * usage: id [-Ggu] [-nr] [user]
7  *
8  * The default output format looks something like:
9  *      uid=xxx(chet) gid=xx groups=aa(aname), bb(bname), cc(cname)
10  */
11
12 #include <config.h>
13 #include <stdio.h>
14 #include "bashtypes.h"
15 #include <pwd.h>
16 #include <grp.h>
17 #include "bashansi.h"
18
19 #ifdef HAVE_LIMITS_H
20 #  include <limits.h>
21 #else
22 #  include <sys/param.h>
23 #endif
24
25 #if !defined (HAVE_GETPW_DECLS)
26 extern struct passwd *getpwuid ();
27 #endif
28 extern struct group *getgrgid ();
29
30 #include "shell.h"
31 #include "builtins.h"
32 #include "stdc.h"
33 #include "common.h"
34 #include "bashgetopt.h"
35
36 #define ID_ALLGROUPS    0x001           /* -G */
37 #define ID_GIDONLY      0x002           /* -g */
38 #define ID_USENAME      0x004           /* -n */
39 #define ID_USEREAL      0x008           /* -r */
40 #define ID_USERONLY     0x010           /* -u */
41
42 #define ID_FLAGSET(s)   ((id_flags & (s)) != 0)
43
44 static int id_flags;
45
46 static uid_t ruid, euid;
47 static gid_t rgid, egid;
48
49 static char *id_user;
50
51 static int inituser ();
52
53 static int id_pruser ();
54 static int id_prgrp ();
55 static int id_prgroups ();
56 static int id_prall ();
57
58 int
59 id_builtin (list)
60      WORD_LIST *list;
61 {
62   int opt;
63   char *user;
64
65   id_flags = 0;
66   reset_internal_getopt ();
67   while ((opt = internal_getopt (list, "Ggnru")) != -1)
68     {
69       switch (opt)
70         {
71         case 'G': id_flags |= ID_ALLGROUPS; break;
72         case 'g': id_flags |= ID_GIDONLY; break;
73         case 'n': id_flags |= ID_USENAME; break;
74         case 'r': id_flags |= ID_USEREAL; break;
75         case 'u': id_flags |= ID_USERONLY; break;
76         default:
77           builtin_usage ();
78           return (EX_USAGE);
79         }
80     }
81   list = loptend;
82
83   user = list ? list->word->word : (char *)NULL;
84
85   /* Check for some invalid option combinations */
86   opt = ID_FLAGSET (ID_ALLGROUPS) + ID_FLAGSET (ID_GIDONLY) + ID_FLAGSET (ID_USERONLY);
87   if (opt > 1 || (opt == 0 && ((id_flags & (ID_USEREAL|ID_USENAME)) != 0)))
88     {
89       builtin_usage ();
90       return (EX_USAGE);
91     }
92
93   if (list && list->next)
94     {
95       builtin_usage ();
96       return (EX_USAGE);
97     }
98
99   if (inituser (user) < 0)
100     return (EXECUTION_FAILURE);
101
102   opt = 0;
103   if (id_flags & ID_USERONLY)
104     opt += id_pruser ((id_flags & ID_USEREAL) ? ruid : euid);
105   else if (id_flags & ID_GIDONLY)
106     opt += id_prgrp ((id_flags & ID_USEREAL) ? rgid : egid);
107   else if (id_flags & ID_ALLGROUPS)
108     opt += id_prgroups (user);
109   else
110     opt += id_prall (user);
111   putchar ('\n');
112   fflush (stdout);
113
114   return (opt == 0 ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
115 }
116
117 static int
118 inituser (uname)
119      char *uname;
120 {
121   struct passwd *pwd;
122
123   if (uname)
124     {
125       pwd = getpwnam (uname);
126       if (pwd == 0)
127         {
128           builtin_error ("%s: no such user", uname);
129           return -1;
130         }
131       ruid = euid = pwd->pw_uid;
132       rgid = egid = pwd->pw_gid;
133     }
134   else
135     {
136       ruid = current_user.uid;
137       euid = current_user.euid;
138       rgid = current_user.gid;
139       egid = current_user.egid;
140     }
141   return 0;
142 }
143
144 /* Print the name or value of user ID UID. */
145 static int
146 id_pruser (uid)
147      int uid;
148 {
149   struct passwd *pwd = NULL;
150   int r;
151
152   r = 0;
153   if (id_flags & ID_USENAME)
154     {
155       pwd = getpwuid (uid);
156       if (pwd == NULL)
157         r = 1;
158     }
159   if (pwd)
160     printf ("%s", pwd->pw_name);
161   else
162     printf ("%u", (unsigned) uid);
163       
164   return r;
165 }
166
167 /* Print the name or value of group ID GID. */
168
169 static int
170 id_prgrp (gid)
171      int gid;
172 {
173   struct group *grp = NULL;
174   int r;
175
176   r = 0;
177   if (id_flags & ID_USENAME)
178     {
179       grp = getgrgid (gid);
180       if (grp == NULL)
181         r = 1;
182     }
183
184   if (grp)
185     printf ("%s", grp->gr_name);
186   else
187     printf ("%u", (unsigned) gid);
188
189   return r;
190 }
191
192 static int
193 id_prgroups (uname)
194      char *uname;
195 {
196   int *glist, ng, i, r;
197
198   r = 0;
199   id_prgrp (rgid);
200   if (egid != rgid)
201     {
202       putchar (' ');
203       id_prgrp (egid);
204     }
205
206   if (uname)
207     {
208       builtin_error ("supplementary groups for other users not yet implemented");
209       glist = (int *)NULL;
210       ng = 0;
211       r = 1;
212     }
213   else
214     glist = get_group_array (&ng);
215
216   for (i = 0; i < ng; i++)
217     if (glist[i] != rgid && glist[i] != egid)
218       {
219         putchar (' ');
220         id_prgrp (glist[i]);
221       }
222   
223   return r;
224 }
225
226 static int
227 id_prall (uname)
228      char *uname;
229 {
230   int r, i, ng, *glist;
231   struct passwd *pwd;
232   struct group *grp;
233
234   r = 0;
235   printf ("uid=%u", (unsigned) ruid);
236   pwd = getpwuid (ruid);
237   if (pwd == NULL)
238     r = 1;
239   else
240     printf ("(%s)", pwd->pw_name);
241
242   printf (" gid=%u", (unsigned) rgid);
243   grp = getgrgid (rgid);
244   if (grp == NULL)
245     r = 1;
246   else
247     printf ("(%s)", grp->gr_name);
248
249   if (euid != ruid)
250     { 
251       printf (" euid=%u", (unsigned) euid);
252       pwd = getpwuid (euid);
253       if (pwd == NULL)
254         r = 1;
255       else 
256         printf ("(%s)", pwd->pw_name);
257     }
258
259   if (egid != rgid) 
260     {
261       printf (" egid=%u", (unsigned) egid);
262       grp = getgrgid (egid);
263       if (grp == NULL)
264         r = 1;
265       else
266         printf ("(%s)", grp->gr_name);
267     }
268
269   if (uname)
270     {
271       builtin_error ("supplementary groups for other users not yet implemented");
272       glist = (int *)NULL;
273       ng = 0;
274       r = 1;
275     }
276   else
277     glist = get_group_array (&ng);
278
279   if (ng > 0)
280     printf (" groups=");
281   for (i = 0; i < ng; i++)
282     {
283       if (i > 0)
284         printf (", ");
285       printf ("%u", (unsigned) glist[i]);
286       grp = getgrgid (glist[i]);
287       if (grp == NULL)
288         r = 1;
289       else
290         printf ("(%s)", grp->gr_name);
291     }
292
293   return r;
294 }
295
296 char *id_doc[] = {
297         "return information about user identity",
298         (char *)NULL
299 };
300
301 struct builtin id_struct = {
302         "id",
303         id_builtin,
304         BUILTIN_ENABLED,
305         id_doc,
306         "id [user]\n\tid -G [-n] [user]\n\tid -g [-nr] [user]\n\tid -u [-nr] [user]",
307         0
308 };