int i;
int changed_lines;
int ret = -1; /* failure */
+ /* used as a bool: "are we modifying /etc/shadow?" */
+#if ENABLE_FEATURE_SHADOWPASSWDS
+ const char *shadow = strstr(filename, "shadow");
+#else
+# define shadow NULL
+#endif
filename = xmalloc_follow_symlinks(filename);
if (filename == NULL)
name = xasprintf("%s:", name);
user_len = strlen(name);
- if (strstr(filename, "shadow"))
+ if (shadow)
old_fp = fopen(filename, "r+");
else
old_fp = fopen_or_warn(filename, "r+");
- if (!old_fp)
+ if (!old_fp) {
+ if (shadow)
+ ret = 0; /* missing shadow is not an error */
goto free_mem;
+ }
old_fd = fileno(old_fp);
selinux_preserve_fcontext(old_fd);
fchown(new_fd, sb.st_uid, sb.st_gid);
}
errno = 0;
- new_fp = fdopen(new_fd, "w");
- if (!new_fp) {
- bb_perror_nomsg();
- close(new_fd);
- goto unlink_new;
- }
+ new_fp = xfdopen_for_write(new_fd);
/* Backup file is "/etc/passwd-" */
*sfx_char = '-';
) {
/* Change passwd */
cp = strchrnul(cp, ':'); /* move past old passwd */
- /* name: + new_passwd + :rest of line */
- fprintf(new_fp, "%s%s%s\n", name, new_passwd, cp);
+
+ if (shadow && *cp == ':') {
+ /* /etc/shadow's field 3 (passwd change date) needs updating */
+ /* move past old change date */
+ cp = strchrnul(cp + 1, ':');
+ /* "name:" + "new_passwd" + ":" + "change date" + ":rest of line" */
+ fprintf(new_fp, "%s%s:%u%s\n", name, new_passwd,
+ (unsigned)(time(NULL)) / (24*60*60), cp);
+ } else {
+ /* "name:" + "new_passwd" + ":rest of line" */
+ fprintf(new_fp, "%s%s%s\n", name, new_passwd, cp);
+ }
changed_lines++;
} /* else delete user or group: skip the line */
next:
}
if (changed_lines == 0) {
- if (ENABLE_FEATURE_DEL_USER_FROM_GROUP && member)
+#if ENABLE_FEATURE_DEL_USER_FROM_GROUP
+ if (member)
bb_error_msg("can't find %s in %s", member, filename);
+#endif
if ((ENABLE_ADDUSER || ENABLE_ADDGROUP)
&& applet_name[0] == 'a' && !member
) {