>From ae7adc97280eade6793b3349df9448863b20fe86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?= Date: Fri, 20 Sep 2013 12:38:00 +0100 Subject: [PATCH] id: support specifying the user by user ID * src/id.c (usage): Remove 'name' from the synopsis, implying that one can also specify by user ID. (main): Like chown(1), call parse_user_spec() to implement user name or ID lookup with appropriate precedence. * doc/coreutils.texi (id invocation): Mention that a user ID is supported and how '+' affects lookup order. * tests/misc/id-groups.sh: Remove test now subsumed into... * tests/misc/id-uid.sh: New test covering new interface. * tests/local.mk: Rename the test. * NEWS: Mention the new feature. Addresses http://bugs.gnu.org/15421 --- NEWS | 2 ++ doc/coreutils.texi | 5 ++++- src/id.c | 31 ++++++++++++++++++++++++------- tests/local.mk | 2 +- tests/misc/{id-groups.sh => id-uid.sh} | 20 +++++++++++++++++--- 5 files changed, 49 insertions(+), 13 deletions(-) rename tests/misc/{id-groups.sh => id-uid.sh} (58%) diff --git a/NEWS b/NEWS index d26722d..cc47c7c 100644 --- a/NEWS +++ b/NEWS @@ -47,6 +47,8 @@ GNU coreutils NEWS -*- outline -*- id and ls with -Z report the SMACK security context where available. mkdir, mkfifo and mknod with -Z set the SMACK context where available. + id can now lookup by user ID, in addition to the existing name lookup. + join accepts a new option: --zero-terminated (-z). As with the sort,uniq option of the same name, this makes join consume and produce NUL-terminated lines rather than newline-terminated lines. diff --git a/doc/coreutils.texi b/doc/coreutils.texi index 21216b4..aa99aef 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -14456,9 +14456,12 @@ logins, groups, and so forth. running it if no user is specified. Synopsis: @example -id address@hidden@dots{} address@hidden +id address@hidden@dots{} address@hidden @end example address@hidden can be either a user ID or a name, with name lookup +taking precedence unless the ID is specified with a leading @samp{+}. + @vindex POSIXLY_CORRECT By default, it prints the real user ID, real group ID, effective user ID if different from the real user ID, effective group ID if different from diff --git a/src/id.c b/src/id.c index 3e7016f..c35dee4 100644 --- a/src/id.c +++ b/src/id.c @@ -31,6 +31,7 @@ #include "quote.h" #include "group-list.h" #include "smack.h" +#include "userspec.h" /* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "id" @@ -79,10 +80,10 @@ usage (int status) emit_try_help (); else { - printf (_("Usage: %s [OPTION]... [USERNAME]\n"), program_name); + printf (_("Usage: %s [OPTION]... [USER]\n"), program_name); fputs (_("\ -Print user and group information for the specified USERNAME,\n\ -or (when USERNAME omitted) for the current user.\n\ +Print user and group information for the specified USER,\n\ +or (when USER omitted) for the current user.\n\ \n\ -a ignore, for compatibility with other versions\n\ -Z, --context print only the security context of the current user\n\ @@ -109,6 +110,7 @@ main (int argc, char **argv) int optc; int selinux_enabled = (is_selinux_enabled () > 0); bool smack_enabled = is_smack_enabled (); + const char *pw_name = NULL; /* If true, output the list of all group IDs. -G */ bool just_group_list = false; @@ -212,9 +214,24 @@ main (int argc, char **argv) if (n_ids == 1) { - struct passwd *pwd = getpwnam (argv[optind]); + struct passwd *pwd = NULL; + const char *spec = argv[optind]; + /* Disallow an empty spec here as parse_user_spec() doesn't + give an error for that as it seems it's a valid way to + specify a noop or "reset special bits" depending on the system. */ + if (*spec) + { + if (parse_user_spec (spec, &euid, NULL, NULL, NULL) == NULL) + { + /* parse_user_spec will only extract a numeric spec, + so we lookup that here to verify and also retrieve + the PW_NAME used subsequently in group lookup. */ + pwd = getpwuid (euid); + } + } if (pwd == NULL) - error (EXIT_FAILURE, 0, _("%s: no such user"), argv[optind]); + error (EXIT_FAILURE, 0, _("%s: no such user"), spec); + pw_name = xstrdup (pwd->pw_name); ruid = euid = pwd->pw_uid; rgid = egid = pwd->pw_gid; } @@ -269,7 +286,7 @@ main (int argc, char **argv) } else if (just_group_list) { - if (!print_group_list (argv[optind], ruid, rgid, egid, use_name)) + if (!print_group_list (pw_name, ruid, rgid, egid, use_name)) ok = false; } else if (just_context) @@ -278,7 +295,7 @@ main (int argc, char **argv) } else { - print_full_info (argv[optind]); + print_full_info (pw_name); } putchar ('\n'); diff --git a/tests/local.mk b/tests/local.mk index b00ff59..e5e3f74 100644 --- a/tests/local.mk +++ b/tests/local.mk @@ -275,7 +275,7 @@ all_tests = \ tests/misc/head-c.sh \ tests/misc/head-pos.sh \ tests/misc/id-context.sh \ - tests/misc/id-groups.sh \ + tests/misc/id-uid.sh \ tests/misc/id-setgid.sh \ tests/misc/md5sum.pl \ tests/misc/md5sum-bsd.sh \ diff --git a/tests/misc/id-groups.sh b/tests/misc/id-uid.sh similarity index 58% rename from tests/misc/id-groups.sh rename to tests/misc/id-uid.sh index ff3dc59..13f5663 100755 --- a/tests/misc/id-groups.sh +++ b/tests/misc/id-uid.sh @@ -1,6 +1,6 @@ #!/bin/sh -# Ensure that "id" outputs groups for a user -# Copyright (C) 2009-2013 Free Software Foundation, Inc. +# Ensure that "id" works with numeric user ids +# Copyright (C) 2013 Free Software Foundation, Inc. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,6 +18,20 @@ . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src print_ver_ id -id -G $(id -nu) || fail=1 +uid=$(id -u) || fail=1 +user=$(id -nu) || fail=1 + +# Ensure the empty user spec is discarded +id '' && fail=1 + +for mode in '' '-G' '-g'; do + id $mode $user > user_out || fail=1 # lookup name for comparison + + id $mode $uid > uid_out || fail=1 # lookup name "$uid" before id "$uid" + compare user_out uid_out || fail=1 + + id $mode +$uid > uid_out || fail=1 # lookup only id "$uid" + compare user_out uid_out || fail=1 +done Exit $fail -- 1.7.7.6