diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-09-18 00:56:24 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-09-18 00:56:24 +0000 |
commit | 2228426512eabc05767b5abac69770e3ae9cd9bb (patch) | |
tree | 913718f56916075be130a9ea2290ff36664d4803 | |
parent | 28f5619e842d4a4e03abe6f96d7f9fd5a70e223f (diff) | |
download | busybox-w32-2228426512eabc05767b5abac69770e3ae9cd9bb.tar.gz busybox-w32-2228426512eabc05767b5abac69770e3ae9cd9bb.tar.bz2 busybox-w32-2228426512eabc05767b5abac69770e3ae9cd9bb.zip |
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
-rw-r--r-- | coreutils/id.c | 50 | ||||
-rw-r--r-- | libpwdgrp/pwd_grp.c | 70 |
2 files changed, 87 insertions, 33 deletions
diff --git a/coreutils/id.c b/coreutils/id.c index 5225f357c..aa27ed394 100644 --- a/coreutils/id.c +++ b/coreutils/id.c | |||
@@ -38,14 +38,25 @@ static int printf_full(unsigned id, const char *arg, const char *prefix) | |||
38 | return status; | 38 | return status; |
39 | } | 39 | } |
40 | 40 | ||
41 | #if (defined(__GLIBC__) && !defined(__UCLIBC__)) | ||
42 | #define HAVE_getgrouplist 1 | ||
43 | #elif ENABLE_USE_BB_PWD_GRP | ||
44 | #define HAVE_getgrouplist 1 | ||
45 | #else | ||
46 | #define HAVE_getgrouplist 0 | ||
47 | #endif | ||
48 | |||
41 | int id_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 49 | int id_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
42 | int id_main(int argc UNUSED_PARAM, char **argv) | 50 | int id_main(int argc UNUSED_PARAM, char **argv) |
43 | { | 51 | { |
52 | const char *username; | ||
44 | struct passwd *p; | 53 | struct passwd *p; |
45 | uid_t uid; | 54 | uid_t uid; |
46 | gid_t gid; | 55 | gid_t gid; |
56 | #if HAVE_getgrouplist | ||
47 | gid_t *groups; | 57 | gid_t *groups; |
48 | int n; | 58 | int n; |
59 | #endif | ||
49 | unsigned flags; | 60 | unsigned flags; |
50 | short status; | 61 | short status; |
51 | #if ENABLE_SELINUX | 62 | #if ENABLE_SELINUX |
@@ -55,6 +66,7 @@ int id_main(int argc UNUSED_PARAM, char **argv) | |||
55 | /* Don't allow more than one username */ | 66 | /* Don't allow more than one username */ |
56 | 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"); | 67 | 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"); |
57 | flags = getopt32(argv, "rnugG" USE_SELINUX("Z")); | 68 | flags = getopt32(argv, "rnugG" USE_SELINUX("Z")); |
69 | username = argv[optind]; | ||
58 | 70 | ||
59 | /* This values could be overwritten later */ | 71 | /* This values could be overwritten later */ |
60 | uid = geteuid(); | 72 | uid = geteuid(); |
@@ -64,19 +76,34 @@ int id_main(int argc UNUSED_PARAM, char **argv) | |||
64 | gid = getgid(); | 76 | gid = getgid(); |
65 | } | 77 | } |
66 | 78 | ||
67 | if (argv[optind]) { | 79 | if (username) { |
68 | p = getpwnam(argv[optind]); | 80 | #if HAVE_getgrouplist |
81 | int m; | ||
82 | #endif | ||
83 | p = getpwnam(username); | ||
69 | /* xuname2uid is needed because it exits on failure */ | 84 | /* xuname2uid is needed because it exits on failure */ |
70 | uid = xuname2uid(argv[optind]); | 85 | uid = xuname2uid(username); |
71 | gid = p->pw_gid; | 86 | gid = p->pw_gid; /* in this case PRINT_REAL is the same */ |
72 | /* in this case PRINT_REAL is the same */ | 87 | |
88 | #if HAVE_getgrouplist | ||
89 | n = 16; | ||
90 | groups = NULL; | ||
91 | do { | ||
92 | m = n; | ||
93 | groups = xrealloc(groups, sizeof(groups[0]) * m); | ||
94 | getgrouplist(username, gid, groups, &n); /* GNUism? */ | ||
95 | } while (n > m); | ||
96 | #endif | ||
97 | } else { | ||
98 | #if HAVE_getgrouplist | ||
99 | n = getgroups(0, NULL); | ||
100 | groups = xmalloc(sizeof(groups[0]) * n); | ||
101 | getgroups(n, groups); | ||
102 | #endif | ||
73 | } | 103 | } |
74 | 104 | ||
75 | n = getgroups(0, NULL); | ||
76 | groups = xmalloc(sizeof(groups[0]) * n); | ||
77 | getgroups(n, groups); | ||
78 | |||
79 | if (flags & JUST_ALL_GROUPS) { | 105 | if (flags & JUST_ALL_GROUPS) { |
106 | #if HAVE_getgrouplist | ||
80 | while (n--) { | 107 | while (n--) { |
81 | if (flags & NAME_NOT_NUMBER) | 108 | if (flags & NAME_NOT_NUMBER) |
82 | printf("%s", bb_getgrgid(NULL, 0, *groups++)); | 109 | printf("%s", bb_getgrgid(NULL, 0, *groups++)); |
@@ -84,6 +111,7 @@ int id_main(int argc UNUSED_PARAM, char **argv) | |||
84 | printf("%u", (unsigned) *groups++); | 111 | printf("%u", (unsigned) *groups++); |
85 | bb_putchar((n > 0) ? ' ' : '\n'); | 112 | bb_putchar((n > 0) ? ' ' : '\n'); |
86 | } | 113 | } |
114 | #endif | ||
87 | /* exit */ | 115 | /* exit */ |
88 | fflush_stdout_and_exit(EXIT_SUCCESS); | 116 | fflush_stdout_and_exit(EXIT_SUCCESS); |
89 | } | 117 | } |
@@ -105,7 +133,7 @@ int id_main(int argc UNUSED_PARAM, char **argv) | |||
105 | #if ENABLE_SELINUX | 133 | #if ENABLE_SELINUX |
106 | if (flags & JUST_CONTEXT) { | 134 | if (flags & JUST_CONTEXT) { |
107 | selinux_or_die(); | 135 | selinux_or_die(); |
108 | if (argv[optind]) { | 136 | if (username) { |
109 | bb_error_msg_and_die("user name can't be passed with -Z"); | 137 | bb_error_msg_and_die("user name can't be passed with -Z"); |
110 | } | 138 | } |
111 | 139 | ||
@@ -123,6 +151,7 @@ int id_main(int argc UNUSED_PARAM, char **argv) | |||
123 | /* bb_getpwuid(0) doesn't exit on failure (returns NULL) */ | 151 | /* bb_getpwuid(0) doesn't exit on failure (returns NULL) */ |
124 | status = printf_full(uid, bb_getpwuid(NULL, 0, uid), "uid="); | 152 | status = printf_full(uid, bb_getpwuid(NULL, 0, uid), "uid="); |
125 | status |= printf_full(gid, bb_getgrgid(NULL, 0, gid), " gid="); | 153 | status |= printf_full(gid, bb_getgrgid(NULL, 0, gid), " gid="); |
154 | #if HAVE_getgrouplist | ||
126 | { | 155 | { |
127 | const char *msg = " groups="; | 156 | const char *msg = " groups="; |
128 | while (n--) { | 157 | while (n--) { |
@@ -132,6 +161,7 @@ int id_main(int argc UNUSED_PARAM, char **argv) | |||
132 | } | 161 | } |
133 | } | 162 | } |
134 | /* we leak groups vector... */ | 163 | /* we leak groups vector... */ |
164 | #endif | ||
135 | 165 | ||
136 | #if ENABLE_SELINUX | 166 | #if ENABLE_SELINUX |
137 | if (is_selinux_enabled()) { | 167 | if (is_selinux_enabled()) { |
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) |