+ if (quiet)
+ freopen(_PATH_DEVNULL, "w", stderr);
+
+ cnf = get_userconfig(cfg);
+
+ mix_config(cmdcnf, cnf);
+ if (default_passwd)
+ cmdcnf->default_password = boolean_val(default_passwd,
+ cnf->default_password);
+ if (genconf) {
+ if (name != NULL)
+ errx(EX_DATAERR, "can't combine `-D' with `-n name'");
+ if (userid != NULL) {
+ if ((p = strtok(userid, ", \t")) != NULL)
+ cmdcnf->min_uid = pw_checkid(p, UID_MAX);
+ if (cmdcnf->min_uid == 0)
+ cmdcnf->min_uid = 1000;
+ if ((p = strtok(NULL, " ,\t")) != NULL)
+ cmdcnf->max_uid = pw_checkid(p, UID_MAX);
+ if (cmdcnf->max_uid == 0)
+ cmdcnf->max_uid = 32000;
+ }
+ if (groupid != NULL) {
+ if ((p = strtok(groupid, ", \t")) != NULL)
+ cmdcnf->min_gid = pw_checkid(p, GID_MAX);
+ if (cmdcnf->min_gid == 0)
+ cmdcnf->min_gid = 1000;
+ if ((p = strtok(NULL, " ,\t")) != NULL)
+ cmdcnf->max_gid = pw_checkid(p, GID_MAX);
+ if (cmdcnf->max_gid == 0)
+ cmdcnf->max_gid = 32000;
+ }
+ if (write_userconfig(cmdcnf, cfg))
+ return (EXIT_SUCCESS);
+ err(EX_IOERR, "config update");
+ }
+
+ if (userid)
+ id = pw_checkid(userid, UID_MAX);
+ if (id < 0 && name == NULL)
+ errx(EX_DATAERR, "user name or id required");
+
+ if (name == NULL)
+ errx(EX_DATAERR, "login name required");
+
+ if (GETPWNAM(name) != NULL)
+ errx(EX_DATAERR, "login name `%s' already exists", name);
+
+ pwd = &fakeuser;
+ pwd->pw_name = name;
+ pwd->pw_class = cmdcnf->default_class ? cmdcnf->default_class : "";
+ pwd->pw_uid = pw_uidpolicy(cmdcnf, id);
+ pwd->pw_gid = pw_gidpolicy(cnf, grname, pwd->pw_name,
+ (gid_t) pwd->pw_uid, dryrun);
+ pwd->pw_change = cmdcnf->password_days;
+ pwd->pw_expire = cmdcnf->expire_days;
+ pwd->pw_dir = pw_homepolicy(cmdcnf, homedir, pwd->pw_name);
+ pwd->pw_shell = pw_shellpolicy(cmdcnf);
+ lc = login_getpwclass(pwd);
+ if (lc == NULL || login_setcryptfmt(lc, "sha512", NULL) == NULL)
+ warn("setting crypt(3) format");
+ login_close(lc);
+ pwd->pw_passwd = pw_password(cmdcnf, pwd->pw_name, dryrun);
+ if (pwd->pw_uid == 0 && strcmp(pwd->pw_name, "root") != 0)
+ warnx("WARNING: new account `%s' has a uid of 0 "
+ "(superuser access!)", pwd->pw_name);
+ if (gecos)
+ pwd->pw_gecos = gecos;
+
+ if (fd != -1)
+ pw_set_passwd(pwd, fd, precrypted, false);
+
+ if (dryrun)
+ return (print_user(pwd, pretty, false));
+
+ if ((rc = addpwent(pwd)) != 0) {
+ if (rc == -1)
+ errx(EX_IOERR, "user '%s' already exists",
+ pwd->pw_name);
+ else if (rc != 0)
+ err(EX_IOERR, "passwd file update");
+ }
+ if (nis && cmdcnf->nispasswd && *cmdcnf->nispasswd == '/') {
+ printf("%s\n", cmdcnf->nispasswd);
+ rc = addnispwent(cmdcnf->nispasswd, pwd);
+ if (rc == -1)
+ warnx("User '%s' already exists in NIS passwd",
+ pwd->pw_name);
+ else if (rc != 0)
+ warn("NIS passwd update");
+ /* NOTE: we treat NIS-only update errors as non-fatal */
+ }
+
+ if (cmdcnf->groups != NULL) {
+ for (i = 0; i < cmdcnf->groups->sl_cur; i++) {
+ grp = GETGRNAM(cmdcnf->groups->sl_str[i]);
+ grp = gr_add(grp, pwd->pw_name);
+ /*
+ * grp can only be NULL in 2 cases:
+ * - the new member is already a member
+ * - a problem with memory occurs
+ * in both cases we want to skip now.
+ */
+ if (grp == NULL)
+ continue;
+ chggrent(grp->gr_name, grp);
+ free(grp);
+ }
+ }
+
+ pwd = GETPWNAM(name);
+ if (pwd == NULL)
+ errx(EX_NOUSER, "user '%s' disappeared during update", name);
+
+ grp = GETGRGID(pwd->pw_gid);
+ pw_log(cnf, M_ADD, W_USER, "%s(%ju):%s(%ju):%s:%s:%s",
+ pwd->pw_name, (uintmax_t)pwd->pw_uid,
+ grp ? grp->gr_name : "unknown",
+ (uintmax_t)(grp ? grp->gr_gid : (uid_t)-1),
+ pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell);