diff options
author | Elliott Hughes <enh@google.com> | 2019-11-02 22:58:42 -0700 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2019-11-03 19:20:31 -0600 |
commit | 126c317d5ceee7802d52fc6be1b695f759aa6725 (patch) | |
tree | 6e7e0e35dcf9171b5eb34aa2c9e6fa3e6c9c772b | |
parent | 3ead70e503b2809a250a70d161d525213f5328d8 (diff) | |
download | toybox-126c317d5ceee7802d52fc6be1b695f759aa6725.tar.gz |
id: support numeric lookup.
Fall back to converting the "name" to an integer and calling getpwuid().
We need to update `username` for the later call to getgrouplist().
Also fix the separator printing logic to avoid a trailing ',' on `id 0`.
Switch to FLAG() and move some declarations down to where they can be
initialized, both for clarity.
Also add simple tests. Sadly, there's no always-present user that is in
multiple groups.
-rwxr-xr-x | tests/id.test | 10 | ||||
-rw-r--r-- | toys/posix/id.c | 49 |
2 files changed, 36 insertions, 23 deletions
diff --git a/tests/id.test b/tests/id.test new file mode 100755 index 00000000..6d0f63a8 --- /dev/null +++ b/tests/id.test @@ -0,0 +1,10 @@ +#!/bin/bash + +[ -f testing.sh ] && . testing.sh + +#testing "name" "command" "result" "infile" "stdin" + +testing "id 0" "id 0" "uid=0(root) gid=0(root) groups=0(root)\n" "" "" +testing "id root" "id root" "uid=0(root) gid=0(root) groups=0(root)\n" "" "" +testing "id no-such-user" "id no-such-user 2>/dev/null ; echo \$?" "1\n" "" "" +testing "id 9999999" "id 9999999 2>/dev/null ; echo \$?" "1\n" "" "" diff --git a/toys/posix/id.c b/toys/posix/id.c index db3cc317..b3be1e6e 100644 --- a/toys/posix/id.c +++ b/toys/posix/id.c @@ -65,11 +65,13 @@ config WHOAMI GLOBALS( int is_groups; + int separator; ) static void s_or_u(char *s, unsigned u, int done) { - if (toys.optflags&FLAG_n) printf("%s", s); + if (TT.separator) xputc(TT.separator); + if (FLAG(n)) printf("%s", s); else printf("%u", u); if (done) { xputc('\n'); @@ -79,39 +81,41 @@ static void s_or_u(char *s, unsigned u, int done) static void showid(char *header, unsigned u, char *s) { + if (TT.separator) xputc(TT.separator); printf("%s%u(%s)", header, u, s); } static void do_id(char *username) { - int flags, i, ngroups; struct passwd *pw; struct group *grp; uid_t uid = getuid(), euid = geteuid(); - gid_t gid = getgid(), egid = getegid(), *groups; - - flags = toys.optflags; + gid_t gid = getgid(), egid = getegid(); // check if a username is given if (username) { - pw = xgetpwnam(username); + pw = getpwnam(username); + if (!pw) { + uid = atolx_range(username, 0, INT_MAX); + if ((pw = getpwuid(uid))) username = pw->pw_name; + } + if (!pw) perror_exit("no such user '%s'", username); uid = euid = pw->pw_uid; gid = egid = pw->pw_gid; if (TT.is_groups) printf("%s : ", pw->pw_name); } - i = flags & FLAG_r; - pw = xgetpwuid(i ? uid : euid); - if (toys.optflags&FLAG_u) s_or_u(pw->pw_name, pw->pw_uid, 1); + pw = xgetpwuid(FLAG(r) ? uid : euid); + if (FLAG(u)) s_or_u(pw->pw_name, pw->pw_uid, 1); - grp = xgetgrgid(i ? gid : egid); - if (flags & FLAG_g) s_or_u(grp->gr_name, grp->gr_gid, 1); + grp = xgetgrgid(FLAG(r) ? gid : egid); + if (FLAG(g)) s_or_u(grp->gr_name, grp->gr_gid, 1); if (!(toys.optflags&(FLAG_G|FLAG_g|FLAG_Z))) { showid("uid=", pw->pw_uid, pw->pw_name); showid(" gid=", grp->gr_gid, grp->gr_name); - if (!i) { + if (!FLAG(r)) { if (uid != euid) { pw = xgetpwuid(euid); showid(" euid=", pw->pw_uid, pw->pw_name); @@ -125,23 +129,22 @@ static void do_id(char *username) showid(" groups=", grp->gr_gid, grp->gr_name); } - if (!(toys.optflags&FLAG_Z)) { - groups = (gid_t *)toybuf; - i = sizeof(toybuf)/sizeof(gid_t); + if (!FLAG(Z)) { + gid_t *groups = (gid_t *)toybuf; + int i = sizeof(toybuf)/sizeof(gid_t), ngroups; + ngroups = username ? getgrouplist(username, gid, groups, &i) : getgroups(i, groups); if (ngroups<0) perror_exit(0); - int show_separator = !(toys.optflags&FLAG_G); for (i = 0; i<ngroups; i++) { - if (show_separator) xputc((toys.optflags&FLAG_G) ? ' ' : ','); - show_separator = 1; + TT.separator = FLAG(G) ? ' ' : ','; if (!(grp = getgrgid(groups[i]))) perror_msg(0); - else if (toys.optflags&FLAG_G) s_or_u(grp->gr_name, grp->gr_gid, 0); + else if (FLAG(G)) s_or_u(grp->gr_name, grp->gr_gid, 0); else if (grp->gr_gid != egid) showid("", grp->gr_gid, grp->gr_name); - else show_separator = 0; // Because we didn't show anything this time. + else TT.separator = 0; // Because we didn't show anything this time. } - if (toys.optflags&FLAG_G) { + if (FLAG(G)) { xputc('\n'); xexit(); } @@ -151,9 +154,9 @@ static void do_id(char *username) if (lsm_enabled()) { char *context = lsm_context(); - printf(" context=%s"+!!(toys.optflags&FLAG_Z), context); + printf(" context=%s"+!!FLAG(Z), context); if (CFG_TOYBOX_FREE) free(context); - } else if (toys.optflags&FLAG_Z) error_exit("%s disabled", lsm_name()); + } else if (FLAG(Z)) error_exit("%s disabled", lsm_name()); } xputc('\n'); |