summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/pwd_mkdb/pwd_mkdb.87
-rw-r--r--usr.sbin/pwd_mkdb/pwd_mkdb.c42
2 files changed, 43 insertions, 6 deletions
diff --git a/usr.sbin/pwd_mkdb/pwd_mkdb.8 b/usr.sbin/pwd_mkdb/pwd_mkdb.8
index 54abc76..7beecd7 100644
--- a/usr.sbin/pwd_mkdb/pwd_mkdb.8
+++ b/usr.sbin/pwd_mkdb/pwd_mkdb.8
@@ -40,6 +40,7 @@
.Sh SYNOPSIS
.Nm pwd_mkdb
.Op Fl C
+.Op Fl N
.Op Fl p
.Op Fl d Ar directory
.Op Fl s Ar cachesize
@@ -67,6 +68,12 @@ The options are as follows:
.It Fl C
Check if the password file is in the correct format. Do not
change, add, or remove any files.
+.It Fl N
+Tell
+.Nm Pwd_mkdb
+to exit with an error if it cannot obtain a lock on the file. By default,
+we block waiting for a lock on the source file. The lock is held through
+the rebuilding of the database.
.It Fl p
Create a Version 7 style password file and install it into
.Pa /etc/passwd .
diff --git a/usr.sbin/pwd_mkdb/pwd_mkdb.c b/usr.sbin/pwd_mkdb/pwd_mkdb.c
index 9df6680..4c5a518 100644
--- a/usr.sbin/pwd_mkdb/pwd_mkdb.c
+++ b/usr.sbin/pwd_mkdb/pwd_mkdb.c
@@ -42,7 +42,7 @@ static const char copyright[] =
static char sccsid[] = "@(#)pwd_mkdb.c 8.5 (Berkeley) 4/20/94";
#endif
static const char rcsid[] =
- "$Id: pwd_mkdb.c,v 1.27 1998/09/29 20:01:21 dt Exp $";
+ "$Id: pwd_mkdb.c,v 1.28 1998/12/12 16:08:41 foxfair Exp $";
#endif /* not lint */
#include <sys/param.h>
@@ -109,6 +109,7 @@ main(argc, argv)
char *username;
u_int method, methoduid;
int Cflag;
+ int nblock = 0;
Cflag = 0;
strcpy(prefix, _PATH_PWD);
@@ -133,6 +134,9 @@ main(argc, argv)
break;
case 'v': /* backward compatible */
break;
+ case 'N': /* do not wait for lock */
+ nblock = LOCK_NB;
+ break;
default:
usage();
}
@@ -158,9 +162,30 @@ main(argc, argv)
(void)umask(0);
pname = *argv;
- /* Open the original password file */
- if (!(fp = fopen(pname, "r")))
- error(pname);
+
+ /*
+ * Open and lock the original password file. We have to check
+ * the hardlink count after we get the lock to handle any potential
+ * unlink/rename race.
+ *
+ * This lock is necessary when someone runs pwd_mkdb manually, directly
+ * on master.passwd, to handle the case where a user might try to
+ * change his password while pwd_mkdb is running.
+ */
+ for (;;) {
+ struct stat st;
+
+ if (!(fp = fopen(pname, "r")))
+ error(pname);
+ if (flock(fileno(fp), LOCK_EX|nblock) < 0)
+ error("flock");
+ if (fstat(fileno(fp), &st) < 0)
+ error(pname);
+ if (st.st_nlink != 0)
+ break;
+ fclose(fp);
+ fp = NULL;
+ }
/* check only if password database is valid */
if (Cflag) {
@@ -431,8 +456,6 @@ main(argc, argv)
/* Set master.passwd permissions, in case caller forgot. */
(void)fchmod(fileno(fp), S_IRUSR|S_IWUSR);
- if (fclose(fp) == EOF)
- error("close fp");
/* Install as the real password files. */
(void)snprintf(buf, sizeof(buf), "%s/%s.tmp", prefix, _MP_DB);
@@ -454,6 +477,13 @@ main(argc, argv)
*/
(void)snprintf(buf, sizeof(buf), "%s/%s", prefix, _MASTERPASSWD);
mv(pname, buf);
+
+ /*
+ * Close locked password file after rename()
+ */
+ if (fclose(fp) == EOF)
+ error("close fp");
+
exit(0);
}
OpenPOWER on IntegriCloud