diff options
-rw-r--r-- | include/pwd.h | 28 | ||||
-rw-r--r-- | libc/pwd_grp/Makefile | 5 | ||||
-rw-r--r-- | libc/pwd_grp/__getpwent_r.c | 112 | ||||
-rw-r--r-- | libc/pwd_grp/fgetpwent.c | 20 | ||||
-rw-r--r-- | libc/pwd_grp/getpwnam.c | 32 | ||||
-rw-r--r-- | libc/pwd_grp/getpwuid.c | 30 | ||||
-rw-r--r-- | libc/pwd_grp/pwent.c | 21 |
7 files changed, 221 insertions, 27 deletions
diff --git a/include/pwd.h b/include/pwd.h index 1b48c6a6e..6cadcf38a 100644 --- a/include/pwd.h +++ b/include/pwd.h @@ -22,18 +22,38 @@ extern void setpwent __P ((void)); extern void endpwent __P ((void)); extern struct passwd * getpwent __P ((void)); -extern int putpwent __P ((__const struct passwd * __p, FILE * __f)); +extern int putpwent __P ((const struct passwd * __p, FILE * __f)); extern int getpw __P ((uid_t uid, char *buf)); extern struct passwd * fgetpwent __P ((FILE * file)); -extern struct passwd * getpwuid __P ((__const uid_t)); -extern struct passwd * getpwnam __P ((__const char *)); +extern struct passwd * getpwuid __P ((const uid_t)); +extern struct passwd * getpwnam __P ((const char *)); + + +extern int getpwent_r __P ((struct passwd *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct passwd **__restrict __result)); +extern int getpwuid_r __P ((uid_t __uid, + struct passwd *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct passwd **__restrict __result)); +extern int getpwnam_r __P ((const char *__restrict __name, + struct passwd *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct passwd **__restrict __result)); +extern int fgetpwent_r __P ((FILE *__restrict __stream, + struct passwd *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct passwd **__restrict __result)); #ifdef __LIBC__ -extern struct passwd * __getpwent __P ((__const int passwd_fd)); +/* This is used internally to uClibc */ +extern int __getpwent_r(struct passwd * passwd, char * line_buff, + size_t buflen, int pwd_fd); #endif + #endif /* pwd.h */ diff --git a/libc/pwd_grp/Makefile b/libc/pwd_grp/Makefile index bdd3c9782..d37efbdf3 100644 --- a/libc/pwd_grp/Makefile +++ b/libc/pwd_grp/Makefile @@ -24,8 +24,9 @@ TOPDIR=../ include $(TOPDIR)Rules.mak LIBC=$(TOPDIR)libc.a -CSRC=__getpwent.c pwent.c getpwnam.c getpwuid.c putpwent.c getpw.c fgetpwent.c \ - __getgrent.c grent.c getgrnam.c getgrgid.c fgetgrent.c initgroups.c +CSRC= pwent.c getpwnam.c getpwuid.c putpwent.c getpw.c fgetpwent.c \ + __getgrent.c grent.c getgrnam.c getgrgid.c fgetgrent.c \ + initgroups.c __getpwent_r.c COBJS=$(patsubst %.c,%.o, $(CSRC)) OBJS=$(COBJS) diff --git a/libc/pwd_grp/__getpwent_r.c b/libc/pwd_grp/__getpwent_r.c new file mode 100644 index 000000000..aa2b990a4 --- /dev/null +++ b/libc/pwd_grp/__getpwent_r.c @@ -0,0 +1,112 @@ +/* + * __getpwent_r.c - This file is part of the libc-8086/pwd package for ELKS, + * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>. + * Copyright (C) 2001 Erik Andersen <andersee@debian.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * March 7, 2001 -- Reworked to be reentrant by Erik Andersen + */ + +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <pwd.h> + + +/* This isn't as flash as my previous version -- it doesn't dynamically + scale down the gecos on too-long lines, but it also makes fewer syscalls, + so it's probably nicer. Write me if you want the old version. Maybe I + should include it as a build-time option... ? + -Nat <ndf@linux.mit.edu> */ + +int __getpwent_r(struct passwd * passwd, char * line_buff, size_t buflen, int pwd_fd) +{ + char *field_begin; + char *endptr; + char *gid_ptr=NULL; + char *uid_ptr=NULL; + int line_len; + int i; + + /* We use the restart label to handle malformatted lines */ + restart: + /* Read the passwd line into the static buffer using a minimal of + syscalls. */ + if ((line_len = read(pwd_fd, line_buff, buflen)) <= 0) + return -1; + field_begin = strchr(line_buff, '\n'); + if (field_begin != NULL) + lseek(pwd_fd, (long) (1 + field_begin - (line_buff + line_len)), + SEEK_CUR); + else { /* The line is too long - skip it. :-\ */ + + do { + if ((line_len = read(pwd_fd, line_buff, buflen)) <= 0) + return -1; + } while (!(field_begin = strchr(line_buff, '\n'))); + lseek(pwd_fd, (long) (field_begin - line_buff) - line_len + 1, + SEEK_CUR); + goto restart; + } + if (*line_buff == '#' || *line_buff == ' ' || *line_buff == '\n' || + *line_buff == '\t') + goto restart; + *field_begin = '\0'; + + /* We've read the line; now parse it. */ + field_begin = line_buff; + for (i = 0; i < 7; i++) { + switch (i) { + case 0: + passwd->pw_name = field_begin; + break; + case 1: + passwd->pw_passwd = field_begin; + break; + case 2: + uid_ptr = field_begin; + break; + case 3: + gid_ptr = field_begin; + break; + case 4: + passwd->pw_gecos = field_begin; + break; + case 5: + passwd->pw_dir = field_begin; + break; + case 6: + passwd->pw_shell = field_begin; + break; + } + if (i < 6) { + field_begin = strchr(field_begin, ':'); + if (field_begin == NULL) + goto restart; + *field_begin++ = '\0'; + } + } + passwd->pw_gid = (gid_t) strtoul(gid_ptr, &endptr, 10); + if (*endptr != '\0') + goto restart; + + passwd->pw_uid = (uid_t) strtoul(uid_ptr, &endptr, 10); + if (*endptr != '\0') + goto restart; + + return 0; +} diff --git a/libc/pwd_grp/fgetpwent.c b/libc/pwd_grp/fgetpwent.c index cd8742d80..74c59427c 100644 --- a/libc/pwd_grp/fgetpwent.c +++ b/libc/pwd_grp/fgetpwent.c @@ -22,12 +22,26 @@ #include <stdio.h> #include <pwd.h> -struct passwd *fgetpwent(FILE * file) +#define PWD_BUFFER_SIZE 256 + +/* file descriptor for the password file currently open */ +static char line_buff[PWD_BUFFER_SIZE]; +static struct passwd pwd; + +int fgetpwent_r (FILE *file, struct passwd *password, + char *buff, size_t buflen, struct passwd **crap) { if (file == NULL) { errno = EINTR; - return NULL; + return -1; } + return(__getpwent_r(password, buff, buflen, fileno(file))); +} - return __getpwent(fileno(file)); +struct passwd *fgetpwent(FILE * file) +{ + if (fgetpwent_r(file, &pwd, line_buff, PWD_BUFFER_SIZE, NULL) != -1) { + return &pwd; + } + return NULL; } diff --git a/libc/pwd_grp/getpwnam.c b/libc/pwd_grp/getpwnam.c index 63671927b..399e24ddc 100644 --- a/libc/pwd_grp/getpwnam.c +++ b/libc/pwd_grp/getpwnam.c @@ -25,25 +25,41 @@ #include <pwd.h> -struct passwd *getpwnam(const char *name) +#define PWD_BUFFER_SIZE 256 + +/* file descriptor for the password file currently open */ +static char line_buff[PWD_BUFFER_SIZE]; +static struct passwd pwd; + + +int getpwnam_r (const char *name, struct passwd *password, + char *buff, size_t buflen, struct passwd **crap) { int passwd_fd; - struct passwd *passwd; if (name == NULL) { errno = EINVAL; - return NULL; + return -1; } if ((passwd_fd = open("/etc/passwd", O_RDONLY)) < 0) - return NULL; + return -1; - while ((passwd = __getpwent(passwd_fd)) != NULL) - if (!strcmp(passwd->pw_name, name)) { + while (__getpwent_r(password, buff, buflen, passwd_fd) != -1) + if (!strcmp(password->pw_name, name)) { close(passwd_fd); - return passwd; + return 0; } close(passwd_fd); - return NULL; + return -1; } + +struct passwd *getpwnam(const char *name) +{ + if (getpwnam_r(name, &pwd, line_buff, PWD_BUFFER_SIZE, NULL) != -1) { + return &pwd; + } + return NULL; +} + diff --git a/libc/pwd_grp/getpwuid.c b/libc/pwd_grp/getpwuid.c index 1cd0d691c..307f840e1 100644 --- a/libc/pwd_grp/getpwuid.c +++ b/libc/pwd_grp/getpwuid.c @@ -23,20 +23,36 @@ #include <fcntl.h> #include <pwd.h> -struct passwd *getpwuid(uid_t uid) + +#define PWD_BUFFER_SIZE 256 + +/* file descriptor for the password file currently open */ +static char line_buff[PWD_BUFFER_SIZE]; +static struct passwd pwd; + +int getpwuid_r (uid_t uid, struct passwd *password, + char *buff, size_t buflen, struct passwd **crap) { int passwd_fd; - struct passwd *passwd; if ((passwd_fd = open("/etc/passwd", O_RDONLY)) < 0) - return NULL; + return -1; - while ((passwd = __getpwent(passwd_fd)) != NULL) - if (passwd->pw_uid == uid) { + while (__getpwent_r(password, buff, buflen, passwd_fd) != -1) + if (password->pw_uid == uid) { close(passwd_fd); - return passwd; + return 0; } close(passwd_fd); - return NULL; + return -1; } + +struct passwd *getpwuid(uid_t uid) +{ + if (getpwuid_r(uid, &pwd, line_buff, PWD_BUFFER_SIZE, NULL) != -1) { + return &pwd; + } + return NULL; +} + diff --git a/libc/pwd_grp/pwent.c b/libc/pwd_grp/pwent.c index 475c8e560..6f81f1ea6 100644 --- a/libc/pwd_grp/pwent.c +++ b/libc/pwd_grp/pwent.c @@ -30,8 +30,12 @@ * link them all in together. */ +#define PWD_BUFFER_SIZE 256 + /* file descriptor for the password file currently open */ static int pw_fd = -1; +static char line_buff[PWD_BUFFER_SIZE]; +static struct passwd pwd; void setpwent(void) { @@ -48,9 +52,20 @@ void endpwent(void) pw_fd = -1; } +int getpwent_r (struct passwd *password, char *buff, + size_t buflen, struct passwd **crap) +{ + if (pw_fd != -1 && __getpwent_r(password, buff, buflen, pw_fd) != -1) { + return 0; + } + return -1; +} + struct passwd *getpwent(void) { - if (pw_fd != -1) - return (__getpwent(pw_fd)); - return NULL; + if (getpwent_r(&pwd, line_buff, PWD_BUFFER_SIZE, NULL) != -1) { + return &pwd; + } + return NULL; } + |