Reported 26 Mar 2001, by Neal H Walfield <neal@cs.uml.edu> ---------------------------------------------------------- idvec_merge_implied_gids (a part of libshouldbeinlibc) only merges in primary ids and not secondary ids as it should. This patch corrects that. The following is a test program showing what happened before and after: #define _GNU_SOURCE 1 #include <stdio.h> #include <stdlib.h> #include <idvec.h> int main (int argc, char *argv[]) { int i; char **arg; struct idvec *uids = make_idvec (); struct idvec *gids = make_idvec (); for (arg = &argv[1]; *arg; arg ++) idvec_add (uids, atoi (*arg)); idvec_merge_implied_gids (gids, uids); for (i = 0; i < gids->num; i ++) printf ("0 ", gids->ids[i]); printf ("\n"); return 0; } $ grep neal /etc/group adm:1bTB8THYRhlbo:4:neal neal:x:1000: $ ./idvec-test 1000 1000 $ ./idvec-test-new 1000 1000 4 I am also worried about the code to cache the groups associated with an id: if the program is long running and things change, the cache will become stale; this should be removed. 2001-03-17 Neal H Walfield <neal@cs.uml.edu> * idvec-impgids.c (idvec_merge_implied_gids): Add code to check for secondary groups. diff --exclude CVS -Nur hurd-20010307-snapshot/libshouldbeinlibc/idvec-impgids.c hurd-20010313/libshouldbeinlibc/idvec-impgids.c --- hurd-20010307-snapshot/libshouldbeinlibc/idvec-impgids.c Wed Aug 6 22:57:46 1997 +++ hurd-20010313/libshouldbeinlibc/idvec-impgids.c Sat Mar 17 08:19:00 2001 @@ -20,6 +20,7 @@ #include <stdlib.h> #include <errno.h> +#include <alloca.h> #include <idvec.h> #include <pwd.h> #include <grp.h> @@ -112,12 +117,49 @@ idvec_merge_implied_gids (struct idvec *gids, const struct idvec *uids) { int i; - error_t err = 0; + error_t initial_err = 0; +#define ERR(err) \ + do { if ((err) && ! initial_err) initial_err = err; } while (0) + + if (uids->num == 0) + return 0; + + /* Merge the primary group associated with each uid. */ for (i = 0; i < uids->num; i++) - { - error_t this_err = _merge_implied_gids (gids, uids->ids[i]); - if (this_err && !err) - err = this_err; - } - return err; + ERR (_merge_implied_gids (gids, uids->ids[i])); + + /* Merge the secondary group associated with each uid. */ + { + struct group *group; + char *names[uids->num]; + int last_name = 0; + + setgrent (); + + /* getgrent returns a string and we are only given the numerical uids. + Build a list of strings from the uids. */ + for (i = 0; i < uids->num; i ++) + { + struct passwd *passwd = getpwuid (uids->ids[i]); + if (passwd) + names[last_name ++] = strdupa (passwd->pw_name); + } + + if (last_name == 0) + goto out; + + while ((group = getgrent ())) + { + char **member; + for (i = 0; i < last_name; i ++) + for (member = group->gr_mem; *member; member ++) + if (strcmp (*member, names[i]) == 0) + ERR (idvec_add (gids, group->gr_gid)); + } + + endgrent (); + } + +out: + return initial_err; }