diff options
Diffstat (limited to 'libpwdgrp/pwd_grp.c')
-rw-r--r-- | libpwdgrp/pwd_grp.c | 70 |
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 | ||
623 | int initgroups(const char *user, gid_t gid) | 623 | static 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; | 657 | int 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! */ | ||
671 | int 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 | ||
662 | int putpwent(const struct passwd *__restrict p, FILE *__restrict f) | 686 | int putpwent(const struct passwd *__restrict p, FILE *__restrict f) |