+int
+pw_usernext(struct userconf *cnf, bool quiet)
+{
+ uid_t next = pw_uidpolicy(cnf, -1);
+
+ if (quiet)
+ return (next);
+
+ printf("%u:", next);
+ pw_groupnext(cnf, quiet);
+
+ return (EXIT_SUCCESS);
+}
+
+static int
+pw_usershow(char *name, long id, struct passwd *fakeuser)
+{
+ struct passwd *pwd = NULL;
+
+ if (id < 0 && name == NULL && !conf.all)
+ errx(EX_DATAERR, "username or id or '-a' required");
+
+ if (conf.all) {
+ SETPWENT();
+ while ((pwd = GETPWENT()) != NULL)
+ print_user(pwd);
+ ENDPWENT();
+ return (EXIT_SUCCESS);
+ }
+
+ pwd = (name != NULL) ? GETPWNAM(pw_checkname(name, 0)) : GETPWUID(id);
+ if (pwd == NULL) {
+ if (conf.force) {
+ pwd = fakeuser;
+ } else {
+ if (name == NULL)
+ errx(EX_NOUSER, "no such uid `%ld'", id);
+ errx(EX_NOUSER, "no such user `%s'", name);
+ }
+ }
+
+ return (print_user(pwd));
+}
+
+static void
+perform_chgpwent(const char *name, struct passwd *pwd)
+{
+ int rc;
+
+ rc = chgpwent(name, pwd);
+ if (rc == -1)
+ errx(EX_IOERR, "user '%s' does not exist (NIS?)", pwd->pw_name);
+ else if (rc != 0)
+ err(EX_IOERR, "passwd file update");
+
+ if (conf.userconf->nispasswd && *conf.userconf->nispasswd == '/') {
+ rc = chgnispwent(conf.userconf->nispasswd, name, pwd);
+ if (rc == -1)
+ warn("User '%s' not found in NIS passwd", pwd->pw_name);
+ else
+ warn("NIS passwd update");
+ /* NOTE: NIS-only update errors are not fatal */
+ }
+}
+
+/*
+ * The M_LOCK and M_UNLOCK functions simply add or remove
+ * a "*LOCKED*" prefix from in front of the password to
+ * prevent it decoding correctly, and therefore prevents
+ * access. Of course, this only prevents access via
+ * password authentication (not ssh, kerberos or any
+ * other method that does not use the UNIX password) but
+ * that is a known limitation.
+ */
+static int
+pw_userlock(char *name, long id, int mode)
+{
+ struct passwd *pwd = NULL;
+ char *passtmp = NULL;
+ bool locked = false;
+
+ if (id < 0 && name == NULL)
+ errx(EX_DATAERR, "username or id required");
+
+ pwd = (name != NULL) ? GETPWNAM(pw_checkname(name, 0)) : GETPWUID(id);
+ if (pwd == NULL) {
+ if (name == NULL)
+ errx(EX_NOUSER, "no such uid `%ld'", id);
+ errx(EX_NOUSER, "no such user `%s'", name);
+ }
+
+ if (name == NULL)
+ name = pwd->pw_name;
+
+ if (strncmp(pwd->pw_passwd, locked_str, sizeof(locked_str) -1) == 0)
+ locked = true;
+ if (mode == M_LOCK && locked)
+ errx(EX_DATAERR, "user '%s' is already locked", pwd->pw_name);
+ if (mode == M_UNLOCK && !locked)
+ errx(EX_DATAERR, "user '%s' is not locked", pwd->pw_name);
+
+ if (mode == M_LOCK) {
+ asprintf(&passtmp, "%s%s", locked_str, pwd->pw_passwd);
+ if (passtmp == NULL) /* disaster */
+ errx(EX_UNAVAILABLE, "out of memory");
+ pwd->pw_passwd = passtmp;
+ } else {
+ pwd->pw_passwd += sizeof(locked_str)-1;
+ }
+
+ perform_chgpwent(name, pwd);
+ free(passtmp);
+
+ return (EXIT_SUCCESS);
+}
+