Index: pw.c
===================================================================
--- pw.c	(revision 283843)
+++ pw.c	(working copy)
@@ -56,7 +56,7 @@
 
 struct pwf PWF =
 {
-	0,
+	PWF_REGULAR,
 	setpwent,
 	endpwent,
 	getpwent,
@@ -71,7 +71,7 @@
 };
 struct pwf VPWF =
 {
-	1,
+	PWF_ALT,
 	vsetpwent,
 	vendpwent,
 	vgetpwent,
@@ -99,24 +99,27 @@
 	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 @@
 			/*
 			 * Special case, allow pw -V
  [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 @@
 					++argv;
 					--argc;
 				}
-				addarg(&arglist, 'V', optarg);
+				addarg(&arglist, arg, optarg);
 			} else
 				break;
 		}
@@ -217,19 +221,29 @@
 
 	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
Index: pw_user.c
===================================================================
--- pw_user.c	(revision 283843)
+++ pw_user.c	(working copy)
@@ -63,6 +63,28 @@
 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 @@
 	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_log(cnf, mode, W_USER, "%s(%u) account removed", a_name->val, uid);
 
-			if (!PWALTDIR()) {
+			if (PWALTDIR()) {
 				/*
 				 * Remove mail file
 				 */
@@ -800,11 +823,13 @@
 	 * 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,13 +838,10 @@
 	 * 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
 	 */
Index: pwupd.h
===================================================================
--- pwupd.h	(revision 283843)
+++ pwupd.h	(working copy)
@@ -71,6 +71,10 @@
 #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"