]> git.cameronkatri.com Git - pw-darwin.git/blobdiff - pw/pw_group.c
Let the afterinstall target ignore failures from running chflags. This
[pw-darwin.git] / pw / pw_group.c
index 1c63a11722b263603f84b2d7f9880fca02b90040..a8f182cae259efed7ef18d7de5aec51466882d1f 100644 (file)
@@ -32,12 +32,16 @@ static const char rcsid[] =
 #include <ctype.h>
 #include <err.h>
 #include <termios.h>
+#include <stdbool.h>
 #include <unistd.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);
 
@@ -207,37 +211,40 @@ 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) {
+                               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;
@@ -272,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
 gr_gidpolicy(struct userconf * cnf, struct cargs * args)
 {