SCCS-vsn: usr.sbin/vipw/vipw.c 5.7
SCCS-vsn: usr.sbin/vipw/vipw.8 6.4
.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.\" @(#)vipw.8 6.3 (Berkeley) %G%
+.\" @(#)vipw.8 6.4 (Berkeley) %G%
edits the password file while setting the appropriate locks,
and does any necessary processing after the password file is unlocked.
If the password file is already being edited, then you will be told
edits the password file while setting the appropriate locks,
and does any necessary processing after the password file is unlocked.
If the password file is already being edited, then you will be told
+to try again later.
+The
.I vi
editor will be used unless the environment variable EDITOR indicates
an alternate editor.
.I vi
editor will be used unless the environment variable EDITOR indicates
an alternate editor.
-performs a number of consistency checks on the password entry for
-.IR root ,
-and will not allow a password file with a ``mangled'' root entry
-to be installed.
+performs a number of consistency checks on the password entries,
+and will not allow a password file with a ``mangled'' entry to be
+installed.
+If
+.I vipw
+rejects the new password file, the user is prompted to re-enter
+the edit session.
.PP
Once the information has been verified,
.I vipw
.PP
Once the information has been verified,
.I vipw
#endif /* not lint */
#ifndef lint
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)vipw.c 5.6 (Berkeley) %G%";
+static char sccsid[] = "@(#)vipw.c 5.7 (Berkeley) %G%";
#endif /* not lint */
#include <sys/param.h>
#endif /* not lint */
#include <sys/param.h>
#include <errno.h>
#include <pwd.h>
#include <stdio.h>
#include <errno.h>
#include <pwd.h>
#include <stdio.h>
+#include <strings.h>
+
+char *passwd, *temp;
main()
{
extern int errno;
register int n, fd_passwd, fd;
struct rlimit rlim;
main()
{
extern int errno;
register int n, fd_passwd, fd;
struct rlimit rlim;
- struct stat s1, s2;
- char *fend, *passwd, *temp, *tend;
+ struct stat s1;
+ char *fend, *tend;
char buf[8*1024], from[MAXPATHLEN], to[MAXPATHLEN];
char buf[8*1024], from[MAXPATHLEN], to[MAXPATHLEN];
- char *strerror(), *strcpy();
(void)signal(SIGHUP, SIG_IGN);
(void)signal(SIGINT, SIG_IGN);
(void)signal(SIGHUP, SIG_IGN);
(void)signal(SIGINT, SIG_IGN);
temp = _PATH_PTMP;
if ((fd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0) {
if (errno == EEXIST)
temp = _PATH_PTMP;
if ((fd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0) {
if (errno == EEXIST)
- fprintf(stderr, "vipw: password file busy.\n");
+ (void)fprintf(stderr, "vipw: password file busy.\n");
"vipw: %s: %s\n", temp, strerror(errno));
exit(1);
}
passwd = _PATH_MASTERPASSWD;
if ((fd_passwd = open(passwd, O_RDONLY, 0)) < 0) {
"vipw: %s: %s\n", temp, strerror(errno));
exit(1);
}
passwd = _PATH_MASTERPASSWD;
if ((fd_passwd = open(passwd, O_RDONLY, 0)) < 0) {
- fprintf(stderr, "vipw: %s: %s\n", passwd, strerror(errno));
+ (void)fprintf(stderr, "vipw: %s: %s\n", passwd,
+ strerror(errno));
exit(1);
}
while ((n = read(fd_passwd, buf, sizeof(buf))) > 0)
exit(1);
}
while ((n = read(fd_passwd, buf, sizeof(buf))) > 0)
if (n == -1 || close(fd_passwd) || fsync(fd) ||
fstat(fd, &s1) || close(fd)) {
if (n == -1 || close(fd_passwd) || fsync(fd) ||
fstat(fd, &s1) || close(fd)) {
-syserr: fprintf(stderr, "vipw: %s", strerror(errno));
- goto bad;
- }
-
- if (edit(temp)) {
- fprintf(stderr, "vipw: edit failed");
- goto bad;
+syserr: (void)fprintf(stderr, "vipw: %s; ", strerror(errno));
+ stop(1);
- if (!freopen(temp, "r", stdin) || fstat(fileno(stdin), &s2) ||
- !s2.st_size) {
- fprintf(stderr, "vipw: can't read temp file");
- goto bad;
- }
-
- if (s1.st_mtime == s2.st_mtime) {
- fprintf(stderr, "vipw: %s unchanged.\n", passwd);
- (void)unlink(temp);
- exit(0);
+ for (;;) {
+ if (edit()) {
+ (void)fprintf(stderr, "vipw: edit failed; ");
+ stop(1);
+ }
+ if (!check(&s1))
+ break;
+ if (prompt())
+ stop(0);
- if (!check())
- goto bad;
-
switch(fork()) {
case 0:
break;
case -1:
switch(fork()) {
case 0:
break;
case -1:
- fprintf(stderr, "vipw: can't fork");
- goto bad;
+ (void)fprintf(stderr, "vipw: can't fork; ");
+ stop(1);
/* NOTREACHED */
default:
exit(0);
/* NOTREACHED */
default:
exit(0);
- fprintf(stderr, "vipw: mkpasswd failed");
-bad: fprintf(stderr, "; %s unchanged.\n", passwd);
- (void)unlink(temp);
- exit(1);
+ (void)fprintf(stderr, "vipw: mkpasswd failed; ");
+ stop(1);
+check(s1)
+ struct stat *s1;
{
register long id;
register int lcnt, root;
register char *p, *sh;
{
register long id;
register int lcnt, root;
register char *p, *sh;
+ struct stat s2;
+ FILE *tfp;
- char buf[1024], *getusershell(), *strsep();
+ char buf[1024], *getusershell();
+
+ if (!(tfp = fopen(temp, "r")) || fstat(fileno(tfp), &s2) ||
+ !s2.st_size) {
+ (void)fprintf(stderr, "vipw: can't read temp file; ");
+ stop(1);
+ }
- for (lcnt = 1; fgets(buf, sizeof(buf), stdin); ++lcnt) {
+ if (s1->st_mtime == s2.st_mtime) {
+ (void)fprintf(stderr, "vipw: ");
+ stop(0);
+ }
+
+ for (lcnt = 1; fgets(buf, sizeof(buf), tfp); ++lcnt) {
/* skip lines that are too big */
if (!index(buf, '\n')) {
/* skip lines that are too big */
if (!index(buf, '\n')) {
- fprintf(stderr, "vipw: line too long");
+ (void)fprintf(stderr, "vipw: line too long");
goto bad;
}
if (!(p = strsep(buf, ":\n"))) /* login */
goto bad;
}
if (!(p = strsep(buf, ":\n"))) /* login */
goto general;
id = atol(p);
if (root && id) {
goto general;
id = atol(p);
if (root && id) {
- fprintf(stderr, "vipw: root uid should be 0");
+ (void)fprintf(stderr, "vipw: root uid should be 0");
goto bad;
}
if (id > USHRT_MAX) {
goto bad;
}
if (id > USHRT_MAX) {
- fprintf(stderr, "vipw: %s > max uid value (%d)",
+ (void)fprintf(stderr, "vipw: %s > max uid value (%d)",
p, USHRT_MAX);
goto bad;
}
p, USHRT_MAX);
goto bad;
}
goto general;
id = atol(p);
if (id > USHRT_MAX) {
goto general;
id = atol(p);
if (id > USHRT_MAX) {
- fprintf(stderr, "vipw: %s > max gid value (%d)",
+ (void)fprintf(stderr, "vipw: %s > max gid value (%d)",
p, USHRT_MAX);
goto bad;
}
p, USHRT_MAX);
goto bad;
}
if (!(p = strsep((char *)NULL, ":\n"))) /* shell */
goto general;
if (root && *p) /* empty == /bin/sh */
if (!(p = strsep((char *)NULL, ":\n"))) /* shell */
goto general;
if (root && *p) /* empty == /bin/sh */
if (!(sh = getusershell())) {
if (!(sh = getusershell())) {
- fprintf(stderr,
- "vipw: warning, unknown root shell.");
+ (void)fprintf(stderr,
+ "vipw: warning, unknown root shell.\n");
break;
}
else if (!strcmp(p, sh))
break;
if (strsep((char *)NULL, ":\n")) { /* too many */
break;
}
else if (!strcmp(p, sh))
break;
if (strsep((char *)NULL, ":\n")) { /* too many */
-general: fprintf(stderr, "vipw: corrupted entry");
-bad: fprintf(stderr, "; line #%d", lcnt);
- return(0);
+general: (void)fprintf(stderr, "vipw: corrupted entry");
+bad: (void)fprintf(stderr, "; line #%d.\n", lcnt);
+ (void)fflush(stderr);
+ return(1);
return(w == -1 || status);
}
return(w == -1 || status);
}
-edit(file)
- char *file;
- char *p, *editor, *getenv(), *rindex();
+ char *p, *editor, *getenv(), *strerror();
if (editor = getenv("EDITOR")) {
if (p = rindex(editor, '/'))
if (editor = getenv("EDITOR")) {
if (p = rindex(editor, '/'))
else
p = editor = "vi";
if (!(pid = vfork())) {
else
p = editor = "vi";
if (!(pid = vfork())) {
- execlp(editor, p, file, NULL);
+ execlp(editor, p, temp, NULL);
+ (void)fprintf(stderr, "vipw: %s: %s\n", editor,
+ strerror(errno));
_exit(127);
}
while ((w = wait(&status)) != pid && w != -1);
return(w == -1 || status);
}
_exit(127);
}
while ((w = wait(&status)) != pid && w != -1);
return(w == -1 || status);
}
+
+prompt()
+{
+ register int c;
+
+ for (;;) {
+ (void)printf("re-edit the password file? [y]: ");
+ (void)fflush(stdout);
+ c = getchar();
+ if (c != EOF && c != (int)'\n')
+ while (getchar() != (int)'\n');
+ return(c == (int)'n');
+ }
+ /* NOTREACHED */
+}
+
+stop(val)
+ int val;
+{
+ (void)fprintf(stderr, "%s unchanged.\n", passwd);
+ (void)unlink(temp);
+ exit(val);
+}