549e2ce77cd82eb941602aba9865b5704221d808
[dragonfly.git] / usr.bin / id / id.c
1 /*-
2  * Copyright (c) 1991, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * @(#) Copyright (c) 1991, 1993 The Regents of the University of California.  All rights reserved.
34  * @(#)id.c     8.2 (Berkeley) 2/16/94
35  * $FreeBSD: src/usr.bin/id/id.c,v 1.12.2.3 2001/12/20 12:09:03 ru Exp $
36  * $DragonFly: src/usr.bin/id/id.c,v 1.6 2004/12/31 20:58:17 cpressey Exp $
37  */
38
39 #include <sys/param.h>
40
41 #include <err.h>
42 #include <grp.h>
43 #include <pwd.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <unistd.h>
48
49 int             main(int, char *[]);
50 static void     current(void);
51 static void     pline(struct passwd *);
52 static void     pretty(struct passwd *);
53 static void     group(struct passwd *, int);
54 static void     usage(void);
55 static void     user(struct passwd *);
56 static struct passwd *
57                 who(char *);
58
59 int isgroups, iswhoami;
60
61 int
62 main(int argc, char **argv)
63 {
64         struct group *gr;
65         struct passwd *pw;
66         int Gflag, Pflag, ch, gflag, id, nflag, pflag, rflag, uflag;
67         const char *myname;
68
69         Gflag = Pflag = gflag = nflag = pflag = rflag = uflag = 0;
70
71         myname = strrchr(argv[0], '/');
72         myname = (myname != NULL) ? myname + 1 : argv[0];
73         if (strcmp(myname, "groups") == 0) {
74                 isgroups = 1;
75                 Gflag = nflag = 1;
76         }
77         else if (strcmp(myname, "whoami") == 0) {
78                 iswhoami = 1;
79                 uflag = nflag = 1;
80         }
81
82         while ((ch = getopt(argc, argv,
83             (isgroups || iswhoami) ? "" : "PGgnpru")) != -1)
84                 switch(ch) {
85                 case 'G':
86                         Gflag = 1;
87                         break;
88                 case 'P':
89                         Pflag = 1;
90                         break;
91                 case 'g':
92                         gflag = 1;
93                         break;
94                 case 'n':
95                         nflag = 1;
96                         break;
97                 case 'p':
98                         pflag = 1;
99                         break;
100                 case 'r':
101                         rflag = 1;
102                         break;
103                 case 'u':
104                         uflag = 1;
105                         break;
106                 case '?':
107                 default:
108                         usage();
109                 }
110         argc -= optind;
111         argv += optind;
112
113         if (iswhoami && argc > 0)
114                 usage();
115
116         switch(Gflag + Pflag + gflag + pflag + uflag) {
117         case 1:
118                 break;
119         case 0:
120                 if (!nflag && !rflag)
121                         break;
122                 /* FALLTHROUGH */
123         default:
124                 usage();
125         }
126
127         pw = *argv ? who(*argv) : NULL;
128
129         if (gflag) {
130                 id = pw ? pw->pw_gid : rflag ? getgid() : getegid();
131                 if (nflag && (gr = getgrgid(id)))
132                         printf("%s\n", gr->gr_name);
133                 else
134                         printf("%u\n", id);
135                 exit(0);
136         }
137
138         if (uflag) {
139                 id = pw ? pw->pw_uid : rflag ? getuid() : geteuid();
140                 if (nflag && (pw = getpwuid(id)))
141                         printf("%s\n", pw->pw_name);
142                 else
143                         printf("%u\n", id);
144                 exit(0);
145         }
146
147         if (Gflag) {
148                 group(pw, nflag);
149                 exit(0);
150         }
151
152         if (Pflag) {
153                 pline(pw);
154                 exit(0);
155         }
156
157         if (pflag) {
158                 pretty(pw);
159                 exit(0);
160         }
161
162         if (pw)
163                 user(pw);
164         else
165                 current();
166         exit(0);
167 }
168
169 static void
170 pretty(struct passwd *pw)
171 {
172         struct group *gr;
173         u_int eid, rid;
174         char *login;
175
176         if (pw) {
177                 printf("uid\t%s\n", pw->pw_name);
178                 printf("groups\t");
179                 group(pw, 1);
180         } else {
181                 if ((login = getlogin()) == NULL)
182                         err(1, "getlogin");
183
184                 pw = getpwuid(rid = getuid());
185                 if (pw == NULL || strcmp(login, pw->pw_name))
186                         printf("login\t%s\n", login);
187                 if (pw)
188                         printf("uid\t%s\n", pw->pw_name);
189                 else
190                         printf("uid\t%u\n", rid);
191
192                 if ((eid = geteuid()) != rid) {
193                         if ((pw = getpwuid(eid)))
194                                 printf("euid\t%s\n", pw->pw_name);
195                         else
196                                 printf("euid\t%u\n", eid);
197                 }
198                 if ((rid = getgid()) != (eid = getegid())) {
199                         if ((gr = getgrgid(rid)))
200                                 printf("rgid\t%s\n", gr->gr_name);
201                         else
202                                 printf("rgid\t%u\n", rid);
203                 }
204                 printf("groups\t");
205                 group(NULL, 1);
206         }
207 }
208
209 static void
210 current(void)
211 {
212         struct group *gr;
213         struct passwd *pw;
214         int cnt, id, eid, lastid, ngroups;
215         gid_t groups[NGROUPS];
216         const char *fmt;
217
218         id = getuid();
219         printf("uid=%u", id);
220         if ((pw = getpwuid(id)))
221                 printf("(%s)", pw->pw_name);
222         if ((eid = geteuid()) != id) {
223                 printf(" euid=%u", eid);
224                 if ((pw = getpwuid(eid)))
225                         printf("(%s)", pw->pw_name);
226         }
227         id = getgid();
228         printf(" gid=%u", id);
229         if ((gr = getgrgid(id)))
230                 printf("(%s)", gr->gr_name);
231         if ((eid = getegid()) != id) {
232                 printf(" egid=%u", eid);
233                 if ((gr = getgrgid(eid)))
234                         printf("(%s)", gr->gr_name);
235         }
236         if ((ngroups = getgroups(NGROUPS, groups))) {
237                 for (fmt = " groups=%u", lastid = -1, cnt = 0; cnt < ngroups;
238                     fmt = ", %u", lastid = id) {
239                         id = groups[cnt++];
240                         if (lastid == id)
241                                 continue;
242                         printf(fmt, id);
243                         if ((gr = getgrgid(id)))
244                                 printf("(%s)", gr->gr_name);
245                 }
246         }
247         printf("\n");
248 }
249
250 static void
251 user(struct passwd *pw)
252 {
253         struct group *gr;
254         const char *fmt;
255         int cnt, ngroups;
256         gid_t gid, lastgid, groups[NGROUPS + 1];
257
258         printf("uid=%u(%s)", pw->pw_uid, pw->pw_name);
259         gid = pw->pw_gid;
260         printf(" gid=%u", gid);
261         if ((gr = getgrgid(gid)))
262                 printf("(%s)", gr->gr_name);
263         ngroups = NGROUPS + 1;
264         getgrouplist(pw->pw_name, gid, groups, &ngroups);
265         fmt = " groups=%u";
266         for (lastgid = -1, cnt = 0; cnt < ngroups; ++cnt) {
267                 if (lastgid == (gid = groups[cnt]))
268                         continue;
269                 printf(fmt, gid);
270                 fmt = ", %u";
271                 if ((gr = getgrgid(gid)))
272                         printf("(%s)", gr->gr_name);
273                 lastgid = gid;
274         }
275         printf("\n");
276 }
277
278 static void
279 group(struct passwd *pw, int nflag)
280 {
281         struct group *gr;
282         int cnt, id, lastid, ngroups;
283         gid_t groups[NGROUPS + 1];
284         const char *fmt;
285
286         if (pw) {
287                 ngroups = NGROUPS + 1;
288                 getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
289         } else {
290                 groups[0] = getgid();
291                 ngroups = getgroups(NGROUPS, groups + 1) + 1;
292         }
293         fmt = nflag ? "%s" : "%u";
294         for (lastid = -1, cnt = 0; cnt < ngroups; ++cnt) {
295                 if (lastid == (id = groups[cnt]))
296                         continue;
297                 if (nflag) {
298                         if ((gr = getgrgid(id)))
299                                 printf(fmt, gr->gr_name);
300                         else
301                                 printf(*fmt == ' ' ? " %u" : "%u",
302                                     id);
303                         fmt = " %s";
304                 } else {
305                         printf(fmt, id);
306                         fmt = " %u";
307                 }
308                 lastid = id;
309         }
310         printf("\n");
311 }
312
313 static struct passwd *
314 who(char *u)
315 {
316         struct passwd *pw;
317         long id;
318         char *ep;
319
320         /*
321          * Translate user argument into a pw pointer.  First, try to
322          * get it as specified.  If that fails, try it as a number.
323          */
324         if ((pw = getpwnam(u)))
325                 return(pw);
326         id = strtol(u, &ep, 10);
327         if (*u && !*ep && (pw = getpwuid(id)))
328                 return(pw);
329         errx(1, "%s: no such user", u);
330         /* NOTREACHED */
331 }
332
333 static void
334 pline(struct passwd *pw)
335 {
336         u_int rid;
337
338         if (!pw) {
339                 if ((pw = getpwuid(rid = getuid())) == NULL)
340                         err(1, "getpwuid");
341         }
342
343         printf("%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", pw->pw_name,
344                         pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class,
345                         (long)pw->pw_change, (long)pw->pw_expire, pw->pw_gecos,
346                         pw->pw_dir, pw->pw_shell);
347 }
348
349
350 static void
351 usage(void)
352 {
353
354         if (isgroups)
355                 fprintf(stderr, "usage: groups [user]\n");
356         else if (iswhoami)
357                 fprintf(stderr, "usage: whoami\n");
358         else
359                 fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n",
360                     "usage: id [user]",
361                     "       id -G [-n] [user]",
362                     "       id -P [user]",
363                     "       id -g [-nr] [user]",
364                     "       id -p [user]",
365                     "       id -u [-nr] [user]");
366         exit(1);
367 }