Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 3 Jun 2015 19:08:26 +0000 (UTC)
From:      Baptiste Daroussin <bapt@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r283961 - head/usr.sbin/pw
Message-ID:  <201506031908.t53J8Q8P024606@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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"



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201506031908.t53J8Q8P024606>