1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-29 12:03:03 +00:00

Add the groupmod '-d' option to pw to allow the deletion of existing users

from a group without the need to perform the same operation by replacing
the existing list via the '-M' option.  The '-M' option requires someone
to fetch the existing members with pw, deleting the undesired members from
the list and sending the altered list back to pw.

Approved by:	wes (mentor)
MFC after:	5 days
This commit is contained in:
Sean Farley 2008-02-23 01:25:22 +00:00
parent 72d1b828b3
commit bc991a6d5f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=176474
3 changed files with 92 additions and 16 deletions

View File

@ -155,6 +155,7 @@
.Op Fl l Ar name .Op Fl l Ar name
.Op Fl M Ar members .Op Fl M Ar members
.Op Fl m Ar newmembers .Op Fl m Ar newmembers
.Op Fl d Ar oldmembers
.Op Fl h Ar fd | Fl H Ar fd .Op Fl h Ar fd | Fl H Ar fd
.Op Fl N .Op Fl N
.Op Fl P .Op Fl P
@ -779,6 +780,15 @@ of existing users to a group without replacing the existing list of
members. members.
Login names or user ids may be used, and duplicate users are Login names or user ids may be used, and duplicate users are
silently eliminated. silently eliminated.
.It Fl d Ar oldmembers
Similar to
.Fl M ,
this option allows the
.Em deletion
of existing users from a group without replacing the existing list of
members.
Login names or user ids may be used, and duplicate users are
silently eliminated.
.El .El
.Pp .Pp
.Ar groupadd .Ar groupadd

View File

@ -117,7 +117,7 @@ main(int argc, char *argv[])
{ /* grp */ { /* grp */
"V:C:qn:g:h:H:M:opNPY", "V:C:qn:g:h:H:M:opNPY",
"V:C:qn:g:Y", "V:C:qn:g:Y",
"V:C:qn:g:l:h:H:FM:m:NPY", "V:C:qn:d:g:l:h:H:FM:m:NPY",
"V:C:qn:g:FPa", "V:C:qn:g:FPa",
"V:C:q" "V:C:q"
} }
@ -409,6 +409,7 @@ cmdhelp(int mode, int which)
"\t-g gid group id\n" "\t-g gid group id\n"
"\t-M usr1,usr2 replaces users as group members\n" "\t-M usr1,usr2 replaces users as group members\n"
"\t-m usr1,usr2 add users as group members\n" "\t-m usr1,usr2 add users as group members\n"
"\t-d usr1,usr2 delete users as group members\n"
"\t-l name new group name\n" "\t-l name new group name\n"
"\t-Y update NIS maps\n" "\t-Y update NIS maps\n"
"\t-N no update\n", "\t-N no update\n",

View File

@ -32,12 +32,16 @@ static const char rcsid[] =
#include <ctype.h> #include <ctype.h>
#include <err.h> #include <err.h>
#include <termios.h> #include <termios.h>
#include <stdbool.h>
#include <unistd.h> #include <unistd.h>
#include "pw.h" #include "pw.h"
#include "bitmap.h" #include "bitmap.h"
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 int print_group(struct group * grp, int pretty); static int print_group(struct group * grp, int pretty);
static gid_t gr_gidpolicy(struct userconf * cnf, struct cargs * args); static gid_t gr_gidpolicy(struct userconf * cnf, struct cargs * args);
@ -207,14 +211,18 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
} }
} }
if (((arg = getarg(args, 'M')) != NULL || (arg = getarg(args, 'm')) != NULL) && arg->val) { if (((arg = getarg(args, 'M')) != NULL ||
(arg = getarg(args, 'd')) != NULL ||
(arg = getarg(args, 'm')) != NULL) && arg->val) {
int i = 0; int i = 0;
char *p; char *p;
struct passwd *pwd; struct passwd *pwd;
/* Make sure this is not stay NULL with -M "" */ /* Make sure this is not stay NULL with -M "" */
extendarray(&members, &grmembers, 200); extendarray(&members, &grmembers, 200);
if (arg->ch == 'm') { if (arg->ch == 'd')
delete_members(&members, &grmembers, &i, arg, grp);
else if (arg->ch == 'm') {
int k = 0; int k = 0;
while (grp->gr_mem[k] != NULL) { while (grp->gr_mem[k] != NULL) {
@ -223,20 +231,20 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
k++; k++;
} }
} }
for (p = strtok(arg->val, ", \t"); p != NULL; p = strtok(NULL, ", \t")) {
int j; if (arg->ch != 'd')
if ((pwd = GETPWNAM(p)) == NULL) { for (p = strtok(arg->val, ", \t"); p != NULL; p = strtok(NULL, ", \t")) {
if (!isdigit((unsigned char)*p) || (pwd = getpwuid((uid_t) atoi(p))) == NULL) int j;
errx(EX_NOUSER, "user `%s' does not exist", p);
/*
* 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);
} }
/*
* Check for duplicates
*/
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) while (i < grmembers)
members[i++] = NULL; members[i++] = NULL;
grp->gr_mem = members; grp->gr_mem = members;
@ -271,6 +279,63 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
} }
/*
* Lookup a passwd entry using a name or UID.
*/
static struct passwd *
lookup_pwent(const char *user)
{
struct passwd *pwd;
if ((pwd = GETPWNAM(user)) == NULL &&
(!isdigit((unsigned char)*user) ||
(pwd = getpwuid((uid_t) atoi(user))) == NULL))
errx(EX_NOUSER, "user `%s' does not exist", user);
return (pwd);
}
/*
* Delete requested members from a group.
*/
static void
delete_members(char ***members, int *grmembers, int *i, struct carg *arg,
struct group *grp)
{
bool matchFound;
char *user;
char *valueCopy;
char *valuePtr;
int k;
struct passwd *pwd;
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;
break;
}
}
free(valueCopy);
if (!matchFound &&
extendarray(members, grmembers, *i + 2) != -1)
(*members)[(*i)++] = grp->gr_mem[k];
k++;
}
return;
}
static gid_t static gid_t
gr_gidpolicy(struct userconf * cnf, struct cargs * args) gr_gidpolicy(struct userconf * cnf, struct cargs * args)
{ {