diff options
Diffstat (limited to 'login')
-rw-r--r-- | login/Makefile | 13 | ||||
-rw-r--r-- | login/getutent.c | 34 | ||||
-rw-r--r-- | login/getutent_r.c | 211 | ||||
-rw-r--r-- | login/getutid.c | 36 | ||||
-rw-r--r-- | login/getutid_r.c | 118 | ||||
-rw-r--r-- | login/getutline.c | 36 | ||||
-rw-r--r-- | login/getutline_r.c | 91 | ||||
-rw-r--r-- | login/login.c | 81 | ||||
-rw-r--r-- | login/logout.c | 11 | ||||
-rw-r--r-- | login/logwtmp.c | 28 | ||||
-rw-r--r-- | login/utmp-private.h | 41 | ||||
-rw-r--r-- | login/utmp.h | 43 | ||||
-rw-r--r-- | login/utmp_db.c | 102 | ||||
-rw-r--r-- | login/utmp_file.c | 385 |
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 (©, &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 (©, &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 (©, &data); + getutline_r (©, &utbuf, &old); + + /* Write the entry. */ + pututline (©); /* 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 (©, &data); - } + while (! getutent_r (&utbuf, &up)); + + /* Write the new entry. */ + pututline (©); /* 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; +} |