diff options
Diffstat (limited to 'REORG.TODO/login')
47 files changed, 3489 insertions, 0 deletions
diff --git a/REORG.TODO/login/Makefile b/REORG.TODO/login/Makefile new file mode 100644 index 0000000000..011724cb5d --- /dev/null +++ b/REORG.TODO/login/Makefile @@ -0,0 +1,73 @@ +# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 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 +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# <http://www.gnu.org/licenses/>. + +# +# Sub-makefile for login portion of the library. +# + +subdir := login + +include ../Makeconfig + +headers := utmp.h bits/utmp.h lastlog.h pty.h + +routines := getlogin getlogin_r setlogin getlogin_r_chk \ + getutent getutent_r getutid getutline getutid_r getutline_r \ + utmp_file utmpname updwtmp getpt grantpt unlockpt ptsname \ + ptsname_r_chk + +CFLAGS-grantpt.c = -DLIBEXECDIR='"$(libexecdir)"' + +others = utmpdump + +ifeq (yes,$(build-pt-chown)) +others += pt_chown +others-pie = pt_chown +install-others-programs = $(inst_libexecdir)/pt_chown +endif + +subdir-dirs = programs +vpath %.c programs + +tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin + +# Build the -lutil library with these extra functions. +extra-libs := libutil +extra-libs-others := $(extra-libs) + +libutil-routines:= login login_tty logout logwtmp openpty forkpty + +include ../Rules + +CFLAGS-getpt.c = -fexceptions + +ifeq (yesyes,$(have-fpie)$(build-shared)) +pt_chown-cflags += $(pie-ccflag) +endif +ifeq (yes,$(have-libcap)) +libcap = -lcap +endif +CFLAGS-pt_chown.c = $(pt_chown-cflags) +LDLIBS-pt_chown = $(libcap) +ifeq (yesyes,$(have-fpie)$(build-shared)) +LDFLAGS-pt_chown = -Wl,-z,now +endif + +# pt_chown needs to be setuid root. +$(inst_libexecdir)/pt_chown: $(objpfx)pt_chown $(+force) + $(make-target-directory) + -$(INSTALL_PROGRAM) -m 4755 -o root $< $@ diff --git a/REORG.TODO/login/Versions b/REORG.TODO/login/Versions new file mode 100644 index 0000000000..475fcf063f --- /dev/null +++ b/REORG.TODO/login/Versions @@ -0,0 +1,54 @@ +libc { + GLIBC_2.0 { + # e* + endutent; + + # g* + getlogin; getlogin_r; getutent; getutent_r; getutid; getutid_r; getutline; + getutline_r; + + # p* + pututline; + + # s* + setlogin; + setutent; + + # u* + updwtmp; utmpname; + } + GLIBC_2.1 { + # e* + endutxent; + + # g* + getpt; getutxent; getutxid; getutxline; grantpt; + + # p* + ptsname; ptsname_r; pututxline; + + # s* + setutxent; + + # u* + unlockpt; updwtmpx; utmpxname; + } + GLIBC_2.1.1 { + # g* + getutmpx; getutmp; + } + GLIBC_2.2.1 { + # p* + posix_openpt; + } + GLIBC_2.4 { + __getlogin_r_chk; + __ptsname_r_chk; + } +} + +libutil { + GLIBC_2.0 { + forkpty; login; login_tty; logout; logwtmp; openpty; + } +} diff --git a/REORG.TODO/login/endutxent.c b/REORG.TODO/login/endutxent.c new file mode 100644 index 0000000000..e8a351a230 --- /dev/null +++ b/REORG.TODO/login/endutxent.c @@ -0,0 +1,26 @@ +/* Copyright (C) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <utmp.h> +#include <utmpx.h> + +void +endutxent (void) +{ + __endutent (); +} diff --git a/REORG.TODO/login/forkpty.c b/REORG.TODO/login/forkpty.c new file mode 100644 index 0000000000..cb1ddab7ad --- /dev/null +++ b/REORG.TODO/login/forkpty.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <sys/types.h> +#include <termios.h> +#include <unistd.h> +#include <utmp.h> +#include <pty.h> + +int +forkpty (int *amaster, char *name, const struct termios *termp, + const struct winsize *winp) +{ + int master, slave, pid; + + if (openpty (&master, &slave, name, termp, winp) == -1) + return -1; + + switch (pid = fork ()) + { + case -1: + close (master); + close (slave); + return -1; + case 0: + /* Child. */ + close (master); + if (login_tty (slave)) + _exit (1); + + return 0; + default: + /* Parent. */ + *amaster = master; + close (slave); + + return pid; + } +} diff --git a/REORG.TODO/login/getlogin.c b/REORG.TODO/login/getlogin.c new file mode 100644 index 0000000000..2743578d16 --- /dev/null +++ b/REORG.TODO/login/getlogin.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1991-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <stddef.h> +#include <errno.h> +#include <unistd.h> + +/* Return the login name of the user, or NULL if it can't be determined. + The returned pointer, if not NULL, is good only until the next call. */ +char * +getlogin (void) +{ + __set_errno (ENOSYS); + return NULL; +} + +stub_warning (getlogin) diff --git a/REORG.TODO/login/getlogin_r.c b/REORG.TODO/login/getlogin_r.c new file mode 100644 index 0000000000..209d78ffce --- /dev/null +++ b/REORG.TODO/login/getlogin_r.c @@ -0,0 +1,35 @@ +/* Reentrant function to return the current login name. Stub version. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <unistd.h> + +/* Return at most NAME_LEN characters of the login name of the user in NAME. + If it cannot be determined or some other error occurred, return the error + code. Otherwise return 0. */ +int +__getlogin_r (char *name, size_t name_len) +{ + __set_errno (ENOSYS); + return errno; +} +libc_hidden_def (__getlogin_r) +weak_alias (__getlogin_r, getlogin_r) +libc_hidden_weak (getlogin_r) + +stub_warning (getlogin_r) diff --git a/REORG.TODO/login/getlogin_r_chk.c b/REORG.TODO/login/getlogin_r_chk.c new file mode 100644 index 0000000000..5e98e5ad48 --- /dev/null +++ b/REORG.TODO/login/getlogin_r_chk.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2005-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <unistd.h> + + +int +__getlogin_r_chk (char *buf, size_t buflen, size_t nreal) +{ + if (buflen > nreal) + __chk_fail (); + + return getlogin_r (buf, buflen); +} diff --git a/REORG.TODO/login/getpt.c b/REORG.TODO/login/getpt.c new file mode 100644 index 0000000000..aa859725b0 --- /dev/null +++ b/REORG.TODO/login/getpt.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <stdlib.h> +#include <errno.h> + +/* Open the master side of a pseudoterminal and return its file + descriptor, or -1 on error. */ +int +__getpt (void) +{ + __set_errno (ENOSYS); + return -1; +} +weak_alias (__getpt, getpt) + +/* We cannot define posix_openpt in general for BSD systems. */ +int +__posix_openpt (int oflag) +{ + __set_errno (ENOSYS); + return -1; +} +weak_alias (__posix_openpt, posix_openpt) + +stub_warning (getpt) +stub_warning (posix_openpt) diff --git a/REORG.TODO/login/getutent.c b/REORG.TODO/login/getutent.c new file mode 100644 index 0000000000..114f7dbbc7 --- /dev/null +++ b/REORG.TODO/login/getutent.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <stdlib.h> +#include <utmp.h> + + +/* Local buffer to store the result. */ +libc_freeres_ptr (static struct utmp *buffer); + + +struct utmp * +__getutent (void) +{ + struct utmp *result; + + if (buffer == NULL) + { + buffer = (struct utmp *) malloc (sizeof (struct utmp)); + if (buffer == NULL) + return NULL; + } + + if (__getutent_r (buffer, &result) < 0) + return NULL; + + return result; +} +weak_alias (__getutent, getutent) diff --git a/REORG.TODO/login/getutent_r.c b/REORG.TODO/login/getutent_r.c new file mode 100644 index 0000000000..62272a2841 --- /dev/null +++ b/REORG.TODO/login/getutent_r.c @@ -0,0 +1,183 @@ +/* Copyright (C) 1996-2017 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <libc-lock.h> +#include <stdlib.h> +#include <utmp.h> + +#include "utmp-private.h" + + +/* Functions defined here. */ +static int setutent_unknown (void); +static int getutent_r_unknown (struct utmp *buffer, struct utmp **result); +static int getutid_r_unknown (const struct utmp *line, struct utmp *buffer, + struct utmp **result); +static int getutline_r_unknown (const struct utmp *id, struct utmp *buffer, + struct utmp **result); +static struct utmp *pututline_unknown (const struct utmp *data); +static void endutent_unknown (void); + +/* Initial Jump table. */ +const struct utfuncs __libc_utmp_unknown_functions = +{ + setutent_unknown, + getutent_r_unknown, + getutid_r_unknown, + getutline_r_unknown, + pututline_unknown, + endutent_unknown, + NULL +}; + +/* Currently selected backend. */ +const struct utfuncs *__libc_utmp_jump_table = &__libc_utmp_unknown_functions; + +/* We need to protect the opening of the file. */ +__libc_lock_define_initialized (, __libc_utmp_lock attribute_hidden) + + +static int +setutent_unknown (void) +{ + int result; + + result = (*__libc_utmp_file_functions.setutent) (); + if (result) + __libc_utmp_jump_table = &__libc_utmp_file_functions; + + return result; +} + + +static int +getutent_r_unknown (struct utmp *buffer, struct utmp **result) +{ + /* The backend was not yet initialized. */ + if (setutent_unknown ()) + return (*__libc_utmp_jump_table->getutent_r) (buffer, result); + + /* Not available. */ + *result = NULL; + return -1; +} + + +static int +getutid_r_unknown (const struct utmp *id, struct utmp *buffer, + struct utmp **result) +{ + /* The backend was not yet initialized. */ + if (setutent_unknown ()) + return (*__libc_utmp_jump_table->getutid_r) (id, buffer, result); + + /* Not available. */ + *result = NULL; + return -1; +} + + +static int +getutline_r_unknown (const struct utmp *line, struct utmp *buffer, + struct utmp **result) +{ + /* The backend was not yet initialized. */ + if (setutent_unknown ()) + return (*__libc_utmp_jump_table->getutline_r) (line, buffer, result); + + /* Not available. */ + *result = NULL; + return -1; +} + + +static struct utmp * +pututline_unknown (const struct utmp *data) +{ + /* The backend was not yet initialized. */ + if (setutent_unknown ()) + return (*__libc_utmp_jump_table->pututline) (data); + + /* Not available. */ + return NULL; +} + + +static void +endutent_unknown (void) +{ + /* Nothing to do. */ +} + + +void +__setutent (void) +{ + __libc_lock_lock (__libc_utmp_lock); + + (*__libc_utmp_jump_table->setutent) (); + + __libc_lock_unlock (__libc_utmp_lock); +} +weak_alias (__setutent, setutent) + + +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) + + +struct utmp * +__pututline (const struct utmp *data) +{ + struct utmp *buffer; + + __libc_lock_lock (__libc_utmp_lock); + + buffer = (*__libc_utmp_jump_table->pututline) (data); + + __libc_lock_unlock (__libc_utmp_lock); + + return buffer; +} +weak_alias (__pututline, pututline) + + +void +__endutent (void) +{ + __libc_lock_lock (__libc_utmp_lock); + + (*__libc_utmp_jump_table->endutent) (); + __libc_utmp_jump_table = &__libc_utmp_unknown_functions; + + __libc_lock_unlock (__libc_utmp_lock); +} +weak_alias (__endutent, endutent) diff --git a/REORG.TODO/login/getutid.c b/REORG.TODO/login/getutid.c new file mode 100644 index 0000000000..003bc657e6 --- /dev/null +++ b/REORG.TODO/login/getutid.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <stdlib.h> +#include <utmp.h> + + +/* Local buffer to store the result. */ +libc_freeres_ptr (static struct utmp *buffer); + +struct utmp * +__getutid (const struct utmp *id) +{ + struct utmp *result; + + if (buffer == NULL) + { + buffer = (struct utmp *) malloc (sizeof (struct utmp)); + if (buffer == NULL) + return NULL; + } + if (__getutid_r (id, buffer, &result) < 0) + return NULL; + + return result; +} +weak_alias (__getutid, getutid) diff --git a/REORG.TODO/login/getutid_r.c b/REORG.TODO/login/getutid_r.c new file mode 100644 index 0000000000..f82301322f --- /dev/null +++ b/REORG.TODO/login/getutid_r.c @@ -0,0 +1,62 @@ +/* Copyright (C) 1996-2017 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <libc-lock.h> +#include <errno.h> +#include <stdlib.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 attribute_hidden) + + +int +__getutid_r (const struct utmp *id, struct utmp *buffer, struct utmp **result) +{ +#if (_HAVE_UT_ID - 0) && (_HAVE_UT_TYPE - 0) + int retval; + + /* 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. */ + { + __set_errno (EINVAL); + *result = NULL; + return -1; + } + + __libc_lock_lock (__libc_utmp_lock); + + retval = (*__libc_utmp_jump_table->getutid_r) (id, buffer, result); + + __libc_lock_unlock (__libc_utmp_lock); + + return retval; +#else /* !_HAVE_UT_ID && !_HAVE_UT_TYPE */ + __set_errno (ENOSYS); + return -1; +#endif +} +weak_alias (__getutid_r, getutid_r) diff --git a/REORG.TODO/login/getutline.c b/REORG.TODO/login/getutline.c new file mode 100644 index 0000000000..f5291e8a8e --- /dev/null +++ b/REORG.TODO/login/getutline.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <stdlib.h> +#include <utmp.h> + + +/* Local buffer to store the result. */ +libc_freeres_ptr (static struct utmp *buffer); + + +struct utmp * +__getutline (const struct utmp *line) +{ + struct utmp *result; + + if (buffer == NULL) + { + buffer = (struct utmp *) malloc (sizeof (struct utmp)); + if (buffer == NULL) + return NULL; + } + if (__getutline_r (line, buffer, &result) < 0) + return NULL; + + return result; +} +weak_alias (__getutline, getutline) diff --git a/REORG.TODO/login/getutline_r.c b/REORG.TODO/login/getutline_r.c new file mode 100644 index 0000000000..1a6f1688ee --- /dev/null +++ b/REORG.TODO/login/getutline_r.c @@ -0,0 +1,45 @@ +/* Copyright (C) 1996-2017 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <libc-lock.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 attribute_hidden) + + +int +__getutline_r (const struct utmp *line, struct utmp *buffer, + struct utmp **result) +{ + int retval; + + __libc_lock_lock (__libc_utmp_lock); + + retval = (*__libc_utmp_jump_table->getutline_r) (line, buffer, result); + + __libc_lock_unlock (__libc_utmp_lock); + + return retval; +} +weak_alias (__getutline_r, getutline_r) diff --git a/REORG.TODO/login/getutmp.c b/REORG.TODO/login/getutmp.c new file mode 100644 index 0000000000..4160cf589a --- /dev/null +++ b/REORG.TODO/login/getutmp.c @@ -0,0 +1,45 @@ +/* Copyright (C) 1999-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <string.h> +#include <utmp.h> +#include <utmpx.h> + +/* Copy the information in UTMPX to UTMP. */ +void +getutmp (const struct utmpx *utmpx, struct utmp *utmp) +{ +#if _HAVE_UT_TYPE - 0 + utmp->ut_type = utmpx->ut_type; +#endif +#if _HAVE_UT_PID - 0 + utmp->ut_pid = utmpx->ut_pid; +#endif + memcpy (utmp->ut_line, utmpx->ut_line, sizeof (utmp->ut_line)); + memcpy (utmp->ut_user, utmpx->ut_user, sizeof (utmp->ut_user)); +#if _HAVE_UT_ID - 0 + memcpy (utmp->ut_id, utmpx->ut_id, sizeof (utmp->ut_id)); +#endif +#if _HAVE_UT_HOST - 0 + memcpy (utmp->ut_host, utmpx->ut_host, sizeof (utmp->ut_host)); +#endif +#if _HAVE_UT_TV - 0 + utmp->ut_tv = utmpx->ut_tv; +#else + utmp->ut_time = utmpx->ut_time; +#endif +} diff --git a/REORG.TODO/login/getutmpx.c b/REORG.TODO/login/getutmpx.c new file mode 100644 index 0000000000..77dc78cc3e --- /dev/null +++ b/REORG.TODO/login/getutmpx.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1999-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <string.h> +#include <utmp.h> +#include <utmpx.h> + +/* Copy the information in UTMP to UTMPX. */ +void +getutmpx (const struct utmp *utmp, struct utmpx *utmpx) +{ + memset (utmpx, 0, sizeof (struct utmpx)); + +#if _HAVE_UT_TYPE - 0 + utmpx->ut_type = utmp->ut_type; +#endif +#if _HAVE_UT_PID - 0 + utmpx->ut_pid = utmp->ut_pid; +#endif + memcpy (utmpx->ut_line, utmp->ut_line, sizeof (utmp->ut_line)); + memcpy (utmpx->ut_user, utmp->ut_user, sizeof (utmp->ut_user)); +#if _HAVE_UT_ID - 0 + memcpy (utmpx->ut_id, utmp->ut_id, sizeof (utmp->ut_id)); +#endif +#if _HAVE_UT_HOST - 0 + memcpy (utmpx->ut_host, utmp->ut_host, sizeof (utmp->ut_host)); +#endif +#if _HAVE_UT_TV - 0 + utmpx->ut_tv = utmp->ut_tv; +#else + utmpx->ut_time = utmp->ut_time; +#endif +} diff --git a/REORG.TODO/login/getutxent.c b/REORG.TODO/login/getutxent.c new file mode 100644 index 0000000000..89bdb2e271 --- /dev/null +++ b/REORG.TODO/login/getutxent.c @@ -0,0 +1,26 @@ +/* Copyright (C) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <utmp.h> +#include <utmpx.h> + +struct utmpx * +getutxent (void) +{ + return (struct utmpx *) __getutent (); +} diff --git a/REORG.TODO/login/getutxid.c b/REORG.TODO/login/getutxid.c new file mode 100644 index 0000000000..435c96d0ef --- /dev/null +++ b/REORG.TODO/login/getutxid.c @@ -0,0 +1,26 @@ +/* Copyright (C) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <utmp.h> +#include <utmpx.h> + +struct utmpx * +getutxid (const struct utmpx *id) +{ + return (struct utmpx *) __getutid ((const struct utmp *) id); +} diff --git a/REORG.TODO/login/getutxline.c b/REORG.TODO/login/getutxline.c new file mode 100644 index 0000000000..f71a43011f --- /dev/null +++ b/REORG.TODO/login/getutxline.c @@ -0,0 +1,26 @@ +/* Copyright (C) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <utmp.h> +#include <utmpx.h> + +struct utmpx * +getutxline (const struct utmpx *line) +{ + return (struct utmpx *) __getutline ((const struct utmp *) line); +} diff --git a/REORG.TODO/login/grantpt.c b/REORG.TODO/login/grantpt.c new file mode 100644 index 0000000000..badc004083 --- /dev/null +++ b/REORG.TODO/login/grantpt.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <stdlib.h> +#include <errno.h> + +/* Given a fd on a master pseudoterminal, chown the file associated + with the slave to the calling process, and set its group and + mode appropriately. Note that this is an unprivileged operation. */ +int +grantpt (int fd __attribute__ ((unused))) +{ + __set_errno (ENOSYS); + return -1; +} + +stub_warning (grantpt) diff --git a/REORG.TODO/login/lastlog.h b/REORG.TODO/login/lastlog.h new file mode 100644 index 0000000000..8cc4254364 --- /dev/null +++ b/REORG.TODO/login/lastlog.h @@ -0,0 +1,4 @@ +/* This header file is used in 4.3BSD to define `struct lastlog', + which we define in <bits/utmp.h>. */ + +#include <utmp.h> diff --git a/REORG.TODO/login/login.c b/REORG.TODO/login/login.c new file mode 100644 index 0000000000..b8171de83c --- /dev/null +++ b/REORG.TODO/login/login.c @@ -0,0 +1,143 @@ +/* Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <utmp.h> + + +/* Return the result of ttyname in the buffer pointed to by TTY, which should + be of length BUF_LEN. If it is too long to fit in this buffer, a + sufficiently long buffer is allocated using malloc, and returned in TTY. + 0 is returned upon success, -1 otherwise. */ +static int +tty_name (int fd, char **tty, size_t buf_len) +{ + int rv; /* Return value. 0 = success. */ + char *buf = *tty; /* Buffer for ttyname, initially the user's. */ + + for (;;) + { + char *new_buf; + + if (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. */ + break; + + /* Try again with a longer buffer. */ + buf_len += buf_len; /* Double it */ + } + else + /* No initial buffer; start out by mallocing one. */ + buf_len = 128; /* First time guess. */ + + if (buf != *tty) + /* We've already malloced another buffer at least once. */ + new_buf = realloc (buf, buf_len); + else + new_buf = malloc (buf_len); + if (! new_buf) + { + rv = -1; + __set_errno (ENOMEM); + break; + } + buf = new_buf; + } + + if (rv == 0) + *tty = buf; /* Return buffer to the user. */ + else if (buf != *tty) + free (buf); /* Free what we malloced when returning an error. */ + + return rv; +} + +void +login (const struct utmp *ut) +{ +#ifdef PATH_MAX + char _tty[PATH_MAX + UT_LINESIZE]; +#else + char _tty[512 + UT_LINESIZE]; +#endif + char *tty = _tty; + int found_tty; + const char *ttyp; + struct utmp copy = *ut; + + /* Fill in those fields we supply. */ +#if _HAVE_UT_TYPE - 0 + copy.ut_type = USER_PROCESS; +#endif +#if _HAVE_UT_PID - 0 + copy.ut_pid = getpid (); +#endif + + /* Seek tty. */ + found_tty = tty_name (STDIN_FILENO, &tty, sizeof (_tty)); + if (found_tty < 0) + found_tty = tty_name (STDOUT_FILENO, &tty, sizeof (_tty)); + if (found_tty < 0) + found_tty = tty_name (STDERR_FILENO, &tty, sizeof (_tty)); + + if (found_tty >= 0) + { + /* We only want to insert the name of the tty without path. + But take care of name like /dev/pts/3. */ + if (strncmp (tty, "/dev/", 5) == 0) + ttyp = tty + 5; /* Skip the "/dev/". */ + else + ttyp = basename (tty); + + /* Position to record for this tty. */ + strncpy (copy.ut_line, ttyp, UT_LINESIZE); + + /* Tell that we want to use the UTMP file. */ + if (utmpname (_PATH_UTMP) == 0) + { + /* Open UTMP file. */ + setutent (); + + /* Write the entry. */ + pututline (©); + + /* Close UTMP file. */ + endutent (); + } + + if (tty != _tty) + free (tty); /* Free buffer malloced by tty_name. */ + } + else + /* We provide a default value so that the output does not contain + an random bytes in this field. */ + strncpy (copy.ut_line, "???", UT_LINESIZE); + + /* Update the WTMP file. Here we have to add a new entry. */ + updwtmp (_PATH_WTMP, ©); +} diff --git a/REORG.TODO/login/login_tty.c b/REORG.TODO/login/login_tty.c new file mode 100644 index 0000000000..a94f5cb861 --- /dev/null +++ b/REORG.TODO/login/login_tty.c @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 1990, 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. + * 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_tty.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include <errno.h> +#include <sys/param.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <fcntl.h> +#include <utmp.h> + +int +login_tty (int fd) +{ + (void) setsid(); +#ifdef TIOCSCTTY + if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) + return (-1); +#else + { + /* This might work. */ + char *fdname = ttyname (fd); + int newfd; + if (fdname) + { + if (fd != 0) + (void) close (0); + if (fd != 1) + (void) close (1); + if (fd != 2) + (void) close (2); + newfd = open (fdname, O_RDWR); + (void) close (newfd); + } + } +#endif + while (dup2(fd, 0) == -1 && errno == EBUSY) + ; + while (dup2(fd, 1) == -1 && errno == EBUSY) + ; + while (dup2(fd, 2) == -1 && errno == EBUSY) + ; + if (fd > 2) + (void) close(fd); + return (0); +} +libutil_hidden_def (login_tty) diff --git a/REORG.TODO/login/logout.c b/REORG.TODO/login/logout.c new file mode 100644 index 0000000000..6a8ce265ee --- /dev/null +++ b/REORG.TODO/login/logout.c @@ -0,0 +1,72 @@ +/* Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <string.h> +#include <utmp.h> +#include <sys/time.h> + +int +logout (const char *line) +{ + struct utmp tmp, utbuf; + struct utmp *ut; + int result = 0; + + /* Tell that we want to use the UTMP file. */ + if (utmpname (_PATH_UTMP) == -1) + return 0; + + /* Open UTMP file. */ + setutent (); + + /* Fill in search information. */ +#if _HAVE_UT_TYPE - 0 + tmp.ut_type = USER_PROCESS; +#endif + strncpy (tmp.ut_line, line, sizeof tmp.ut_line); + + /* Read the record. */ + if (getutline_r (&tmp, &utbuf, &ut) >= 0) + { + /* Clear information about who & from where. */ + memset (ut->ut_name, '\0', sizeof ut->ut_name); +#if _HAVE_UT_HOST - 0 + memset (ut->ut_host, '\0', sizeof ut->ut_host); +#endif +#if _HAVE_UT_TV - 0 + struct timeval tv; + __gettimeofday (&tv, NULL); + ut->ut_tv.tv_sec = tv.tv_sec; + ut->ut_tv.tv_usec = tv.tv_usec; +#else + ut->ut_time = time (NULL); +#endif +#if _HAVE_UT_TYPE - 0 + ut->ut_type = DEAD_PROCESS; +#endif + + if (pututline (ut) != NULL) + result = 1; + } + + /* Close UTMP file. */ + endutent (); + + return result; +} diff --git a/REORG.TODO/login/logwtmp.c b/REORG.TODO/login/logwtmp.c new file mode 100644 index 0000000000..b62c887adf --- /dev/null +++ b/REORG.TODO/login/logwtmp.c @@ -0,0 +1,55 @@ +/* Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <string.h> +#include <sys/time.h> +#include <time.h> +#include <unistd.h> +#include <utmp.h> + + +void +logwtmp (const char *line, const char *name, const char *host) +{ + struct utmp ut; + + /* Set information in new entry. */ + memset (&ut, 0, sizeof (ut)); +#if _HAVE_UT_PID - 0 + ut.ut_pid = getpid (); +#endif +#if _HAVE_UT_TYPE - 0 + ut.ut_type = name[0] ? USER_PROCESS : DEAD_PROCESS; +#endif + strncpy (ut.ut_line, line, sizeof ut.ut_line); + strncpy (ut.ut_name, name, sizeof ut.ut_name); +#if _HAVE_UT_HOST - 0 + strncpy (ut.ut_host, host, sizeof ut.ut_host); +#endif + +#if _HAVE_UT_TV - 0 + struct timeval tv; + __gettimeofday (&tv, NULL); + ut.ut_tv.tv_sec = tv.tv_sec; + ut.ut_tv.tv_usec = tv.tv_usec; +#else + ut.ut_time = time (NULL); +#endif + + updwtmp (_PATH_WTMP, &ut); +} diff --git a/REORG.TODO/login/openpty.c b/REORG.TODO/login/openpty.c new file mode 100644 index 0000000000..41ab0483e2 --- /dev/null +++ b/REORG.TODO/login/openpty.c @@ -0,0 +1,140 @@ +/* Copyright (C) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <pty.h> +#include <stdlib.h> +#include <string.h> +#include <termios.h> +#include <unistd.h> +#include <sys/types.h> + + +/* Return the result of ptsname_r in the buffer pointed to by PTS, + which should be of length BUF_LEN. If it is too long to fit in + this buffer, a sufficiently long buffer is allocated using malloc, + and returned in PTS. 0 is returned upon success, -1 otherwise. */ +static int +pts_name (int fd, char **pts, size_t buf_len) +{ + int rv; + char *buf = *pts; + + for (;;) + { + char *new_buf; + + if (buf_len) + { + rv = ptsname_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. */ + break; + + /* Try again with a longer buffer. */ + buf_len += buf_len; /* Double it */ + } + else + /* No initial buffer; start out by mallocing one. */ + buf_len = 128; /* First time guess. */ + + if (buf != *pts) + /* We've already malloced another buffer at least once. */ + new_buf = realloc (buf, buf_len); + else + new_buf = malloc (buf_len); + if (! new_buf) + { + rv = -1; + __set_errno (ENOMEM); + break; + } + buf = new_buf; + } + + if (rv == 0) + *pts = buf; /* Return buffer to the user. */ + else if (buf != *pts) + free (buf); /* Free what we malloced when returning an error. */ + + return rv; +} + +/* Create pseudo tty master slave pair and set terminal attributes + according to TERMP and WINP. Return handles for both ends in + AMASTER and ASLAVE, and return the name of the slave end in NAME. */ +int +openpty (int *amaster, int *aslave, char *name, + const struct termios *termp, const struct winsize *winp) +{ +#ifdef PATH_MAX + char _buf[PATH_MAX]; +#else + char _buf[512]; +#endif + char *buf = _buf; + int master, slave; + + master = getpt (); + if (master == -1) + return -1; + + if (grantpt (master)) + goto fail; + + if (unlockpt (master)) + goto fail; + + if (pts_name (master, &buf, sizeof (_buf))) + goto fail; + + slave = open (buf, O_RDWR | O_NOCTTY); + if (slave == -1) + { + if (buf != _buf) + free (buf); + + goto fail; + } + + /* XXX Should we ignore errors here? */ + if (termp) + tcsetattr (slave, TCSAFLUSH, termp); +#ifdef TIOCSWINSZ + if (winp) + ioctl (slave, TIOCSWINSZ, winp); +#endif + + *amaster = master; + *aslave = slave; + if (name != NULL) + strcpy (name, buf); + + if (buf != _buf) + free (buf); + return 0; + + fail: + close (master); + return -1; +} +libutil_hidden_def (openpty) diff --git a/REORG.TODO/login/programs/pt_chown.c b/REORG.TODO/login/programs/pt_chown.c new file mode 100644 index 0000000000..f12064bea5 --- /dev/null +++ b/REORG.TODO/login/programs/pt_chown.c @@ -0,0 +1,215 @@ +/* pt_chmod - helper program for `grantpt'. + Copyright (C) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by C. Scott Ananian <cananian@alumni.princeton.edu>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <argp.h> +#include <errno.h> +#include <error.h> +#include <grp.h> +#include <libintl.h> +#include <locale.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> +#ifdef HAVE_LIBCAP +# include <sys/capability.h> +# include <sys/prctl.h> +#endif + +#include "pty-private.h" + +/* Get libc version number. */ +#include "../version.h" + +#define PACKAGE _libc_intl_domainname + +/* Name and version of program. */ +static void print_version (FILE *stream, struct argp_state *state); +void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; + +/* Function to print some extra text in the help message. */ +static char *more_help (int key, const char *text, void *input); + +/* Data structure to communicate with argp functions. */ +static struct argp argp = +{ + NULL, NULL, NULL, NULL, NULL, more_help +}; + + +/* Print the version information. */ +static void +print_version (FILE *stream, struct argp_state *state) +{ + fprintf (stream, "pt_chown %s%s\n", PKGVERSION, VERSION); + fprintf (stream, gettext ("\ +Copyright (C) %s Free Software Foundation, Inc.\n\ +This is free software; see the source for copying conditions. There is NO\n\ +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ +"), "2017"); +} + +static char * +more_help (int key, const char *text, void *input) +{ + char *cp; + char *tp; + + switch (key) + { + case ARGP_KEY_HELP_PRE_DOC: + asprintf (&cp, gettext ("\ +Set the owner, group and access permission of the slave pseudo\ + terminal corresponding to the master pseudo terminal passed on\ + file descriptor `%d'. This is the helper program for the\ + `grantpt' function. It is not intended to be run directly from\ + the command line.\n"), + PTY_FILENO); + return cp; + case ARGP_KEY_HELP_EXTRA: + /* We print some extra information. */ + if (asprintf (&tp, gettext ("\ +For bug reporting instructions, please see:\n\ +%s.\n"), REPORT_BUGS_TO) < 0) + return NULL; + if (asprintf (&cp, gettext ("\ +The owner is set to the current user, the group is set to `%s',\ + and the access permission is set to `%o'.\n\n\ +%s"), + TTY_GROUP, S_IRUSR|S_IWUSR|S_IWGRP, tp) < 0) + { + free (tp); + return NULL; + } + return cp; + default: + break; + } + return (char *) text; +} + +static int +do_pt_chown (void) +{ + char *pty; + struct stat64 st; + struct group *p; + gid_t gid; + + /* Check that PTY_FILENO is a valid master pseudo terminal. */ + pty = ptsname (PTY_FILENO); + if (pty == NULL) + return errno == EBADF ? FAIL_EBADF : FAIL_EINVAL; + + /* Check that the returned slave pseudo terminal is a + character device. */ + if (stat64 (pty, &st) < 0 || !S_ISCHR (st.st_mode)) + return FAIL_EINVAL; + + /* Get the group ID of the special `tty' group. */ + p = getgrnam (TTY_GROUP); + gid = p ? p->gr_gid : getgid (); + + /* Set the owner to the real user ID, and the group to that special + group ID. */ + if (chown (pty, getuid (), gid) < 0) + return FAIL_EACCES; + + /* Set the permission mode to readable and writable by the owner, + and writable by the group. */ + if ((st.st_mode & ACCESSPERMS) != (S_IRUSR|S_IWUSR|S_IWGRP) + && chmod (pty, S_IRUSR|S_IWUSR|S_IWGRP) < 0) + return FAIL_EACCES; + + return 0; +} + + +int +main (int argc, char *argv[]) +{ + uid_t euid = geteuid (); + uid_t uid = getuid (); + int remaining; + sigset_t signalset; + + /* Clear any signal mask from the parent process. */ + sigemptyset (&signalset); + sigprocmask (SIG_SETMASK, &signalset, NULL); + + if (argc == 1 && euid == 0) + { +#ifdef HAVE_LIBCAP + /* Drop privileges. */ + if (uid != euid) + { + static const cap_value_t cap_list[] = + { CAP_CHOWN, CAP_FOWNER }; +# define ncap_list (sizeof (cap_list) / sizeof (cap_list[0])) + cap_t caps = cap_init (); + if (caps == NULL) + return FAIL_ENOMEM; + + /* There is no reason why these should not work. */ + cap_set_flag (caps, CAP_PERMITTED, ncap_list, cap_list, CAP_SET); + cap_set_flag (caps, CAP_EFFECTIVE, ncap_list, cap_list, CAP_SET); + + int res = cap_set_proc (caps); + + cap_free (caps); + + if (__glibc_unlikely (res != 0)) + return FAIL_EXEC; + } +#endif + + /* Normal invocation of this program is with no arguments and + with privileges. */ + return do_pt_chown (); + } + + /* We aren't going to be using privileges, so drop them right now. */ + setuid (uid); + + /* Set locale via LC_ALL. */ + setlocale (LC_ALL, ""); + + /* Set the text message domain. */ + textdomain (PACKAGE); + + /* parse and process arguments. */ + argp_parse (&argp, argc, argv, 0, &remaining, NULL); + + if (remaining < argc) + { + /* We should not be called with any non-option parameters. */ + error (0, 0, gettext ("too many arguments")); + argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR, + program_invocation_short_name); + return EXIT_FAILURE; + } + + /* Check if we are properly installed. */ + if (euid != 0) + error (FAIL_EXEC, 0, gettext ("needs to be installed setuid `root'")); + + return EXIT_SUCCESS; +} diff --git a/REORG.TODO/login/programs/utmpdump.c b/REORG.TODO/login/programs/utmpdump.c new file mode 100644 index 0000000000..35bf0f9c27 --- /dev/null +++ b/REORG.TODO/login/programs/utmpdump.c @@ -0,0 +1,99 @@ +/* utmpdump - dump utmp-like files. + Copyright (C) 1997-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> +#include <utmp.h> + +static void +print_entry (struct utmp *up) +{ + /* Mixed 32-/64-bit systems may have timeval structs of different sixe + but need struct utmp to be the same size. So in 64-bit up->ut_tv may + not be a timeval but a struct of __int32_t's. This would cause a compile + time warning and a formating error when 32-bit int is passed where + a 64-bit long is expected. So copy up->up_tv to a temporary timeval. + This is 32-/64-bit agnostic and expands the timeval fields to the + expected size as needed. */ + struct timeval temp_tv; + temp_tv.tv_sec = up->ut_tv.tv_sec; + temp_tv.tv_usec = up->ut_tv.tv_usec; + + (printf) ( + /* The format string. */ +#if _HAVE_UT_TYPE + "[%d] " +#endif +#if _HAVE_UT_PID + "[%05d] " +#endif +#if _HAVE_UT_ID + "[%-4.4s] " +#endif + "[%-8.8s] [%-12.12s]" +#if _HAVE_UT_HOST + " [%-16.16s]" +#endif + " [%-15.15s]" +#if _HAVE_UT_TV + " [%ld]" +#endif + "\n" + /* The arguments. */ +#if _HAVE_UT_TYPE + , up->ut_type +#endif +#if _HAVE_UT_PID + , up->ut_pid +#endif +#if _HAVE_UT_ID + , up->ut_id +#endif + , up->ut_user, up->ut_line +#if _HAVE_UT_HOST + , up->ut_host +#endif +#if _HAVE_UT_TV + , 4 + ctime (&temp_tv.tv_sec) + , (long int) temp_tv.tv_usec +#else + , 4 + ctime (&up->ut_time) +#endif + ); +} + +int +main (int argc, char *argv[]) +{ + struct utmp *up; + + if (argc > 1) + utmpname (argv[1]); + + setutent (); + + while ((up = getutent ())) + print_entry (up); + + endutent (); + + return EXIT_SUCCESS; +} diff --git a/REORG.TODO/login/ptsname.c b/REORG.TODO/login/ptsname.c new file mode 100644 index 0000000000..c9da2dc6ad --- /dev/null +++ b/REORG.TODO/login/ptsname.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> + +/* Given the file descriptor of a master pty, return the pathname + of the associated slave. */ + +char * +ptsname (int fd __attribute__ ((unused))) +{ + __set_errno (ENOSYS); + return NULL; +} + +int +__ptsname_r (int fd __attribute__ ((unused)), + char *buf __attribute__ ((unused)), + size_t len __attribute__ ((unused))) +{ + __set_errno (ENOSYS); + return ENOSYS; +} +weak_alias (__ptsname_r, ptsname_r) + +stub_warning(ptsname) +stub_warning(ptsname_r) diff --git a/REORG.TODO/login/ptsname_r_chk.c b/REORG.TODO/login/ptsname_r_chk.c new file mode 100644 index 0000000000..cfabdc941f --- /dev/null +++ b/REORG.TODO/login/ptsname_r_chk.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2005-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <stdlib.h> + + +int +__ptsname_r_chk (int fd, char *buf, size_t buflen, size_t nreal) +{ + if (buflen > nreal) + __chk_fail (); + + return __ptsname_r (fd, buf, buflen); +} diff --git a/REORG.TODO/login/pty.h b/REORG.TODO/login/pty.h new file mode 100644 index 0000000000..f4327508aa --- /dev/null +++ b/REORG.TODO/login/pty.h @@ -0,0 +1,48 @@ +/* Functions for pseudo TTY handling. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _PTY_H +#define _PTY_H 1 + +#include <features.h> + +struct termios; +struct winsize; + +#include <termios.h> +#include <sys/ioctl.h> + + +__BEGIN_DECLS + +/* Create pseudo tty master slave pair with NAME and set terminal + attributes according to TERMP and WINP and return handles for both + ends in AMASTER and ASLAVE. */ +extern int openpty (int *__amaster, int *__aslave, char *__name, + const struct termios *__termp, + const struct winsize *__winp) __THROW; + +/* Create child process and establish the slave pseudo terminal as the + child's controlling terminal. */ +extern int forkpty (int *__amaster, char *__name, + const struct termios *__termp, + const struct winsize *__winp) __THROW; + +__END_DECLS + +#endif /* pty.h */ diff --git a/REORG.TODO/login/pututxline.c b/REORG.TODO/login/pututxline.c new file mode 100644 index 0000000000..08ab1bf4fa --- /dev/null +++ b/REORG.TODO/login/pututxline.c @@ -0,0 +1,26 @@ +/* Copyright (C) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <utmp.h> +#include <utmpx.h> + +struct utmpx * +pututxline (const struct utmpx *utmpx) +{ + return (struct utmpx *) __pututline ((const struct utmp *) utmpx); +} diff --git a/REORG.TODO/login/setlogin.c b/REORG.TODO/login/setlogin.c new file mode 100644 index 0000000000..4601d99591 --- /dev/null +++ b/REORG.TODO/login/setlogin.c @@ -0,0 +1,29 @@ +/* Copyright (C) 1991-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <unistd.h> + +/* Set the login name returned by `getlogin'. */ +int +setlogin (const char *name) +{ + __set_errno (ENOSYS); + return -1; +} + +stub_warning (setlogin) diff --git a/REORG.TODO/login/setutxent.c b/REORG.TODO/login/setutxent.c new file mode 100644 index 0000000000..6c742f76a6 --- /dev/null +++ b/REORG.TODO/login/setutxent.c @@ -0,0 +1,26 @@ +/* Copyright (C) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <utmp.h> +#include <utmpx.h> + +void +setutxent (void) +{ + return __setutent (); +} diff --git a/REORG.TODO/login/tst-getlogin.c b/REORG.TODO/login/tst-getlogin.c new file mode 100644 index 0000000000..5675fef0e0 --- /dev/null +++ b/REORG.TODO/login/tst-getlogin.c @@ -0,0 +1,60 @@ +/* Copyright (C) 1999-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <unistd.h> +#include <stdio.h> +#include <string.h> + +static int +do_test (void) +{ + char *login; + int errors = 0; + + login = getlogin (); + if (login == NULL) + puts ("getlogin returned NULL, no further tests"); + else + { + char name[1024]; + int ret; + + printf ("getlogin returned: `%s'\n", login); + + ret = getlogin_r (name, sizeof (name)); + if (ret == 0) + { + printf ("getlogin_r returned: `%s'\n", name); + if (strcmp (name, login) != 0) + { + puts ("Error: getlogin and getlogin_r returned different names"); + ++errors; + } + } + else + { + printf ("Error: getlogin_r returned: %d (%s)\n", + ret, strerror (ret)); + ++errors; + } + } + + return errors != 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/REORG.TODO/login/tst-grantpt.c b/REORG.TODO/login/tst-grantpt.c new file mode 100644 index 0000000000..65bb344909 --- /dev/null +++ b/REORG.TODO/login/tst-grantpt.c @@ -0,0 +1,81 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> + +static int +test_ebadf (void) +{ + int fd, ret, err; + + fd = posix_openpt (O_RDWR); + if (fd == -1) + { + printf ("posix_openpt(O_RDWR) failed\nerrno %d (%s)\n", + errno, strerror (errno)); + /* We don't fail because of this; maybe the system does not have + SUS pseudo terminals. */ + return 0; + } + unlockpt (fd); + close (fd); + + ret = grantpt (fd); + err = errno; + if (ret != -1 || err != EBADF) + { + printf ("grantpt(): expected: return = %d, errno = %d\n", -1, EBADF); + printf (" got: return = %d, errno = %d\n", ret, err); + return 1; + } + return 0; +} + +static int +test_einval (void) +{ + int fd, ret, err; + const char file[] = "./grantpt-einval"; + + fd = open (file, O_RDWR | O_CREAT, 0600); + if (fd == -1) + { + printf ("open(\"%s\", O_RDWR) failed\nerrno %d (%s)\n", + file, errno, strerror (errno)); + return 0; + } + unlink (file); + + ret = grantpt (fd); + err = errno; + if (ret != -1 || err != EINVAL) + { + printf ("grantpt(): expected: return = %d, errno = %d\n", -1, EINVAL); + printf (" got: return = %d, errno = %d\n", ret, err); + ret = 1; + } + else + ret = 0; + + close (fd); + + return ret; +} + +static int +do_test (void) +{ + int result = 0; + + result += test_ebadf (); + result += test_einval (); + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/REORG.TODO/login/tst-ptsname.c b/REORG.TODO/login/tst-ptsname.c new file mode 100644 index 0000000000..96f0449788 --- /dev/null +++ b/REORG.TODO/login/tst-ptsname.c @@ -0,0 +1,107 @@ +/* Test for ptsname/ptsname_r. + Copyright (C) 2014-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aurelien Jarno <aurelien@aurel32.net>, 2014. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define DEV_TTY "/dev/tty" +#define PTSNAME_EINVAL "./ptsname-einval" + +static int +do_single_test (int fd, char *buf, size_t buflen, int expected_err) +{ + + int ret = ptsname_r (fd, buf, buflen); + int err = errno; + + if (expected_err == 0) + { + if (ret != 0) + { + printf ("ptsname_r: expected: return = 0\n"); + printf (" got: return = %d, errno = %d (%s)\n", + ret, err, strerror (err)); + return 1; + } + } + else + { + if (ret == 0 || errno != expected_err) + { + printf ("ptsname_r: expected: return = %d, errno = %d (%s)\n", + -1, expected_err, strerror (expected_err)); + printf (" got: return = %d, errno = %d (%s)\n", + ret, err, strerror (err)); + return 1; + } + } + + return 0; +} + +static int +do_test (void) +{ + char buf[512]; + int result = 0; + + /* Tests with a real PTS master. */ + int fd = posix_openpt (O_RDWR); + if (fd != -1) + { + result |= do_single_test (fd, buf, sizeof (buf), 0); + result |= do_single_test (fd, buf, 1, ERANGE); + close (fd); + } + else + printf ("posix_openpt (O_RDWR) failed\nerrno %d (%s)\n", + errno, strerror (errno)); + + /* Test with a terminal device which is not a PTS master. */ + fd = open (DEV_TTY, O_RDONLY); + if (fd != -1) + { + result |= do_single_test (fd, buf, sizeof (buf), ENOTTY); + close (fd); + } + else + printf ("open (\"%s\", O_RDWR) failed\nerrno %d (%s)\n", + DEV_TTY, errno, strerror (errno)); + + /* Test with a file. */ + fd = open (PTSNAME_EINVAL, O_RDWR | O_CREAT, 0600); + if (fd != -1) + { + result |= do_single_test (fd, buf, sizeof (buf), ENOTTY); + close (fd); + unlink (PTSNAME_EINVAL); + } + else + printf ("open (\"%s\", O_RDWR | OCREAT) failed\nerrno %d (%s)\n", + PTSNAME_EINVAL, errno, strerror (errno)); + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/REORG.TODO/login/tst-utmp.c b/REORG.TODO/login/tst-utmp.c new file mode 100644 index 0000000000..01771df740 --- /dev/null +++ b/REORG.TODO/login/tst-utmp.c @@ -0,0 +1,403 @@ +/* Tests for UTMP functions. + Copyright (C) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <error.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <time.h> + +#ifdef UTMPX +# include <utmpx.h> +# define utmp utmpx +# define utmpname utmpxname +# define setutent setutxent +# define getutent getutxent +# define endutent endutxent +# define getutline getutxline +# define getutid getutxid +# define pututline pututxline +#else +# include <utmp.h> +#endif + + +#if defined UTMPX || _HAVE_UT_TYPE + +/* Prototype for our test function. */ +static int do_test (int argc, char *argv[]); + +/* We have a preparation function. */ +static void do_prepare (int argc, char *argv[]); +#define PREPARE do_prepare + +/* This defines the `main' function and some more. */ +#include <test-skeleton.c> + + +/* These are for the temporary file we generate. */ +char *name; +int fd; + +static void +do_prepare (int argc, char *argv[]) +{ + size_t name_len; + + name_len = strlen (test_dir); + name = xmalloc (name_len + sizeof ("/utmpXXXXXX")); + mempcpy (mempcpy (name, test_dir, name_len), + "/utmpXXXXXX", sizeof ("/utmpXXXXXX")); + + /* Open our test file. */ + fd = mkstemp (name); + if (fd == -1) + error (EXIT_FAILURE, errno, "cannot open test file `%s'", name); + add_temp_file (name); +} + +struct utmp entry[] = +{ +#if defined UTMPX || _HAVE_UT_TV +#define UT(a) .ut_tv = { .tv_sec = (a)} +#else +#define UT(a) .ut_time = (a) +#endif + + { .ut_type = BOOT_TIME, .ut_pid = 1, UT(1000) }, + { .ut_type = RUN_LVL, .ut_pid = 1, UT(2000) }, + { .ut_type = INIT_PROCESS, .ut_pid = 5, .ut_id = "si", UT(3000) }, + { .ut_type = LOGIN_PROCESS, .ut_pid = 23, .ut_line = "tty1", .ut_id = "1", + .ut_user = "LOGIN", UT(4000) }, + { .ut_type = USER_PROCESS, .ut_pid = 24, .ut_line = "tty2", .ut_id = "2", + .ut_user = "albert", UT(8000) }, + { .ut_type = USER_PROCESS, .ut_pid = 196, .ut_line = "ttyp0", .ut_id = "p0", + .ut_user = "niels", UT(10000) }, + { .ut_type = DEAD_PROCESS, .ut_line = "ttyp1", .ut_id = "p1", UT(16000) }, + { .ut_type = EMPTY }, + { .ut_type = EMPTY } +}; +int num_entries = sizeof entry / sizeof (struct utmp); + +time_t entry_time = 20000; +pid_t entry_pid = 234; + +static int +do_init (void) +{ + int n; + + setutent (); + + for (n = 0; n < num_entries; n++) + { + if (pututline (&entry[n]) == NULL) + { + error (0, errno, "cannot write UTMP entry"); + return 1; + } + } + + endutent (); + + return 0; +} + + +static int +do_check (void) +{ + struct utmp *ut; + int n; + + setutent (); + + n = 0; + while ((ut = getutent ())) + { + if (n < num_entries && + memcmp (ut, &entry[n], sizeof (struct utmp))) + { + error (0, 0, "UTMP entry does not match"); + return 1; + } + + n++; + } + + if (n != num_entries) + { + error (0, 0, "number of UTMP entries is incorrect"); + return 1; + } + + endutent (); + + return 0; +} + +static int +simulate_login (const char *line, const char *user) +{ + int n; + + for (n = 0; n < num_entries; n++) + { + if (strcmp (line, entry[n].ut_line) == 0 || + entry[n].ut_type == DEAD_PROCESS) + { + if (entry[n].ut_pid == DEAD_PROCESS) + entry[n].ut_pid = (entry_pid += 27); + entry[n].ut_type = USER_PROCESS; + strncpy (entry[n].ut_user, user, sizeof (entry[n].ut_user)); +#if defined UTMPX || _HAVE_UT_TV - 0 + entry[n].ut_tv.tv_sec = (entry_time += 1000); +#else + entry[n].ut_time = (entry_time += 1000); +#endif + setutent (); + + if (pututline (&entry[n]) == NULL) + { + error (0, errno, "cannot write UTMP entry"); + return 1; + } + + endutent (); + + return 0; + } + } + + error (0, 0, "no entries available"); + return 1; +} + +static int +simulate_logout (const char *line) +{ + int n; + + for (n = 0; n < num_entries; n++) + { + if (strcmp (line, entry[n].ut_line) == 0) + { + entry[n].ut_type = DEAD_PROCESS; + strncpy (entry[n].ut_user, "", sizeof (entry[n].ut_user)); +#if defined UTMPX || _HAVE_UT_TV - 0 + entry[n].ut_tv.tv_sec = (entry_time += 1000); +#else + entry[n].ut_time = (entry_time += 1000); +#endif + setutent (); + + if (pututline (&entry[n]) == NULL) + { + error (0, errno, "cannot write UTMP entry"); + return 1; + } + + endutent (); + + return 0; + } + } + + error (0, 0, "no entry found for `%s'", line); + return 1; +} + +static int +check_login (const char *line) +{ + struct utmp *up; + struct utmp ut; + int n; + + setutent (); + + strcpy (ut.ut_line, line); + up = getutline (&ut); + if (up == NULL) + { + error (0, errno, "cannot get entry for line `%s'", line); + return 1; + } + + endutent (); + + for (n = 0; n < num_entries; n++) + { + if (strcmp (line, entry[n].ut_line) == 0) + { + if (memcmp (up, &entry[n], sizeof (struct utmp))) + { + error (0, 0, "UTMP entry does not match"); + return 1; + } + + return 0; + } + } + + error (0, 0, "bogus entry for line `%s'", line); + return 1; +} + +static int +check_logout (const char *line) +{ + struct utmp ut; + + setutent (); + + strcpy (ut.ut_line, line); + if (getutline (&ut) != NULL) + { + error (0, 0, "bogus login entry for `%s'", line); + return 1; + } + + endutent (); + + return 0; +} + +static int +check_id (const char *id) +{ + struct utmp *up; + struct utmp ut; + int n; + + setutent (); + + ut.ut_type = USER_PROCESS; + strcpy (ut.ut_id, id); + up = getutid (&ut); + if (up == NULL) + { + error (0, errno, "cannot get entry for ID `%s'", id); + return 1; + } + + endutent (); + + for (n = 0; n < num_entries; n++) + { + if (strcmp (id, entry[n].ut_id) == 0) + { + if (memcmp (up, &entry[n], sizeof (struct utmp))) + { + error (0, 0, "UTMP entry does not match"); + return 1; + } + + return 0; + } + } + + error (0, 0, "bogus entry for ID `%s'", id); + return 1; +} + +static int +check_type (int type) +{ + struct utmp *up; + struct utmp ut; + int n; + + setutent (); + + ut.ut_type = type; + up = getutid (&ut); + if (up == NULL) + { + error (0, errno, "cannot get entry for type `%d'", type); + return 1; + } + + endutent (); + + for (n = 0; n < num_entries; n++) + { + if (type == entry[n].ut_type) + { + if (memcmp (up, &entry[n], sizeof (struct utmp))) + { + error (0, 0, "UTMP entry does not match"); + return 1; + } + + return 0; + } + } + + error (0, 0, "bogus entry for type `%d'", type); + return 1; +} + +static int +do_test (int argc, char *argv[]) +{ + int result = 0; + + utmpname (name); + + result |= do_init (); + result |= do_check (); + + result |= simulate_login ("tty1", "erwin"); + result |= do_check (); + + result |= simulate_login ("ttyp1", "paul"); + result |= do_check (); + + result |= simulate_logout ("tty2"); + result |= do_check (); + + result |= simulate_logout ("ttyp0"); + result |= do_check (); + + result |= simulate_login ("ttyp2", "richard"); + result |= do_check (); + + result |= check_login ("tty1"); + result |= check_logout ("ttyp0"); + result |= check_id ("p1"); + result |= check_id ("2"); + result |= check_id ("si"); + result |= check_type (BOOT_TIME); + result |= check_type (RUN_LVL); + + return result; +} + +#else + +/* No field 'ut_type' in struct utmp. */ +int +main (void) +{ + return 0; +} + +#endif diff --git a/REORG.TODO/login/tst-utmpx.c b/REORG.TODO/login/tst-utmpx.c new file mode 100644 index 0000000000..edb5551d71 --- /dev/null +++ b/REORG.TODO/login/tst-utmpx.c @@ -0,0 +1,2 @@ +#define UTMPX +#include "tst-utmp.c" diff --git a/REORG.TODO/login/unlockpt.c b/REORG.TODO/login/unlockpt.c new file mode 100644 index 0000000000..fd31855790 --- /dev/null +++ b/REORG.TODO/login/unlockpt.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <stdlib.h> +#include <errno.h> + +/* Given a fd on a master pseudoterminal, clear a kernel lock so that + the slave can be opened. This is to avoid a race between opening the + master and calling grantpt() to take possession of the slave. */ +int +unlockpt (int fd __attribute__ ((unused))) +{ + __set_errno (ENOSYS); + return -1; +} + +stub_warning (unlockpt) diff --git a/REORG.TODO/login/updwtmp.c b/REORG.TODO/login/updwtmp.c new file mode 100644 index 0000000000..7788614ed3 --- /dev/null +++ b/REORG.TODO/login/updwtmp.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1997-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <utmp.h> + +#include "utmp-private.h" + +#ifndef TRANSFORM_UTMP_FILE_NAME +# define TRANSFORM_UTMP_FILE_NAME(file_name) (file_name) +#endif + +void +__updwtmp (const char *wtmp_file, const struct utmp *utmp) +{ + const char *file_name = TRANSFORM_UTMP_FILE_NAME (wtmp_file); + + (*__libc_utmp_file_functions.updwtmp) (file_name, utmp); +} +weak_alias (__updwtmp, updwtmp) diff --git a/REORG.TODO/login/updwtmpx.c b/REORG.TODO/login/updwtmpx.c new file mode 100644 index 0000000000..5877303401 --- /dev/null +++ b/REORG.TODO/login/updwtmpx.c @@ -0,0 +1,26 @@ +/* Copyright (C) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <utmp.h> +#include <utmpx.h> + +void +updwtmpx (const char *wtmpx_file, const struct utmpx *utmpx) +{ + __updwtmp (wtmpx_file, (const struct utmp *) utmpx); +} diff --git a/REORG.TODO/login/utmp-private.h b/REORG.TODO/login/utmp-private.h new file mode 100644 index 0000000000..3c9dcb9803 --- /dev/null +++ b/REORG.TODO/login/utmp-private.h @@ -0,0 +1,53 @@ +/* Internal definitions and declarations for UTMP functions. + Copyright (C) 1996-2017 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _UTMP_PRIVATE_H +#define _UTMP_PRIVATE_H 1 + +#include <utmp.h> +#include <libc-lock.h> + +/* The structure describing the functions in a backend. */ +struct utfuncs +{ + int (*setutent) (void); + 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 (*updwtmp) (const char *, const struct utmp *); +}; + +/* The tables from the services. */ +extern const struct utfuncs __libc_utmp_file_functions attribute_hidden; +extern const struct utfuncs __libc_utmp_unknown_functions attribute_hidden; + +/* Currently selected backend. */ +extern const struct utfuncs *__libc_utmp_jump_table attribute_hidden; + +/* Current file name. */ +extern const char *__libc_utmp_file_name attribute_hidden; + +/* Locks access to the global data. */ +__libc_lock_define (extern, __libc_utmp_lock attribute_hidden) + + +#endif /* utmp-private.h */ diff --git a/REORG.TODO/login/utmp.h b/REORG.TODO/login/utmp.h new file mode 100644 index 0000000000..c1a0448065 --- /dev/null +++ b/REORG.TODO/login/utmp.h @@ -0,0 +1,96 @@ +/* Copyright (C) 1993-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _UTMP_H +#define _UTMP_H 1 + +#include <features.h> + +#include <sys/types.h> + + +__BEGIN_DECLS + +/* Get system dependent values and data structures. */ +#include <bits/utmp.h> + +/* Compatibility names for the strings of the canonical file names. */ +#define UTMP_FILE _PATH_UTMP +#define UTMP_FILENAME _PATH_UTMP +#define WTMP_FILE _PATH_WTMP +#define WTMP_FILENAME _PATH_WTMP + + + +/* Make FD be the controlling terminal, stdin, stdout, and stderr; + then close FD. Returns 0 on success, nonzero on error. */ +extern int login_tty (int __fd) __THROW; + + +/* Write the given entry into utmp and wtmp. */ +extern void login (const struct utmp *__entry) __THROW; + +/* Write the utmp entry to say the user on UT_LINE has logged out. */ +extern int logout (const char *__ut_line) __THROW; + +/* Append to wtmp an entry for the current time and the given info. */ +extern void logwtmp (const char *__ut_line, const char *__ut_name, + const char *__ut_host) __THROW; + +/* Append entry UTMP to the wtmp-like file WTMP_FILE. */ +extern void updwtmp (const char *__wtmp_file, const struct utmp *__utmp) + __THROW; + +/* Change name of the utmp file to be examined. */ +extern int utmpname (const char *__file) __THROW; + +/* Read next entry from a utmp-like file. */ +extern struct utmp *getutent (void) __THROW; + +/* Reset the input stream to the beginning of the file. */ +extern void setutent (void) __THROW; + +/* Close the current open file. */ +extern void endutent (void) __THROW; + +/* Search forward from the current point in the utmp file until the + next entry with a ut_type matching ID->ut_type. */ +extern struct utmp *getutid (const struct utmp *__id) __THROW; + +/* Search forward from the current point in the utmp file until the + next entry with a ut_line matching LINE->ut_line. */ +extern struct utmp *getutline (const struct utmp *__line) __THROW; + +/* Write out entry pointed to by UTMP_PTR into the utmp file. */ +extern struct utmp *pututline (const struct utmp *__utmp_ptr) __THROW; + + +#ifdef __USE_MISC +/* Reentrant versions of the file for handling utmp files. */ +extern int getutent_r (struct utmp *__buffer, struct utmp **__result) __THROW; + +extern int getutid_r (const struct utmp *__id, struct utmp *__buffer, + struct utmp **__result) __THROW; + +extern int getutline_r (const struct utmp *__line, + struct utmp *__buffer, struct utmp **__result) __THROW; + +#endif /* Use misc. */ + +__END_DECLS + +#endif /* utmp.h */ diff --git a/REORG.TODO/login/utmp_file.c b/REORG.TODO/login/utmp_file.c new file mode 100644 index 0000000000..240e0e3c10 --- /dev/null +++ b/REORG.TODO/login/utmp_file.c @@ -0,0 +1,524 @@ +/* Copyright (C) 1996-2017 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <utmp.h> +#include <not-cancel.h> +#include <kernel-features.h> +#include <sigsetops.h> + +#include "utmp-private.h" +#include "utmp-equal.h" + + +/* Descriptor for the file and position. */ +static int file_fd = -1; +static bool file_writable; +static off64_t file_offset; + +/* Cache for the last read entry. */ +static struct utmp last_entry; + + +/* Locking timeout. */ +#ifndef TIMEOUT +# define TIMEOUT 10 +#endif + +/* Do-nothing handler for locking timeout. */ +static void timeout_handler (int signum) {}; + +/* LOCK_FILE(fd, type) failure_statement + attempts to get a lock on the utmp file referenced by FD. If it fails, + the failure_statement is executed, otherwise it is skipped. + LOCKING_FAILED() + jumps into the UNLOCK_FILE macro and ensures cleanup of LOCK_FILE. + UNLOCK_FILE(fd) + unlocks the utmp file referenced by FD and performs the cleanup of + LOCK_FILE. + */ +#define LOCK_FILE(fd, type) \ +{ \ + struct flock fl; \ + struct sigaction action, old_action; \ + unsigned int old_timeout; \ + \ + /* Cancel any existing alarm. */ \ + old_timeout = alarm (0); \ + \ + /* Establish signal handler. */ \ + action.sa_handler = timeout_handler; \ + __sigemptyset (&action.sa_mask); \ + action.sa_flags = 0; \ + __sigaction (SIGALRM, &action, &old_action); \ + \ + alarm (TIMEOUT); \ + \ + /* Try to get the lock. */ \ + memset (&fl, '\0', sizeof (struct flock)); \ + fl.l_type = (type); \ + fl.l_whence = SEEK_SET; \ + if (fcntl_not_cancel ((fd), F_SETLKW, &fl) < 0) + +#define LOCKING_FAILED() \ + goto unalarm_return + +#define UNLOCK_FILE(fd) \ + /* Unlock the file. */ \ + fl.l_type = F_UNLCK; \ + fcntl_not_cancel ((fd), F_SETLKW, &fl); \ + \ + unalarm_return: \ + /* Reset the signal handler and alarm. We must reset the alarm \ + before resetting the handler so our alarm does not generate a \ + spurious SIGALRM seen by the user. However, we cannot just set \ + the user's old alarm before restoring the handler, because then \ + it's possible our handler could catch the user alarm's SIGARLM \ + and then the user would never see the signal he expected. */ \ + alarm (0); \ + __sigaction (SIGALRM, &old_action, NULL); \ + if (old_timeout != 0) \ + alarm (old_timeout); \ +} while (0) + + +/* Functions defined here. */ +static int setutent_file (void); +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 updwtmp_file (const char *file, const struct utmp *utmp); + +/* Jump table for file functions. */ +const struct utfuncs __libc_utmp_file_functions = +{ + setutent_file, + getutent_r_file, + getutid_r_file, + getutline_r_file, + pututline_file, + endutent_file, + updwtmp_file +}; + + +#ifndef TRANSFORM_UTMP_FILE_NAME +# define TRANSFORM_UTMP_FILE_NAME(file_name) (file_name) +#endif + +static int +setutent_file (void) +{ + if (file_fd < 0) + { + const char *file_name; + + file_name = TRANSFORM_UTMP_FILE_NAME (__libc_utmp_file_name); + + file_writable = false; + file_fd = open_not_cancel_2 + (file_name, O_RDONLY | O_LARGEFILE | O_CLOEXEC); + if (file_fd == -1) + return 0; + } + + __lseek64 (file_fd, 0, SEEK_SET); + file_offset = 0; + + /* Make sure the entry won't match. */ +#if _HAVE_UT_TYPE - 0 + last_entry.ut_type = -1; +#else + last_entry.ut_line[0] = '\177'; +# if _HAVE_UT_ID - 0 + last_entry.ut_id[0] = '\0'; +# endif +#endif + + return 1; +} + + +static int +getutent_r_file (struct utmp *buffer, struct utmp **result) +{ + ssize_t nbytes; + + assert (file_fd >= 0); + + if (file_offset == -1l) + { + /* Not available. */ + *result = NULL; + return -1; + } + + LOCK_FILE (file_fd, F_RDLCK) + { + nbytes = 0; + LOCKING_FAILED (); + } + + /* Read the next entry. */ + nbytes = read_not_cancel (file_fd, &last_entry, sizeof (struct utmp)); + + UNLOCK_FILE (file_fd); + + if (nbytes != sizeof (struct utmp)) + { + if (nbytes != 0) + 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; +} + + +static int +internal_getut_r (const struct utmp *id, struct utmp *buffer, + bool *lock_failed) +{ + int result = -1; + + LOCK_FILE (file_fd, F_RDLCK) + { + *lock_failed = true; + LOCKING_FAILED (); + } + +#if _HAVE_UT_TYPE - 0 + 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_not_cancel (file_fd, buffer, sizeof (struct utmp)) + != sizeof (struct utmp)) + { + __set_errno (ESRCH); + file_offset = -1l; + goto unlock_return; + } + file_offset += sizeof (struct utmp); + + if (id->ut_type == buffer->ut_type) + break; + } + } + else +#endif /* _HAVE_UT_TYPE */ + { + /* 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_not_cancel (file_fd, buffer, sizeof (struct utmp)) + != sizeof (struct utmp)) + { + __set_errno (ESRCH); + file_offset = -1l; + goto unlock_return; + } + file_offset += sizeof (struct utmp); + + if (__utmp_equal (buffer, id)) + break; + } + } + + result = 0; + +unlock_return: + UNLOCK_FILE (file_fd); + + return result; +} + + +/* 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) +{ + assert (file_fd >= 0); + + if (file_offset == -1l) + { + *result = NULL; + return -1; + } + + /* We don't have to distinguish whether we can lock the file or + whether there is no entry. */ + bool lock_failed = false; + if (internal_getut_r (id, &last_entry, &lock_failed) < 0) + { + *result = NULL; + return -1; + } + + 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) +{ + assert (file_fd >= 0); + + if (file_offset == -1l) + { + *result = NULL; + return -1; + } + + LOCK_FILE (file_fd, F_RDLCK) + { + *result = NULL; + LOCKING_FAILED (); + } + + while (1) + { + /* Read the next entry. */ + if (read_not_cancel (file_fd, &last_entry, sizeof (struct utmp)) + != sizeof (struct utmp)) + { + __set_errno (ESRCH); + file_offset = -1l; + *result = NULL; + goto unlock_return; + } + file_offset += sizeof (struct utmp); + + /* 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; + } + + memcpy (buffer, &last_entry, sizeof (struct utmp)); + *result = buffer; + +unlock_return: + UNLOCK_FILE (file_fd); + + return ((*result == NULL) ? -1 : 0); +} + + +static struct utmp * +pututline_file (const struct utmp *data) +{ + struct utmp buffer; + struct utmp *pbuf; + int found; + + assert (file_fd >= 0); + + if (! file_writable) + { + /* We must make the file descriptor writable before going on. */ + const char *file_name = TRANSFORM_UTMP_FILE_NAME (__libc_utmp_file_name); + + int new_fd = open_not_cancel_2 + (file_name, O_RDWR | O_LARGEFILE | O_CLOEXEC); + if (new_fd == -1) + return NULL; + + if (__lseek64 (new_fd, __lseek64 (file_fd, 0, SEEK_CUR), SEEK_SET) == -1 + || __dup2 (new_fd, file_fd) < 0) + { + close_not_cancel_no_status (new_fd); + return NULL; + } + close_not_cancel_no_status (new_fd); + file_writable = true; + } + + /* Find the correct place to insert the data. */ + if (file_offset > 0 + && ( +#if _HAVE_UT_TYPE - 0 + (last_entry.ut_type == data->ut_type + && (last_entry.ut_type == RUN_LVL + || last_entry.ut_type == BOOT_TIME + || last_entry.ut_type == OLD_TIME + || last_entry.ut_type == NEW_TIME)) + || +#endif + __utmp_equal (&last_entry, data))) + found = 1; + else + { + bool lock_failed = false; + found = internal_getut_r (data, &buffer, &lock_failed); + + if (__builtin_expect (lock_failed, false)) + { + __set_errno (EAGAIN); + return NULL; + } + } + + LOCK_FILE (file_fd, F_WRLCK) + { + pbuf = NULL; + LOCKING_FAILED (); + } + + if (found < 0) + { + /* We append the next entry. */ + file_offset = __lseek64 (file_fd, 0, SEEK_END); + if (file_offset % sizeof (struct utmp) != 0) + { + file_offset -= file_offset % sizeof (struct utmp); + __ftruncate64 (file_fd, file_offset); + + if (__lseek64 (file_fd, 0, SEEK_END) < 0) + { + pbuf = NULL; + goto unlock_return; + } + } + } + else + { + /* We replace the just read entry. */ + file_offset -= sizeof (struct utmp); + __lseek64 (file_fd, file_offset, SEEK_SET); + } + + /* Write the new data. */ + if (write_not_cancel (file_fd, data, sizeof (struct utmp)) + != sizeof (struct utmp)) + { + /* If we appended a new record this is only partially written. + Remove it. */ + if (found < 0) + (void) __ftruncate64 (file_fd, file_offset); + pbuf = NULL; + } + else + { + file_offset += sizeof (struct utmp); + pbuf = (struct utmp *) data; + } + + unlock_return: + UNLOCK_FILE (file_fd); + + return pbuf; +} + + +static void +endutent_file (void) +{ + assert (file_fd >= 0); + + close_not_cancel_no_status (file_fd); + file_fd = -1; +} + + +static int +updwtmp_file (const char *file, const struct utmp *utmp) +{ + int result = -1; + off64_t offset; + int fd; + + /* Open WTMP file. */ + fd = open_not_cancel_2 (file, O_WRONLY | O_LARGEFILE); + if (fd < 0) + return -1; + + LOCK_FILE (fd, F_WRLCK) + LOCKING_FAILED (); + + /* Remember original size of log file. */ + offset = __lseek64 (fd, 0, SEEK_END); + if (offset % sizeof (struct utmp) != 0) + { + offset -= offset % sizeof (struct utmp); + __ftruncate64 (fd, offset); + + if (__lseek64 (fd, 0, SEEK_END) < 0) + goto unlock_return; + } + + /* Write the entry. If we can't write all the bytes, reset the file + size back to the original size. That way, no partial entries + will remain. */ + if (write_not_cancel (fd, utmp, sizeof (struct utmp)) + != sizeof (struct utmp)) + { + __ftruncate64 (fd, offset); + goto unlock_return; + } + + result = 0; + +unlock_return: + UNLOCK_FILE (fd); + + /* Close WTMP file. */ + close_not_cancel_no_status (fd); + + return result; +} diff --git a/REORG.TODO/login/utmpname.c b/REORG.TODO/login/utmpname.c new file mode 100644 index 0000000000..74a4caf71b --- /dev/null +++ b/REORG.TODO/login/utmpname.c @@ -0,0 +1,76 @@ +/* Copyright (C) 1997-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <libc-lock.h> +#include <stdlib.h> +#include <string.h> +#include <utmp.h> + +#include "utmp-private.h" + + +/* This is the default name. */ +static const char default_file_name[] = _PATH_UTMP; + +/* Current file name. */ +const char *__libc_utmp_file_name = (const char *) default_file_name; + +/* We have to use the lock in getutent_r.c. */ +__libc_lock_define (extern, __libc_utmp_lock attribute_hidden) + + +int +__utmpname (const char *file) +{ + int result = -1; + + __libc_lock_lock (__libc_utmp_lock); + + /* Close the old file. */ + (*__libc_utmp_jump_table->endutent) (); + __libc_utmp_jump_table = &__libc_utmp_unknown_functions; + + if (strcmp (file, __libc_utmp_file_name) != 0) + { + if (strcmp (file, default_file_name) == 0) + { + free ((char *) __libc_utmp_file_name); + + __libc_utmp_file_name = default_file_name; + } + else + { + char *file_name = __strdup (file); + if (file_name == NULL) + /* Out of memory. */ + goto done; + + if (__libc_utmp_file_name != default_file_name) + free ((char *) __libc_utmp_file_name); + + __libc_utmp_file_name = file_name; + } + } + + result = 0; + +done: + __libc_lock_unlock (__libc_utmp_lock); + return result; +} +weak_alias (__utmpname, utmpname) diff --git a/REORG.TODO/login/utmpxname.c b/REORG.TODO/login/utmpxname.c new file mode 100644 index 0000000000..90497b91bb --- /dev/null +++ b/REORG.TODO/login/utmpxname.c @@ -0,0 +1,26 @@ +/* Copyright (C) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <utmp.h> +#include <utmpx.h> + +int +utmpxname (const char *file) +{ + return __utmpname (file); +} |