svn commit: trunk/busybox: coreutils libpwdgrp

vda at busybox.net vda at busybox.net
Thu Sep 18 00:56:24 UTC 2008


Author: vda
Date: 2008-09-17 17:56:24 -0700 (Wed, 17 Sep 2008)
New Revision: 23419

Log:
id: fix "id <user>" case. Requires getgrouplist().

function                                             old     new   delta
getgrouplist_internal                                  -     200    +200
id_main                                              462     539     +77
bb_internal_getgrouplist                               -      67     +67
bb__parsespent                                       119     117      -2
bb_internal_initgroups                               213      58    -155
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 1/2 up/down: 344/-157)          Total: 187 bytes



Modified:
   trunk/busybox/coreutils/id.c
   trunk/busybox/libpwdgrp/pwd_grp.c


Changeset:
Modified: trunk/busybox/coreutils/id.c
===================================================================
--- trunk/busybox/coreutils/id.c	2008-09-17 21:36:21 UTC (rev 23418)
+++ trunk/busybox/coreutils/id.c	2008-09-18 00:56:24 UTC (rev 23419)
@@ -38,14 +38,25 @@
 	return status;
 }
 
+#if (defined(__GLIBC__) && !defined(__UCLIBC__))
+#define HAVE_getgrouplist 1
+#elif ENABLE_USE_BB_PWD_GRP
+#define HAVE_getgrouplist 1
+#else
+#define HAVE_getgrouplist 0
+#endif
+
 int id_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int id_main(int argc UNUSED_PARAM, char **argv)
 {
+	const char *username;
 	struct passwd *p;
 	uid_t uid;
 	gid_t gid;
+#if HAVE_getgrouplist
 	gid_t *groups;
 	int n;
+#endif
 	unsigned flags;
 	short status;
 #if ENABLE_SELINUX
@@ -55,6 +66,7 @@
 	/* Don't allow more than one username */
 	opt_complementary = "?1:u--g:g--u:G--u:u--G:g--G:G--g:r?ugG:n?ugG" USE_SELINUX(":u--Z:Z--u:g--Z:Z--g");
 	flags = getopt32(argv, "rnugG" USE_SELINUX("Z"));
+	username = argv[optind];
 
 	/* This values could be overwritten later */
 	uid = geteuid();
@@ -64,19 +76,34 @@
 		gid = getgid();
 	}
 
