summaryrefslogtreecommitdiffstats
path: root/pw
diff options
context:
space:
mode:
authorBaptiste Daroussin <bapt@FreeBSD.org>2015-06-03 19:08:25 +0000
committerBaptiste Daroussin <bapt@FreeBSD.org>2015-06-03 19:08:25 +0000
commitf1cacd691c6b62757f4a0168eded3d8672a06b13 (patch)
tree564c42a9fa9e4ce076cbe45dcc7e3020e1194eaa /pw
parent8f462098108bd06c25d0d54f3ff624a3f7103a82 (diff)
downloadpw-darwin-f1cacd691c6b62757f4a0168eded3d8672a06b13.tar.gz
pw-darwin-f1cacd691c6b62757f4a0168eded3d8672a06b13.tar.zst
pw-darwin-f1cacd691c6b62757f4a0168eded3d8672a06b13.zip
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
Diffstat (limited to 'pw')
-rw-r--r--pw/pw.c79
-rw-r--r--pw/pw_user.c44
-rw-r--r--pw/pwupd.h4
3 files changed, 89 insertions, 38 deletions
diff --git a/pw/pw.c b/pw/pw.c
index 0c41f03..496ecd8 100644
--- a/pw/pw.c
+++ b/pw/pw.c
@@ -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"
}
diff --git a/pw/pw_user.c b/pw/pw_user.c
index 48eb934..cb4c3de 100644
--- a/pw/pw_user.c
+++ b/pw/pw_user.c
@@ -63,6 +63,28 @@ static char *shell_path(char const * path, char *shells[], char *sh);
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 cargs * args)
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, struct cargs * args)
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, struct cargs * args)
* 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, struct cargs * args)
* 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
diff --git a/pw/pwupd.h b/pw/pwupd.h
index 1d13511..f936483 100644
--- a/pw/pwupd.h
+++ b/pw/pwupd.h
@@ -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"