Browse Source

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

Eric Andersen 24 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=../../../
 TOPDIR=../../../
 include $(TOPDIR)Rules.mak
 include $(TOPDIR)Rules.mak
 
 
-CSRC=utent.c
+CSRC=utent.c wtent.c
 COBJS=$(patsubst %.c,%.o, $(CSRC))
 COBJS=$(patsubst %.c,%.o, $(CSRC))
 OBJS=$(COBJS)
 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
    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
    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 <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <fcntl.h>
 #include <paths.h>
 #include <paths.h>
@@ -15,132 +20,187 @@
 #include <string.h>
 #include <string.h>
 #include <utmp.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)
 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)
 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)
 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;
 	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
 #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 <string.h>
 #include <sys/time.h>
 #include <sys/time.h>
 #include <time.h>
 #include <time.h>
 #include <unistd.h>
 #include <unistd.h>
-#include <fcntl.h>
 #include <utmp.h>
 #include <utmp.h>
+#include <fcntl.h>
+#include <sys/file.h>
 
 
 
 
 void logwtmp (const char *line, const char *name, const char *host)
 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