update from main archive 961126
authordrepper <drepper>
Wed, 27 Nov 1996 06:07:48 +0000 (06:07 +0000)
committerdrepper <drepper>
Wed, 27 Nov 1996 06:07:48 +0000 (06:07 +0000)
17 files changed:
libio/libio.h
libio/strfile.h
libio/strops.c
login/Makefile
login/getutent.c
login/getutent_r.c
login/getutid.c
login/getutid_r.c
login/getutline.c
login/getutline_r.c
login/login.c
login/logout.c
login/logwtmp.c
login/utmp-private.h [new file with mode: 0644]
login/utmp.h
login/utmp_db.c [new file with mode: 0644]
login/utmp_file.c [new file with mode: 0644]

index 0cd6b39..7dd47db 100644 (file)
@@ -303,6 +303,9 @@ extern int _IO_vfprintf __P((_IO_FILE*, const char*, _IO_va_list));
 extern _IO_ssize_t _IO_padn __P((_IO_FILE *, int, _IO_ssize_t));
 extern _IO_size_t _IO_sgetn __P((_IO_FILE *, void*, _IO_size_t));
 
+extern _IO_fpos_t _IO_seekoff __P((_IO_FILE*, _IO_off_t, int, int));
+extern _IO_fpos_t _IO_seekpos __P((_IO_FILE*, _IO_fpos_t, int));
+
 extern void _IO_free_backup_area __P((_IO_FILE*));
 
 #ifdef __cplusplus
index 55783bb..4934a06 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
 Copyright (C) 1993 Free Software Foundation
 
 This file is part of the GNU IO Library.  This library is free
@@ -32,8 +32,6 @@ typedef void (*_IO_free_type) __P((void*));
 
 struct _IO_str_fields
 {
-  /* The current length is max(_len, _IO_write_ptr-_IO_write_base). */
-  _IO_size_t _len;
   _IO_alloc_type _allocate_buffer;
   _IO_free_type _free_buffer;
 };
index 4640633..8a6c56d 100644 (file)
@@ -26,7 +26,31 @@ the executable file might be covered by the GNU General Public License. */
 #include "libioP.h"
 #include <string.h>
 
-#define LEN(fp) (((_IO_strfile*)(fp))->_s._len)
+#if 0
+/* The following definitions are for exposition only.
+   They map the terminlogy used in the ANSI/ISO C++ draft standard
+   to the implementation. */
+
+/* allocated:  set  when a dynamic array object has been allocated, and
+   hence should be freed by the destructor for the strstreambuf object. */
+#define ALLOCATED(FP) ((FP)->_f._IO_buf_base && DYNAMIC(FP))
+
+/* constant:  set when the array object has const elements,
+   so the output sequence cannot be written. */
+#define CONSTANT(FP) ((FP)->_f._IO_file_flags & _IO_NO_WRITES)
+
+/* alsize:  the suggested minimum size for a dynamic array object. */
+#define ALSIZE(FP) ??? /* not stored */
+
+/* palloc: points to the function to call to allocate a dynamic array object.*/
+#define PALLOC(FP) \
+  ((FP)->_s._allocate_buffer == default_alloc ? 0 : (FP)->_s._allocate_buffer)
+
+/* pfree: points  to  the  function  to call to free a dynamic array object. */
+#define PFREE(FP) \
+  ((FP)->_s._free_buffer == default_free ? 0 : (FP)->_s._free_buffer)
+
+#endif
 
 #ifdef TODO
 /* An "unbounded buffer" is when a buffer is supplied, but with no
@@ -44,27 +68,17 @@ DEFUN(_IO_str_init_static, (fp, ptr, size, pstart),
     {
       /* If size is negative 'the characters are assumed to
         continue indefinitely.'  This is kind of messy ... */
-#if 1
       int s;
       size = 512;
-      /* Try increasing powers of 2, as long as we don't wrap around.
-        This can lose in pathological cases (ptr near the end
-        of the address space).  A better solution might be to
-        adjust the size on underflow/overflow.  FIXME. */
-      for ( ; s = 2*size, s > 0 && ptr + s > ptr && s < 0x4000000L; )
+      /* Try increasing powers of 2, as long as we don't wrap around. */
+      for (; s = 2*size, s > 0 && ptr + s > ptr && s < 0x4000000L; )
        size = s;
-      size = s;
-#else
-      /* The following semi-portable kludge assumes that
-        sizeof(unsigned long) == sizeof(char*). Hence,
-        (unsigned long)(-1) should be the largest possible address. */
-      unsigned long highest = (unsigned long)(-1);
-      /* Pointers are signed on some brain-damaged systems, in
-        which case we divide by two to get the maximum signed address. */
-      if  ((char*)highest < ptr)
-       highest >>= 1;
-      size = (char*)highest - ptr;
-#endif
+      /* Try increasing size as much as we can without wrapping around. */
+      for (s = size >> 1; s > 0; s >>= 1)
+       {
+         if (ptr + size + s > ptr)
+           size += s;
+       }
     }
   _IO_setb(fp, ptr, ptr+size, 0);
 
@@ -83,7 +97,6 @@ DEFUN(_IO_str_init_static, (fp, ptr, size, pstart),
       fp->_IO_write_end = ptr;
       fp->_IO_read_end = ptr+size;
     }
-  LEN(fp) = size;
   /* A null _allocate_buffer function flags the strfile as being static. */
   (((_IO_strfile*)(fp))->_s._allocate_buffer) =  (_IO_alloc_type)0;
 }
@@ -101,34 +114,25 @@ DEFUN(_IO_str_overflow, (fp, c),
       register _IO_FILE* fp AND int c)
 {
   int flush_only = c == EOF;
-  _IO_size_t pos = fp->_IO_write_ptr - fp->_IO_write_base;
-  _IO_size_t get_pos = fp->_IO_read_ptr - fp->_IO_read_base;
+  _IO_size_t pos;
   if (fp->_flags & _IO_NO_WRITES)
       return flush_only ? 0 : EOF;
-  if (pos > LEN(fp)) LEN(fp) = pos;
   if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING))
     {
-      pos = get_pos;
       fp->_flags |= _IO_CURRENTLY_PUTTING;
-      get_pos = LEN(fp);
+      fp->_IO_write_ptr = fp->_IO_read_ptr;
+      fp->_IO_read_ptr = fp->_IO_read_end;
     }
