]> git.cameronkatri.com Git - pw-darwin.git/blobdiff - pw/pw_user.c
Teach pw(8) about how to use pw/gr API to reduce code duplication
[pw-darwin.git] / pw / pw_user.c
index c8364cad51f4298df03c28c651b04dc65b7afe93..abf1c354bc03de9a071caed86303851f9c100d62 100644 (file)
@@ -42,6 +42,9 @@ static const char rcsid[] =
 #include <sys/resource.h>
 #include <unistd.h>
 #include <login_cap.h>
+#include <pwd.h>
+#include <grp.h>
+#include <libutil.h>
 #include "pw.h"
 #include "bitmap.h"
 
@@ -107,7 +110,6 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
        struct stat     st;
        char            line[_PASSWORD_LEN+1];
        FILE           *fp;
-       mode_t dmode;
        char *dmode_c;
        void *set = NULL;
 
@@ -156,9 +158,8 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
                if ((set = setmode(dmode_c)) == NULL)
                        errx(EX_DATAERR, "invalid directory creation mode '%s'",
                            dmode_c);
-               dmode = getmode(set, S_IRWXU | S_IRWXG | S_IRWXO);
+               cnf->homemode = getmode(set, _DEF_DIRMODE);
                free(set);
-               cnf->homemode = dmode;
        }
 
        /*
@@ -186,7 +187,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
                        if (strchr(cnf->home+1, '/') == NULL) {
                                strcpy(dbuf, "/usr");
                                strncat(dbuf, cnf->home, MAXPATHLEN-5);
-                               if (mkdir(dbuf, cnf->homemode) != -1 || errno == EEXIST) {
+                               if (mkdir(dbuf, _DEF_DIRMODE) != -1 || errno == EEXIST) {
                                        chown(dbuf, 0, 0);
                                        /*
                                         * Skip first "/" and create symlink:
@@ -202,7 +203,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
                                while ((p = strchr(++p, '/')) != NULL) {
                                        *p = '\0';
                                        if (stat(dbuf, &st) == -1) {
-                                               if (mkdir(dbuf, cnf->homemode) == -1)
+                                               if (mkdir(dbuf, _DEF_DIRMODE) == -1)
                                                        goto direrr;
                                                chown(dbuf, 0, 0);
                                        } else if (!S_ISDIR(st.st_mode))
@@ -211,7 +212,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
                                }
                        }
                        if (stat(dbuf, &st) == -1) {
-                               if (mkdir(dbuf, cnf->homemode) == -1) {
+                               if (mkdir(dbuf, _DEF_DIRMODE) == -1) {
                                direrr: err(EX_OSFILE, "mkdir '%s'", dbuf);
                                }
                                chown(dbuf, 0, 0);
@@ -294,7 +295,6 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
        if (mode == M_PRINT && getarg(args, 'a')) {
                int             pretty = getarg(args, 'P') != NULL;
                int             v7 = getarg(args, '7') != NULL;
-
                SETPWENT();
                while ((pwd = GETPWENT()) != NULL)
                        print_user(pwd, pretty, v7);
@@ -317,7 +317,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
                 */
                if (mode != M_ADD && pwd == NULL
                    && strspn(a_name->val, "0123456789") == strlen(a_name->val)
-                   && atoi(a_name->val) > 0) { /* Assume uid */
+                   && *a_name->val) {
                        (a_uid = a_name)->ch = 'u';
                        a_name = NULL;
                }
@@ -424,7 +424,24 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
                                /* non-fatal */
                        }
 
-                       editgroups(a_name->val, NULL);
+                       grp = GETGRNAM(a_name->val);
+                       if (*grp->gr_mem == NULL)
+                               delgrent(GETGRNAM(a_name->val));
+                       SETGRENT();
+                       while ((grp = GETGRENT()) != NULL) {
+                               int i;
+                               char group[MAXLOGNAME];
+                               for (i = 0; grp->gr_mem[i] != NULL; i++) {
+                                       if (!strcmp(grp->gr_mem[i], a_name->val)) {
+                                               while (grp->gr_mem[i] != NULL) {
+                                                       grp->gr_mem[i] = grp->gr_mem[i+1];
+                                               }       
+                                               strlcpy(group, grp->gr_name, MAXLOGNAME);
+                                               chggrent(group, grp);
+                                       }
+                               }
+                       }
+                       ENDGRENT();
 
                        pw_log(cnf, mode, W_USER, "%s(%ld) account removed", a_name->val, (long) uid);
 
@@ -727,8 +744,29 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
         * Ok, user is created or changed - now edit group file
         */
 
-       if (mode == M_ADD || getarg(args, 'G') != NULL)
-               editgroups(pwd->pw_name, cnf->groups);
+       if (mode == M_ADD || getarg(args, 'G') != NULL) {
+               int i, j;
+               for (i = 0; cnf->groups[i] != NULL; i++) {
+                       grp = GETGRNAM(cnf->groups[i]);
+                       for (j = 0; grp->gr_mem[j] != NULL; j++) {
+                               if (!strcmp(grp->gr_mem[j], pwd->pw_name))
+                                       break;
+                       }
+                       if (grp->gr_mem[j] != NULL) /* user already member of group */
+                               continue;
+
+                       if (j == 0)
+                               grp->gr_mem = NULL;
+
+                       grp->gr_mem = reallocf(grp->gr_mem, sizeof(*grp->gr_mem) *
+                                                           (j + 2));
+
+                       grp->gr_mem[j] = pwd->pw_name;
+                       grp->gr_mem[j+1] = NULL;
+                       chggrent(cnf->groups[i], grp);
+               }
+       }
+
 
        /* go get a current version of pwd */
        pwd = GETPWNAM(a_name->val);
@@ -1030,6 +1068,7 @@ pw_pwcrypt(char *password)
 {
        int             i;
        char            salt[SALTSIZE + 1];
+       char            *cryptpw;
 
        static char     buf[256];
 
@@ -1040,7 +1079,10 @@ pw_pwcrypt(char *password)
                salt[i] = chars[arc4random_uniform(sizeof(chars) - 1)];
        salt[SALTSIZE] = '\0';
 
-       return strcpy(buf, crypt(password, salt));
+       cryptpw = crypt(password, salt);
+       if (cryptpw == NULL)
+               errx(EX_CONFIG, "crypt(3) failure");
+       return strcpy(buf, cryptpw);
 }
 
 
@@ -1088,10 +1130,14 @@ static int
 print_user(struct passwd * pwd, int pretty, int v7)
 {
        if (!pretty) {
-               char            buf[_UC_MAXLINE];
+               char            *buf;
+
+               if (!v7)
+                       pwd->pw_passwd = (pwd->pw_passwd == NULL) ? "" : "*";
 
-               fmtpwentry(buf, pwd, v7 ? PWF_PASSWD : PWF_STANDARD);
-               fputs(buf, stdout);
+               buf = v7 ? pw_make_v7(pwd) : pw_make(pwd);
+               printf("%s\n", buf);
+               free(buf);
        } else {
                int             j;
                char           *p;
@@ -1210,7 +1256,7 @@ pw_checkname(u_char *name, int gecos)
        if (reject) {
                snprintf(showch, sizeof(showch), (*ch >= ' ' && *ch < 127)
                    ? "`%c'" : "0x%02x", *ch);
-               errx(EX_DATAERR, "invalid character %s at position %d in %s",
+               errx(EX_DATAERR, "invalid character %s at position %td in %s",
                    showch, (ch - name), showtype);
        }
        if (!gecos && (ch - name) > LOGNAMESIZE)