From d83aa1f777ba3bacaa5ab65a508ff7d11756c95a Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Mon, 17 Jun 2002 18:58:58 +0000 Subject: Some cleanups so utmp/wtmp behaves. Fix potential use of uninitialized memory. Prepare to reentrantify the utmp stuff. -Erik --- libc/misc/utmp/Makefile | 2 +- libc/misc/utmp/utent.c | 238 ++++++++++++++++++++++++++++++------------------ libc/misc/utmp/wtent.c | 60 ++++++++++++ 3 files changed, 210 insertions(+), 90 deletions(-) create mode 100644 libc/misc/utmp/wtent.c (limited to 'libc/misc') diff --git a/libc/misc/utmp/Makefile b/libc/misc/utmp/Makefile index 7a68f1175..1a50070db 100644 --- a/libc/misc/utmp/Makefile +++ b/libc/misc/utmp/Makefile @@ -24,7 +24,7 @@ TOPDIR=../../../ include $(TOPDIR)Rules.mak -CSRC=utent.c +CSRC=utent.c wtent.c COBJS=$(patsubst %.c,%.o, $(CSRC)) OBJS=$(COBJS) diff --git a/libc/misc/utmp/utent.c b/libc/misc/utmp/utent.c index cc092a996..3833742cc 100644 --- a/libc/misc/utmp/utent.c +++ b/libc/misc/utmp/utent.c @@ -5,9 +5,14 @@ Note that because of the way this stupid stupid standard works, you have to call endutent() to close the file even if you've not called - setutent -- getutid and family use the same file descriptor. */ + setutent -- getutid and family use the same file descriptor. + Modified by Erik Andersen for uClibc... +*/ + +#include #include +#include #include #include #include @@ -15,132 +20,187 @@ #include #include -static const char *ut_name = _PATH_UTMP; -static int ut_fd = -1; -struct utmp *__getutent(int utmp_fd) +#ifdef __UCLIBC_HAS_THREADS__ +#include +static pthread_mutex_t utmplock = PTHREAD_MUTEX_INITIALIZER; +# define LOCK pthread_mutex_lock(&utmplock) +# define UNLOCK pthread_mutex_unlock(&utmplock); +#else +# define LOCK +# define UNLOCK +#endif + + + +/* Some global crap */ +static int static_fd = -1; +static struct utmp static_utmp; +static const char default_file_name[] = _PATH_UTMP; +static const char *static_ut_name = (const char *) default_file_name; + + + +static struct utmp *__getutent(int utmp_fd) + { - static struct utmp utmp; - if (read(utmp_fd, (char *) &utmp, sizeof(struct utmp)) != - sizeof(struct utmp)) return NULL; + if (utmp_fd == -1) { + setutent(); + } + if (utmp_fd == -1) { + return NULL; + } - return &utmp; + LOCK; + if (read(utmp_fd, (char *) &static_utmp, sizeof(struct utmp)) != sizeof(struct utmp)) + { + return NULL; + } + + UNLOCK; + return &static_utmp; } void setutent(void) { - if (ut_fd != -1) - close(ut_fd); - if ((ut_fd = open(ut_name, O_RDWR)) < 0) { - ut_fd = -1; + int ret; + + LOCK; + if (static_fd == -1) { + if ((static_fd = open(static_ut_name, O_RDWR)) < 0) { + if ((static_fd = open(static_ut_name, O_RDONLY)) < 0) { + goto bummer; + } + } + /* Make sure the file will be closed on exec() */ + ret = fcntl(static_fd, F_GETFD, 0); + if (ret >= 0) { + ret = fcntl(static_fd, F_GETFD, 0); } + if (ret < 0) { +bummer: + UNLOCK; + static_fd = -1; + close(static_fd); + return; + } + } + lseek(static_fd, 0, SEEK_SET); + UNLOCK; + return; } void endutent(void) { - if (ut_fd != -1) - close(ut_fd); - ut_fd = -1; + LOCK; + if (static_fd != -1) { + close(static_fd); + } + static_fd = -1; + UNLOCK; } +/* Locking is done in __getutent */ struct utmp *getutent(void) { - if (ut_fd == -1) - setutent(); - if (ut_fd == -1) - return NULL; - return __getutent(ut_fd); + return __getutent(static_fd); } -struct utmp *getutid (const struct utmp *utmp_entry) +#if 0 +struct utmp * getutent(void) { - struct utmp *utmp; - - if (ut_fd == -1) - setutent(); - if (ut_fd == -1) - return NULL; - - while ((utmp = __getutent(ut_fd)) != NULL) { - if ((utmp_entry->ut_type == RUN_LVL || - utmp_entry->ut_type == BOOT_TIME || - utmp_entry->ut_type == NEW_TIME || - utmp_entry->ut_type == OLD_TIME) && - utmp->ut_type == utmp_entry->ut_type) return utmp; - if ((utmp_entry->ut_type == INIT_PROCESS || - utmp_entry->ut_type == DEAD_PROCESS || - utmp_entry->ut_type == LOGIN_PROCESS || - utmp_entry->ut_type == USER_PROCESS) && - !strcmp(utmp->ut_id, utmp_entry->ut_id)) return utmp; - } + struct utmp *result; + static struct utmp buffer; + if (getutent_r(&buffer, &result) < 0) return NULL; -} -struct utmp *getutline(const struct utmp *utmp_entry) -{ - struct utmp *utmp; - - if (ut_fd == -1) - setutent(); - if (ut_fd == -1) - return NULL; - -#if 0 - /* This is driving me nuts. It's not an implementation problem - - it's a matter of how things _SHOULD_ behave. Groan. */ - lseek(ut_fd, SEEK_CUR, -sizeof(struct utmp)); + return result; +} #endif - while ((utmp = __getutent(ut_fd)) != NULL) { - if ((utmp->ut_type == USER_PROCESS || - utmp->ut_type == LOGIN_PROCESS) && - !strcmp(utmp->ut_line, utmp_entry->ut_line)) return utmp; +/* Locking is done in __getutent */ +struct utmp *getutid (const struct utmp *utmp_entry) +{ + struct utmp *lutmp; + + while ((lutmp = __getutent(static_fd)) != NULL) { + if ( (utmp_entry->ut_type == RUN_LVL || + utmp_entry->ut_type == BOOT_TIME || + utmp_entry->ut_type == NEW_TIME || + utmp_entry->ut_type == OLD_TIME) && + lutmp->ut_type == utmp_entry->ut_type) + { + return lutmp; } + if ( (utmp_entry->ut_type == INIT_PROCESS || + utmp_entry->ut_type == DEAD_PROCESS || + utmp_entry->ut_type == LOGIN_PROCESS || + utmp_entry->ut_type == USER_PROCESS) && + !strcmp(lutmp->ut_id, utmp_entry->ut_id)) + { + return lutmp; + } + } - return NULL; + return NULL; } -struct utmp *pututline (const struct utmp *utmp_entry) +/* Locking is done in __getutent */ +struct utmp *getutline(const struct utmp *utmp_entry) { - struct utmp *ut; - - /* Ignore the return value. That way, if they've already positioned - the file pointer where they want it, everything will work out. */ - (void) lseek(ut_fd, (off_t) - sizeof(struct utmp), SEEK_CUR); - - if ((ut = getutid(utmp_entry)) != NULL) { - lseek(ut_fd, (off_t) - sizeof(struct utmp), SEEK_CUR); - if (write(ut_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) - return NULL; - } else { - lseek(ut_fd, (off_t) 0, SEEK_END); - if (write(ut_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) - return NULL; + struct utmp *lutmp; + + while ((lutmp = __getutent(static_fd)) != NULL) { + if ((lutmp->ut_type == USER_PROCESS || lutmp->ut_type == LOGIN_PROCESS) && + !strcmp(lutmp->ut_line, utmp_entry->ut_line)) + { + return lutmp; } + } - return (struct utmp *)utmp_entry; + return NULL; } -int utmpname (const char *new_ut_name) +struct utmp *pututline (const struct utmp *utmp_entry) { - if (new_ut_name != NULL) - ut_name = new_ut_name; - - if (ut_fd != -1) - close(ut_fd); - return 0; + LOCK; + /* Ignore the return value. That way, if they've already positioned + the file pointer where they want it, everything will work out. */ + lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR); + + if (getutid(utmp_entry) != NULL) { + lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR); + if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) + return NULL; + } else { + lseek(static_fd, (off_t) 0, SEEK_END); + if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) + return NULL; + } + + UNLOCK; + return (struct utmp *)utmp_entry; } -extern void updwtmp(const char *wtmp_file, const struct utmp *ut) +int utmpname (const char *new_ut_name) { - int fd; - - fd = open(wtmp_file, O_APPEND | O_WRONLY, 0); - if (fd >= 0) { - write(fd, (const char *) ut, sizeof(*ut)); - close(fd); + LOCK; + if (new_ut_name != NULL) { + if (static_ut_name != default_file_name) + free((char *)static_ut_name); + static_ut_name = strdup(new_ut_name); + if (static_ut_name == NULL) { + /* We should probably whine about out-of-memory + * errors here... Instead just reset to the default */ + static_ut_name = default_file_name; } + } + + if (static_fd != -1) + close(static_fd); + UNLOCK; + return 0; } diff --git a/libc/misc/utmp/wtent.c b/libc/misc/utmp/wtent.c new file mode 100644 index 000000000..ef5663feb --- /dev/null +++ b/libc/misc/utmp/wtent.c @@ -0,0 +1,60 @@ +/* wtmp support rubbish (i.e. complete crap) + * + * Written by Erik Andersen + * + * 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; see the file COPYING.LIB. If not, + * write to the Free Software Foundation, Inc., 675 Mass Ave, + * Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include +#include +#include + + +#if 0 +/* This is enabled in uClibc/libutil/logwtmp.c */ +void logwtmp (const char *line, const char *name, const char *host) +{ + struct utmp lutmp; + memset (&(lutmp), 0, sizeof (struct utmp)); + + lutmp.ut_type = (name && *name)? USER_PROCESS : DEAD_PROCESS; + lutmp.ut_pid = getpid(); + strncpy(lutmp.ut_line, line, sizeof(lutmp.ut_line)-1); + strncpy(lutmp.ut_name, name, sizeof(lutmp.ut_name)-1); + strncpy(lutmp.ut_host, host, sizeof(lutmp.ut_host)-1); + gettimeofday(&(lutmp.ut_tv), NULL); + + updwtmp(_PATH_WTMP, &(lutmp)); +} +#endif + +extern void updwtmp(const char *wtmp_file, const struct utmp *lutmp) +{ + int fd; + + fd = open(wtmp_file, O_APPEND | O_WRONLY, 0); + if (fd >= 0) { + if (lockf(fd, F_LOCK, 0)==0) { + write(fd, (const char *) lutmp, sizeof(struct utmp)); + lockf(fd, F_ULOCK, 0); + close(fd); + } + } +} + -- cgit v1.2.3