for (;;) {
struct stat st;
- lockfd = open(masterpasswd, O_RDONLY, 0);
- if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1)
- err(1, "%s", masterpasswd);
- /* XXX vulnerable to race conditions */
- if (flock(lockfd, LOCK_EX|LOCK_NB) == -1) {
+ lockfd = flopen(masterpasswd, O_RDONLY|O_NONBLOCK|O_CLOEXEC, 0);
+ if (lockfd == -1) {
if (errno == EWOULDBLOCK) {
errx(1, "the password db file is busy");
} else {
sigprocmask(SIG_SETMASK, &oldsigset, NULL);
if (stat(tempname, &st2) == -1)
return (-1);
- return (st1.st_mtime != st2.st_mtime);
+ return (st1.st_mtim.tv_sec != st2.st_mtim.tv_sec ||
+ st1.st_mtim.tv_nsec != st2.st_mtim.tv_nsec);
}
/*
pw->pw_passwd, (uintmax_t)pw->pw_uid, (uintmax_t)pw->pw_gid,
pw->pw_class, (uintmax_t)pw->pw_change, (uintmax_t)pw->pw_expire,
pw->pw_gecos, pw->pw_dir, pw->pw_shell);
- return line;
+ return (line);
+}
+
+/*
+ * Make a passwd line (in v7 format) out of a struct passwd
+ */
+char *
+pw_make_v7(const struct passwd *pw)
+{
+ char *line;
+
+ asprintf(&line, "%s:*:%ju:%ju:%s:%s:%s", pw->pw_name,
+ (uintmax_t)pw->pw_uid, (uintmax_t)pw->pw_gid,
+ pw->pw_gecos, pw->pw_dir, pw->pw_shell);
+ return (line);
}
/*
size_t len;
int eof, readlen;
- spw = pw;
+ if (old_pw == NULL && pw == NULL)
+ return (-1);
+
+ spw = old_pw;
+ /* deleting a user */
if (pw == NULL) {
line = NULL;
- if (old_pw == NULL)
+ } else {
+ if ((line = pw_make(pw)) == NULL)
return (-1);
- spw = old_pw;
- } else if ((line = pw_make(pw)) == NULL)
- return (-1);
+ }
+
+ /* adding a user */
+ if (spw == NULL)
+ spw = pw;
eof = 0;
len = 0;
*/
*q = t;
- if (fpw == NULL || fpw->pw_uid != spw->pw_uid) {
+ if (fpw == NULL || strcmp(fpw->pw_name, spw->pw_name) != 0) {
/* nope */
if (fpw != NULL)
free(fpw);