-  if (pos >= (_IO_size_t) (_IO_blen(fp) + flush_only))
+  pos =  fp->_IO_write_ptr - fp->_IO_write_base;
+  if (pos >= _IO_blen(fp) + flush_only)
     {
       if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */
-       {
-#ifdef TODO
-         if (indefinite size)
-           {
-             fp->_IO_buf_end += 512;
-           }
-         else
-#endif
-         return EOF;
-       }
+       return EOF;
       else
        {
          char *new_buf;
-         _IO_size_t new_size = 2 * _IO_blen(fp);
+         char *old_buf = fp->_IO_buf_base;
+         _IO_size_t new_size = 2 * _IO_blen(fp) + 100;
          new_buf
            = (char*)(*((_IO_strfile*)fp)->_s._allocate_buffer)(new_size);
          if (new_buf == NULL)
@@ -136,31 +140,32 @@ DEFUN(_IO_str_overflow, (fp, c),
              /*          __ferror(fp) = 1; */
              return EOF;
            }
-         memcpy(new_buf, fp->_IO_buf_base, _IO_blen(fp));
-#if 0
-         if (lenp == &LEN(fp)) /* use '\0'-filling */
-             memset(new_buf + pos, 0, blen() - pos);
-#endif
          if (fp->_IO_buf_base)
            {
+             memcpy(new_buf, old_buf, _IO_blen(fp));
              (*((_IO_strfile*)fp)->_s._free_buffer)(fp->_IO_buf_base);
              /* Make sure _IO_setb won't try to delete _IO_buf_base. */
              fp->_IO_buf_base = NULL;
            }
+#if 0
+         if (lenp == &LEN(fp)) /* use '\0'-filling */
+             memset(new_buf + pos, 0, blen() - pos);
+#endif
          _IO_setb(fp, new_buf, new_buf + new_size, 1);
+         fp->_IO_read_base = new_buf + (fp->_IO_read_base - old_buf);
+         fp->_IO_read_ptr = new_buf + (fp->_IO_read_ptr - old_buf);
+         fp->_IO_read_end = new_buf + (fp->_IO_read_end - old_buf);
+         fp->_IO_write_ptr = new_buf + (fp->_IO_write_ptr - old_buf);
+
          fp->_IO_write_base = new_buf;
+         fp->_IO_write_end = fp->_IO_buf_end;
        }
-      fp->_IO_write_end = fp->_IO_buf_end;
     }
 
-  fp->_IO_write_ptr = fp->_IO_buf_base + pos;
-
-  fp->_IO_read_base = fp->_IO_buf_base;
-  fp->_IO_read_ptr = fp->_IO_buf_base + get_pos;
-  fp->_IO_read_end = fp->_IO_buf_base + LEN(fp);
-
   if (!flush_only)
     *fp->_IO_write_ptr++ = (unsigned char) c;
+  if (fp->_IO_write_ptr > fp->_IO_read_end)
+    fp->_IO_read_end = fp->_IO_write_ptr;
   return c;
 }
 
@@ -168,28 +173,29 @@ int
 DEFUN(_IO_str_underflow, (fp),
       register _IO_FILE* fp)
 {
-  _IO_size_t ppos = fp->_IO_write_ptr - fp->_IO_write_base;
-  if (ppos > LEN(fp)) LEN(fp) = ppos;
+  if (fp->_IO_write_ptr > fp->_IO_read_end)
+    fp->_IO_read_end = fp->_IO_write_ptr;
   if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING))
     {
       fp->_flags &= ~_IO_CURRENTLY_PUTTING;
+      fp->_IO_read_ptr = fp->_IO_write_ptr;
       fp->_IO_write_ptr = fp->_IO_write_end;
     }
-  fp->_IO_read_end = fp->_IO_read_base + LEN(fp);
   if (fp->_IO_read_ptr < fp->_IO_read_end)
     return *fp->_IO_read_ptr;
   else
     return EOF;
 }
 
+/* The size of the valid part of the buffer.  */
+
 _IO_ssize_t
 DEFUN(_IO_str_count, (fp),
       register _IO_FILE *fp)
 {
-  _IO_ssize_t put_len = fp->_IO_write_ptr - fp->_IO_write_base;
-  if (put_len < (_IO_ssize_t) LEN(fp))
-    put_len = LEN(fp);
-  return put_len;
+  return (fp->_IO_write_ptr > fp->_IO_read_end ? fp->_IO_write_ptr
+         : fp->_IO_read_end)
+    - fp->_IO_read_base;
 }
 
 _IO_pos_t
@@ -236,7 +242,6 @@ DEFUN(_IO_str_seekoff, (fp, offset, dir, mode),
        }
       if (offset < 0 || (_IO_ssize_t)offset > cur_size)
        return EOF;
-      LEN(fp) = cur_size;
       fp->_IO_write_ptr = fp->_IO_write_base + offset;
       new_pos = offset;
     }
index 247ab95..da47089 100644 (file)
@@ -12,9 +12,9 @@
 # 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.
+# 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.
 
 #
 #      Sub-makefile for login portion of the library.
@@ -24,9 +24,10 @@ subdir       := login
 
 headers        := utmp.h utmpbits.h lastlog.h pty.h
 
-routines := setutent endutent getutent getutid getutline pututline     \
-           setutent_r endutent_r getutent_r getutid_r getutline_r      \
-           pututline_r
+routines := getutent getutent_r getutid getutline getutid_r getutline_r \
+           utmp_file utmp_db
+
+distribtue := utmp-private.h
 
 # Build the -lutil library with these extra functions.
 extra-libs      := libutil
index 03b49db..e9462db 100644 (file)
@@ -1,27 +1,27 @@
 /* Copyright (C) 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+   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 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.
+   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.  */
+   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.  */
 
 #include <utmp.h>
 
 
