From 8206db524ca681a973d30eda2098cb943ba2f056 Mon Sep 17 00:00:00 2001 From: Daniel Walter Date: Tue, 21 Feb 2012 21:39:20 -0600 Subject: update id to be SUS compliant * add -n and -G flag * allow a username to be given as argument * display complete list of groups * include it in default build --- toys/id.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 128 insertions(+), 12 deletions(-) diff --git a/toys/id.c b/toys/id.c index 6f0d12fd..6ae3efe5 100644 --- a/toys/id.c +++ b/toys/id.c @@ -8,49 +8,165 @@ * * See http://www.opengroup.org/onlinepubs/009695399/utilities/id.html -USE_ID(NEWTOY(id, "gru", TOYFLAG_BIN)) +USE_ID(NEWTOY(id, "nGgru", TOYFLAG_BIN)) config ID bool "id" - default n + default y help - usage: id [-gru] + usage: id [-nGgru] Print user and group ID. + -n print names instead of numeric IDs (to be used with -Ggu) + -G Show only the group IDs -g Show only the effective group ID -r Show real ID instead of effective ID -u Show only the effective user ID */ +#include +#include +#include #include "toys.h" +#define FLAG_n (1<<4) +#define FLAG_G (1<<3) #define FLAG_g (1<<2) #define FLAG_r (1<<1) #define FLAG_u 1 +void +pretty_print(struct passwd *pw, struct group *grp, struct group **grps, int n) +{ + int i; + printf("uid= %d(%s) gid= %d(%s)", pw->pw_uid, pw->pw_name, + grp->gr_gid, grp->gr_name); + if (n) { + printf(" groups= "); + } + for (i = 0; i < n; i++) { + printf("%d(%s)%s", grps[i]->gr_gid, grps[i]->gr_name, + (i < n-1) ? ",": ""); + } + printf("\n"); +} + void id_main(void) { int flags = toys.optflags; + struct passwd *pw; + struct group *grp; + struct group **grps; uid_t uid; gid_t gid; + gid_t *groups; + int i; + int ngroups; + char *username; - /* show effective, unless user specifies real */ - uid = geteuid(); - gid = getegid(); + /* check if a username is given */ + if (*toys.optargs) { + username = *(toys.optargs); + pw = getpwnam(username); + if (!pw) { + printf("id: %s: no such user\n", username); + toys.exitval = 1; + return; + } + uid = pw->pw_uid; + gid = pw->pw_gid; + } else { + /* show effective, unless user specifies real */ + if (flags & FLAG_r) { + uid = getuid(); + gid = getgid(); + } else { + uid = geteuid(); + gid = getegid(); + } + } - if (flags & FLAG_r) { - uid = getuid(); - gid = getgid(); + pw = getpwuid(uid); + if (!pw) { + perror("id"); + toys.exitval = 1; + return; + } + + grp = getgrgid(pw->pw_gid); + if (!grp) { + perror("id"); + toys.exitval = 1; + return; } + if (flags & FLAG_u) { - printf("%d\n", uid); + if (flags & FLAG_n) + printf("%s\n", pw->pw_name); + else + printf("%d\n", pw->pw_uid); return; } if (flags & FLAG_g) { - printf("%d\n", gid); + if (flags & FLAG_n) + printf("%s\n", grp->gr_name); + else + printf("%d\n", grp->gr_gid); return; } - printf("%d %d\n", uid, gid); + + + if (flags & FLAG_r) { + printf("-r can only be used in combination with -u or -g\n"); + toys.exitval = 1; + return; + } + ngroups = sysconf(_SC_NGROUPS_MAX); + /* fallback for number of groups to 32 */ + if (ngroups < 0) + ngroups = 32; + groups = malloc(ngroups * sizeof(gid_t)); + if (!groups) { + perror("id"); + toys.exitval = 1; + return; + } + if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups) < 0) { + perror("id"); + toys.exitval = 1; + return; + } + grps = malloc(ngroups * sizeof(struct group *)); + for (i = 0; i < ngroups; i++) { + struct group *tmp; + grps[i] = malloc(sizeof(struct group)); + size_t f = sysconf(_SC_GETGR_R_SIZE_MAX); + char *buf = malloc(f); + if (getgrgid_r(groups[i], grps[i], buf, f, &tmp) < 0) { + perror("id"); + continue; + } + if (tmp == NULL) { + perror("id"); + continue; + } + } + + if (flags & FLAG_G) { + for (i = 0; i < ngroups; i++) { + if (flags & FLAG_n) + printf("%s%s", !i ? "" : " ", grps[i]->gr_name); + else + printf("%s%d", !i ? "" : " ", grps[i]->gr_gid); + } + printf("\n"); + return; + } + + pretty_print(pw, grp, grps, ngroups); + for (i=0; i < ngroups; i++) + free(grps[i]); + } -- cgit v1.2.3