Author: bapt
Date: Wed Jun  3 19:08:25 2015
New Revision: 283961
URL: https://svnweb.freebsd.org/changeset/base/283961

Log:
  New pw -R rootdir option
  
  This allows to set an alternate root directory in which the users/groups will 
be
  manipulated
  
  Requested by: gjb, ian
  Tested by:    gjb

Modified:
  head/usr.sbin/pw/pw.c
  head/usr.sbin/pw/pw_user.c
  head/usr.sbin/pw/pwupd.h

Modified: head/usr.sbin/pw/pw.c
==============================================================================
--- head/usr.sbin/pw/pw.c       Wed Jun  3 18:33:47 2015        (r283960)
+++ head/usr.sbin/pw/pw.c       Wed Jun  3 19:08:25 2015        (r283961)
@@ -56,7 +56,7 @@ static const char *Combo2[] = {
 
 struct pwf PWF =
 {
-       0,
+       PWF_REGULAR,
        setpwent,
        endpwent,
        getpwent,
@@ -71,7 +71,7 @@ struct pwf PWF =
 };
 struct pwf VPWF =
 {
-       1,
+       PWF_ALT,
        vsetpwent,
        vendpwent,
        vgetpwent,
@@ -99,24 +99,27 @@ main(int argc, char *argv[])
        char            *config = NULL;
        struct userconf *cnf;
        struct stat     st;
+       char            arg;
+       struct carg     *carg;
+       char            *etcpath = NULL;
 
        static const char *opts[W_NUM][M_NUM] =
        {
                { /* user */
-                       "V:C:qn:u:c:d:e:p:g:G:mM:k:s:oL:i:w:h:H:Db:NPy:Y",
-                       "V:C:qn:u:rY",
-                       "V:C:qn:u:c:d:e:p:g:G:mM:l:k:s:w:L:h:H:FNPY",
-                       "V:C:qn:u:FPa7",
-                       "V:C:q",
-                       "V:C:q",
-                       "V:C:q"
+                       "R:V:C:qn:u:c:d:e:p:g:G:mM:k:s:oL:i:w:h:H:Db:NPy:Y",
+                       "R:V:C:qn:u:rY",
+                       "R:V:C:qn:u:c:d:e:p:g:G:mM:l:k:s:w:L:h:H:FNPY",
+                       "R:V:C:qn:u:FPa7",
+                       "R:V:C:q",
+                       "R:V:C:q",
+                       "R:V:C:q"
                },
                { /* grp  */
-                       "V:C:qn:g:h:H:M:opNPY",
-                       "V:C:qn:g:Y",
-                       "V:C:qn:d:g:l:h:H:FM:m:NPY",
-                       "V:C:qn:g:FPa",
-                       "V:C:q"
+                       "R:V:C:qn:g:h:H:M:opNPY",
+                       "R:V:C:qn:g:Y",
+                       "R:V:C:qn:d:g:l:h:H:FM:m:NPY",
+                       "R:V:C:qn:g:FPa",
+                       "R:V:C:q"
                 }
        };
 
@@ -141,7 +144,8 @@ main(int argc, char *argv[])
                        /*
                         * Special case, allow pw -V<dir> <operation> [args] 
for scripts etc.
                         */
-                       if (argv[1][1] == 'V') {
+                       arg = argv[1][1];
+                       if (arg == 'V' || arg == 'R') {
                                optarg = &argv[1][2];
                                if (*optarg == '\0') {
                                        if (stat(argv[2], &st) != 0)
@@ -155,7 +159,7 @@ main(int argc, char *argv[])
                                        ++argv;
                                        --argc;
                                }
-                               addarg(&arglist, 'V', optarg);
+                               addarg(&arglist, arg, optarg);
                        } else
                                break;
                }
@@ -217,19 +221,29 @@ main(int argc, char *argv[])
 
        config = getarg(&arglist, 'C') ? getarg(&arglist, 'C')->val : NULL;
 
-       if (getarg(&arglist, 'V') != NULL) {
-               char * etcpath = getarg(&arglist, 'V')->val;
-               if (*etcpath) {
-                       if (config == NULL) {   /* Only override config 
location if -C not specified */
-                               asprintf(&config, "%s/pw.conf", etcpath);
-                               if (config == NULL)
-                                        errx(EX_OSERR, "out of memory");
-                       }
-                       memcpy(&PWF, &VPWF, sizeof PWF);
-                       setpwdir(etcpath);
-                       setgrdir(etcpath);
+       if ((carg = getarg(&arglist, 'R')) != NULL) {
+               asprintf(&etcpath, "%s/etc", carg->val);
+               if (etcpath == NULL)
+                       errx(EX_OSERR, "out of memory");
+       }
+       if (etcpath == NULL && (carg = getarg(&arglist, 'V')) != NULL) {
+               etcpath = strdup(carg->val);
+               if (etcpath == NULL)
+                       errx(EX_OSERR, "out of memory");
+       }
+       if (etcpath && *etcpath) {
+               if (config == NULL) {   /* Only override config location if -C 
not specified */
+                       asprintf(&config, "%s/pw.conf", etcpath);
+                       if (config == NULL)
+                                errx(EX_OSERR, "out of memory");
                }
+               setpwdir(etcpath);
+               setgrdir(etcpath);
+               memcpy(&PWF, &VPWF, sizeof PWF);
+               if (getarg(&arglist, 'R'))
+                       PWF._altdir = PWF_ROOTDIR;
        }
+       free(etcpath);
 
        /*
         * Now, let's do the common initialisation
@@ -303,6 +317,7 @@ cmdhelp(int mode, int which)
                        {
                                "usage: pw useradd [name] [switches]\n"
                                "\t-V etcdir      alternate /etc location\n"
+                               "\t-R rootir      alternate root directory\n"
                                "\t-C config      configuration file\n"
                                "\t-q             quiet operation\n"
                                "  Adding users:\n"
@@ -325,6 +340,7 @@ cmdhelp(int mode, int which)
                                "\t-N             no update\n"
                                "  Setting defaults:\n"
                                "\t-V etcdir      alternate /etc location\n"
+                               "\t-R rootir      alternate root directory\n"
                                "\t-D             set user defaults\n"
                                "\t-b dir         default home root dir\n"
                                "\t-e period      default expiry period\n"
@@ -341,12 +357,14 @@ cmdhelp(int mode, int which)
                                "\t-y path        set NIS passwd file path\n",
                                "usage: pw userdel [uid|name] [switches]\n"
                                "\t-V etcdir      alternate /etc location\n"
+                               "\t-R rootir      alternate root directory\n"
                                "\t-n name        login name\n"
                                "\t-u uid         user id\n"
                                "\t-Y             update NIS maps\n"
                                "\t-r             remove home & contents\n",
                                "usage: pw usermod [uid|name] [switches]\n"
                                "\t-V etcdir      alternate /etc location\n"
+                               "\t-R rootir      alternate root directory\n"
                                "\t-C config      configuration file\n"
                                "\t-q             quiet operation\n"
                                "\t-F             force add if no user\n"
@@ -370,6 +388,7 @@ cmdhelp(int mode, int which)
                                "\t-N             no update\n",
                                "usage: pw usershow [uid|name] [switches]\n"
                                "\t-V etcdir      alternate /etc location\n"
+                               "\t-R rootir      alternate root directory\n"
                                "\t-n name        login name\n"
                                "\t-u uid         user id\n"
                                "\t-F             force print\n"
@@ -378,6 +397,7 @@ cmdhelp(int mode, int which)
                                "\t-7             print in v7 format\n",
                                "usage: pw usernext [switches]\n"
                                "\t-V etcdir      alternate /etc location\n"
+                               "\t-R rootir      alternate root directory\n"
                                "\t-C config      configuration file\n"
                                "\t-q             quiet operation\n",
                                "usage pw: lock [switches]\n"
@@ -392,6 +412,7 @@ cmdhelp(int mode, int which)
                        {
                                "usage: pw groupadd [group|gid] [switches]\n"
                                "\t-V etcdir      alternate /etc location\n"
+                               "\t-R rootir      alternate root directory\n"
                                "\t-C config      configuration file\n"
                                "\t-q             quiet operation\n"
                                "\t-n group       group name\n"
@@ -402,11 +423,13 @@ cmdhelp(int mode, int which)
                                "\t-N             no update\n",
                                "usage: pw groupdel [group|gid] [switches]\n"
                                "\t-V etcdir      alternate /etc location\n"
+                               "\t-R rootir      alternate root directory\n"
                                "\t-n name        group name\n"
                                "\t-g gid         group id\n"
                                "\t-Y             update NIS maps\n",
                                "usage: pw groupmod [group|gid] [switches]\n"
                                "\t-V etcdir      alternate /etc location\n"
+                               "\t-R rootir      alternate root directory\n"
                                "\t-C config      configuration file\n"
                                "\t-q             quiet operation\n"
                                "\t-F             force add if not exists\n"
@@ -420,6 +443,7 @@ cmdhelp(int mode, int which)
                                "\t-N             no update\n",
                                "usage: pw groupshow [group|gid] [switches]\n"
                                "\t-V etcdir      alternate /etc location\n"
+                               "\t-R rootir      alternate root directory\n"
                                "\t-n name        group name\n"
                                "\t-g gid         group id\n"
                                "\t-F             force print\n"
@@ -427,6 +451,7 @@ cmdhelp(int mode, int which)
                                "\t-a             print all accounting 
groups\n",
                                "usage: pw groupnext [switches]\n"
                                "\t-V etcdir      alternate /etc location\n"
+                               "\t-R rootir      alternate root directory\n"
                                "\t-C config      configuration file\n"
                                "\t-q             quiet operation\n"
                        }

Modified: head/usr.sbin/pw/pw_user.c
==============================================================================
--- head/usr.sbin/pw/pw_user.c  Wed Jun  3 18:33:47 2015        (r283960)
+++ head/usr.sbin/pw/pw_user.c  Wed Jun  3 19:08:25 2015        (r283961)
@@ -63,6 +63,28 @@ static char    *shell_path(char const * 
 static void     rmat(uid_t uid);
 static void     rmopie(char const * name);
 
+static void
+create_and_populate_homedir(int mode, struct cargs *args, struct passwd *pwd,
+    struct userconf *cnf)
+{
+       char *homedir, *dotdir;
+       struct carg     *arg;
+
+       homedir = dotdir = NULL;
+
+       if ((arg = getarg(args, 'R'))) {
+               asprintf(&homedir, "%s/%s", arg->val, pwd->pw_dir);
+               if (homedir == NULL)
+                       errx(EX_OSERR, "out of memory");
+               asprintf(&dotdir, "%s/%s", arg->val, cnf->dotdir);
+       }
+
+       copymkdir(homedir ? homedir : pwd->pw_dir, dotdir ? dotdir: cnf->dotdir,
+           cnf->homemode, pwd->pw_uid, pwd->pw_gid);
+       pw_log(cnf, mode, W_USER, "%s(%u) home %s made", pwd->pw_name,
+           pwd->pw_uid, pwd->pw_dir);
+}
+
 /*-
  * -C config      configuration file
  * -q             quiet operation
@@ -108,6 +130,7 @@ pw_user(struct userconf * cnf, int mode,
        struct group   *grp;
        struct stat     st;
        char            line[_PASSWORD_LEN+1];
+       char            path[MAXPATHLEN];
        FILE           *fp;
        char *dmode_c;
        void *set = NULL;
@@ -451,7 +474,7 @@ pw_user(struct userconf * cnf, int mode,
 
                        pw_log(cnf, mode, W_USER, "%s(%u) account removed", 
a_name->val, uid);
 
-                       if (!PWALTDIR()) {
+                       if (PWALTDIR()) {
                                /*
                                 * Remove mail file
                                 */
@@ -800,11 +823,13 @@ pw_user(struct userconf * cnf, int mode,
         * doesn't hurt anything to create the empty mailfile
         */
        if (mode == M_ADD) {
-               if (!PWALTDIR()) {
-                       snprintf(line, sizeof(line), "%s/%s", _PATH_MAILDIR, 
pwd->pw_name);
-                       close(open(line, O_RDWR | O_CREAT, 0600));      /* 
Preserve contents &
+               if (PWALTDIR() != PWF_ALT) {
+                       arg = getarg(args, 'R');
+                       snprintf(path, sizeof(path), "%s%s/%s",
+                           arg ? arg->val : "", _PATH_MAILDIR, pwd->pw_name);
+                       close(open(path, O_RDWR | O_CREAT, 0600));      /* 
Preserve contents &
                                                                         * 
mtime */
-                       chown(line, pwd->pw_uid, pwd->pw_gid);
+                       chown(path, pwd->pw_uid, pwd->pw_gid);
                }
        }
 
@@ -813,12 +838,9 @@ pw_user(struct userconf * cnf, int mode,
         * that this also `works' for editing users if -m is used, but
         * existing files will *not* be overwritten.
         */
-       if (!PWALTDIR() && getarg(args, 'm') != NULL && pwd->pw_dir && 
*pwd->pw_dir == '/' && pwd->pw_dir[1]) {
-               copymkdir(pwd->pw_dir, cnf->dotdir, cnf->homemode, pwd->pw_uid, 
pwd->pw_gid);
-               pw_log(cnf, mode, W_USER, "%s(%u) home %s made",
-                      pwd->pw_name, pwd->pw_uid, pwd->pw_dir);
-       }
-
+       if (PWALTDIR() != PWF_ALT && getarg(args, 'm') != NULL && pwd->pw_dir &&
+           *pwd->pw_dir == '/' && pwd->pw_dir[1])
+               create_and_populate_homedir(mode, args, pwd, cnf);
 
        /*
         * Finally, send mail to the new user as well, if we are asked to

Modified: head/usr.sbin/pw/pwupd.h
==============================================================================
--- head/usr.sbin/pw/pwupd.h    Wed Jun  3 18:33:47 2015        (r283960)
+++ head/usr.sbin/pw/pwupd.h    Wed Jun  3 19:08:25 2015        (r283961)
@@ -71,6 +71,10 @@ extern struct pwf VPWF;
 #define GETGRGID(gid)  PWF._getgrgid(gid)
 #define GETGRNAM(nam)  PWF._getgrnam(nam)
 
+#define PWF_REGULAR 0
+#define PWF_ALT 1
+#define PWF_ROOTDIR 2
+
 #define PWALTDIR()     PWF._altdir
 #ifndef _PATH_PWD
 #define _PATH_PWD      "/etc"
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to