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"