summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPádraig Brady <P@draigBrady.com>2013-09-20 12:38:00 +0100
committerPádraig Brady <P@draigBrady.com>2013-09-22 03:27:17 +0100
commit7415d8d9f823dae484d3791b425f184f1e3b4cad (patch)
treeca7c6b5124d25e355d8b210ac1d79ff2b6ffc414
parentf9992690f40646f64d8bd0bfb55faed1980df0ad (diff)
downloadcoreutils-7415d8d9f823dae484d3791b425f184f1e3b4cad.tar.xz
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
-rw-r--r--NEWS2
-rw-r--r--doc/coreutils.texi5
-rw-r--r--src/id.c32
-rw-r--r--tests/local.mk2
-rwxr-xr-xtests/misc/id-uid.sh (renamed from tests/misc/id-groups.sh)20
5 files changed, 49 insertions, 12 deletions
diff --git a/NEWS b/NEWS
index 23c7b54fd..c152bbf05 100644
--- a/NEWS
+++ b/NEWS
@@ -50,6 +50,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 d022c4560..5b2f6247b 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 [@var{option}]@dots{} [@var{username}]
+id [@var{option}]@dots{} [@var{user}]
@end example
+@var{user} 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 a0334ba73..bae9c181a 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"
@@ -80,10 +81,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"),
stdout);
fputs (_("\
@@ -115,6 +116,7 @@ main (int argc, char **argv)
int selinux_enabled = (is_selinux_enabled () > 0);
bool smack_enabled = is_smack_enabled ();
bool opt_zero = false;
+ char *pw_name = NULL;
/* If true, output the list of all group IDs. -G */
bool just_group_list = false;
@@ -225,9 +227,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;
}
@@ -282,7 +299,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,
opt_zero ? '\0' : ' '))
ok = false;
}
@@ -292,10 +309,11 @@ main (int argc, char **argv)
}
else
{
- print_full_info (argv[optind]);
+ print_full_info (pw_name);
}
putchar (opt_zero ? '\0' : '\n');
+ IF_LINT (free (pw_name));
exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/tests/local.mk b/tests/local.mk
index 8f76b2371..1f3e82fe0 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/id-zero.sh \
tests/misc/md5sum.pl \
diff --git a/tests/misc/id-groups.sh b/tests/misc/id-uid.sh
index ff3dc59fc..13f5663a6 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