Rework groupmod modification:

Use gr_add(3) when possible to avoid code duplication.
Use a simpler logic to delete members of a group
This commit is contained in:
Baptiste Daroussin 2015-07-11 22:35:07 +00:00
parent 8970fe5251
commit 5ebd525aab
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=285411
2 changed files with 55 additions and 60 deletions

View File

@ -42,8 +42,7 @@ static const char rcsid[] =
static struct passwd *lookup_pwent(const char *user);
static void delete_members(char ***members, int *grmembers, int *i,
struct carg *arg, struct group *grp);
static void delete_members(struct group *grp, char *list);
static int print_group(struct group * grp);
static gid_t gr_gidpolicy(struct userconf * cnf, long id);
@ -163,7 +162,6 @@ pw_group(int mode, char *name, long id, struct cargs * args)
int rc;
struct carg *arg;
struct group *grp = NULL;
int grmembers = 0;
char **members = NULL;
struct userconf *cnf = conf.userconf;
@ -216,13 +214,11 @@ pw_group(int mode, char *name, long id, struct cargs * args)
else if (grp != NULL) /* Exists */
errx(EX_DATAERR, "group name `%s' already exists", name);
extendarray(&members, &grmembers, 200);
members[0] = NULL;
grp = &fakegroup;
grp->gr_name = pw_checkname(name, 0);
grp->gr_passwd = "*";
grp->gr_gid = gr_gidpolicy(cnf, id);
grp->gr_mem = members;
grp->gr_mem = NULL;
}
/*
@ -238,42 +234,31 @@ pw_group(int mode, char *name, long id, struct cargs * args)
if (((arg = getarg(args, 'M')) != NULL ||
(arg = getarg(args, 'd')) != NULL ||
(arg = getarg(args, 'm')) != NULL) && arg->val) {
int i = 0;
char *p;
struct passwd *pwd;
/* Make sure this is not stay NULL with -M "" */
extendarray(&members, &grmembers, 200);
if (arg->ch == 'd')
delete_members(&members, &grmembers, &i, arg, grp);
else if (arg->ch == 'm') {
int k = 0;
delete_members(grp, arg->val);
else if (arg->ch == 'M')
grp->gr_mem = NULL;
if (grp->gr_mem != NULL) {
while (grp->gr_mem[k] != NULL) {
if (extendarray(&members, &grmembers, i + 2) != -1)
members[i++] = grp->gr_mem[k];
k++;
}
for (p = strtok(arg->val, ", \t"); arg->ch != 'd' && p != NULL;
p = strtok(NULL, ", \t")) {
int j;
/*
* Check for duplicates
*/
pwd = lookup_pwent(p);
for (j = 0; grp->gr_mem != NULL && grp->gr_mem[j] != NULL; j++) {
if (strcmp(grp->gr_mem[j], pwd->pw_name) == 0)
break;
}
if (grp->gr_mem != NULL && grp->gr_mem[j] != NULL)
continue;
grp = gr_add(grp, pwd->pw_name);
}
if (arg->ch != 'd')
for (p = strtok(arg->val, ", \t"); p != NULL; p = strtok(NULL, ", \t")) {
int j;
/*
* Check for duplicates
*/
pwd = lookup_pwent(p);
for (j = 0; j < i && strcmp(members[j], pwd->pw_name) != 0; j++)
;
if (j == i && extendarray(&members, &grmembers, i + 2) != -1)
members[i++] = newstr(pwd->pw_name);
}
while (i < grmembers)
members[i++] = NULL;
grp->gr_mem = members;
}
if (conf.dryrun)
@ -328,42 +313,25 @@ lookup_pwent(const char *user)
* Delete requested members from a group.
*/
static void
delete_members(char ***members, int *grmembers, int *i, struct carg *arg,
struct group *grp)
delete_members(struct group *grp, char *list)
{
bool matchFound;
char *user;
char *valueCopy;
char *valuePtr;
char *p;
int k;
struct passwd *pwd;
if (grp->gr_mem == NULL)
return;
k = 0;
while (grp->gr_mem[k] != NULL) {
matchFound = false;
if ((valueCopy = strdup(arg->val)) == NULL)
errx(EX_UNAVAILABLE, "out of memory");
valuePtr = valueCopy;
while ((user = strsep(&valuePtr, ", \t")) != NULL) {
pwd = lookup_pwent(user);
if (strcmp(grp->gr_mem[k], pwd->pw_name) == 0) {
matchFound = true;
for (p = strtok(list, ", \t"); p != NULL; p = strtok(NULL, ", \t")) {
for (k = 0; grp->gr_mem[k] != NULL; k++) {
if (strcmp(grp->gr_mem[k], p) == 0)
break;
}
}
free(valueCopy);
if (grp->gr_mem[k] == NULL) /* No match */
continue;
if (!matchFound &&
extendarray(members, grmembers, *i + 2) != -1)
(*members)[(*i)++] = grp->gr_mem[k];
k++;
for (; grp->gr_mem[k] != NULL; k++)
grp->gr_mem[k] = grp->gr_mem[k+1];
}
return;
}

View File

@ -81,6 +81,32 @@ groupmod_rename_body() {
grep "^bar:.*" ${HOME}/group
}
atf_test_case groupmod_members
groupmod_members_body() {
populate_etc_skel
for i in user1 user2 user3 user4; do
atf_check -s exit:0 ${PW} useradd $i
done
atf_check -s exit:0 ${PW} groupadd foo -M "user1, user2"
atf_check -o inline:"foo:*:1005:user1,user2\n" -s exit:0 \
${PW} groupshow foo
atf_check -s exit:0 ${PW} groupmod foo -m "user3, user4"
atf_check -o inline:"foo:*:1005:user1,user2,user3,user4\n" -s exit:0 \
${PW} groupshow foo
atf_check -s exit:0 ${PW} groupmod foo -M "user1, user4"
atf_check -o inline:"foo:*:1005:user1,user4\n" -s exit:0 \
${PW} groupshow foo
# what about duplicates
atf_check -s exit:0 ${PW} groupmod foo -m "user1, user2, user3, user4"
atf_check -o inline:"foo:*:1005:user1,user4,user2,user3\n" -s exit:0 \
${PW} groupshow foo
atf_check -s exit:0 ${PW} groupmod foo -d "user1, user3"
atf_check -o inline:"foo:*:1005:user4,user2\n" -s exit:0 \
${PW} groupshow foo
}
atf_init_test_cases() {
atf_add_test_case groupmod_user
atf_add_test_case groupmod_invalid_user
@ -88,4 +114,5 @@ atf_init_test_cases() {
atf_add_test_case usermod_bug_185666
atf_add_test_case do_not_duplicate_group_on_gid_change
atf_add_test_case groupmod_rename
atf_add_test_case groupmod_members
}