1181834Sroberto/*- 2181834Sroberto * Copyright (c) 1991, 1993 3181834Sroberto * The Regents of the University of California. All rights reserved. 4181834Sroberto * 5181834Sroberto * Redistribution and use in source and binary forms, with or without 6181834Sroberto * modification, are permitted provided that the following conditions 7181834Sroberto * are met: 8181834Sroberto * 1. Redistributions of source code must retain the above copyright 9181834Sroberto * notice, this list of conditions and the following disclaimer. 10181834Sroberto * 2. Redistributions in binary form must reproduce the above copyright 11181834Sroberto * notice, this list of conditions and the following disclaimer in the 12181834Sroberto * documentation and/or other materials provided with the distribution. 13181834Sroberto * 3. Neither the name of the University nor the names of its contributors 14181834Sroberto * may be used to endorse or promote products derived from this software 15280849Scy * without specific prior written permission. 16181834Sroberto * 17181834Sroberto * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18181834Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19181834Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20181834Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21181834Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22181834Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23181834Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24181834Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25181834Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26280849Scy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27181834Sroberto * SUCH DAMAGE. 28181834Sroberto */ 29181834Sroberto 30181834Sroberto#include <sys/cdefs.h> 31181834Sroberto#ifndef lint 32181834Sroberto__COPYRIGHT("@(#) Copyright (c) 1991, 1993\ 33181834Sroberto The Regents of the University of California. All rights reserved."); 34181834Sroberto#endif /* not lint */ 35181834Sroberto 36181834Sroberto#ifndef lint 37181834Sroberto#if 0 38181834Srobertostatic char sccsid[] = "@(#)id.c 8.3 (Berkeley) 4/28/95"; 39181834Sroberto#else 40181834Sroberto__RCSID("$NetBSD: id.c,v 1.31 2009/04/12 10:51:38 lukem Exp $"); 41181834Sroberto#endif 42280849Scy#endif /* not lint */ 43181834Sroberto 44181834Sroberto#include <sys/param.h> 45181834Sroberto 46181834Sroberto#include <err.h> 47181834Sroberto#include <errno.h> 48181834Sroberto#include <grp.h> 49181834Sroberto#include <pwd.h> 50181834Sroberto#include <stdio.h> 51181834Sroberto#include <stdlib.h> 52181834Sroberto#include <string.h> 53181834Sroberto#include <unistd.h> 54181834Sroberto 55181834Srobertostatic void current(void); 56181834Srobertostatic void pretty(struct passwd *); 57181834Srobertostatic void group(struct passwd *, int); 58280849Scy__dead static void usage(void); 59280849Scystatic void user(struct passwd *); 60280849Scystatic struct passwd *who(char *); 61181834Sroberto 62181834Srobertostatic int maxgroups; 63181834Srobertostatic gid_t *groups; 64181834Sroberto 65181834Srobertoint 66181834Srobertomain(int argc, char *argv[]) 67181834Sroberto{ 68181834Sroberto struct group *gr; 69181834Sroberto struct passwd *pw; 70181834Sroberto int ch, id; 71181834Sroberto int Gflag, gflag, nflag, pflag, rflag, uflag; 72181834Sroberto const char *opts; 73181834Sroberto 74280849Scy Gflag = gflag = nflag = pflag = rflag = uflag = 0; 75280849Scy 76280849Scy if (strcmp(getprogname(), "groups") == 0) { 77280849Scy Gflag = 1; 78280849Scy nflag = 1; 79280849Scy opts = ""; 80280849Scy if (argc > 2) 81280849Scy usage(); 82280849Scy } else if (strcmp(getprogname(), "whoami") == 0) { 83280849Scy uflag = 1; 84280849Scy nflag = 1; 85280849Scy opts = ""; 86280849Scy if (argc > 1) 87280849Scy usage(); 88280849Scy } else 89181834Sroberto opts = "Ggnpru"; 90280849Scy 91280849Scy while ((ch = getopt(argc, argv, opts)) != -1) 92280849Scy switch (ch) { 93280849Scy case 'G': 94280849Scy Gflag = 1; 95280849Scy break; 96280849Scy case 'g': 97280849Scy gflag = 1; 98280849Scy break; 99280849Scy case 'n': 100280849Scy nflag = 1; 101181834Sroberto break; 102280849Scy case 'p': 103280849Scy pflag = 1; 104280849Scy break; 105280849Scy case 'r': 106280849Scy rflag = 1; 107280849Scy break; 108280849Scy case 'u': 109280849Scy uflag = 1; 110280849Scy break; 111280849Scy case '?': 112181834Sroberto default: 113280849Scy usage(); 114280849Scy } 115280849Scy argc -= optind; 116280849Scy argv += optind; 117181834Sroberto 118280849Scy switch (Gflag + gflag + pflag + uflag) { 119280849Scy case 1: 120280849Scy break; 121280849Scy case 0: 122280849Scy if (!nflag && !rflag) 123280849Scy break; 124280849Scy /* FALLTHROUGH */ 125280849Scy default: 126280849Scy usage(); 127280849Scy } 128280849Scy 129280849Scy if (strcmp(opts, "") != 0 && argc > 1) 130280849Scy usage(); 131280849Scy 132280849Scy pw = *argv ? who(*argv) : NULL; 133280849Scy 134280849Scy maxgroups = sysconf(_SC_NGROUPS_MAX); 135280849Scy if ((groups = malloc((maxgroups + 1) * sizeof(gid_t))) == NULL) 136280849Scy err(1, NULL); 137181834Sroberto 138280849Scy if (gflag) { 139280849Scy id = pw ? pw->pw_gid : rflag ? getgid() : getegid(); 140280849Scy if (nflag && (gr = getgrgid(id))) 141280849Scy (void)printf("%s\n", gr->gr_name); 142280849Scy else 143280849Scy (void)printf("%u\n", id); 144280849Scy goto done; 145280849Scy } 146280849Scy 147280849Scy if (uflag) { 148280849Scy id = pw ? pw->pw_uid : rflag ? getuid() : geteuid(); 149280849Scy if (nflag && (pw = getpwuid(id))) 150280849Scy (void)printf("%s\n", pw->pw_name); 151280849Scy else 152280849Scy (void)printf("%u\n", id); 153280849Scy goto done; 154280849Scy } 155181834Sroberto 156280849Scy if (Gflag) { 157280849Scy group(pw, nflag); 158280849Scy goto done; 159280849Scy } 160280849Scy 161280849Scy if (pflag) { 162280849Scy pretty(pw); 163280849Scy goto done; 164280849Scy } 165280849Scy 166280849Scy if (pw) 167280849Scy user(pw); 168280849Scy else 169280849Scy current(); 170280849Scydone: 171280849Scy free(groups); 172280849Scy 173280849Scy return 0; 174280849Scy} 175280849Scy 176280849Scystatic void 177280849Scypretty(struct passwd *pw) 178280849Scy{ 179280849Scy struct group *gr; 180280849Scy u_int eid, rid; 181280849Scy char *login; 182280849Scy 183280849Scy if (pw) { 184280849Scy (void)printf("uid\t%s\n", pw->pw_name); 185280849Scy (void)printf("groups\t"); 186280849Scy group(pw, 1); 187280849Scy } else { 188280849Scy if ((login = getlogin()) == NULL) 189280849Scy err(1, "getlogin"); 190280849Scy 191280849Scy pw = getpwuid(rid = getuid()); 192280849Scy if (pw == NULL || strcmp(login, pw->pw_name)) 193280849Scy (void)printf("login\t%s\n", login); 194280849Scy if (pw) 195280849Scy (void)printf("uid\t%s\n", pw->pw_name); 196280849Scy else 197280849Scy (void)printf("uid\t%u\n", rid); 198280849Scy 199280849Scy if ((eid = geteuid()) != rid) { 200280849Scy if ((pw = getpwuid(eid)) != NULL) 201280849Scy (void)printf("euid\t%s\n", pw->pw_name); 202280849Scy else 203280849Scy (void)printf("euid\t%u\n", eid); 204280849Scy } 205280849Scy if ((rid = getgid()) != (eid = getegid())) { 206280849Scy if ((gr = getgrgid(rid)) != NULL) 207280849Scy (void)printf("rgid\t%s\n", gr->gr_name); 208280849Scy else 209280849Scy (void)printf("rgid\t%u\n", rid); 210280849Scy } 211280849Scy (void)printf("groups\t"); 212280849Scy group(NULL, 1); 213280849Scy } 214280849Scy} 215280849Scy 216280849Scystatic void 217280849Scycurrent(void) 218280849Scy{ 219280849Scy struct group *gr; 220280849Scy struct passwd *pw; 221280849Scy gid_t gid, egid, lastid; 222280849Scy uid_t uid, euid; 223280849Scy int cnt, ngroups; 224280849Scy const char *fmt; 225280849Scy 226280849Scy uid = getuid(); 227280849Scy (void)printf("uid=%ju", (uintmax_t)uid); 228280849Scy if ((pw = getpwuid(uid)) != NULL) 229280849Scy (void)printf("(%s)", pw->pw_name); 230280849Scy gid = getgid(); 231280849Scy (void)printf(" gid=%ju", (uintmax_t)gid); 232280849Scy if ((gr = getgrgid(gid)) != NULL) 233280849Scy (void)printf("(%s)", gr->gr_name); 234280849Scy if ((euid = geteuid()) != uid) { 235280849Scy (void)printf(" euid=%ju", (uintmax_t)euid); 236280849Scy if ((pw = getpwuid(euid)) != NULL) 237280849Scy (void)printf("(%s)", pw->pw_name); 238280849Scy } 239280849Scy if ((egid = getegid()) != gid) { 240280849Scy (void)printf(" egid=%ju", (uintmax_t)egid); 241280849Scy if ((gr = getgrgid(egid)) != NULL) 242280849Scy (void)printf("(%s)", gr->gr_name); 243280849Scy } 244280849Scy if ((ngroups = getgroups(maxgroups, groups)) != 0) { 245280849Scy for (fmt = " groups=%ju", lastid = -1, cnt = 0; cnt < ngroups; 246280849Scy fmt = ",%ju", lastid = gid, cnt++) { 247280849Scy gid = groups[cnt]; 248280849Scy if (lastid == gid) 249280849Scy continue; 250280849Scy (void)printf(fmt, (uintmax_t)gid); 251280849Scy if ((gr = getgrgid(gid)) != NULL) 252280849Scy (void)printf("(%s)", gr->gr_name); 253280849Scy } 254280849Scy } 255280849Scy (void)printf("\n"); 256280849Scy} 257280849Scy 258280849Scystatic void 259280849Scyuser(struct passwd *pw) 260280849Scy{ 261280849Scy struct group *gr; 262280849Scy const char *fmt; 263280849Scy int cnt, id, lastid, ngroups; 264280849Scy gid_t *glist = groups; 265280849Scy 266280849Scy id = pw->pw_uid; 267280849Scy (void)printf("uid=%u(%s)", id, pw->pw_name); 268280849Scy (void)printf(" gid=%lu", (u_long)pw->pw_gid); 269280849Scy if ((gr = getgrgid(pw->pw_gid)) != NULL) 270280849Scy (void)printf("(%s)", gr->gr_name); 271280849Scy ngroups = maxgroups + 1; 272280849Scy if (getgrouplist(pw->pw_name, pw->pw_gid, glist, &ngroups) == -1) { 273280849Scy glist = malloc(ngroups * sizeof(gid_t)); 274280849Scy (void) getgrouplist(pw->pw_name, pw->pw_gid, glist, &ngroups); 275280849Scy } 276280849Scy for (fmt = " groups=%u", lastid = -1, cnt = 0; cnt < ngroups; 277280849Scy fmt=",%u", lastid = id, cnt++) { 278280849Scy id = glist[cnt]; 279280849Scy if (lastid == id) 280280849Scy continue; 281280849Scy (void)printf(fmt, id); 282280849Scy if ((gr = getgrgid(id)) != NULL) 283280849Scy (void)printf("(%s)", gr->gr_name); 284280849Scy } 285280849Scy (void)printf("\n"); 286280849Scy if (glist != groups) 287280849Scy free(glist); 288280849Scy} 289280849Scy 290280849Scystatic void 291280849Scygroup(struct passwd *pw, int nflag) 292280849Scy{ 293280849Scy struct group *gr; 294280849Scy int cnt, ngroups; 295280849Scy gid_t id, lastid; 296280849Scy const char *fmt; 297280849Scy gid_t *glist = groups; 298280849Scy 299280849Scy if (pw) { 300280849Scy ngroups = maxgroups; 301280849Scy if (getgrouplist(pw->pw_name, pw->pw_gid, glist, &ngroups) 302280849Scy == -1) { 303280849Scy glist = malloc(ngroups * sizeof(gid_t)); 304280849Scy (void) getgrouplist(pw->pw_name, pw->pw_gid, glist, 305280849Scy &ngroups); 306280849Scy } 307280849Scy } else { 308280849Scy glist[0] = getgid(); 309280849Scy ngroups = getgroups(maxgroups, glist + 1) + 1; 310280849Scy } 311280849Scy fmt = nflag ? "%s" : "%u"; 312280849Scy for (lastid = -1, cnt = 0; cnt < ngroups; ++cnt) { 313280849Scy if (lastid == (id = glist[cnt]) || (cnt && id == glist[0])) 314280849Scy continue; 315280849Scy if (nflag) { 316280849Scy if ((gr = getgrgid(id)) != NULL) 317280849Scy (void)printf(fmt, gr->gr_name); 318280849Scy else 319280849Scy (void)printf(*fmt == ' ' ? " %u" : "%u", 320280849Scy id); 321280849Scy fmt = " %s"; 322280849Scy } else { 323280849Scy (void)printf(fmt, id); 324280849Scy fmt = " %u"; 325280849Scy } 326280849Scy lastid = id; 327280849Scy } 328285169Scy (void)printf("\n"); 329285169Scy if (glist != groups) 330285169Scy free(glist); 331280849Scy} 332280849Scy 333280849Scystatic struct passwd * 334280849Scywho(char *u) 335280849Scy{ 336280849Scy struct passwd *pw; 337280849Scy long id; 338280849Scy char *ep; 339280849Scy 340280849Scy /* 341280849Scy * Translate user argument into a pw pointer. First, try to 342280849Scy * get it as specified. If that fails, try it as a number. 343280849Scy */ 344280849Scy if ((pw = getpwnam(u)) != NULL) 345280849Scy return pw; 346280849Scy id = strtol(u, &ep, 10); 347280849Scy if (*u && !*ep && (pw = getpwuid(id))) 348280849Scy return pw; 349280849Scy errx(1, "%s: No such user", u); 350280849Scy /* NOTREACHED */ 351280849Scy return NULL; 352280849Scy} 353280849Scy 354280849Scystatic void 355280849Scyusage(void) 356280849Scy{ 357280849Scy 358280849Scy if (strcmp(getprogname(), "groups") == 0) { 359280849Scy (void)fprintf(stderr, "usage: groups [user]\n"); 360280849Scy } else if (strcmp(getprogname(), "whoami") == 0) { 361280849Scy (void)fprintf(stderr, "usage: whoami\n"); 362280849Scy } else { 363280849Scy (void)fprintf(stderr, "usage: id [user]\n"); 364280849Scy (void)fprintf(stderr, " id -G [-n] [user]\n"); 365280849Scy (void)fprintf(stderr, " id -g [-nr] [user]\n"); 366280849Scy (void)fprintf(stderr, " id -p [user]\n"); 367280849Scy (void)fprintf(stderr, " id -u [-nr] [user]\n"); 368280849Scy } 369280849Scy exit(1); 370280849Scy} 371280849Scy