summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
Diffstat (limited to 'libc')
-rw-r--r--libc/misc/utmp/Makefile2
-rw-r--r--libc/misc/utmp/utent.c238
-rw-r--r--libc/misc/utmp/wtent.c60
3 files changed, 210 insertions, 90 deletions
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 <features.h>
#include <stdio.h>
+#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <paths.h>
@@ -15,132 +20,187 @@
#include <string.h>
#include <utmp.h>
-static const char *ut_name = _PATH_UTMP;
-static int ut_fd = -1;
-struct utmp *__getutent(int utmp_fd)
+#ifdef __UCLIBC_HAS_THREADS__
+#include <pthread.h>
+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 <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; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 675 Mass Ave,
+ * Cambridge, MA 02139, USA. */
+
+#include <string.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+#include <utmp.h>
+#include <fcntl.h>
+#include <sys/file.h>
+
+
+#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);
+ }
+ }
+}
+