-/* The global data defined in setutent.c.  */
-extern struct utmp_data __utmp_data;
+/* Local buffer to store the result.  */
+static struct utmp buffer;
 
 
 struct utmp *
@@ -29,7 +29,7 @@ getutent (void)
 {
   struct utmp *result;
 
-  if (__getutent_r (&result, &__utmp_data) < 0)
+  if (__getutent_r (&buffer, &result) < 0)
     return NULL;
 
   return result;
index e355001..df9a797 100644 (file)
 /* Copyright (C) 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>
+   and Paul Janzen <pcj@primenet.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 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.
+   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.  */
+   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.  */
 
-#include <unistd.h>
+#include <assert.h>
+#include <db.h>
+#include <fcntl.h>
+#include <libc-lock.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <utmp.h>
+#include <gnu/lib-names.h>
+#include <sys/stat.h>
 
+#include "utmp-private.h"
+#include "../elf/link.h"
 
-int
-__getutent_r (struct utmp **utmp, struct utmp_data *utmp_data)
+
+/* The various backends we have.  */
+static int __setutent_unknown (int reset);
+static int __getutent_r_unknown (struct utmp *buffer, struct utmp **result);
+static void __pututline_unknown (const struct utmp *data);
+static void __endutent_unknown (void);
+
+
+/* We have three jump tables: unknown, db, or file.  */
+static struct utfuncs unknown_functions =
+{
+  __setutent_unknown,
+  __getutent_r_unknown,
+  NULL,
+  NULL,
+  __pututline_unknown,
+  __endutent_unknown,
+  NULL
+};
+
+/* Currently selected backend.  */
+struct utfuncs *__libc_utmp_jump_table = &unknown_functions;
+
+/* The tables from the services.  */
+extern struct utfuncs __libc_utmp_db_functions;
+extern struct utfuncs __libc_utmp_file_functions;
+
+
+/* We need to protect the opening of the file.  */
+__libc_lock_define_initialized (, __libc_utmp_lock)
+
+void
+__setutent (void)
+{
+  __libc_lock_lock (__libc_utmp_lock);
+
+  (void) (*__libc_utmp_jump_table->setutent) (1);
+
+  __libc_lock_unlock (__libc_utmp_lock);
+}
+weak_alias (__setutent, setutent)
+
+
+static int
+__setutent_unknown (int reset)
 {
-  /* Open utmp file if not already done.  */
-  if (utmp_data->ut_fd == -1)
+  /* We have to test whether it is still not decided which backend to use.  */
+  assert (__libc_utmp_jump_table == &unknown_functions);
+
+  /* See whether utmp db file exists.  */
+  if ((*__libc_utmp_db_functions.setutent) (reset))
+    __libc_utmp_jump_table = &__libc_utmp_db_functions;
+  else
     {
-      setutent_r (utmp_data);
-      if (utmp_data->ut_fd == -1)
-       return -1;
+      /* Either the db file does not exist or we have other
+        problems.  So use the normal file.  */
+      (*__libc_utmp_file_functions.setutent) (reset);
+      __libc_utmp_jump_table = &__libc_utmp_file_functions;
     }
 
-  /* Position file correctly.  */
-  if (lseek (utmp_data->ut_fd, utmp_data->loc_utmp, SEEK_SET) == -1)
-    return -1;
+  return 0;
+}
+
 
-  /* Read the next entry.  */
-  if (read (utmp_data->ut_fd, &utmp_data->ubuf, sizeof (struct utmp))
-      != sizeof (struct utmp))
-    return -1;
+void
+__endutent (void)
+{
+  __libc_lock_lock (__libc_utmp_lock);
+
+  (*__libc_utmp_jump_table->endutent) ();
 
-  /* Update position pointer.  */
-  utmp_data->loc_utmp += sizeof (struct utmp);
+  __libc_lock_unlock (__libc_utmp_lock);
+}
+weak_alias (__endutent, endutent)
 
-  *utmp = &utmp_data->ubuf;
 
-  return 0;
+static void
+__endutent_unknown (void)
+{
+  /* Huh, how do we came here?  Nothing to do.  */
+}
+
+
+int
+__getutent_r (struct utmp *buffer, struct utmp **result)
+{
+  int retval;
+
+  __libc_lock_lock (__libc_utmp_lock);
+
+  retval = (*__libc_utmp_jump_table->getutent_r) (buffer, result);
+
+  __libc_lock_unlock (__libc_utmp_lock);
+
+  return retval;
 }
 weak_alias (__getutent_r, getutent_r)
+
+
+static int
+__getutent_r_unknown (struct utmp *buffer, struct utmp **result)
+{
+  /* It is not yet initialized.  */
+  __setutent_unknown (0);
+
+  return (*__libc_utmp_jump_table->getutent_r) (buffer, result);
+}
+
+
+void
+__pututline (const struct utmp *data)
+{
+  __libc_lock_lock (__libc_utmp_lock);
+
+  (*__libc_utmp_jump_table->pututline) (data);
+
+  __libc_lock_unlock (__libc_utmp_lock);
+}
+
+
+static void
+__pututline_unknown (const struct utmp *data)
+{
+  /* It is not yet initialized.  */
+  __setutent_unknown (0);
+
+  (*__libc_utmp_jump_table->pututline) (data);
+}
+
+
+int
+__utmpname (const char *file)
+{
+  int result = -1;
+
+  __libc_lock_lock (__libc_utmp_lock);
+
+  /* Close the old file.  */
+  (*__libc_utmp_jump_table->endutent) ();
+
+  /* Store new names.  */
+  if ((*__libc_utmp_file_functions.utmpname) (file) == 0
+      && !(*__libc_utmp_db_functions.utmpname) (file) == 0)
+    {
+      /* Try to find out whether we are supposed to work with a db
+        file or not.  Do this by looking for the extension ".db".  */
+      const char *ext = strrchr (file, '.');
+
+      if (ext != NULL && strcmp (ext, ".db") == 0)
+       __libc_utmp_jump_table = &__libc_utmp_db_functions;
+      else
+       __libc_utmp_jump_table = &unknown_functions;
+
+      result = 0;
+    }
+
+  __libc_lock_unlock (__libc_utmp_lock);
+
+  return result;
+}
+weak_alias (__utmpname, utmpname)
index 64ced6a..d3d3b5d 100644 (file)
@@ -1,27 +1,27 @@
 /* Copyright (C) 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+   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 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.
+   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.  */
+   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.  */
 
 #include <utmp.h>
 
 
-/* The global data defined in setutent.c.  */
-extern struct utmp_data __utmp_data;
+/* Local buffer to store the result.  */
+static struct utmp buffer;
 
 
 struct utmp *
@@ -29,8 +29,8 @@ getutid (const struct utmp *id)
 {
   struct utmp *result;
 
-  if (__getutid_r (id, &result, &__utmp_data) < 0)
+  if (__getutid_r (id, &buffer, &result) < 0)
     return NULL;
 
-  return (struct utmp *) result;
+  return result;
 }
index 8107015..52b83cd 100644 (file)
@@ -1,35 +1,45 @@
 /* Copyright (C) 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>
+   and Paul Janzen <pcj@primenet.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 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.
+   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.  */
+   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.  */
 
 #include <errno.h>
+#include <libc-lock.h>
 #include <string.h>
 #include <unistd.h>
 #include <utmp.h>
 
+#include "utmp-private.h"
+
+
+/* We have to use the lock in getutent_r.c.  */
+__libc_lock_define (extern, __libc_utmp_lock)
+
+/* The jump table is also in getutent_r.c.  */
+extern struct utfuncs *__libc_utmp_jump_table;
+
 
-/* For implementing this function we don't use the getutent_r function
-   because we can avoid the reposition on every new entry this way.  */
 int
-__getutid_r (const struct utmp *id, struct utmp **utmp,
-            struct utmp_data *utmp_data)
+__getutid_r (const struct utmp *id, struct utmp *buffer, struct utmp **result)
 {
 #if (_HAVE_UT_ID - 0) && (_HAVE_UT_TYPE - 0)
+  int retval = -1;
+
   /* Test whether ID has any of the legal types.  */
   if (id->ut_type != RUN_LVL && id->ut_type != BOOT_TIME
       && id->ut_type != OLD_TIME && id->ut_type != NEW_TIME
@@ -38,77 +48,21 @@ __getutid_r (const struct utmp *id, struct utmp **utmp,
     /* No, using '<' and '>' for the test is not possible.  */
     {
       __set_errno (EINVAL);
+      *result = NULL;
       return -1;
     }
 
-  /* Open utmp file if not already done.  */
-  if (utmp_data->ut_fd == -1)
-    {
-      setutent_r (utmp_data);
-      if (utmp_data->ut_fd == -1)
-       return -1;
-    }
-
-  /* Position file correctly.  */
-  if (lseek (utmp_data->ut_fd, utmp_data->loc_utmp, SEEK_SET) == -1)
-    return -1;
-
-  if (id->ut_type == RUN_LVL || id->ut_type == BOOT_TIME
-      || id->ut_type == OLD_TIME || id->ut_type == NEW_TIME)
-    {
-      /* Search for next entry with type RUN_LVL, BOOT_TIME,
-        OLD_TIME, or NEW_TIME.  */
-
-      while (1)
-       {
-         /* Read the next entry.  */
-         if (read (utmp_data->ut_fd, &utmp_data->ubuf, sizeof (struct utmp))
-             != sizeof (struct utmp))
-           {
-             utmp_data->loc_utmp = 0; /* Mark loc_utmp invalid. */
-             __set_errno (ESRCH);
-             return -1;
-           }
-
-         /* Update position pointer.  */
-         utmp_data->loc_utmp += sizeof (struct utmp);
+  __libc_lock_lock (__libc_utmp_lock);
 
-         if (id->ut_type == utmp_data->ubuf.ut_type)
-           break;
-       }
-    }
+  /* Not yet initialized.  */
+  if ((*__libc_utmp_jump_table->setutent) (0))
+    retval = (*__libc_utmp_jump_table->getutid_r) (id, buffer, result);
   else
-    {
-      /* Search for the next entry with the specified ID and with type
-        INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, or DEAD_PROCESS.  */
-
-      while (1)
-       {
-         /* Read the next entry.  */
-         if (read (utmp_data->ut_fd, &utmp_data->ubuf, sizeof (struct utmp))
-             != sizeof (struct utmp))
-           {
-             utmp_data->loc_utmp = 0; /* Mark loc_utmp invalid. */
-             __set_errno (ESRCH);
-             return -1;
-           }
-
-         /* Update position pointer.  */
-         utmp_data->loc_utmp += sizeof (struct utmp);
-
-         if ((   utmp_data->ubuf.ut_type == INIT_PROCESS
-              || utmp_data->ubuf.ut_type == LOGIN_PROCESS
-              || utmp_data->ubuf.ut_type == USER_PROCESS
-              || utmp_data->ubuf.ut_type == DEAD_PROCESS)
-             && (strncmp (utmp_data->ubuf.ut_id, id->ut_id, sizeof id->ut_id)
-                 == 0))
-           break;
-       }
-    }
+    *result = NULL;
 
-  *utmp = &utmp_data->ubuf;
+  __libc_lock_unlock (__libc_utmp_lock);
 
-  return 0;
+  return retval;
 #else  /* !_HAVE_UT_ID && !_HAVE_UT_TYPE */
   __set_errno (ENOSYS);
   return -1;
index c21f817..16a02f6 100644 (file)
@@ -1,27 +1,27 @@
 /* Copyright (C) 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+   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 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.
+   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.  */
+   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.  */
 
 #include <utmp.h>
 
 
-/* The global data defined in setutent.c.  */
-extern struct utmp_data __utmp_data;
+/* Local buffer to store the result.  */
+static struct utmp buffer;
 
 
 struct utmp *
@@ -29,8 +29,8 @@ getutline (const struct utmp *line)
 {
   struct utmp *result;
 
-  if (__getutline_r (line, &result, &__utmp_data) < 0)
+  if (__getutline_r (line, &buffer, &result) < 0)
     return NULL;
 
-  return (struct utmp *) result;
+  return result;
 }
index e88267d..2285248 100644 (file)
@@ -1,74 +1,55 @@
 /* Copyright (C) 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>
+   and Paul Janzen <pcj@primenet.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 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.
+   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.  */
+   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.  */
 
 #include <errno.h>
+#include <libc-lock.h>
 #include <string.h>
 #include <unistd.h>
 #include <utmp.h>
 
+#include "utmp-private.h"
 
-/* For implementing this function we don't use the getutent_r function
-   because we can avoid the reposition on every new entry this way.  */
-int
-__getutline_r (const struct utmp *line, struct utmp **utmp,
-              struct utmp_data *utmp_data)
-{
-  /* Open utmp file if not already done.  */
-  if (utmp_data->ut_fd == -1)
-    {
-      __setutent_r (utmp_data);
-      if (utmp_data->ut_fd == -1)
-       return -1;
-    }
 
-  /* Position file correctly.  */
-  if (lseek (utmp_data->ut_fd, utmp_data->loc_utmp, SEEK_SET) == -1)
-    return -1;
+/* We have to use the lock in getutent_r.c.  */
+__libc_lock_define (extern, __libc_utmp_lock)
+
+/* The jump table is also in getutent_r.c.  */
+extern struct utfuncs *__libc_utmp_jump_table;
 
-  while (1)
-    {
-      /* Read the next entry.  */
-      if (read (utmp_data->ut_fd, &utmp_data->ubuf, sizeof (struct utmp))
-         != sizeof (struct utmp))
-       {
-         utmp_data->loc_utmp = 0; /* Mark UTMP_DATA->ubuf invalid.  */
-         __set_errno (ESRCH);
-         return -1;
-       }
 
-      /* Update position pointer.  */
-      utmp_data->loc_utmp += sizeof (struct utmp);
+int
+__getutline_r (const struct utmp *line, struct utmp *buffer,
+              struct utmp **result)
+{
+  int retval = -1;
+
+  __libc_lock_lock (__libc_utmp_lock);
 
-      if (
-#if _HAVE_UT_TYPE - 0
-         (utmp_data->ubuf.ut_type == USER_PROCESS
-          || utmp_data->ubuf.ut_type == LOGIN_PROCESS)
-         &&
-#endif
-         ! strncmp (line->ut_line, utmp_data->ubuf.ut_line,
-                    sizeof line->ut_line))
-       /* Stop if we found a user or login entry.  */
-       break;
-    }
+  /* Not yet initialized.  */
+  if ((*__libc_utmp_jump_table->setutent) (0))
+    retval = (*__libc_utmp_jump_table->getutline_r) (line, buffer, result);
+  else
+    *result = NULL;
 
-  *utmp = &utmp_data->ubuf;
+  __libc_lock_unlock (__libc_utmp_lock);
 
-  return 0;
+  return retval;
 }
 weak_alias (__getutline_r, getutline_r)
index 00b176a..7cbe8b6 100644 (file)
@@ -1,21 +1,21 @@
 /* Copyright (C) 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+   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 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.
+   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.  */
+   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.  */
 
 #include <errno.h>
 #include <limits.h>
@@ -43,8 +43,8 @@ tty_name (int fd, char **tty, size_t buf_len)
          rv = ttyname_r (fd, buf, buf_len);
 
          if (rv < 0 || memchr (buf, '\0', buf_len))
-           /* We either got an error, or we succeeded and the returned name fit
-              in the buffer.  */
+           /* We either got an error, or we succeeded and the
+              returned name fit in the buffer.  */
            break;
 
          /* Try again with a longer buffer.  */
@@ -68,9 +68,9 @@ tty_name (int fd, char **tty, size_t buf_len)
     }
 
   if (rv == 0)
-    *tty = buf;                        /* Return buffer to the user.  */
+    *tty = buf;                /* Return buffer to the user.  */
   else if (buf != *tty)
-    free (buf);                        /* Free what we malloced when returning an error.  */
+    free (buf);                /* Free what we malloced when returning an error.  */
 
   return rv;
 }
@@ -86,8 +86,8 @@ login (const struct utmp *ut)
   char *tty = _tty;
   int found_tty;
   const char *ttyp;
-  struct utmp_data data = { -1 };
   struct utmp copy = *ut;
+  struct utmp utbuf;
 
   /* Fill in those fields we supply.  */
 #if _HAVE_UT_TYPE - 0
@@ -118,26 +118,16 @@ login (const struct utmp *ut)
          struct utmp *old;
 
          /* Open UTMP file.  */
-         setutent_r (&data);
+         setutent ();
 
          /* Read the record.  */
-         if (getutline_r (&copy, &old, &data) >= 0)
-           {
-#if _HAVE_UT_TYPE - 0
-             /* We have to fake the old entry because this `login'
-                function does not fit well into the UTMP file
-                handling scheme.  */
-             old->ut_type = copy.ut_type;
-#endif
-             pututline_r (&copy, &data);
-           }
-         else if (errno == ESRCH)
-           /* We didn't find anything.  pututline_r will add UT at the end
-              of the file in this case.  */
-           pututline_r (&copy, &data);
+         getutline_r (&copy, &utbuf, &old);
+
+         /* Write the entry.  */
+         pututline (&copy);
 
          /* Close UTMP file.  */
-         endutent_r (&data);
+         endutent ();
        }
 
       if (tty != _tty)
@@ -147,23 +137,18 @@ login (const struct utmp *ut)
   /* Update the WTMP file.  Here we have to add a new entry.  */
   if (utmpname (_PATH_WTMP) != 0)
     {
+      struct utmp *up;
+
       /* Open the WTMP file.  */
-      setutent_r (&data);
+      setutent ();
 
       /* Position at end of file.  */
-      data.loc_utmp = lseek (data.ut_fd, 0, SEEK_END);
-      if (data.loc_utmp != -1)
-       {
-#if _HAVE_UT_TYPE - 0
-         /* We have to fake the old entry because this `login'
-            function does not fit well into the UTMP file handling
-            scheme.  */
-         data.ubuf.ut_type = copy.ut_type;
-#endif
-         pututline_r (&copy, &data);
-       }
+      while (! getutent_r (&utbuf, &up));
+
+      /* Write the new entry.  */
+      pututline (&copy);
 
       /* Close WTMP file.  */
-      endutent_r (&data);
+      endutent ();
     }
 }
index 8575512..3e62548 100644 (file)
@@ -25,8 +25,7 @@ Boston, MA 02111-1307, USA.  */
 int
 logout (const char *line)
 {
-  struct utmp_data data = { ut_fd: -1 };
-  struct utmp tmp;
+  struct utmp tmp, utbuf;
   struct utmp *ut;
   int result = 0;
 
@@ -35,7 +34,7 @@ logout (const char *line)
     return 0;
 
   /* Open UTMP file.  */
-  setutent_r (&data);
+  setutent ();
 
   /* Fill in search information.  */
 #if _HAVE_UT_TYPE - 0
@@ -44,7 +43,7 @@ logout (const char *line)
   strncpy (tmp.ut_line, line, sizeof tmp.ut_line);
 
   /* Read the record.  */
-  if (getutline_r (&tmp, &ut, &data) >= 0)
+  if (getutline_r (&tmp, &utbuf, &ut) >= 0)
     {
       /* Clear information about who & from where.  */
       bzero (ut->ut_name, sizeof ut->ut_name);
@@ -57,12 +56,12 @@ logout (const char *line)
       time (&ut->ut_time);
 #endif
 
-      if (pututline_r (ut, &data) >= 0)
+      if (pututline (ut) >= 0)
        result = 1;
     }
 
   /* Close UTMP file.  */
-  endutent_r (&data);
+  endutent ();
 
   return result;
 }
index 17c9001..0d5e48e 100644 (file)
@@ -1,21 +1,21 @@
 /* Copyright (C) 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+   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 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.
+   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.  */
+   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.  */
 
 #include <errno.h>
 #include <string.h>
diff --git a/login/utmp-private.h b/login/utmp-private.h
new file mode 100644 (file)
index 0000000..4825ae3
--- /dev/null
@@ -0,0 +1,41 @@
+/* Internal definitions and declarations for UTMP functions.
+   Copyright (C) 1996 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>
+   and Paul Janzen <pcj@primenet.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.  */
+
+#ifndef _UTMP_PRIVATE_H
+#define _UTMP_PRIVATE_H        1
+
+#include <utmp.h>
+
+/* The extra `int' argument for each function shows whether locking is
+   wanted or not.  */
+struct utfuncs
+{
+  int (*setutent) (int);
+  int (*getutent_r) (struct utmp *, struct utmp **);
+  int (*getutid_r) (const struct utmp *, struct utmp *, struct utmp **);
+  int (*getutline_r) (const struct utmp *, struct utmp *, struct utmp **);
+  struct utmp *(*pututline) (const struct utmp *);
+  void (*endutent) (void);
+  int (*utmpname) (const char *);
+
+};
+
+#endif /* utmp-private.h */
index 6786190..87f822d 100644 (file)
@@ -58,9 +58,11 @@ extern int utmpname __P ((__const char *__file));
 extern struct utmp *getutent __P ((void));
 
 /* Rest the input stream to the beginning of the file.  */
+extern void __setutent __P ((void));
 extern void setutent __P ((void));
 
 /* Close the current open file.  */
+extern void __endutent __P ((void));
 extern void endutent __P ((void));
 
 /* Search forward from the current point in the utmp file until the
@@ -76,42 +78,19 @@ extern struct utmp *pututline __P ((__const struct utmp *__utmp_ptr));
 
 
 #ifdef __USE_REENTRANT
-/* Define the data structure needed for the reentrant version.  */
-struct utmp_data
-{
-  int ut_fd;
-  off_t loc_utmp;
-  struct utmp ubuf;
-};
-
-
 /* Reentrant versions of the file for handling utmp files.  */
-extern int __getutent_r __P ((struct utmp **__utmp,
-                             struct utmp_data *__utmp_data));
-extern int getutent_r __P ((struct utmp **__utmp,
-                           struct utmp_data *__utmp_data));
-
-extern void __setutent_r __P ((struct utmp_data *__utmp_data));
-extern void setutent_r __P ((struct utmp_data *__utmp_data));
-
-extern void __endutent_r __P ((struct utmp_data *__utmp_data));
-extern void endutent_r __P ((struct utmp_data *__utmp_data));
+extern int __getutent_r __P ((struct utmp *__buffer, struct utmp **__result));
+extern int getutent_r __P ((struct utmp *__buffer, struct utmp **__result));
 
-extern int __getutid_r __P ((__const struct utmp *__id, struct utmp **__utmp,
-                            struct utmp_data *__utmp_data));
-extern int getutid_r __P ((__const struct utmp *__id, struct utmp **__utmp,
-                          struct utmp_data *__utmp_data));
+extern int __getutid_r __P ((__const struct utmp *__id, struct utmp *__buffer,
+                            struct utmp **__result));
+extern int getutid_r __P ((__const struct utmp *__id, struct utmp *__buffer,
+                          struct utmp **__result));
 
 extern int __getutline_r __P ((__const struct utmp *__line,
-                              struct utmp **__utmp,
-                              struct utmp_data *__utmp_data));
-extern int getutline_r __P ((__const struct utmp *__line, struct utmp **__utmp,
-                            struct utmp_data *__utmp_data));
-
-extern int __pututline_r __P ((__const struct utmp *__utmp_ptr,
-                              struct utmp_data *__utmp_data));
-extern int pututline_r __P ((__const struct utmp *__utmp_ptr,
-                            struct utmp_data *__utmp_data));
+                              struct utmp *__buffer, struct utmp **__result));
+extern int getutline_r __P ((__const struct utmp *__line,
+                            struct utmp *__buffer, struct utmp **__result));
 
 #endif /* Use reentrant.  */
 
