|
@@ -64,6 +64,8 @@ extern int __parsespent(void *sp, char *line) attribute_hidden;
|
|
|
extern int __pgsreader(int (*__parserfunc)(void *d, char *line), void *data,
|
|
|
char *__restrict line_buff, size_t buflen, FILE *f) attribute_hidden;
|
|
|
|
|
|
+extern gid_t* __getgrouplist_internal(const char *user, gid_t gid, int *ngroups) attribute_hidden;
|
|
|
+
|
|
|
|
|
|
|
|
|
*
|
|
@@ -684,62 +686,105 @@ struct spwd *sgetspent(const char *string)
|
|
|
|
|
|
#endif
|
|
|
|
|
|
-#ifdef L_initgroups
|
|
|
+#ifdef L___getgrouplist_internal
|
|
|
|
|
|
-#ifdef __USE_BSD
|
|
|
-
|
|
|
-libc_hidden_proto(setgroups)
|
|
|
-
|
|
|
-int initgroups(const char *user, gid_t gid)
|
|
|
+gid_t attribute_hidden *__getgrouplist_internal(const char *user, gid_t gid, int *ngroups)
|
|
|
{
|
|
|
FILE *grfile;
|
|
|
gid_t *group_list;
|
|
|
- int num_groups, rv;
|
|
|
- char **m;
|
|
|
+ int num_groups;
|
|
|
struct group group;
|
|
|
char buff[__UCLIBC_PWD_BUFFER_SIZE__];
|
|
|
|
|
|
- rv = -1;
|
|
|
+ *ngroups = num_groups = 1;
|
|
|
|
|
|
|
|
|
- if (((group_list = (gid_t *) malloc(8*sizeof(gid_t *))) != NULL)
|
|
|
- && ((grfile = fopen(_PATH_GROUP, "r")) != NULL)
|
|
|
- ) {
|
|
|
-
|
|
|
- __STDIO_SET_USER_LOCKING(grfile);
|
|
|
-
|
|
|
- *group_list = gid;
|
|
|
- num_groups = 1;
|
|
|
-
|
|
|
- while (!__pgsreader(__parsegrent, &group, buff, sizeof(buff), grfile)) {
|
|
|
- assert(group.gr_mem);
|
|
|
- if (group.gr_gid != gid) {
|
|
|
- for (m=group.gr_mem ; *m ; m++) {
|
|
|
- if (!strcmp(*m, user)) {
|
|
|
- if (!(num_groups & 7)) {
|
|
|
- gid_t *tmp = (gid_t *)
|
|
|
- realloc(group_list,
|
|
|
- (num_groups+8) * sizeof(gid_t *));
|
|
|
- if (!tmp) {
|
|
|
- rv = -1;
|
|
|
- goto DO_CLOSE;
|
|
|
- }
|
|
|
- group_list = tmp;
|
|
|
- }
|
|
|
- group_list[num_groups++] = group.gr_gid;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
+ group_list = malloc(8 * sizeof(group_list[0]));
|
|
|
+ if (!group_list)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ group_list[0] = gid;
|
|
|
+ grfile = fopen(_PATH_GROUP, "r");
|
|
|
+
|
|
|
+ if (!grfile)
|
|
|
+ return group_list;
|
|
|
+
|
|
|
+ __STDIO_SET_USER_LOCKING(grfile);
|
|
|
+
|
|
|
+ while (!__pgsreader(__parsegrent, &group, buff, sizeof(buff), grfile)) {
|
|
|
+ char **m;
|
|
|
+
|
|
|
+ assert(group.gr_mem);
|
|
|
+ if (group.gr_gid == gid)
|
|
|
+ continue;
|
|
|
+ for (m = group.gr_mem; *m; m++) {
|
|
|
+ if (strcmp(*m, user) != 0)
|
|
|
+ continue;
|
|
|
+ if (!(num_groups & 7)) {
|
|
|
+ gid_t *tmp = realloc(group_list, (num_groups+8) * sizeof(group_list[0]));
|
|
|
+ if (!tmp)
|
|
|
+ goto DO_CLOSE;
|
|
|
+ group_list = tmp;
|
|
|
}
|
|
|
+ group_list[num_groups++] = group.gr_gid;
|
|
|
+ break;
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ DO_CLOSE:
|
|
|
+ fclose(grfile);
|
|
|
+ *ngroups = num_groups;
|
|
|
+ return group_list;
|
|
|
+}
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef L_getgrouplist
|
|
|
|
|
|
- rv = setgroups(num_groups, group_list);
|
|
|
- DO_CLOSE:
|
|
|
- fclose(grfile);
|
|
|
+#if defined __USE_BSD || defined __USE_GNU
|
|
|
+int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups)
|
|
|
+{
|
|
|
+ int sz = *ngroups;
|
|
|
+ gid_t *group_list = __getgrouplist_internal(user, gid, ngroups);
|
|
|
+
|
|
|
+ if (!group_list) {
|
|
|
+
|
|
|
+ * fail with ENOMEM? I bet users never check for that */
|
|
|
+
|
|
|
+ if (sz) {
|
|
|
+ groups[0] = gid;
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ if (sz > *ngroups)
|
|
|
+ sz = *ngroups;
|
|
|
+ if (sz)
|
|
|
+ memcpy(groups, group_list, sz * sizeof(group_list[0]));
|
|
|
+ free(group_list);
|
|
|
+ if (sz < *ngroups)
|
|
|
+ return -1;
|
|
|
+ return sz;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef L_initgroups
|
|
|
|
|
|
-
|
|
|
- * warnings from various malloc debuggers. */
|
|
|
+#ifdef __USE_BSD
|
|
|
+libc_hidden_proto(setgroups)
|
|
|
+
|
|
|
+int initgroups(const char *user, gid_t gid)
|
|
|
+{
|
|
|
+ int rv;
|
|
|
+ int num_groups = ((unsigned)~0) >> 1;
|
|
|
+ gid_t *group_list = __getgrouplist_internal(user, gid, &num_groups);
|
|
|
+ if (!group_list)
|
|
|
+ return -1;
|
|
|
+ rv = setgroups(num_groups, group_list);
|
|
|
free(group_list);
|
|
|
return rv;
|
|
|
}
|