PR/18150: John F. Woods: Print meaningful error messages on inconsistent/

corrupt entries.
This commit is contained in:
christos 2008-12-21 17:54:43 +00:00
parent beb4d1e5cc
commit fa2088e532
1 changed files with 35 additions and 17 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: passwd.c,v 1.45 2006/12/20 16:47:13 christos Exp $ */ /* $NetBSD: passwd.c,v 1.46 2008/12/21 17:54:43 christos Exp $ */
/* /*
* Copyright (c) 1987, 1993, 1994, 1995 * Copyright (c) 1987, 1993, 1994, 1995
@ -31,7 +31,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint) #if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: passwd.c,v 1.45 2006/12/20 16:47:13 christos Exp $"); __RCSID("$NetBSD: passwd.c,v 1.46 2008/12/21 17:54:43 christos Exp $");
#endif /* LIBC_SCCS and not lint */ #endif /* LIBC_SCCS and not lint */
#include <sys/types.h> #include <sys/types.h>
@ -59,7 +59,7 @@ __RCSID("$NetBSD: passwd.c,v 1.45 2006/12/20 16:47:13 christos Exp $");
static const char *pw_filename(const char *filename); static const char *pw_filename(const char *filename);
static void pw_cont(int sig); static void pw_cont(int sig);
static int pw_equal(char *buf, struct passwd *old_pw); static const char * pw_equal(char *buf, struct passwd *old_pw);
static const char *pw_default(const char *option); static const char *pw_default(const char *option);
static int read_line(FILE *fp, char *line, int max); static int read_line(FILE *fp, char *line, int max);
static void trim_whitespace(char *line); static void trim_whitespace(char *line);
@ -290,7 +290,8 @@ pw_prompt(void)
} }
/* for use in pw_copy(). Compare a pw entry to a pw struct. */ /* for use in pw_copy(). Compare a pw entry to a pw struct. */
static int /* returns a character string labelling the miscompared field or 0 */
static const char *
pw_equal(char *buf, struct passwd *pw) pw_equal(char *buf, struct passwd *pw)
{ {
struct passwd buf_pw; struct passwd buf_pw;
@ -303,16 +304,26 @@ pw_equal(char *buf, struct passwd *pw)
if (buf[len-1] == '\n') if (buf[len-1] == '\n')
buf[len-1] = '\0'; buf[len-1] = '\0';
if (!pw_scan(buf, &buf_pw, NULL)) if (!pw_scan(buf, &buf_pw, NULL))
return 0; return "corrupt line";
return !strcmp(pw->pw_name, buf_pw.pw_name) if (strcmp(pw->pw_name, buf_pw.pw_name) != 0)
&& pw->pw_uid == buf_pw.pw_uid return "name";
&& pw->pw_gid == buf_pw.pw_gid if (pw->pw_uid != buf_pw.pw_uid)
&& !strcmp(pw->pw_class, buf_pw.pw_class) return "uid";
&& (long)pw->pw_change == (long)buf_pw.pw_change if (pw->pw_gid != buf_pw.pw_gid)
&& (long)pw->pw_expire == (long)buf_pw.pw_expire return "gid";
&& !strcmp(pw->pw_gecos, buf_pw.pw_gecos) if (strcmp( pw->pw_class, buf_pw.pw_class) != 0)
&& !strcmp(pw->pw_dir, buf_pw.pw_dir) return "class";
&& !strcmp(pw->pw_shell, buf_pw.pw_shell); if (pw->pw_change != buf_pw.pw_change)
return "change";
if (pw->pw_expire != buf_pw.pw_expire)
return "expire";
if (strcmp( pw->pw_gecos, buf_pw.pw_gecos) != 0)
return "gecos";
if (strcmp( pw->pw_dir, buf_pw.pw_dir) != 0)
return "dir";
if (strcmp( pw->pw_shell, buf_pw.pw_shell) != 0)
return "shell";
return (char *)0;
} }
void void
@ -365,6 +376,7 @@ pw_copyx(int ffd, int tfd, struct passwd *pw, struct passwd *old_pw,
} }
for (done = 0; fgets(buf, (int)sizeof(buf), from);) { for (done = 0; fgets(buf, (int)sizeof(buf), from);) {
const char *neq;
if (!strchr(buf, '\n')) { if (!strchr(buf, '\n')) {
snprintf(errbuf, errbufsz, "%s: line too long", mpwd); snprintf(errbuf, errbufsz, "%s: line too long", mpwd);
(void)fclose(from); (void)fclose(from);
@ -402,9 +414,15 @@ pw_copyx(int ffd, int tfd, struct passwd *pw, struct passwd *old_pw,
continue; continue;
} }
*p = ':'; *p = ':';
if (old_pw && !pw_equal(buf, old_pw)) { if (old_pw && (neq = pw_equal(buf, old_pw)) != NULL) {
snprintf(errbuf, errbufsz, "%s: entry inconsistent", if (strcmp(neq, "corrupt line") == 0)
mpwd); (void)snprintf(errbuf, errbufsz,
"%s: entry %s corrupted", mpwd,
pw->pw_name);
else
(void)snprintf(errbuf, errbufsz,
"%s: entry %s inconsistent %s",
mpwd, pw->pw_name, neq);
(void)fclose(from); (void)fclose(from);
(void)fclose(to); (void)fclose(to);
return (0); return (0);