diff --git a/login/utmp_db.c b/login/utmp_db.c
new file mode 100644 (file)
index 0000000..2c5baf6
--- /dev/null
@@ -0,0 +1,102 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>
+   and Paul Janzen <pcj@primenet.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.  */
+
+#include <assert.h>
+#include <db.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <utmp.h>
+#include <sys/stat.h>
+
+#include "utmp-private.h"
+
+
+/* This is the default name.  */
+static const char default_file_name[] = _PATH_UTMP_DB;
+
+/* Current file name.  */
+static const char *file_name = (const char *) default_file_name;
+
+/* Descriptor for database.  */
+static DB *db_fd;
+static char last_date[16];
+
+
+/* Our local functions.  */
+static int setutent_db (int reset);
+static void endutent_db (void);
+static int utmpname_db (const char *name);
+
+
+/* The jump table for the local functions.  */
+struct utfuncs __libc_utmp_db_functions =
+{
+  setutent_db,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  endutent_db,
+  utmpname_db
+};
+
+
+static int
+setutent_db (int reset)
+{
+  return 0;
+}
+
+
+static void
+endutent_db (void)
+{
+}
+
+
+static int
+utmpname_db (const char *name)
+{
+  if (strcmp (name, file_name) != 0)
+    {
+      if (strcmp (name, default_file_name) == 0)
+       {
+         if (file_name != default_file_name)
+           free ((char *) file_name);
+
+         file_name = default_file_name;
+       }
+      else
+       {
+         char *new_name = __strdup (name);
+         if (new_name == NULL)
+           /* Out of memory.  */
+           return -1;
+
+         if (file_name != default_file_name)
+           free ((char *) file_name);
+
+         file_name = new_name;
+       }
+    }
+  return 0;
+}
diff --git a/login/utmp_file.c b/login/utmp_file.c
new file mode 100644 (file)
index 0000000..fff487a
--- /dev/null
@@ -0,0 +1,385 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>
+   and Paul Janzen <pcj@primenet.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.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utmp.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include "utmp-private.h"
+
+
+/* This is the default name.  */
+static const char default_file_name[] = _PATH_UTMP;
+
+/* Current file name.  */
+static const char *file_name = (const char *) default_file_name;
+
+/* Descriptor for the file and position.  */
+static int file_fd = INT_MIN;
+static off_t file_offset;
+
+static struct utmp last_entry;
+
+/* Functions defined here.  */
+static int setutent_file (int reset);
+static int getutent_r_file (struct utmp *buffer, struct utmp **result);
+static int getutid_r_file (const struct utmp *key, struct utmp *buffer,
+                          struct utmp **result);
+static int getutline_r_file (const struct utmp *key, struct utmp *buffer,
+                            struct utmp **result);
+static struct utmp *pututline_file (const struct utmp *data);
+static void endutent_file (void);
+static int utmpname_file (const char *name);
+
+
+/* Jump table for file functions.  */
+struct utfuncs __libc_utmp_file_functions =
+{
+  setutent_file,
+  getutent_r_file,
+  getutid_r_file,
+  getutline_r_file,
+  pututline_file,
+  endutent_file,
+  utmpname_file
+};
+
+
+static int
+setutent_file (int reset)
+{
+  if (file_fd == INT_MIN)
+    {
+      file_fd = open (file_name, O_RDWR);
+      if (file_fd == -1)
+       {
+         /* Hhm, read-write access did not work.  Try read-only.  */
+         file_fd = open (file_name, O_RDONLY);
+         if (file_fd == -1)
+           {
+             perror (_("while opening UTMP file"));
+             return 0;
+           }
+       }
+      file_offset = 0;
+
+      /* Make sure the entry won't match.  */
+      last_entry.ut_type = -1;
+    }
+  else if (reset)
+    {
+      /* Remember we are at beginning of file.  */
+      file_offset = 0;
+
+      /* Make sure the entry won't match.  */
+      last_entry.ut_type = -1;
+    }
+
+  return 1;
+}
+
+
+static void
+endutent_file (void)
+{
+  if (file_fd >= 0)
+    close (file_fd);
+
+  file_fd = INT_MIN;
+}
+
+
+static int
+getutent_r_file (struct utmp *buffer, struct utmp **result)
+{
+  int nbytes;
+
+  /* Open utmp file if not already done.  */
+  if (file_fd == INT_MIN)
+    setutent_file (1);
+
+  if (file_fd == -1 || file_offset == -1l)
+    {
+      /* Not available.  */
+      *result = NULL;
+      return -1;
+    }
+
+  /* Read the next entry.  */
+  flock (file_fd, LOCK_SH);
+  nbytes = read (file_fd, &last_entry, sizeof (struct utmp));
+  flock (file_fd, LOCK_UN);
+
+  if (nbytes!= sizeof (struct utmp))
+    {
+      file_offset = -1l;
+      *result = NULL;
+      return -1;
+    }
+
+  /* Update position pointer.  */
+  file_offset += sizeof (struct utmp);
+
+  memcpy (buffer, &last_entry, sizeof (struct utmp));
+  *result = buffer;
+
+  return 0;
+}
+
+
+/* For implementing this function we don't use the getutent_r function
+   because we can avoid the reposition on every new entry this way.  */
+static int
+getutline_r_file (const struct utmp *line, struct utmp *buffer,
+                 struct utmp **result)
+{
+  if (file_fd < 0 || file_offset == -1l)
+    {
+      *result = NULL;
+      return -1;
+    }
+
+  while (1)
+    {
+      /* Read the next entry.  */
+      if (read (file_fd, &last_entry, sizeof (struct utmp))
+         != sizeof (struct utmp))
+       {
+         __set_errno (ESRCH);
+         file_offset = -1l;
+         *result = NULL;
+         return -1;
+       }
+
+      /* Stop if we found a user or login entry.  */
+      if (
+#if _HAVE_UT_TYPE - 0
+         (last_entry.ut_type == USER_PROCESS
+          || last_entry.ut_type == LOGIN_PROCESS)
+         &&
+#endif
+         !strncmp (line->ut_line, last_entry.ut_line, sizeof line->ut_line))
+       break;
+
+      file_offset += sizeof (struct utmp);
+    }
+
+  memcpy (buffer, &last_entry, sizeof (struct utmp));
+  *result = buffer;
+
+  return 0;
+}
+
+
+static int
+internal_getutid_r (const struct utmp *id, struct utmp *buffer)
+{
+  if (id->ut_type == RUN_LVL || id->ut_type == BOOT_TIME
+      || id->ut_type == OLD_TIME || id->ut_type == NEW_TIME)
+    {
+      /* Search for next entry with type RUN_LVL, BOOT_TIME,
+        OLD_TIME, or NEW_TIME.  */
+
+      while (1)
+       {
+         /* Read the next entry.  */
+         if (read (file_fd, buffer, sizeof (struct utmp))
+             != sizeof (struct utmp))
+           {
+             __set_errno (ESRCH);
+             file_offset = -1l;
+             return -1;
+           }
+
+         if (id->ut_type == buffer->ut_type)
+           break;
+
+         file_offset += sizeof (struct utmp);
+       }
+    }
+  else
+    {
+      /* Search for the next entry with the specified ID and with type
+        INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, or DEAD_PROCESS.  */
+
+      while (1)
+       {
+         /* Read the next entry.  */
+         if (read (file_fd, buffer, sizeof (struct utmp))
+             != sizeof (struct utmp))
+           {
+             __set_errno (ESRCH);
+             file_offset = -1l;
+             return -1;
+           }
+         if ((   buffer->ut_type == INIT_PROCESS
+              || buffer->ut_type == LOGIN_PROCESS
+              || buffer->ut_type == USER_PROCESS
+              || buffer->ut_type == DEAD_PROCESS)
+             && strncmp (buffer->ut_id, id->ut_id, sizeof id->ut_id) == 0)
+           break;
+
+         file_offset += sizeof (struct utmp);
+       }
+    }
+
+  return 0;
+}
+
+
+/* For implementing this function we don't use the getutent_r function
+   because we can avoid the reposition on every new entry this way.  */
+static int
+getutid_r_file (const struct utmp *id, struct utmp *buffer,
+               struct utmp **result)
+{
+  if (file_fd < 0 || file_offset == -1l)
+    {
+      *result = NULL;
+      return -1;
+    }
+
+  if (internal_getutid_r (id, &last_entry) < 0)
+    {
+      *result = NULL;
+      return -1;
+    }
+
+  memcpy (buffer, &last_entry, sizeof (struct utmp));
+  *result = buffer;
+
+  return 0;
+}
+
+
+static struct utmp *
+pututline_file (const struct utmp *data)
+{
+  struct utmp buffer;
+  struct utmp *pbuf;
+  int found;
+
+  if (file_fd < 0)
+    /* Something went wrong.  */
+    return NULL;
+
+  /* Find the correct place to insert the data.  */
+  if (file_offset > 0)
+    found = 0;
+  else
+    if (   last_entry.ut_type == RUN_LVL
+       || last_entry.ut_type == BOOT_TIME
+       || last_entry.ut_type == OLD_TIME
+       || last_entry.ut_type == NEW_TIME
+       || ((   last_entry.ut_type == INIT_PROCESS
+            || last_entry.ut_type == LOGIN_PROCESS
+            || last_entry.ut_type == USER_PROCESS
+            || last_entry.ut_type == DEAD_PROCESS)
+           && !strncmp (last_entry.ut_id, data->ut_id, sizeof data->ut_id)))
+      found = 1;
+    else
+      found = internal_getutid_r (data, &buffer);
+
+  /* Try to lock the file.  */
+  if (flock (file_fd, LOCK_EX | LOCK_NB) < 0 && errno != ENOSYS)
+    {
+      /* Oh, oh.  The file is already locked.  Wait a bit and try again.  */
+      sleep (1);
+
+      /* This time we ignore the error.  */
+      (void) flock (file_fd, LOCK_EX | LOCK_NB);
+    }
+
+  if (found < 0)
+    {
+      /* We append the next entry.  */
+      file_offset = lseek (file_fd, 0, SEEK_END);
+      if (file_offset % sizeof (struct utmp) != 0)
+       {
+         file_offset -= file_offset % sizeof (struct utmp);
+         ftruncate (file_fd, file_offset);
+
+         if (lseek (file_fd, 0, SEEK_END) < 0)
+           {
+             (void) flock (file_fd, LOCK_UN);
+             return NULL;
+           }
+       }
+    }
+  else
+    {
+      /* We replace the just read entry.  */
+      file_offset -= sizeof (struct utmp);
+      lseek (file_fd, file_offset, SEEK_SET);
+    }
+
+  /* Write the new data.  */
+  if (write (file_fd, data, sizeof (struct utmp)) != sizeof (struct utmp)
+      /* If we appended a new record this is only partially written.
+        Remove it.  */
+      && found < 0)
+    {
+      (void) ftruncate (file_fd, file_offset);
+      pbuf = NULL;
+    }
+  else
+    pbuf = (struct utmp *) data;
+
+   /* And unlock the file.  */
+  (void) flock (file_fd, LOCK_UN);
+
+  return pbuf;
+}
+
+
+static int
+utmpname_file (const char *name)
+{
+  if (strcmp (name, file_name) != 0)
+    {
+      if (strcmp (name, default_file_name) == 0)
+       {
+         if (file_name != default_file_name)
+           free ((char *) file_name);
+
+         file_name = default_file_name;
+       }
+      else
+       {
+         char *new_name = __strdup (name);
+         if (new_name == NULL)
+           /* Out of memory.  */
+           return -1;
+
+         if (file_name != default_file_name)
+           free ((char *) file_name);
+
+         file_name = new_name;
+       }
+    }
+  return 0;
+}