aboutsummaryrefslogtreecommitdiff
path: root/login
diff options
context:
space:
mode:
Diffstat (limited to 'login')
-rw-r--r--login/Makefile13
-rw-r--r--login/getutent.c34
-rw-r--r--login/getutent_r.c211
-rw-r--r--login/getutid.c36
-rw-r--r--login/getutid_r.c118
-rw-r--r--login/getutline.c36
-rw-r--r--login/getutline_r.c91
-rw-r--r--login/login.c81
-rw-r--r--login/logout.c11
-rw-r--r--login/logwtmp.c28
-rw-r--r--login/utmp-private.h41
-rw-r--r--login/utmp.h43
-rw-r--r--login/utmp_db.c102
-rw-r--r--login/utmp_file.c385
14 files changed, 901 insertions, 329 deletions
diff --git a/login/Makefile b/login/Makefile
index 247ab958df..da47089b5a 100644
--- a/login/Makefile
+++ b/login/Makefile
@@ -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
diff --git a/login/getutent.c b/login/getutent.c
index 03b49dbf7e..e9462db18d 100644
--- a/login/getutent.c
+++ b/login/getutent.c
@@ -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;
diff --git a/login/getutent_r.c b/login/getutent_r.c
index e3550017f9..df9a7977ab 100644
--- a/login/getutent_r.c
+++ b/login/getutent_r.c
@@ -1,51 +1,196 @@
/* 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)
diff --git a/login/getutid.c b/login/getutid.c
index 64ced6aeea..d3d3b5d068 100644
--- a/login/getutid.c
+++ b/login/getutid.c
@@ -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;
}
diff --git a/login/getutid_r.c b/login/getutid_r.c
index 81070157a4..52b83cd862 100644
--- a/login/getutid_r.c
+++ b/login/getutid_r.c
@@ -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;
diff --git a/login/getutline.c b/login/getutline.c
index c21f81745b..16a02f6e89 100644
--- a/login/getutline.c
+++ b/login/getutline.c
@@ -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;
}
diff --git a/login/getutline_r.c b/login/getutline_r.c
index e88267decb..2285248ece 100644
--- a/login/getutline_r.c
+++ b/login/getutline_r.c
@@ -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)
diff --git a/login/login.c b/login/login.c
index 00b176a104..7cbe8b603e 100644
--- a/login/login.c
+++ b/login/login.c
@@ -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 ();
}
}
diff --git a/login/logout.c b/login/logout.c
index 8575512e0e..3e625486f6 100644
--- a/login/logout.c
+++ b/login/logout.c
@@ -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;
}
diff --git a/login/logwtmp.c b/login/logwtmp.c
index 17c900181f..0d5e48e51f 100644
--- a/login/logwtmp.c
+++ b/login/logwtmp.c
@@ -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
index 0000000000..4825ae3f6d
--- /dev/null
+++ b/login/utmp-private.h
@@ -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 */
diff --git a/login/utmp.h b/login/utmp.h
index 6786190aad..87f822d9c3 100644
--- a/login/utmp.h
+++ b/login/utmp.h
@@ -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
index 0000000000..2c5baf6592
--- /dev/null
+++ b/login/utmp_db.c
@@ -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
index 0000000000..fff487a0a3
--- /dev/null
+++ b/login/utmp_file.c
@@ -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;
+}