Browse Source

Some cleanups so utmp/wtmp behaves. Fix potential use of
uninitialized memory. Prepare to reentrantify the utmp
stuff.
-Erik

Eric Andersen 22 years ago
parent
commit
d83aa1f777
4 changed files with 254 additions and 148 deletions
  1. 1 1
      libc/misc/utmp/Makefile
  2. 149 89
      libc/misc/utmp/utent.c
  3. 60 0
      libc/misc/utmp/wtent.c
  4. 44 58
      libutil/logwtmp.c

+ 1 - 1
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)
 

+ 149 - 89
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;
 }
 

+ 60 - 0
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);
+	}
+    }
+}
+

+ 44 - 58
libutil/logwtmp.c

@@ -1,73 +1,59 @@
-/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
-
-   The GNU C 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.
-
-   The GNU C 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 the GNU C Library; see the file COPYING.LIB.  If not,
-   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+/* 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 <fcntl.h>
 #include <utmp.h>
+#include <fcntl.h>
+#include <sys/file.h>
 
 
 void logwtmp (const char *line, const char *name, const char *host)
 {
-  struct utmp ut;
-  struct flock lock;
-  int ut_fd;
-
-
-  /* Set information in new entry.  */
-  memset (&ut, 0, sizeof (ut));
-#if _HAVE_UT_PID - 0
-  ut.ut_pid = getpid ();
-#endif
-#if _HAVE_UT_TYPE - 0
-  ut.ut_type = name[0] ? USER_PROCESS : DEAD_PROCESS;
-#endif
-  strncpy (ut.ut_line, line, sizeof ut.ut_line);
-  strncpy (ut.ut_name, name, sizeof ut.ut_name);
-#if _HAVE_UT_HOST - 0
-  strncpy (ut.ut_host, host, sizeof ut.ut_host);
-#endif
+    struct utmp lutmp;
+    memset (&(lutmp), 0, sizeof (struct utmp));
 
-#if _HAVE_UT_TV - 0
-  gettimeofday (&ut.ut_tv, NULL);
-#else
-  time (&ut.ut_time);
-#endif
+    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, &ut); */
-/* from tinylogin */
+    updwtmp(_PATH_WTMP, &(lutmp));
+}
 
-	if ((ut_fd = open(_PATH_WTMP, O_APPEND | O_WRONLY)) >= 0) {
-		/* Lock the utmp file before updating */
-		lock.l_type = F_WRLCK;
-		lock.l_whence = SEEK_SET;
-		lock.l_start = 0;
-		lock.l_len = 0;
-		if (fcntl(ut_fd, F_SETLK, &lock) >= 0) {
-			write(ut_fd, (void *) &ut, sizeof(ut));
-			/* Now unlock the utmp file */
-			lock.l_type = F_UNLCK;
-		}
-		close(ut_fd);
+#if 0
+/* This is enabled in uClibc/libc/misc/utmp/wtent.c */
+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);
 	}
-
-
+    }
 }
+#endif