Merge from vendor branch OPENSSH:
[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.4 2003/11/03 19:31:30 eirikn 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 void    current(void);
51 void    pline(struct passwd *);
52 void    pretty(struct passwd *);
53 void    group(struct passwd *, int);
54 void    usage(void);
55 void    user(struct passwd *);
56 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                         (void)printf("%s\n", gr->gr_name);
133                 else
134                         (void)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                         (void)printf("%s\n", pw->pw_name);
142                 else
143                         (void)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 void
170 pretty(struct passwd *pw)
171 {
172         struct group *gr;
173         u_int eid, rid;
174         char *login;
175
176         if (pw) {
177                 (void)printf("uid\t%s\n", pw->pw_name);
178                 (void)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                         (void)printf("login\t%s\n", login);
187                 if (pw)
188                         (void)printf("uid\t%s\n", pw->pw_name);
189                 else
190                         (void)printf("uid\t%u\n", rid);
191
192                 if ((eid = geteuid()) != rid) {
193                         if ((pw = getpwuid(eid)))
194                                 (void)printf("euid\t%s\n", pw->pw_name);
195                         else
196                                 (void)printf("euid\t%u\n", eid);
197                 }
198                 if ((rid = getgid()) != (eid = getegid())) {
199                         if ((gr = getgrgid(rid)))
200                                 (void)printf("rgid\t%s\n", gr->gr_name);
201                         else
202                                 (void)printf("rgid\t%u\n", rid);
203                 }
204                 (void)printf("groups\t");
205                 group(NULL, 1);
206         }
207 }
208
209 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         (void)printf("uid=%u", id);
220         if ((pw = getpwuid(id)))
221                 (void)printf("(%s)", pw->pw_name);
222         if ((eid = geteuid()) != id) {
223                 (void)printf(" euid=%u", eid);
224                 if ((pw = getpwuid(eid)))
225                         (void)printf("(%s)", pw->pw_name);
226         }
227         id = getgid();
228         (void)printf(" gid=%u", id);
229         if ((gr = getgrgid(id)))
230                 (void)printf("(%s)", gr->gr_name);
231         if ((eid = getegid()) != id) {
232                 (void)printf(" egid=%u", eid);
233                 if ((gr = getgrgid(eid)))
234                         (void)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                         (void)printf(fmt, id);
243                         if ((gr = getgrgid(id)))
244                                 (void)printf("(%s)", gr->gr_name);
245                 }
246         }
247         (void)printf("\n");
248 }
249
250 void
251 user(struct passwd *pw)
252 {
253         struct group *gr;
254         const char *fmt;
255         int cnt, gid, lastgid, ngroups, groups[NGROUPS + 1];
256
257         (void)printf("uid=%u(%s)", pw->pw_uid, pw->pw_name);
258         gid = pw->pw_gid;
259         (void)printf(" gid=%u", gid);
260         if ((gr = getgrgid(gid)))
261                 (void)printf("(%s)", gr->gr_name);
262         ngroups = NGROUPS + 1;
263         (void) getgrouplist(pw->pw_name, gid, groups, &ngroups);
264         fmt = " groups=%u";
265         for (lastgid = -1, cnt = 0; cnt < ngroups; ++cnt) {
266                 if (lastgid == (gid = groups[cnt]))
267                         continue;
268                 (void)printf(fmt, gid);
269                 fmt = ", %u";
270                 if ((gr = getgrgid(gid)))
271                         (void)printf("(%s)", gr->gr_name);
272                 lastgid = gid;
273         }
274         (void)printf("\n");
275 }
276
277 void
278 group(struct passwd *pw, int nflag)
279 {
280         struct group *gr;
281         int cnt, id, lastid, ngroups;
282         gid_t groups[NGROUPS + 1];
283         const char *fmt;
284
285         if (pw) {
286                 ngroups = NGROUPS + 1;
287                 (void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
288         } else {
289                 groups[0] = getgid();
290                 ngroups = getgroups(NGROUPS, groups + 1) + 1;
291         }
292         fmt = nflag ? "%s" : "%u";
293         for (lastid = -1, cnt = 0; cnt < ngroups; ++cnt) {
294                 if (lastid == (id = groups[cnt]))
295                         continue;
296                 if (nflag) {
297                         if ((gr = getgrgid(id)))
298                                 (void)printf(fmt, gr->gr_name);
299                         else
300                                 (void)printf(*fmt == ' ' ? " %u" : "%u",
301                                     id);
302                         fmt = " %s";
303                 } else {
304                         (void)printf(fmt, id);
305                         fmt = " %u";
306                 }
307                 lastid = id;
308         }
309         (void)printf("\n");
310 }
311
312 struct passwd *
313 who(char *u)
314 {
315         struct passwd *pw;
316         long id;
317         char *ep;
318
319         /*
320          * Translate user argument into a pw pointer.  First, try to
321          * get it as specified.  If that fails, try it as a number.
322          */
323         if ((pw = getpwnam(u)))
324                 return(pw);
325         id = strtol(u, &ep, 10);
326         if (*u && !*ep && (pw = getpwuid(id)))
327                 return(pw);
328         errx(1, "%s: no such user", u);
329         /* NOTREACHED */
330 }
331
332 void
333 pline(struct passwd *pw)
334 {
335         u_int rid;
336
337         if (!pw) {
338                 if ((pw = getpwuid(rid = getuid())) == NULL)
339                         err(1, "getpwuid");
340         }
341
342         (void)printf("%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", pw->pw_name,
343                         pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class,
344                         (long)pw->pw_change, (long)pw->pw_expire, pw->pw_gecos,
345                         pw->pw_dir, pw->pw_shell);
346 }
347
348
349 void
350 usage(void)
351 {
352
353         if (isgroups)
354                 (void)fprintf(stderr, "usage: groups [user]\n");
355         else if (iswhoami)
356                 (void)fprintf(stderr, "usage: whoami\n");
357         else
358                 (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n",
359                     "usage: id [user]",
360                     "       id -G [-n] [user]",
361                     "       id -P [user]",
362                     "       id -g [-nr] [user]",
363                     "       id -p [user]",
364                     "       id -u [-nr] [user]");
365         exit(1);
366 }