aboutsummaryrefslogtreecommitdiff
path: root/libpwdgrp/pwd_grp.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpwdgrp/pwd_grp.c')
-rw-r--r--libpwdgrp/pwd_grp.c70
1 files changed, 47 insertions, 23 deletions
diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c
index 206519084..98b8367ca 100644
--- a/libpwdgrp/pwd_grp.c
+++ b/libpwdgrp/pwd_grp.c
@@ -620,43 +620,67 @@ struct spwd *sgetspent(const char *string)
620} 620}
621#endif 621#endif
622 622
623int initgroups(const char *user, gid_t gid) 623static gid_t *getgrouplist_internal(int *ngroups_ptr, const char *user, gid_t gid)
624{ 624{
625 FILE *grfile; 625 FILE *grfile;
626 gid_t *group_list; 626 gid_t *group_list;
627 int num_groups, rv; 627 int ngroups;
628 char **m;
629 struct group group; 628 struct group group;
630 char buff[PWD_BUFFER_SIZE]; 629 char buff[PWD_BUFFER_SIZE];
631 630
632 rv = -1; 631 /* We alloc space for 8 gids at a time. */
633 grfile = fopen_for_read(_PATH_GROUP); 632 group_list = xmalloc(8 * sizeof(group_list[0]));
634 if (grfile != NULL) { 633 group_list[0] = gid;
635 634 ngroups = 1;
636 /* We alloc space for 8 gids at a time. */
637 group_list = xmalloc(8 * sizeof(gid_t *));
638 *group_list = gid;
639 num_groups = 1;
640 635
636 grfile = fopen_for_read(_PATH_GROUP);
637 if (grfile) {
641 while (!bb__pgsreader(bb__parsegrent, &group, buff, sizeof(buff), grfile)) { 638 while (!bb__pgsreader(bb__parsegrent, &group, buff, sizeof(buff), grfile)) {
639 char **m;
642 assert(group.gr_mem); /* Must have at least a NULL terminator. */ 640 assert(group.gr_mem); /* Must have at least a NULL terminator. */
643 if (group.gr_gid != gid) { 641 if (group.gr_gid == gid)
644 for (m = group.gr_mem; *m; m++) { 642 continue;
645 if (!strcmp(*m, user)) { 643 for (m = group.gr_mem; *m; m++) {
646 group_list = xrealloc_vector(group_list, 3, num_groups); 644 if (strcmp(*m, user) != 0)
647 group_list[num_groups++] = group.gr_gid; 645 continue;
648 break; 646 group_list = xrealloc_vector(group_list, 3, ngroups);
649 } 647 group_list[ngroups++] = group.gr_gid;
650 } 648 break;
651 } 649 }
652 } 650 }
653
654 rv = setgroups(num_groups, group_list);
655 free(group_list);
656 fclose(grfile); 651 fclose(grfile);
657 } 652 }
653 *ngroups_ptr = ngroups;
654 return group_list;
655}
658 656
659 return rv; 657int initgroups(const char *user, gid_t gid)
658{
659 int ngroups;
660 gid_t *group_list = getgrouplist_internal(&ngroups, user, gid);
661
662 if (!group_list)
663 return -1;
664
665 ngroups = setgroups(ngroups, group_list);
666 free(group_list);
667 return ngroups;
668}
669
670/* TODO: uclibc needs this ported to it! */
671int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups)
672{
673 int ngroups_old = *ngroups;
674 gid_t *group_list = getgrouplist_internal(ngroups, user, gid);
675
676 if (*ngroups <= ngroups_old) {
677 ngroups_old = *ngroups;
678 memcpy(groups, group_list, ngroups_old * sizeof(groups[0]));
679 } else {
680 ngroups_old = -1;
681 }
682 free(group_list);
683 return ngroups_old;
660} 684}
661 685
662int putpwent(const struct passwd *__restrict p, FILE *__restrict f) 686int putpwent(const struct passwd *__restrict p, FILE *__restrict f)