]> git.cameronkatri.com Git - pw-darwin.git/blobdiff - pw/pw_group.c
Merge sync of head
[pw-darwin.git] / pw / pw_group.c
index 54125d829ff6d40b024c84f1b0bd71e9127b3806..b20ce88fb3014c6f9cbaddfe6e650569ecbb8cb4 100644 (file)
@@ -32,12 +32,18 @@ static const char rcsid[] =
 #include <ctype.h>
 #include <err.h>
 #include <termios.h>
 #include <ctype.h>
 #include <err.h>
 #include <termios.h>
+#include <stdbool.h>
 #include <unistd.h>
 #include <unistd.h>
+#include <grp.h>
+#include <libutil.h>
 
 #include "pw.h"
 #include "bitmap.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);
 
 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;
 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;
        struct carg    *a_name = getarg(args, 'n');
        struct carg    *a_gid = getarg(args, 'g');
        struct carg    *arg;
@@ -60,12 +67,19 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
                NULL
        };
 
                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");
+
        /*
         * With M_NEXT, we only need to return the
         * next gid to stdout
         */
        /*
         * With M_NEXT, we only need to return the
         * next gid to stdout
         */
-       if (mode == M_NEXT)
-       {
+       if (mode == M_NEXT) {
                gid_t next = gr_gidpolicy(cnf, args);
                if (getarg(args, 'q'))
                        return next;
                gid_t next = gr_gidpolicy(cnf, args);
                if (getarg(args, 'q'))
                        return next;
@@ -86,7 +100,7 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
                if (a_name == NULL)
                        errx(EX_DATAERR, "group name or id required");
 
                if (a_name == NULL)
                        errx(EX_DATAERR, "group name or id required");
 
-               if (mode != M_ADD && grp == NULL && isdigit(*a_name->val)) {
+               if (mode != M_ADD && grp == NULL && isdigit((unsigned char)*a_name->val)) {
                        (a_gid = a_name)->ch = 'g';
                        a_name = NULL;
                }
                        (a_gid = a_name)->ch = 'g';
                        a_name = NULL;
                }
@@ -121,7 +135,7 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
                        if (rc == -1)
                                err(EX_IOERR, "group '%s' not available (NIS?)", grp->gr_name);
                        else if (rc != 0) {
                        if (rc == -1)
                                err(EX_IOERR, "group '%s' not available (NIS?)", grp->gr_name);
                        else if (rc != 0) {
-                               warnc(rc, "group update");
+                               warn("group update");
                                return EX_IOERR;
                        }
                        pw_log(cnf, mode, W_GROUP, "%s(%ld) removed", a_name->val, (long) gid);
                                return EX_IOERR;
                        }
                        pw_log(cnf, mode, W_GROUP, "%s(%ld) removed", a_name->val, (long) gid);
@@ -132,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 (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");
        } else {
                if (a_name == NULL)     /* Required */
                        errx(EX_DATAERR, "group name required");
@@ -156,11 +170,13 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
         * software.
         */
 
         * software.
         */
 
-       if ((arg = getarg(args, 'h')) != NULL) {
+       if ((arg = getarg(args, 'h')) != NULL ||
+           (arg = getarg(args, 'H')) != NULL) {
                if (strcmp(arg->val, "-") == 0)
                        grp->gr_passwd = "*";   /* No access */
                else {
                        int             fd = atoi(arg->val);
                if (strcmp(arg->val, "-") == 0)
                        grp->gr_passwd = "*";   /* No access */
                else {
                        int             fd = atoi(arg->val);
+                       int             precrypt = (arg->ch == 'H');
                        int             b;
                        int             istty = isatty(fd);
                        struct termios  t;
                        int             b;
                        int             istty = isatty(fd);
                        struct termios  t;
@@ -194,41 +210,51 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
                                *p = '\0';
                        if (!*line)
                                errx(EX_DATAERR, "empty password read on file descriptor %d", fd);
                                *p = '\0';
                        if (!*line)
                                errx(EX_DATAERR, "empty password read on file descriptor %d", fd);
-                       grp->gr_passwd = pw_pwcrypt(line);
+                       if (precrypt) {
+                               if (strchr(line, ':') != NULL)
+                                       return EX_DATAERR;
+                               grp->gr_passwd = line;
+                       } else
+                               grp->gr_passwd = pw_pwcrypt(line);
                }
        }
 
                }
        }
 
-       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);
                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;
 
                        int     k = 0;
 
-                       while (grp->gr_mem[k] != NULL) {
-                               if (extendarray(&members, &grmembers, i + 2) != -1) {
-                                       members[i++] = grp->gr_mem[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++;
                                }
                                }
-                               k++;
                        }
                }
                        }
                }
-               for (p = strtok(arg->val, ", \t"); p != NULL; p = strtok(NULL, ", \t")) {
-                       int     j;
-                       if ((pwd = GETPWNAM(p)) == NULL) {
-                               if (!isdigit(*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;
                while (i < grmembers)
                        members[i++] = NULL;
                grp->gr_mem = members;
@@ -247,22 +273,83 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
                if (rc == -1)
                        warnx("group '%s' not available (NIS?)", grp->gr_name);
                else
                if (rc == -1)
                        warnx("group '%s' not available (NIS?)", grp->gr_name);
                else
-                       warnc(rc, "group update");
+                       warn("group update");
                return EX_IOERR;
        }
                return EX_IOERR;
        }
+
+       arg = a_newname != NULL ? a_newname : a_name;
        /* grp may have been invalidated */
        /* 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);
 
                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;
 }
 
 
 
        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)
 {
 static          gid_t
 gr_gidpolicy(struct userconf * cnf, struct cargs * args)
 {
@@ -297,7 +384,8 @@ gr_gidpolicy(struct userconf * cnf, struct cargs * args)
                 */
                SETGRENT();
                while ((grp = GETGRENT()) != NULL)
                 */
                SETGRENT();
                while ((grp = GETGRENT()) != NULL)
-                       if (grp->gr_gid >= (int) cnf->min_gid && grp->gr_gid <= (int) cnf->max_gid)
+                       if ((gid_t)grp->gr_gid >= (gid_t)cnf->min_gid &&
+                            (gid_t)grp->gr_gid <= (gid_t)cnf->max_gid)
                                bm_setbit(&bm, grp->gr_gid - cnf->min_gid);
                ENDGRENT();
 
                                bm_setbit(&bm, grp->gr_gid - cnf->min_gid);
                ENDGRENT();
 
@@ -329,11 +417,10 @@ static int
 print_group(struct group * grp, int pretty)
 {
        if (!pretty) {
 print_group(struct group * grp, int pretty)
 {
        if (!pretty) {
-               int             buflen = 0;
                char           *buf = NULL;
 
                char           *buf = NULL;
 
-               fmtgrent(&buf, &buflen, grp);
-               fputs(buf, stdout);
+               buf = gr_make(grp);
+               printf("%s\n", buf);
                free(buf);
        } else {
                int             i;
                free(buf);
        } else {
                int             i;
@@ -341,8 +428,10 @@ print_group(struct group * grp, int pretty)
                printf("Group Name: %-15s   #%lu\n"
                       "   Members: ",
                       grp->gr_name, (long) grp->gr_gid);
                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;
                fputs("\n\n", stdout);
        }
        return EXIT_SUCCESS;