*/
#ifndef lint
-static char sccsid[] = "@(#)pw_util.c 8.3 (Berkeley) 4/2/94";
+#if 0
+static const char sccsid[] = "@(#)pw_util.c 8.3 (Berkeley) 4/2/94";
+#endif
+static const char rcsid[] =
+ "$FreeBSD$";
#endif /* not lint */
/*
*/
#include <sys/param.h>
+#include <sys/errno.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <err.h>
-#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <pwd.h>
#include "pw_util.h"
extern char *tempname;
+static pid_t editpid = -1;
+static int lockfd;
+char *mppath = _PATH_PWD;
+char *masterpasswd = _PATH_MASTERPASSWD;
+
+void
+pw_cont(sig)
+ int sig;
+{
+
+ if (editpid != -1)
+ kill(editpid, sig);
+}
void
pw_init()
(void)signal(SIGPIPE, SIG_IGN);
(void)signal(SIGQUIT, SIG_IGN);
(void)signal(SIGTERM, SIG_IGN);
- (void)signal(SIGTSTP, SIG_IGN);
- (void)signal(SIGTTOU, SIG_IGN);
+ (void)signal(SIGCONT, pw_cont);
/* Create with exact permissions. */
(void)umask(0);
}
-static int lockfd;
-
int
pw_lock()
{
- /*
+ /*
* If the master password file doesn't exist, the system is hosed.
* Might as well try to build one. Set the close-on-exec bit so
* that users can't get at the encrypted passwords while editing.
* Open should allow flock'ing the file; see 4.4BSD. XXX
*/
- lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
- if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1)
- err(1, "%s", _PATH_MASTERPASSWD);
- if (flock(lockfd, LOCK_EX|LOCK_NB))
- errx(1, "the password db file is busy");
+ for (;;) {
+ struct stat st;
+
+ lockfd = open(masterpasswd, O_RDONLY, 0);
+ if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1)
+ err(1, "%s", masterpasswd);
+ if (flock(lockfd, LOCK_EX|LOCK_NB))
+ errx(1, "the password db file is busy");
+
+ /*
+ * If the password file was replaced while we were trying to
+ * get the lock, our hardlink count will be 0 and we have to
+ * close and retry.
+ */
+ if (fstat(lockfd, &st) < 0)
+ errx(1, "fstat() failed");
+ if (st.st_nlink != 0)
+ break;
+ close(lockfd);
+ lockfd = -1;
+ }
return (lockfd);
}
int
pw_tmp()
{
- static char path[MAXPATHLEN] = _PATH_MASTERPASSWD;
+ static char path[MAXPATHLEN];
int fd;
char *p;
- if (p = strrchr(path, '/'))
+ strncpy(path, masterpasswd, MAXPATHLEN - 1);
+ path[MAXPATHLEN] = '\0';
+
+ if ((p = strrchr(path, '/')))
++p;
else
p = path;
}
int
-pw_mkdb()
+pw_mkdb(username)
+char *username;
{
int pstat;
pid_t pid;
- warnx("rebuilding the database...");
(void)fflush(stderr);
- if (!(pid = vfork())) {
- execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL);
+ if (!(pid = fork())) {
+ if(!username) {
+ warnx("rebuilding the database...");
+ execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", "-d", mppath,
+ tempname, (char *)NULL);
+ } else {
+ warnx("updating the database...");
+ execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", "-d", mppath,
+ "-u", username, tempname, (char *)NULL);
+ }
pw_error(_PATH_PWD_MKDB, 1, 1);
}
pid = waitpid(pid, &pstat, 0);
int notsetuid;
{
int pstat;
- pid_t pid;
char *p, *editor;
if (!(editor = getenv("EDITOR")))
editor = _PATH_VI;
- if (p = strrchr(editor, '/'))
+ if ((p = strrchr(editor, '/')))
++p;
- else
+ else
p = editor;
- if (!(pid = vfork())) {
+ if (!(editpid = fork())) {
if (notsetuid) {
(void)setgid(getgid());
(void)setuid(getuid());
}
- execlp(editor, p, tempname, NULL);
- _exit(1);
+ errno = 0;
+ execlp(editor, p, tempname, (char *)NULL);
+ _exit(errno);
}
- pid = waitpid(pid, (int *)&pstat, 0);
- if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
- pw_error(editor, 1, 1);
+ for (;;) {
+ editpid = waitpid(editpid, (int *)&pstat, WUNTRACED);
+ errno = WEXITSTATUS(pstat);
+ if (editpid == -1)
+ pw_error(editor, 1, 1);
+ else if (WIFSTOPPED(pstat))
+ raise(WSTOPSIG(pstat));
+ else if (WIFEXITED(pstat) && errno == 0)
+ break;
+ else
+ pw_error(editor, 1, 1);
+ }
+ editpid = -1;
}
void
pw_prompt()
{
- int c;
+ int c, first;
(void)printf("re-edit the password file? [y]: ");
(void)fflush(stdout);
- c = getchar();
- if (c != EOF && c != '\n')
- while (getchar() != '\n');
- if (c == 'n')
+ first = c = getchar();
+ while (c != '\n' && c != EOF)
+ c = getchar();
+ if (first == 'n')
pw_error(NULL, 0, 0);
}
char *name;
int err, eval;
{
- if (err)
- warn(name);
-
- warnx("%s: unchanged", _PATH_MASTERPASSWD);
+#ifdef YP
+ extern int _use_yp;
+#endif /* YP */
+ if (err) {
+ if (name != NULL)
+ warn("%s", name);
+ else
+ warn(NULL);
+ }
+#ifdef YP
+ if (_use_yp)
+ warnx("NIS information unchanged");
+ else
+#endif /* YP */
+ warnx("%s: unchanged", masterpasswd);
(void)unlink(tempname);
exit(eval);
}