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