]> git.cameronkatri.com Git - pw-darwin.git/blobdiff - pw/pw_group.c
Remove useless call to extendarray
[pw-darwin.git] / pw / pw_group.c
index 10e8675aace5e25930c15abf25a85c0231d83967..b20ce88fb3014c6f9cbaddfe6e650569ecbb8cb4 100644 (file)
@@ -32,12 +32,18 @@ static const char rcsid[] =
 #include <ctype.h>
 #include <err.h>
 #include <termios.h>
+#include <stdbool.h>
 #include <unistd.h>
+#include <grp.h>
+#include <libutil.h>
 
 #include "pw.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 gid_t    gr_gidpolicy(struct userconf * cnf, struct cargs * args);
 
@@ -45,6 +51,7 @@ int
 pw_group(struct userconf * cnf, int mode, struct cargs * args)
 {
        int             rc;
+       struct carg    *a_newname = getarg(args, 'l');
        struct carg    *a_name = getarg(args, 'n');
        struct carg    *a_gid = getarg(args, 'g');
        struct carg    *arg;
@@ -60,6 +67,11 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
                NULL
        };
 
+       if (a_gid != NULL) {
+               if (strspn(a_gid->val, "0123456789") != strlen(a_gid->val))
+                       errx(EX_USAGE, "-g expects a number");
+       }
+
        if (mode == M_LOCK || mode == M_UNLOCK)
                errx(EX_USAGE, "'lock' command is not available for groups");
 
@@ -134,8 +146,8 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
                if (a_gid)
                        grp->gr_gid = (gid_t) atoi(a_gid->val);
 
-               if ((arg = getarg(args, 'l')) != NULL)
-                       grp->gr_name = pw_checkname((u_char *)arg->val, 0);
+               if (a_newname != NULL)
+                       grp->gr_name = pw_checkname((u_char *)a_newname->val, 0);
        } else {
                if (a_name == NULL)     /* Required */
                        errx(EX_DATAERR, "group name required");
@@ -207,36 +219,42 @@ 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;
                char   *p;
                struct passwd   *pwd;
 
                /* Make sure this is not stay NULL with -M "" */
                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;
 
-                       while (grp->gr_mem[k] != NULL) {
-                               if (extendarray(&members, &grmembers, i + 2) != -1)
-                                       members[i++] = grp->gr_mem[k];
-                               k++;
+                       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"); p != NULL; p = strtok(NULL, ", \t")) {
-                       int     j;
-                       if ((pwd = GETPWNAM(p)) == NULL) {
-                               if (!isdigit((unsigned char)*p) || (pwd = getpwuid((uid_t) atoi(p))) == NULL)
-                                       errx(EX_NOUSER, "user `%s' does not exist", p);
+
+               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);
                        }
-                       /*
-                        * 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)
                        members[i++] = NULL;
                grp->gr_mem = members;
@@ -258,19 +276,80 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
                        warn("group update");
                return EX_IOERR;
        }
+
+       arg = a_newname != NULL ? a_newname : a_name;
        /* grp may have been invalidated */
-       if ((grp = GETGRNAM(a_name->val)) == NULL)
+       if ((grp = GETGRNAM(arg->val)) == NULL)
                errx(EX_SOFTWARE, "group disappeared during update");
 
        pw_log(cnf, mode, W_GROUP, "%s(%ld)", grp->gr_name, (long) grp->gr_gid);
 
-       if (members)
-               free(members);
+       free(members);
 
        return EXIT_SUCCESS;
 }
 
 
+/*
+ * 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;
+
+       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;
+                               break;
+                       }
+               }
+               free(valueCopy);
+
+               if (!matchFound &&
+                   extendarray(members, grmembers, *i + 2) != -1)
+                       (*members)[(*i)++] = grp->gr_mem[k];
+
+               k++;
+       }
+
+       return;
+}
+
+
 static          gid_t
 gr_gidpolicy(struct userconf * cnf, struct cargs * args)
 {
@@ -338,11 +417,10 @@ static int
 print_group(struct group * grp, int pretty)
 {
        if (!pretty) {
-               int             buflen = 0;
                char           *buf = NULL;
 
-               fmtgrent(&buf, &buflen, grp);
-               fputs(buf, stdout);
+               buf = gr_make(grp);
+               printf("%s\n", buf);
                free(buf);
        } else {
                int             i;
@@ -350,8 +428,10 @@ print_group(struct group * grp, int pretty)
                printf("Group Name: %-15s   #%lu\n"
                       "   Members: ",
                       grp->gr_name, (long) grp->gr_gid);
-               for (i = 0; grp->gr_mem[i]; i++)
-                       printf("%s%s", i ? "," : "", grp->gr_mem[i]);
+               if (grp->gr_mem != NULL) {
+                       for (i = 0; grp->gr_mem[i]; i++)
+                               printf("%s%s", i ? "," : "", grp->gr_mem[i]);
+               }
                fputs("\n\n", stdout);
        }
        return EXIT_SUCCESS;