From 70a89b8588dae5847fbdfcfc5732a246ec630463 Mon Sep 17 00:00:00 2001
From: Baptiste Daroussin <bapt@FreeBSD.org>
Date: Sat, 24 Jan 2015 19:13:03 +0000
Subject: [PATCH] Allow negative numbers in -u and -g options

PR:		196514
MFC after:	1 week
---
 usr.sbin/pw/pw_group.c            |  6 +++++-
 usr.sbin/pw/pw_user.c             |  5 ++++-
 usr.sbin/pw/tests/Makefile        |  4 +++-
 usr.sbin/pw/tests/pw_groupshow.sh | 19 +++++++++++++++++++
 usr.sbin/pw/tests/pw_usershow.sh  | 19 +++++++++++++++++++
 5 files changed, 50 insertions(+), 3 deletions(-)
 create mode 100755 usr.sbin/pw/tests/pw_groupshow.sh
 create mode 100755 usr.sbin/pw/tests/pw_usershow.sh

diff --git a/usr.sbin/pw/pw_group.c b/usr.sbin/pw/pw_group.c
index b20ce88fb301..51166cdebca5 100644
--- a/usr.sbin/pw/pw_group.c
+++ b/usr.sbin/pw/pw_group.c
@@ -68,7 +68,11 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
 	};
 
 	if (a_gid != NULL) {
-		if (strspn(a_gid->val, "0123456789") != strlen(a_gid->val))
+		const char *teststr;
+		teststr = a_gid->val;
+		if (*teststr == '-')
+			teststr++;
+		if (strspn(teststr, "0123456789") != strlen(teststr))
 			errx(EX_USAGE, "-g expects a number");
 	}
 
diff --git a/usr.sbin/pw/pw_user.c b/usr.sbin/pw/pw_user.c
index 483148af4909..f146b464adb6 100644
--- a/usr.sbin/pw/pw_user.c
+++ b/usr.sbin/pw/pw_user.c
@@ -322,7 +322,10 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
 			a_name = NULL;
 		}
 	} else {
-		if (strspn(a_uid->val, "0123456789") != strlen(a_uid->val))
+		const char *teststr = a_uid->val;
+		if (*teststr == '-')
+			teststr++;
+		if (strspn(teststr, "0123456789") != strlen(teststr))
 			errx(EX_USAGE, "-u expects a number");
 	}
 
diff --git a/usr.sbin/pw/tests/Makefile b/usr.sbin/pw/tests/Makefile
index 1283ff2a7d27..c60988418222 100644
--- a/usr.sbin/pw/tests/Makefile
+++ b/usr.sbin/pw/tests/Makefile
@@ -9,9 +9,11 @@ ATF_TESTS_SH=	pw_etcdir \
 		pw_lock \
 		pw_groupdel \
 		pw_groupmod \
+		pw_groupshow \
 		pw_useradd \
 		pw_userdel \
-		pw_usermod
+		pw_usermod \
+		pw_usershow
 
 .for tp in ${ATF_TESTS_SH}
 TEST_METADATA.${tp}+=	required_user="root"
diff --git a/usr.sbin/pw/tests/pw_groupshow.sh b/usr.sbin/pw/tests/pw_groupshow.sh
new file mode 100755
index 000000000000..2ba53d6ff19f
--- /dev/null
+++ b/usr.sbin/pw/tests/pw_groupshow.sh
@@ -0,0 +1,19 @@
+# $FreeBSD$
+
+# Import helper functions
+. $(atf_get_srcdir)/helper_functions.shin
+
+
+# Test negative uid are still valid
+# PR: 196514
+atf_test_case show_group_with_negative_number
+show_group_with_negative_number_body() {
+	populate_etc_skel
+	atf_check -s exit:0 \
+		-o inline:"wheel:*:0:root\n" \
+		${PW} groupshow -n wheel -g -1
+}
+
+atf_init_test_cases() {
+	atf_add_test_case show_group_with_negative_number
+}
diff --git a/usr.sbin/pw/tests/pw_usershow.sh b/usr.sbin/pw/tests/pw_usershow.sh
new file mode 100755
index 000000000000..4703644ca36c
--- /dev/null
+++ b/usr.sbin/pw/tests/pw_usershow.sh
@@ -0,0 +1,19 @@
+# $FreeBSD$
+
+# Import helper functions
+. $(atf_get_srcdir)/helper_functions.shin
+
+
+# Test negative uid are still valid
+# PR: 196514
+atf_test_case show_user_with_negative_number
+show_user_with_negative_number_body() {
+	populate_etc_skel
+	atf_check -s exit:0 \
+		-o inline:"root:*:0:0::0:0:Charlie &:/root:/bin/csh\n" \
+		${PW} usershow -n root -u -1
+}
+
+atf_init_test_cases() {
+	atf_add_test_case show_user_with_negative_number
+}