diff --git a/usr.sbin/pw/pw.8 b/usr.sbin/pw/pw.8 index 5a93c52bee60..20d195d71121 100644 --- a/usr.sbin/pw/pw.8 +++ b/usr.sbin/pw/pw.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 12, 2016 +.Dd November 5, 2017 .Dt PW 8 .Os .Sh NAME @@ -611,6 +611,14 @@ that the account expires. A value of 0 suppresses automatic calculation of the expiry date. .It Fl p Ar days Set the default password expiration period in days. +When +.Fl D +is used, the +.Ar days +argument is interpreted differently. +It must be numeric and represents the number of days between forced +password changes. +A value of 0 suppresses automatic calculation of the expiry date. .It Fl g Ar group Set the default group for new users. If a blank group is specified using diff --git a/usr.sbin/pw/pw_user.c b/usr.sbin/pw/pw_user.c index 92d5c6c5dbb5..3de3f2aa5b74 100644 --- a/usr.sbin/pw/pw_user.c +++ b/usr.sbin/pw/pw_user.c @@ -22,7 +22,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #ifndef lint @@ -1123,7 +1123,8 @@ validate_mode(char *mode) } static void -mix_config(struct userconf *cmdcnf, struct userconf *cfg) +mix_config(struct userconf *cmdcnf, struct userconf *cfg, bool genconf, + char *edays, char *pdays) { if (cmdcnf->default_password == 0) @@ -1164,10 +1165,62 @@ mix_config(struct userconf *cmdcnf, struct userconf *cfg) cmdcnf->min_gid = cfg->min_gid; if (cmdcnf->max_gid == 0) cmdcnf->max_gid = cfg->max_gid; - if (cmdcnf->expire_days == 0) + + /* + * If we are writing the config, use the values specified on the command + * line. Otherwise, if the values are not specified, use the ones from + * config file. + */ + if (genconf) { + const char *errstr; + cmdcnf->expire_days = cfg->expire_days; - if (cmdcnf->password_days == 0) + if (edays != NULL) { + cmdcnf->expire_days = strtonum(edays, 0, INT_MAX, + &errstr); + if (errstr != NULL) { + errx(EX_USAGE, "argument to -e must be " + "numeric if -D is specified"); + } + } + cmdcnf->password_days = cfg->password_days; + if (pdays != NULL) { + cmdcnf->password_days = strtonum(pdays, 0, INT_MAX, + &errstr); + if (errstr != NULL) { + errx(EX_USAGE, "argument to -p must be " + "numeric if -D is specified"); + } + } + } else { + char *tmp; + time_t now; + + if (edays != NULL) + tmp = strdup(edays); + else if (cfg->expire_days != 0) + asprintf(&tmp, "+%ldd", cfg->expire_days); + else + tmp = strdup("0"); + if (tmp == NULL) + errx(EX_UNAVAILABLE, "out of memory"); + now = time(NULL); + cmdcnf->expire_days = parse_date(now, tmp); + free(tmp); + + if (pdays != NULL) + tmp = strdup(pdays); + else if (cfg->password_days != 0) + asprintf(&tmp, "+%ldd", cfg->password_days); + else + tmp = strdup("0"); + if (tmp == NULL) + errx(EX_UNAVAILABLE, "out of memory"); + now = time(NULL); + cmdcnf->password_days = parse_date(now, tmp); + free(tmp); + } } int @@ -1181,11 +1234,11 @@ pw_user_add(int argc, char **argv, char *arg1) char line[_PASSWORD_LEN+1], path[MAXPATHLEN]; char *gecos, *homedir, *skel, *walk, *userid, *groupid, *grname; char *default_passwd, *name, *p; + char *edays = NULL, *pdays = NULL; const char *cfg = NULL; login_cap_t *lc; FILE *pfp, *fp; intmax_t id = -1; - time_t now; int rc, ch, fd = -1; size_t i; bool dryrun, nis, pretty, quiet, createhome, precrypted, genconf; @@ -1226,12 +1279,10 @@ pw_user_add(int argc, char **argv, char *arg1) homedir = optarg; break; case 'e': - now = time(NULL); - cmdcnf->expire_days = parse_date(now, optarg); + edays = optarg; break; case 'p': - now = time(NULL); - cmdcnf->password_days = parse_date(now, optarg); + pdays = optarg; break; case 'g': validate_grname(cmdcnf, optarg); @@ -1317,7 +1368,7 @@ pw_user_add(int argc, char **argv, char *arg1) cnf = get_userconfig(cfg); - mix_config(cmdcnf, cnf); + mix_config(cmdcnf, cnf, genconf, edays, pdays); if (default_passwd) cmdcnf->default_password = passwd_val(default_passwd, cnf->default_password);