From a11ca3cb1bd8499a67a77c9f83ee3a57e7388374 Mon Sep 17 00:00:00 2001 From: Love Hornquist Astrand Date: Mon, 12 Dec 2011 21:55:06 -0800 Subject: [PATCH] add rk_getpwnam_r --- lib/roken/Makefile.am | 5 ++ lib/roken/getxxyyy.c | 131 ++++++++++++++++++++++++++++++++++++++++++ lib/roken/roken.h.in | 7 +++ 3 files changed, 143 insertions(+) create mode 100644 lib/roken/getxxyyy.c diff --git a/lib/roken/Makefile.am b/lib/roken/Makefile.am index e72328810..2d4a90844 100644 --- a/lib/roken/Makefile.am +++ b/lib/roken/Makefile.am @@ -26,6 +26,7 @@ check_PROGRAMS = \ base64-test \ getaddrinfo-test \ getifaddrs-test \ + getxxyyy-test \ hex-test \ test-readenv \ parse_bytes-test \ @@ -63,6 +64,9 @@ tsearch_test_SOURCES = tsearch-test.c tsearch_test_LDADD = libtest.la $(LDADD) tsearch_test_CFLAGS = -DTEST_TSEARCH +getxxyyy_test_SOURCES = getxxyyy.c +getxxyyy_test_CFLAGS = -DTEST_GETXXYYY + resolve_test_SOURCES = resolve-test.c libroken_la_SOURCES = \ @@ -83,6 +87,7 @@ libroken_la_SOURCES = \ getarg.c \ getnameinfo_verified.c \ getprogname.c \ + getxxyyy.c \ h_errno.c \ hex.c \ hostent_find_fqdn.c \ diff --git a/lib/roken/getxxyyy.c b/lib/roken/getxxyyy.c new file mode 100644 index 000000000..267dec140 --- /dev/null +++ b/lib/roken/getxxyyy.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2011 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "roken.h" + +#ifdef TEST_GETXXYYY +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_getpwnam_r(const char *, struct passwd *, char *, size_t, struct passwd **); +#endif + + +#if !defined(POSIX_GETPWNAM_R) || defined(TEST_GETXXYYY) + +/* + * At least limit the race between threads + */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_getpwnam_r(const char *name, struct passwd *pwd, char *buffer, + size_t bufsize, struct passwd **result) +{ + struct passwd *p; + size_t slen, n = 0; + + *result = NULL; + + p = getpwnam(name); + if(p == NULL) + return (errno = ENOENT); + + memset(pwd, 0, sizeof(*pwd)); + +#define APPEND(el) \ +do { \ + slen = strlen(p->el) + 1; \ + if (slen > bufsize) return (errno = ENOMEM); \ + memcpy(buffer, p->el, slen); \ + pwd->el = buffer; \ + buffer += slen; \ + bufsize -= slen; \ +} while(0) + + APPEND(pw_name); + if (p->pw_passwd) + APPEND(pw_name); + pwd->pw_uid = p->pw_uid; + pwd->pw_gid = p->pw_gid; + APPEND(pw_gecos); + APPEND(pw_dir); + APPEND(pw_shell); + + *result = pwd; + + return 0; +} + +#endif /* POSIX_GETPWNAM_R */ + +#ifdef TEST_GETXXYYY + +#include + +int verbose_flag = 0; + +static void +print_result(struct passwd *p) +{ + if (!verbose_flag) + return; + printf("%s\n", p->pw_name); + printf("%d\n", (int)p->pw_uid); + printf("%s\n", p->pw_shell); + printf("%s\n", p->pw_dir); +} + +int +main(int argc, char **argv) +{ + struct passwd pwd, *result; + char buf[1024]; + int ret; + + ret = rk_getpwnam_r(getenv("USER"), &pwd, buf, sizeof(buf), &result); + if (ret) + errx(1, "rk_getpwnam_r"); + print_result(result); + + ret = rk_getpwnam_r(getenv("USER"), &pwd, buf, 1, &result); + if (ret == 0) + errx(1, "rk_getpwnam_r too small buf"); + + ret = rk_getpwnam_r("no-user-here-promise", &pwd, buf, sizeof(buf), &result); + if (ret == 0) + errx(1, "rk_getpwnam_r no user"); + + return 0; +} + +#endif diff --git a/lib/roken/roken.h.in b/lib/roken/roken.h.in index ab8c8741a..a101f66c2 100644 --- a/lib/roken/roken.h.in +++ b/lib/roken/roken.h.in @@ -601,6 +601,13 @@ ROKEN_LIB_FUNCTION struct passwd * ROKEN_LIB_CALL k_getpwnam (const char *); ROKEN_LIB_FUNCTION struct passwd * ROKEN_LIB_CALL k_getpwuid (uid_t); #endif +#ifdef POSIX_GETPWNAM_R +#define rk_getpwnam_r(_n, _pw, _b, _sz, _pwd) getpwnam_r(_n, _pw, _b, _sz, _pwd) +#else +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_getpwnam_r(const char *, struct passwd *, char *, size_t, struct passwd **); +#endif + ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL get_default_username (void); #ifndef HAVE_SETEUID