From 7c161da819fb61834efb3fc3628dd92834f1548e Mon Sep 17 00:00:00 2001 From: thorpej Date: Tue, 3 Aug 2004 23:29:04 +0000 Subject: [PATCH] - Rename pw_copy() to pw_copyx(), make it return a success/failure code, and add "errbuf" and "errbufsz" parameters so that errors can be handled gracefully, rather than simply exiting the process. - Add a pw_copy() wrapper around pw_copyx() to preserve old behavior for apps that use it. - Bump shlib version to 7.4. --- distrib/sets/lists/base/shl.mi | 6 +-- include/util.h | 4 +- lib/libutil/passwd.c | 95 ++++++++++++++++++++++++---------- lib/libutil/pw_init.3 | 32 ++++++++++-- lib/libutil/shlib_version | 4 +- 5 files changed, 105 insertions(+), 36 deletions(-) diff --git a/distrib/sets/lists/base/shl.mi b/distrib/sets/lists/base/shl.mi index a13af4515e9f..f1ae90f1c83c 100644 --- a/distrib/sets/lists/base/shl.mi +++ b/distrib/sets/lists/base/shl.mi @@ -1,4 +1,4 @@ -# $NetBSD: shl.mi,v 1.277 2004/07/13 15:45:18 seb Exp $ +# $NetBSD: shl.mi,v 1.278 2004/08/03 23:29:04 thorpej Exp $ # Note: libtermcap and libtermlib are hardlinked and share the same version. ./lib/libc.so.12.122 base-sys-shlib ./lib/libcrypt.so.0.1 base-sys-shlib @@ -10,7 +10,7 @@ ./lib/libm.so.0.2 base-sys-shlib ./lib/libtermcap.so.0.5 base-sys-shlib ./lib/libtermlib.so.0.5 base-sys-shlib -./lib/libutil.so.7.3 base-sys-shlib +./lib/libutil.so.7.4 base-sys-shlib ./lib/libz.so.0.4 base-sys-shlib ./usr/lib/i18n/libBIG5.so.4.3 base-i18n-shlib ./usr/lib/i18n/libEUC.so.4.3 base-i18n-shlib @@ -75,6 +75,6 @@ ./usr/lib/libtermcap.so.0.5 base-sys-shlib ./usr/lib/libtermlib.so.0.5 base-sys-shlib ./usr/lib/libusbhid.so.1.0 base-sys-shlib -./usr/lib/libutil.so.7.3 base-sys-shlib +./usr/lib/libutil.so.7.4 base-sys-shlib ./usr/lib/libwrap.so.0.2 base-net-shlib ./usr/lib/libz.so.0.4 base-sys-shlib diff --git a/include/util.h b/include/util.h index 311352241ab0..5dcc743ec4da 100644 --- a/include/util.h +++ b/include/util.h @@ -1,4 +1,4 @@ -/* $NetBSD: util.h,v 1.31 2003/08/07 09:44:11 agc Exp $ */ +/* $NetBSD: util.h,v 1.32 2004/08/03 23:29:04 thorpej Exp $ */ /*- * Copyright (c) 1995 @@ -82,6 +82,8 @@ int pidfile(const char *); int pidlock(const char *, int, pid_t *, const char *); int pw_abort(void); void pw_copy(int, int, struct passwd *, struct passwd *); +int pw_copyx(int, int, struct passwd *, struct passwd *, + char *, size_t); void pw_edit(int, const char *); void pw_error(const char *, int, int); void pw_getconf(char *, size_t, const char *, const char *); diff --git a/lib/libutil/passwd.c b/lib/libutil/passwd.c index dbe6331a5289..b28f3cf5d273 100644 --- a/lib/libutil/passwd.c +++ b/lib/libutil/passwd.c @@ -1,4 +1,4 @@ -/* $NetBSD: passwd.c,v 1.35 2003/08/07 16:44:59 agc Exp $ */ +/* $NetBSD: passwd.c,v 1.36 2004/08/03 23:29:05 thorpej Exp $ */ /* * Copyright (c) 1987, 1993, 1994, 1995 @@ -31,7 +31,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: passwd.c,v 1.35 2003/08/07 16:44:59 agc Exp $"); +__RCSID("$NetBSD: passwd.c,v 1.36 2004/08/03 23:29:05 thorpej Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -319,6 +319,20 @@ pw_equal(char *buf, struct passwd *pw) void pw_copy(int ffd, int tfd, struct passwd *pw, struct passwd *old_pw) +{ + char errbuf[200]; + int rv; + + rv = pw_copyx(ffd, tfd, pw, old_pw, errbuf, sizeof(errbuf)); + if (rv == 0) { + warnx("%s", errbuf); + pw_error(NULL, 0, 1); + } +} + +int +pw_copyx(int ffd, int tfd, struct passwd *pw, struct passwd *old_pw, + char *errbuf, size_t errbufsz) { const char *filename; char mpwd[MAXPATHLEN], mpwdl[MAXPATHLEN], *p, buf[8192]; @@ -326,71 +340,98 @@ pw_copy(int ffd, int tfd, struct passwd *pw, struct passwd *old_pw) int done; _DIAGASSERT(pw != NULL); + _DIAGASSERT(errbuf != NULL); /* old_pw may be NULL */ - if ((filename = pw_filename(_PATH_MASTERPASSWD)) == NULL) - pw_error(pw_prefix, 1,1); + if ((filename = pw_filename(_PATH_MASTERPASSWD)) == NULL) { + snprintf(errbuf, errbufsz, "%s: %s", pw_prefix, + strerror(errno)); + return (0); + } (void)strcpy(mpwd, filename); - if ((filename = pw_filename(_PATH_MASTERPASSWD_LOCK)) == NULL) - pw_error(pw_prefix, 1,1); + if ((filename = pw_filename(_PATH_MASTERPASSWD_LOCK)) == NULL) { + snprintf(errbuf, errbufsz, "%s: %s", pw_prefix, + strerror(errno)); + return (0); + } (void)strcpy(mpwdl, filename); - if (!(from = fdopen(ffd, "r"))) - pw_error(mpwd, 1, 1); - if (!(to = fdopen(tfd, "w"))) - pw_error(mpwdl, 1, 1); + if (!(from = fdopen(ffd, "r"))) { + snprintf(errbuf, errbufsz, "%s: %s", mpwd, strerror(errno)); + return (0); + } + if (!(to = fdopen(tfd, "w"))) { + snprintf(errbuf, errbufsz, "%s: %s", mpwdl, strerror(errno)); + return (0); + } for (done = 0; fgets(buf, sizeof(buf), from);) { if (!strchr(buf, '\n')) { - warnx("%s: line too long", mpwd); - pw_error(NULL, 0, 1); + snprintf(errbuf, errbufsz, "%s: line too long", mpwd); + return (0); } if (done) { (void)fprintf(to, "%s", buf); - if (ferror(to)) - goto err; + if (ferror(to)) { + snprintf(errbuf, errbufsz, "%s", + strerror(errno)); + return (0); + } continue; } if (!(p = strchr(buf, ':'))) { - warnx("%s: corrupted entry", mpwd); - pw_error(NULL, 0, 1); + snprintf(errbuf, errbufsz, "%s: corrupted entry", mpwd); + return (0); } *p = '\0'; if (strcmp(buf, pw->pw_name)) { *p = ':'; (void)fprintf(to, "%s", buf); - if (ferror(to)) - goto err; + if (ferror(to)) { + snprintf(errbuf, errbufsz, "%s", + strerror(errno)); + return (0); + } continue; } *p = ':'; if (old_pw && !pw_equal(buf, old_pw)) { - warnx("%s: entry inconsistent", mpwd); - pw_error(NULL, 0, 1); + snprintf(errbuf, errbufsz, "%s: entry inconsistent", + mpwd); + return (0); } (void)fprintf(to, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class, (long)pw->pw_change, (long)pw->pw_expire, pw->pw_gecos, pw->pw_dir, pw->pw_shell); done = 1; - if (ferror(to)) - goto err; + if (ferror(to)) { + snprintf(errbuf, errbufsz, "%s", strerror(errno)); + return (0); + } } /* Only append a new entry if real uid is root! */ if (!done) { - if (getuid() == 0) + if (getuid() == 0) { (void)fprintf(to, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class, (long)pw->pw_change, (long)pw->pw_expire, pw->pw_gecos, pw->pw_dir, pw->pw_shell); - else - warnx("%s: changes not made, no such entry", mpwd); + done = 1; + } else { + snprintf(errbuf, errbufsz, + "%s: changes not made, no such entry", mpwd); + } } - if (ferror(to)) -err: pw_error(NULL, 1, 1); + if (ferror(to)) { + snprintf(errbuf, errbufsz, "%s", strerror(errno)); + return (0); + } (void)fclose(to); + + return (done); } void diff --git a/lib/libutil/pw_init.3 b/lib/libutil/pw_init.3 index f14561cf915f..a0bdb9b08c2d 100644 --- a/lib/libutil/pw_init.3 +++ b/lib/libutil/pw_init.3 @@ -1,4 +1,4 @@ -.\" $NetBSD: pw_init.3,v 1.12 2003/08/07 16:45:00 agc Exp $ +.\" $NetBSD: pw_init.3,v 1.13 2004/08/03 23:29:05 thorpej Exp $ .\" .\" Copyright (c) 1995 .\" The Regents of the University of California. All rights reserved. @@ -31,7 +31,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd December 15, 1995 +.Dd August 1, 2004 .Dt PW_INIT 3 .Os .Sh NAME @@ -39,6 +39,7 @@ .Nm pw_edit , .Nm pw_prompt , .Nm pw_copy , +.Nm pw_copyx , .Nm pw_scan , .Nm pw_error .Nd utility functions for interactive passwd file updates @@ -56,6 +57,9 @@ .Ft void .Fn pw_copy "int ffd" "int tfd" "struct passwd *pw" "struct passwd *old_pw" .Ft int +.Fn pw_copyx "int ffd" "int tfd" "struct passwd *pw" "struct passwd *old_pw" \ + "char *errbuf" "size_t errbufsz" +.Ft int .Fn pw_scan "char *bp" "struct passwd *pw" "int *flags" .Ft void .Fn pw_error "const char *name" "int err" "int eval" @@ -115,7 +119,24 @@ or the process is aborted. If an entry is not found to match .Fa pw , a new entry is appended to the passwd file only if the real user -ID is 0. +ID is 0. If an error occurs, +.Fn pw_copy +will display a message on +.Dv stderr +and call +.Fn pw_error . +.Pp +The +.Fn pw_copyx +function performs the same operation as +.Fn pw_copy +with the exception of error handling. +Upon an error, +.Fn pw_copyx +will write an error message into the buffer pointed to by +.Fa errbuf +which has the size +.Fa errbufsz . .Pp The .Fn pw_scan @@ -182,6 +203,11 @@ The process exits with status .Fa eval . .Sh RETURN VALUES The +.Fn pw_copyx +function returns 1 if the new password entry was successfully written +to the destination file, and 0 otherwise. +.Pp +The .Fn pw_scan function prints a warning message and returns 0 if the string in the .Fa bp diff --git a/lib/libutil/shlib_version b/lib/libutil/shlib_version index 6cdc10c3cf43..2e0489fb5f46 100644 --- a/lib/libutil/shlib_version +++ b/lib/libutil/shlib_version @@ -1,5 +1,5 @@ -# $NetBSD: shlib_version,v 1.33 2003/04/11 17:37:28 christos Exp $ +# $NetBSD: shlib_version,v 1.34 2004/08/03 23:29:05 thorpej Exp $ # Remember to update distrib/sets/lists/base/shl.* when changing # major=7 -minor=3 +minor=4