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