-	if (argv[optind]) {
-		p = getpwnam(argv[optind]);
+	if (username) {
+#if HAVE_getgrouplist
+		int m;
+#endif
+		p = getpwnam(username);
 		/* xuname2uid is needed because it exits on failure */
-		uid = xuname2uid(argv[optind]);
-		gid = p->pw_gid;
-		/* in this case PRINT_REAL is the same */
+		uid = xuname2uid(username);
+		gid = p->pw_gid; /* in this case PRINT_REAL is the same */
+
+#if HAVE_getgrouplist
+		n = 16;
+		groups = NULL;
+		do {
+			m = n;
+			groups = xrealloc(groups, sizeof(groups[0]) * m);
+			getgrouplist(username, gid, groups, &n); /* GNUism? */
+		} while (n > m);
+#endif
+	} else {
+#if HAVE_getgrouplist
+		n = getgroups(0, NULL);
+		groups = xmalloc(sizeof(groups[0]) * n);
+		getgroups(n, groups);
+#endif
 	}
 
-	n = getgroups(0, NULL);
-	groups = xmalloc(sizeof(groups[0]) * n);
-	getgroups(n, groups);
-
 	if (flags & JUST_ALL_GROUPS) {
+#if HAVE_getgrouplist
 		while (n--) {
 			if (flags & NAME_NOT_NUMBER)
 				printf("%s", bb_getgrgid(NULL, 0, *groups++));
@@ -84,6 +111,7 @@
 				printf("%u", (unsigned) *groups++);
 			bb_putchar((n > 0) ? ' ' : '\n');
 		}
+#endif
 		/* exit */
 		fflush_stdout_and_exit(EXIT_SUCCESS);
 	}
@@ -105,7 +133,7 @@
 #if ENABLE_SELINUX
 		if (flags & JUST_CONTEXT) {
 			selinux_or_die();
-			if (argv[optind]) {
+			if (username) {
 				bb_error_msg_and_die("user name can't be passed with -Z");
 			}
 
@@ -123,6 +151,7 @@
 	/* bb_getpwuid(0) doesn't exit on failure (returns NULL) */
 	status = printf_full(uid, bb_getpwuid(NULL, 0, uid), "uid=");
 	status |= printf_full(gid, bb_getgrgid(NULL, 0, gid), " gid=");
+#if HAVE_getgrouplist
 	{
 		const char *msg = " groups=";
 		while (n--) {
@@ -132,6 +161,7 @@
 		}
 	}
 	/* we leak groups vector... */
+#endif
 
 #if ENABLE_SELINUX
 	if (is_selinux_enabled()) {

Modified: trunk/busybox/libpwdgrp/pwd_grp.c
===================================================================
--- trunk/busybox/libpwdgrp/pwd_grp.c	2008-09-17 21:36:21 UTC (rev 23418)
+++ trunk/busybox/libpwdgrp/pwd_grp.c	2008-09-18 00:56:24 UTC (rev 23419)
@@ -620,45 +620,69 @@
 }
 #endif
 
-int initgroups(const char *user, gid_t gid)
+static gid_t *getgrouplist_internal(int *ngroups_ptr, const char *user, gid_t gid)
 {
 	FILE *grfile;
 	gid_t *group_list;
-	int num_groups, rv;
-	char **m;
+	int ngroups;
 	struct group group;
 	char buff[PWD_BUFFER_SIZE];
 
-	rv = -1;
+	/* We alloc space for 8 gids at a time. */
+	group_list = xmalloc(8 * sizeof(group_list[0]));
+	group_list[0] = gid;
+	ngroups = 1;
+
 	grfile = fopen_for_read(_PATH_GROUP);
-	if (grfile != NULL) {
-
-		/* We alloc space for 8 gids at a time. */
-		group_list = xmalloc(8 * sizeof(gid_t *));
-		*group_list = gid;
-		num_groups = 1;
-
+	if (grfile) {
 		while (!bb__pgsreader(bb__parsegrent, &group, buff, sizeof(buff), grfile)) {
+			char **m;
 			assert(group.gr_mem); /* Must have at least a NULL terminator. */
-			if (group.gr_gid != gid) {
-				for (m = group.gr_mem; *m; m++) {
-					if (!strcmp(*m, user)) {
-						group_list = xrealloc_vector(group_list, 3, num_groups);
-						group_list[num_groups++] = group.gr_gid;
-						break;
-					}
-				}
+			if (group.gr_gid == gid)
+				continue;
+			for (m = group.gr_mem; *m; m++) {
+				if (strcmp(*m, user) != 0)
+					continue;
+				group_list = xrealloc_vector(group_list, 3, ngroups);
+				group_list[ngroups++] = group.gr_gid;
+				break;
 			}
 		}
-
-		rv = setgroups(num_groups, group_list);
-		free(group_list);
 		fclose(grfile);
 	}
+	*ngroups_ptr = ngroups;
+	return group_list;
+}
 
-	return rv;
+int initgroups(const char *user, gid_t gid)
+{
+	int ngroups;
+	gid_t *group_list = getgrouplist_internal(&ngroups, user, gid);
+
+	if (!group_list)
+		return -1;
+
+	ngroups = setgroups(ngroups, group_list);
+	free(group_list);
+	return ngroups;
 }
 
+/* TODO: uclibc needs this ported to it! */
+int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups)
+{
+	int ngroups_old = *ngroups;
+	gid_t *group_list = getgrouplist_internal(ngroups, user, gid);
+
+	if (*ngroups <= ngroups_old) {
+		ngroups_old = *ngroups;
+		memcpy(groups, group_list, ngroups_old * sizeof(groups[0]));
+	} else {
+		ngroups_old = -1;
+	}
+	free(group_list);
+	return ngroups_old;
+}
+
 int putpwent(const struct passwd *__restrict p, FILE *__restrict f)
 {
 	int rv = -1;




More information about the busybox-cvs mailing list