From 0200214b288810fc261b0b65c32f7068fcfa9b40 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Wed, 29 May 1996 04:48:04 +0000 Subject: Tue May 28 04:38:10 1996 Ulrich Drepper * limits.h: Change MB_LEN_MAX to 6. A 31-bit ISO 10646 character in UTF-8 encoding has that many bytes. * locale/langinfo.h: New element _NL_CTYPE_MB_CUR_MAX. * locale/categories.def: Add description of field _NL_CTYPE_MB_CUR_MAX. * locale/Makefile (routines): Add mb_cur_max. * locale/mb_cur_max.c: New file. This function gets called when the macro MB_CUR_MAX is used. * locale/C-ctype.c: Initialize new mb_cur_max field. * locale/localeinfo.h: Change magic value because of incompatible change. * locale/programs/ld-ctype.c: Determine value of mb_cur_max according to current character set and write it out with the rest. * stdlib/stdlib.h (MB_CUR_MAX): Not constant anymore. Get value according to currently used locale for catefory LC_CTYPE by calling the function __ctype_get_mb_cur_max. Tue May 28 03:27:46 1996 Ulrich Drepper * FAQ: Fix some typos. Tell that for Linux the kernel header files are necessary. * PROJECTS: New file. List of open jobs for glibc. * Makefile (distribute): Add PROJECTS. * crypt/GNUmakefile (headers): New variable. Mention crypt.h. * crypt/crypt.h: Header for crypt functions. * elf/elf.h: Add some new constants from recent Cygnus ELF header files. * login/getutid_r.c: Test for correct type. Don't depend on ut_type and ut_id unless _HAVE_UT_TYPE and _HAVE_UT_ID resp. are defined. Make really compliant with specification. * login/getutline_r.c, login/pututline_r.c: Don't depend on ut_type and ut_id unless _HAVE_UT_TYPE and _HAVE_UT_ID resp. are defined. Make really compliant with specification. * login/setutent_r.c: Don't depend on ut_type and ut_id unless _HAVE_UT_TYPE and _HAVE_UT_ID resp. are defined. * login/login.c, login/logout.c, login/logwtmp.c: Complete rewrite. Now based on getut*/setut* functions. * stdlib/strtol.c: Undo changes of Wed May 22 01:48:54 1996. This prevented using this file in other GNU packages. * sysdeps/gnu/utmpbits.h: Define _HAVE_UT_TYPE, _HAVE_UT_ID, and _HAVE_UT_TV because struct utmp has these members. * sysdeps/libm-i387/e_exp.S: Correct exp(+-Inf) case. * utmp.h: New file. Wrapper around login/utmp.h. * elf/dl-error.c (struct catch): New type. (catch): New static variable, struct catch *. (catch_env, signalled_errstring, signalled_objname): Variables removed. (_dl_signal_error): If CATCH is non-null, set its errstring and objname members and jump to CATCH->env. If it is null, call _dl_sysdep_fatal with a standard message. * elf/rtld.c (dl_main): Explode `doit' function into dl_main's body. No longer use _dl_catch_error. --- login/getutid_r.c | 34 +++++++++++- login/getutline_r.c | 23 ++++++-- login/login.c | 148 +++++++++++++++++++++++++++++++++------------------- login/logout.c | 121 ++++++++++++++++++++---------------------- login/logwtmp.c | 111 +++++++++++++++++++-------------------- login/pututline_r.c | 56 ++++++++++++++++---- login/setutent_r.c | 4 +- 7 files changed, 304 insertions(+), 193 deletions(-) (limited to 'login') diff --git a/login/getutid_r.c b/login/getutid_r.c index 351f96e65e..02013c29b9 100644 --- a/login/getutid_r.c +++ b/login/getutid_r.c @@ -18,6 +18,7 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include +#include #include #include @@ -28,6 +29,18 @@ int getutid_r (const struct utmp *id, struct utmp **utmp, struct utmp_data *utmp_data) { +#if (_HAVE_UT_ID - 0) && (_HAVE_UT_TYPE - 0) + /* 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 + && id->ut_type != INIT_PROCESS && id->ut_type != LOGIN_PROCESS + && id->ut_type != USER_PROCESS && id->ut_type != DEAD_PROCESS) + /* No, using '<' and '>' for the test is not possible. */ + { + errno = EINVAL; + return -1; + } + /* Open utmp file if not already done. */ if (utmp_data->ut_fd == -1) { @@ -40,7 +53,7 @@ getutid_r (const struct utmp *id, struct utmp **utmp, if (lseek (utmp_data->ut_fd, utmp_data->loc_utmp, SEEK_SET) == -1) return -1; - do + while (1) { /* Read the next entry. */ if (read (utmp_data->ut_fd, &utmp_data->ubuf, sizeof (struct utmp)) @@ -52,10 +65,27 @@ getutid_r (const struct utmp *id, struct utmp **utmp, /* Update position pointer. */ utmp_data->loc_utmp += sizeof (struct utmp); + + if ((id->ut_type == RUN_LVL || id->ut_type == BOOT_TIME + || id->ut_type == OLD_TIME || id->ut_type == NEW_TIME) + && id->ut_type != utmp_data->ubuf.ut_type) + /* Stop at the next entry with type RUN_LVL, BOOT_TIME, + OLD_TIME, or NEW_TIME. */ + break; + + if ((id->ut_type == INIT_PROCESS || id->ut_type == LOGIN_PROCESS + || id->ut_type == USER_PROCESS || id->ut_type == DEAD_PROCESS) + && strncmp (id->ut_id, utmp_data->ubuf.ut_id, sizeof id->ut_id) == 0) + /* Stop at the next entry with the specified ID and with type + INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, or DEAD_PROCESS. */ + break; } - while (id->ut_type != utmp_data->ubuf.ut_type); *utmp = &utmp_data->ubuf; return 0; +#else /* !_HAVE_UT_ID && !_HAVE_UT_TYPE */ + errno = ENOSYS; + return -1; +#endif } diff --git a/login/getutline_r.c b/login/getutline_r.c index 8df48786dd..0956164eab 100644 --- a/login/getutline_r.c +++ b/login/getutline_r.c @@ -18,9 +18,9 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include +#include #include #include -#include /* For implementing this function we don't use the getutent_r function @@ -41,7 +41,7 @@ getutline_r (const struct utmp *line, struct utmp **utmp, if (lseek (utmp_data->ut_fd, utmp_data->loc_utmp, SEEK_SET) == -1) return -1; - do + while (1) { /* Read the next entry. */ if (read (utmp_data->ut_fd, &utmp_data->ubuf, sizeof (struct utmp)) @@ -53,9 +53,24 @@ getutline_r (const struct utmp *line, struct utmp **utmp, /* Update position pointer. */ utmp_data->loc_utmp += sizeof (struct utmp); + +#if _HAVE_UT_TYPE - 0 + if (utmp_data->ubuf.ut_type == USER_PROCESS + && strncmp (line->ut_line, utmp_data->ubuf.ut_line, + sizeof line->ut_line) == 0) + /* Stop if we found an user entry. */ + break; + + if (utmp_data->ubuf.ut_type == LOGIN_PROCESS) + /* Stop if we found a login entry. */ + break; +#else /* !_HAVE_UT_TYPE */ + if (strncmp (line->ut_line, utmp_data->ubuf.ut_line, + sizeof line->ut_line) == 0) + /* Stop if the line match. */ + break; +#endif } - while (strncmp (line->ut_line, utmp_data->ubuf.ut_line, - sizeof line->ut_line)); *utmp = &utmp_data->ubuf; diff --git a/login/login.c b/login/login.c index 5b71082c52..f74ce41ad8 100644 --- a/login/login.c +++ b/login/login.c @@ -1,63 +1,101 @@ -/* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)login.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ - -#include - -#include +/* Copyright (C) 1996 Free Software Foundation, Inc. +This file is part of the GNU C Library. +Contributed by Ulrich Drepper , 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 +#include +#include #include -#include #include -#include + void -login(ut) - const struct utmp *ut; +login (const struct utmp *ut) { - register int fd; - int tty; - - tty = ttyslot(); - if (tty > 0 && (fd = open(_PATH_UTMP, O_WRONLY|O_CREAT, 0644)) >= 0) { - (void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), L_SET); - (void)write(fd, ut, sizeof(struct utmp)); - (void)close(fd); + char tty[PATH_MAX + UT_LINESIZE]; + int found_tty; + const char *ttyp; + struct utmp_data data; + + /* Seek tty. */ + found_tty = ttyname_r (STDIN_FILENO, tty, sizeof tty); + if (found_tty < 0) + found_tty = ttyname_r (STDOUT_FILENO, tty, sizeof tty); + if (found_tty < 0) + found_tty = ttyname_r (STDERR_FILENO, tty, sizeof tty); + + if (found_tty >= 0) + { + /* Tell that we want to use the UTMP file. */ + if (utmpname (_PATH_UTMP) != 0) + { + struct utmp tmp; + struct utmp *old; + + /* Open UTMP file. */ + setutent_r (&data); + + /* We only want to insert the name of the tty without path. */ + ttyp = basename (tty); + + /* Position to record for this tty. */ +#if _HAVE_UT_TYPE - 0 + tmp.ut_type = USER_PROCESS; +#endif + strncpy (tmp.ut_line, ttyp, UT_LINESIZE); + + /* Read the record. */ + if (getutline_r (&tmp, &old, &data) >= 0 || errno == ESRCH) + { +#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 = ut->ut_type; +#endif + pututline_r (ut, &data); + } + + /* Close UTMP file. */ + endutent_r (&data); } - if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) >= 0) { - (void)write(fd, ut, sizeof(struct utmp)); - (void)close(fd); + } + + /* Update the WTMP file. Here we have to add a new entry. */ + if (utmpname (_PATH_WTMP) != 0) + { + /* Open the WTMP file. */ + setutent_r (&data); + + /* 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 = ut->ut_type; +#endif + pututline_r (ut, &data); } + + /* Close WTMP file. */ + endutent_r (&data); + } } diff --git a/login/logout.c b/login/logout.c index 40ae25456f..d47a392699 100644 --- a/login/logout.c +++ b/login/logout.c @@ -1,72 +1,67 @@ -/* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ +/* Copyright (C) 1996 Free Software Foundation, Inc. +This file is part of the GNU C Library. +Contributed by Ulrich Drepper , 1996. -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)logout.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ +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. -#include -#include +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. -#include -#include -#include -#include -#include +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. */ -typedef struct utmp UTMP; +#include +#include +#include +#include int -logout(line) - register const char *line; +logout (const char *line) { - register int fd; - UTMP ut; - int rval; + struct utmp_data data; + struct utmp tmp; + struct utmp *ut; + int result = 0; + + /* Tell that we want to use the UTMP file. */ + if (utmpname (_PATH_UTMP) == 0) + return 0; + + /* Open UTMP file. */ + setutent_r (&data); + + /* Fill in search information. */ +#if _HAVE_UT_TYPE - 0 + tmp.ut_type = USER_PROCESS; +#endif + strncpy (tmp.ut_line, line, UT_LINESIZE); + + /* Read the record. */ + if (getutline_r (&tmp, &ut, &data) >= 0 || errno == ESRCH) + { + /* Clear information about who & from where. */ + bzero (ut->ut_name, UT_NAMESIZE); + bzero (ut->ut_host, UT_HOSTSIZE); + +#if _HAVE_UT_TV - 0 + gettimeofday (&ut->ut_tv, NULL); +#else + time (&ut->ut_time); +#endif + + if (pututline_r (ut, &data) >= 0) + result = 1; + } + + /* Close UTMP file. */ + endutent_r (&data); - if ((fd = open(_PATH_UTMP, O_RDWR, 0)) < 0) - return(0); - rval = 0; - while (read(fd, &ut, sizeof(UTMP)) == sizeof(UTMP)) { - if (!ut.ut_name[0] || strncmp(ut.ut_line, line, UT_LINESIZE)) - continue; - bzero(ut.ut_name, UT_NAMESIZE); - bzero(ut.ut_host, UT_HOSTSIZE); - (void)time(&ut.ut_time); - (void)lseek(fd, -(off_t)sizeof(UTMP), L_INCR); - (void)write(fd, &ut, sizeof(UTMP)); - rval = 1; - } - (void)close(fd); - return(rval); + return result; } diff --git a/login/logwtmp.c b/login/logwtmp.c index 7734ca9624..10f7384f6c 100644 --- a/login/logwtmp.c +++ b/login/logwtmp.c @@ -1,67 +1,64 @@ -/* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ +/* Copyright (C) 1996 Free Software Foundation, Inc. +This file is part of the GNU C Library. +Contributed by Ulrich Drepper , 1996. -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)logwtmp.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ +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. -#include -#include -#include -#include -#include +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 #include #include + void -logwtmp(line, name, host) - const char *line, *name, *host; +logwtmp (const char *line, const char *name, const char *host) { - struct utmp ut; - struct stat buf; - int fd; + struct utmp_data data; + struct utmp ut; + + /* Tell that we want to use the UTMP file. */ + if (utmpname (_PATH_WTMP) == 0) + return; + + /* Open UTMP file. */ + setutent_r (&data); + + /* Position at end of file. */ + data.loc_utmp = lseek (data.ut_fd, 0, SEEK_END); + if (data.loc_utmp == -1) + return; + + /* Set information in new entry. */ + bzero (&ut, sizeof (ut)); +#if _HAVE_UT_TYPE - 0 + ut.ut_type = USER_PROCESS; +#endif + strncpy (ut.ut_line, line, UT_LINESIZE); + strncpy (ut.ut_name, name, UT_NAMESIZE); + strncpy (ut.ut_host, host, UT_HOSTSIZE); + +#if _HAVE_UT_TV - 0 + gettimeofday (&ut.ut_tv, NULL); +#else + time (&ut.ut_time); +#endif + + /* Write the entry. */ + pututline_r (&ut, &data); + + /* Close UTMP file. */ + endutent_r (&data); - if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) < 0) - return; - if (fstat(fd, &buf) == 0) { - (void) strncpy(ut.ut_line, line, sizeof(ut.ut_line)); - (void) strncpy(ut.ut_name, name, sizeof(ut.ut_name)); - (void) strncpy(ut.ut_host, host, sizeof(ut.ut_host)); - (void) time(&ut.ut_time); - if (write(fd, (char *)&ut, sizeof(struct utmp)) != - sizeof(struct utmp)) - (void) ftruncate(fd, buf.st_size); - } - (void) close(fd); } diff --git a/login/pututline_r.c b/login/pututline_r.c index 92ba8fb308..07322e5740 100644 --- a/login/pututline_r.c +++ b/login/pututline_r.c @@ -26,9 +26,29 @@ Boston, MA 02111-1307, USA. */ #include +/* XXX An alternative solution would be to call a SUID root program + which write the new value. */ + int pututline_r (const struct utmp *utmp_ptr, struct utmp_data *utmp_data) { + struct stat st; + int result = 0; + +#if _HAVE_UT_TYPE - 0 + /* Test whether ID has any of the legal types because we have to + prevent illegal entries. */ + if (id->ut_type != RUN_LVL && id->ut_type != BOOT_TIME + && id->ut_type != OLD_TIME && id->ut_type != NEW_TIME + && id->ut_type != INIT_PROCESS && id->ut_type != LOGIN_PROCESS + && id->ut_type != USER_PROCESS && id->ut_type != DEAD_PROCESS) + /* No, using '<' and '>' for the test is not possible. */ + { + errno = EINVAL; + return -1; + } +#endif + /* Open utmp file if not already done. */ if (utmp_data->ut_fd == -1) { @@ -37,12 +57,14 @@ pututline_r (const struct utmp *utmp_ptr, struct utmp_data *utmp_data) return -1; } +#if _HAVE_UT_TYPE - 0 /* Seek position to write. */ if (utmp_data->ubuf.ut_type != utmp_ptr->ut_type) { /* We must not overwrite the data in UTMP_DATA. */ struct utmp_data *data_tmp = alloca (sizeof (utmp_data)); struct utmp *dummy; + off_t new_pos; *data_tmp = *utmp_data; utmp_data = data_tmp; @@ -50,23 +72,25 @@ pututline_r (const struct utmp *utmp_ptr, struct utmp_data *utmp_data) if (getutid_r (utmp_ptr, &dummy, utmp_data) < 0) { if (errno != ESRCH) + /* Some error occured. If no entry was found, the position + pointer now is at the end of the file. */ return -1; - utmp_data->loc_utmp = lseek (utmp_data->ut_fd, 0, SEEK_END); - if (utmp_data->loc_utmp == -1) - return -1; - } + /* Set position pointer to position after adding of the record. */ + utmp_data->loc_utmp += sizeof (struct utmp); } +#endif + + /* Find out how large the file is. */ + if (fstat (utmp_data->ut_fd, &st) < 0) + return -1; /* Position file correctly. */ - if (utmp_data->loc_utmp > 0 + if (utmp_data->loc_utmp <= st.st_size && lseek (utmp_data->ut_fd, utmp_data->loc_utmp - sizeof (struct utmp), SEEK_SET) < 0) return -1; - /* XXX An alternative solution would be to call an SUID root program - which write the new value. */ - /* Try to lock the file. */ if (flock (utmp_data->ut_fd, LOCK_EX | LOCK_NB) < 0 && errno != ENOSYS) { @@ -78,12 +102,22 @@ pututline_r (const struct utmp *utmp_ptr, struct utmp_data *utmp_data) } /* Write the new data. */ - if (write (utmp_data->ut_fd, &utmp_data->ubuf, sizeof (struct utmp)) + if (write (utmp_data->ut_fd, utmp_ptr, sizeof (struct utmp)) != sizeof (struct utmp)) - return -1; + { + /* If we appended a new record this is only partially written. + Remove it. */ + if (utmp_data->loc_utmp > st.st_size) + { + (void) ftruncate (utmp_data->ut_fd, st.st_size); + utmp_data->loc_utmp = st.st_size; + } + + result = -1; + } /* And unlock the file. */ (void) flock (utmp_data->ut_fd, LOCK_UN); - return 0; + return result; } diff --git a/login/setutent_r.c b/login/setutent_r.c index 715101d659..4b980cf1a7 100644 --- a/login/setutent_r.c +++ b/login/setutent_r.c @@ -52,7 +52,9 @@ setutent_r (struct utmp_data *utmp_data) /* Remember we are at beginning of file. */ utmp_data->loc_utmp = 0; - utmp_data->ubuf.ut_type = -1; +#if _HAVE_UT_TYPE - 0 + utmp_data->ubuf.ut_type = UT_UNKNOWN; +#endif } -- cgit v1.2.3