diff --git a/lib/Makefile.am b/lib/Makefile.am index 0e16e2455..0980aa17c 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -21,7 +21,7 @@ # the same distribution terms as the rest of that program. # # Generated by gnulib-tool. -# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=tools --no-conditional-dependencies --libtool --macro-prefix=gl --no-vc-files argmatch argp error isatty mkstemp mkstemps progname stpcpy strverscmp sys_wait +# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=tools --no-conditional-dependencies --libtool --macro-prefix=gl --no-vc-files argmatch argp closeout closestdout error isatty mkstemp mkstemps progname secure_getenv stpcpy strverscmp sys_wait AUTOMAKE_OPTIONS = 1.9.6 gnits @@ -128,6 +128,22 @@ EXTRA_DIST += c-strcaseeq.h ## end gnulib module c-strcaseeq +## begin gnulib module close-stream + +libgnu_la_SOURCES += close-stream.c + +EXTRA_DIST += close-stream.h + +## end gnulib module close-stream + +## begin gnulib module closeout + +libgnu_la_SOURCES += closeout.c + +EXTRA_DIST += closeout.h + +## end gnulib module closeout + ## begin gnulib module configmake # Listed in the same order as the GNU makefile conventions, and @@ -312,6 +328,15 @@ EXTRA_libgnu_la_SOURCES += float.c itold.c ## end gnulib module float +## begin gnulib module fpending + + +EXTRA_DIST += fpending.c fpending.h stdio-impl.h + +EXTRA_libgnu_la_SOURCES += fpending.c + +## end gnulib module fpending + ## begin gnulib module getopt-posix BUILT_SOURCES += $(GETOPT_H) $(GETOPT_CDEFS_H) @@ -654,6 +679,15 @@ EXTRA_libgnu_la_SOURCES += rawmemchr.c ## end gnulib module rawmemchr +## begin gnulib module secure_getenv + + +EXTRA_DIST += secure_getenv.c + +EXTRA_libgnu_la_SOURCES += secure_getenv.c + +## end gnulib module secure_getenv + ## begin gnulib module size_max libgnu_la_SOURCES += size_max.h diff --git a/lib/close-stream.c b/lib/close-stream.c new file mode 100644 index 000000000..3d5a52ebd --- /dev/null +++ b/lib/close-stream.c @@ -0,0 +1,78 @@ +/* Close a stream, with nicer error checking than fclose's. + + Copyright (C) 1998-2002, 2004, 2006-2018 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include "close-stream.h" + +#include +#include + +#include "fpending.h" + +#if USE_UNLOCKED_IO +# include "unlocked-io.h" +#endif + +/* Close STREAM. Return 0 if successful, EOF (setting errno) + otherwise. A failure might set errno to 0 if the error number + cannot be determined. + + A failure with errno set to EPIPE may or may not indicate an error + situation worth signaling to the user. See the documentation of the + close_stdout_set_ignore_EPIPE function for details. + + If a program writes *anything* to STREAM, that program should close + STREAM and make sure that it succeeds before exiting. Otherwise, + suppose that you go to the extreme of checking the return status + of every function that does an explicit write to STREAM. The last + printf can succeed in writing to the internal stream buffer, and yet + the fclose(STREAM) could still fail (due e.g., to a disk full error) + when it tries to write out that buffered data. Thus, you would be + left with an incomplete output file and the offending program would + exit successfully. Even calling fflush is not always sufficient, + since some file systems (NFS and CODA) buffer written/flushed data + until an actual close call. + + Besides, it's wasteful to check the return value from every call + that writes to STREAM -- just let the internal stream state record + the failure. That's what the ferror test is checking below. */ + +int +close_stream (FILE *stream) +{ + const bool some_pending = (__fpending (stream) != 0); + const bool prev_fail = (ferror (stream) != 0); + const bool fclose_fail = (fclose (stream) != 0); + + /* Return an error indication if there was a previous failure or if + fclose failed, with one exception: ignore an fclose failure if + there was no previous error, no data remains to be flushed, and + fclose failed with EBADF. That can happen when a program like cp + is invoked like this 'cp a b >&-' (i.e., with standard output + closed) and doesn't generate any output (hence no previous error + and nothing to be flushed). */ + + if (prev_fail || (fclose_fail && (some_pending || errno != EBADF))) + { + if (! fclose_fail) + errno = 0; + return EOF; + } + + return 0; +} diff --git a/lib/close-stream.h b/lib/close-stream.h new file mode 100644 index 000000000..be3d4196b --- /dev/null +++ b/lib/close-stream.h @@ -0,0 +1,2 @@ +#include +int close_stream (FILE *stream); diff --git a/lib/closeout.c b/lib/closeout.c new file mode 100644 index 000000000..0672732b6 --- /dev/null +++ b/lib/closeout.c @@ -0,0 +1,136 @@ +/* Close standard output and standard error, exiting with a diagnostic on error. + + Copyright (C) 1998-2002, 2004, 2006, 2008-2018 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include "closeout.h" + +#include +#include +#include +#include + +#include "gettext.h" +#define _(msgid) gettext (msgid) + +#include "close-stream.h" +#include "error.h" +#include "exitfail.h" +#include "quotearg.h" + +#ifndef __has_feature +# define __has_feature(a) false +#endif + +#if defined __SANITIZE_ADDRESS__ || __has_feature (address_sanitizer) +enum { SANITIZE_ADDRESS = true }; +#else +enum { SANITIZE_ADDRESS = false }; +#endif + +static const char *file_name; + +/* Set the file name to be reported in the event an error is detected + by close_stdout. */ +void +close_stdout_set_file_name (const char *file) +{ + file_name = file; +} + +static bool ignore_EPIPE /* = false */; + +/* Specify the reaction to an EPIPE error during the closing of stdout: + - If ignore = true, it shall be ignored. + - If ignore = false, it shall evoke a diagnostic, along with a nonzero + exit status. + The default is ignore = false. + + This setting matters only if the SIGPIPE signal is ignored (i.e. its + handler set to SIG_IGN) or blocked. Only particular programs need to + temporarily ignore SIGPIPE. If SIGPIPE is ignored or blocked because + it was ignored or blocked in the parent process when it created the + child process, it usually is a bug in the parent process: It is bad + practice to have SIGPIPE ignored or blocked while creating a child + process. + + EPIPE occurs when writing to a pipe or socket that has no readers now, + when SIGPIPE is ignored or blocked. + + The ignore = false setting is suitable for a scenario where it is normally + guaranteed that the pipe writer terminates before the pipe reader. In + this case, an EPIPE is an indication of a premature termination of the + pipe reader and should lead to a diagnostic and a nonzero exit status. + + The ignore = true setting is suitable for a scenario where you don't know + ahead of time whether the pipe writer or the pipe reader will terminate + first. In this case, an EPIPE is an indication that the pipe writer can + stop doing useless write() calls; this is what close_stdout does anyway. + EPIPE is part of the normal pipe/socket shutdown protocol in this case, + and should not lead to a diagnostic message. */ + +void +close_stdout_set_ignore_EPIPE (bool ignore) +{ + ignore_EPIPE = ignore; +} + +/* Close standard output. On error, issue a diagnostic and _exit + with status 'exit_failure'. + + Also close standard error. On error, _exit with status 'exit_failure'. + + Since close_stdout is commonly registered via 'atexit', POSIX + and the C standard both say that it should not call 'exit', + because the behavior is undefined if 'exit' is called more than + once. So it calls '_exit' instead of 'exit'. If close_stdout + is registered via atexit before other functions are registered, + the other functions can act before this _exit is invoked. + + Applications that use close_stdout should flush any streams + other than stdout and stderr before exiting, since the call to + _exit will bypass other buffer flushing. Applications should + be flushing and closing other streams anyway, to check for I/O + errors. Also, applications should not use tmpfile, since _exit + can bypass the removal of these files. + + It's important to detect such failures and exit nonzero because many + tools (most notably 'make' and other build-management systems) depend + on being able to detect failure in other tools via their exit status. */ + +void +close_stdout (void) +{ + if (close_stream (stdout) != 0 + && !(ignore_EPIPE && errno == EPIPE)) + { + char const *write_error = _("write error"); + if (file_name) + error (0, errno, "%s: %s", quotearg_colon (file_name), + write_error); + else + error (0, errno, "%s", write_error); + + _exit (exit_failure); + } + + /* Close stderr only if not sanitizing, as sanitizers may report to + stderr after this function returns. */ + if (!SANITIZE_ADDRESS && close_stream (stderr) != 0) + _exit (exit_failure); +} diff --git a/lib/closeout.h b/lib/closeout.h new file mode 100644 index 000000000..6629d4993 --- /dev/null +++ b/lib/closeout.h @@ -0,0 +1,36 @@ +/* Close standard output and standard error. + + Copyright (C) 1998, 2000, 2003-2004, 2006, 2008-2018 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef CLOSEOUT_H +# define CLOSEOUT_H 1 + +# include + +# ifdef __cplusplus +extern "C" { +# endif + +void close_stdout_set_file_name (const char *file); +void close_stdout_set_ignore_EPIPE (bool ignore); +void close_stdout (void); + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/lib/fpending.c b/lib/fpending.c new file mode 100644 index 000000000..de370d4b1 --- /dev/null +++ b/lib/fpending.c @@ -0,0 +1,62 @@ +/* fpending.c -- return the number of pending output bytes on a stream + Copyright (C) 2000, 2004, 2006-2007, 2009-2018 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Jim Meyering. */ + +#include + +/* Specification. */ +#include "fpending.h" + +#include "stdio-impl.h" + +/* This file is not used on systems that already have the __fpending function, + namely glibc >= 2.2, Solaris >= 7, Android API >= 23. */ + +/* Return the number of pending (aka buffered, unflushed) + bytes on the stream, FP, that is open for writing. */ +size_t +__fpending (FILE *fp) +{ + /* Most systems provide FILE as a struct and the necessary bitmask in + , because they need it for implementing getc() and putc() as + fast macros. */ +#if defined _IO_EOF_SEEN || defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 + /* GNU libc, BeOS, Haiku, Linux libc5 */ + return fp->_IO_write_ptr - fp->_IO_write_base; +#elif defined __sferror || defined __DragonFly__ || defined __ANDROID__ + /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Minix 3, Android */ + return fp->_p - fp->_bf._base; +#elif defined __EMX__ /* emx+gcc */ + return fp->_ptr - fp->_buffer; +#elif defined __minix /* Minix */ + return fp_->_ptr - fp_->_buf; +#elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw, MSVC, NonStop Kernel, OpenVMS */ + return (fp_->_ptr ? fp_->_ptr - fp_->_base : 0); +#elif defined __UCLIBC__ /* uClibc */ + return (fp->__modeflags & __FLAG_WRITING ? fp->__bufpos - fp->__bufstart : 0); +#elif defined __QNX__ /* QNX */ + return (fp->_Mode & 0x2000 /*_MWRITE*/ ? fp->_Next - fp->_Buf : 0); +#elif defined __MINT__ /* Atari FreeMiNT */ + return fp->__bufp - fp->__buffer; +#elif defined EPLAN9 /* Plan9 */ + return fp->wp - fp->buf; +#else +# error "Please port gnulib fpending.c to your platform!" + return 1; +#endif +} diff --git a/lib/fpending.h b/lib/fpending.h new file mode 100644 index 000000000..2ff26bc6a --- /dev/null +++ b/lib/fpending.h @@ -0,0 +1,29 @@ +/* Declare __fpending. + + Copyright (C) 2000, 2003, 2005-2006, 2009-2018 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Jim Meyering. */ + +#include +#include +#if HAVE_STDIO_EXT_H +# include +#endif + +#if !HAVE_DECL___FPENDING +size_t __fpending (FILE *) _GL_ATTRIBUTE_PURE; +#endif diff --git a/lib/secure_getenv.c b/lib/secure_getenv.c new file mode 100644 index 000000000..ebe98dbfd --- /dev/null +++ b/lib/secure_getenv.c @@ -0,0 +1,54 @@ +/* Look up an environment variable, returning NULL in insecure situations. + + Copyright 2013-2018 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include + +#if !HAVE___SECURE_GETENV +# if HAVE_ISSETUGID || (HAVE_GETUID && HAVE_GETEUID && HAVE_GETGID && HAVE_GETEGID) +# include +# endif +#endif + +char * +secure_getenv (char const *name) +{ +#if HAVE___SECURE_GETENV /* glibc */ + return __secure_getenv (name); +#elif HAVE_ISSETUGID /* OS X, FreeBSD, NetBSD, OpenBSD */ + if (issetugid ()) + return NULL; + return getenv (name); +#elif HAVE_GETUID && HAVE_GETEUID && HAVE_GETGID && HAVE_GETEGID /* other Unix */ + if (geteuid () != getuid () || getegid () != getgid ()) + return NULL; + return getenv (name); +#elif defined _WIN32 && ! defined __CYGWIN__ /* native Windows */ + /* On native Windows, there is no such concept as setuid or setgid binaries. + - Programs launched as system services have high privileges, but they don't + inherit environment variables from a user. + - Programs launched by a user with "Run as Administrator" have high + privileges and use the environment variables, but the user has been asked + whether he agrees. + - Programs launched by a user without "Run as Administrator" cannot gain + high privileges, therefore there is no risk. */ + return getenv (name); +#else + return NULL; +#endif +} diff --git a/lib/stdio-impl.h b/lib/stdio-impl.h new file mode 100644 index 000000000..393ef0cf5 --- /dev/null +++ b/lib/stdio-impl.h @@ -0,0 +1,202 @@ +/* Implementation details of FILE streams. + Copyright (C) 2007-2008, 2010-2018 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Many stdio implementations have the same logic and therefore can share + the same implementation of stdio extension API, except that some fields + have different naming conventions, or their access requires some casts. */ + +/* Glibc 2.28 made _IO_IN_BACKUP private. For now, work around this + problem by defining it ourselves. FIXME: Do not rely on glibc + internals. */ +#if !defined _IO_IN_BACKUP && defined _IO_EOF_SEEN +# define _IO_IN_BACKUP 0x100 +#endif + +/* BSD stdio derived implementations. */ + +#if defined __NetBSD__ /* NetBSD */ +/* Get __NetBSD_Version__. */ +# include +#endif + +#include /* For detecting Plan9. */ + +#if defined __sferror || defined __DragonFly__ || defined __ANDROID__ + /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Minix 3, Android */ + +# if defined __DragonFly__ /* DragonFly */ + /* See . */ +# define fp_ ((struct { struct __FILE_public pub; \ + struct { unsigned char *_base; int _size; } _bf; \ + void *cookie; \ + void *_close; \ + void *_read; \ + void *_seek; \ + void *_write; \ + struct { unsigned char *_base; int _size; } _ub; \ + int _ur; \ + unsigned char _ubuf[3]; \ + unsigned char _nbuf[1]; \ + struct { unsigned char *_base; int _size; } _lb; \ + int _blksize; \ + fpos_t _offset; \ + /* More fields, not relevant here. */ \ + } *) fp) + /* See . */ +# define _p pub._p +# define _flags pub._flags +# define _r pub._r +# define _w pub._w +# elif defined __ANDROID__ /* Android */ + /* Up to this commit from 2015-10-12 + + the innards of FILE were public, and fp_ub could be defined like for OpenBSD, + see + and . + After this commit, the innards of FILE are hidden. */ +# define fp_ ((struct { unsigned char *_p; \ + int _r; \ + int _w; \ + int _flags; \ + int _file; \ + struct { unsigned char *_base; size_t _size; } _bf; \ + int _lbfsize; \ + void *_cookie; \ + void *_close; \ + void *_read; \ + void *_seek; \ + void *_write; \ + struct { unsigned char *_base; size_t _size; } _ext; \ + unsigned char *_up; \ + int _ur; \ + unsigned char _ubuf[3]; \ + unsigned char _nbuf[1]; \ + struct { unsigned char *_base; size_t _size; } _lb; \ + int _blksize; \ + fpos_t _offset; \ + /* More fields, not relevant here. */ \ + } *) fp) +# else +# define fp_ fp +# endif + +# if (defined __NetBSD__ && __NetBSD_Version__ >= 105270000) || defined __OpenBSD__ || defined __minix /* NetBSD >= 1.5ZA, OpenBSD, Minix 3 */ + /* See + and + and */ + struct __sfileext + { + struct __sbuf _ub; /* ungetc buffer */ + /* More fields, not relevant here. */ + }; +# define fp_ub ((struct __sfileext *) fp->_ext._base)->_ub +# elif defined __ANDROID__ /* Android */ + struct __sfileext + { + struct { unsigned char *_base; size_t _size; } _ub; /* ungetc buffer */ + /* More fields, not relevant here. */ + }; +# define fp_ub ((struct __sfileext *) fp_->_ext._base)->_ub +# else /* FreeBSD, NetBSD <= 1.5Z, DragonFly, Mac OS X, Cygwin */ +# define fp_ub fp_->_ub +# endif + +# define HASUB(fp) (fp_ub._base != NULL) + +# if defined __ANDROID__ /* Android */ + /* Needed after this commit from 2016-01-25 + */ +# ifndef __SEOF +# define __SLBF 1 +# define __SNBF 2 +# define __SRD 4 +# define __SWR 8 +# define __SRW 0x10 +# define __SEOF 0x20 +# define __SERR 0x40 +# endif +# ifndef __SOFF +# define __SOFF 0x1000 +# endif +# endif + +#endif + + +/* SystemV derived implementations. */ + +#ifdef __TANDEM /* NonStop Kernel */ +# ifndef _IOERR +/* These values were determined by the program 'stdioext-flags' at + . */ +# define _IOERR 0x40 +# define _IOREAD 0x80 +# define _IOWRT 0x4 +# define _IORW 0x100 +# endif +#endif + +#if defined _IOERR + +# if defined __sun && defined _LP64 /* Solaris/{SPARC,AMD64} 64-bit */ +# define fp_ ((struct { unsigned char *_ptr; \ + unsigned char *_base; \ + unsigned char *_end; \ + long _cnt; \ + int _file; \ + unsigned int _flag; \ + } *) fp) +# elif defined __VMS /* OpenVMS */ +# define fp_ ((struct _iobuf *) fp) +# else +# define fp_ fp +# endif + +# if defined _SCO_DS /* OpenServer */ +# define _cnt __cnt +# define _ptr __ptr +# define _base __base +# define _flag __flag +# endif + +#elif defined _WIN32 && ! defined __CYGWIN__ /* newer Windows with MSVC */ + +/* does not define the innards of FILE any more. */ +# define WINDOWS_OPAQUE_FILE + +struct _gl_real_FILE +{ + /* Note: Compared to older Windows and to mingw, it has the fields + _base and _cnt swapped. */ + unsigned char *_ptr; + unsigned char *_base; + int _cnt; + int _flag; + int _file; + int _charbuf; + int _bufsiz; +}; +# define fp_ ((struct _gl_real_FILE *) fp) + +/* These values were determined by a program similar to the one at + . */ +# define _IOREAD 0x1 +# define _IOWRT 0x2 +# define _IORW 0x4 +# define _IOEOF 0x8 +# define _IOERR 0x10 + +#endif diff --git a/m4/close-stream.m4 b/m4/close-stream.m4 new file mode 100644 index 000000000..c9bf62e95 --- /dev/null +++ b/m4/close-stream.m4 @@ -0,0 +1,11 @@ +#serial 4 +dnl Copyright (C) 2006-2007, 2009-2018 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Prerequisites of lib/close-stream.c. +AC_DEFUN([gl_CLOSE_STREAM], +[ + : +]) diff --git a/m4/closeout.m4 b/m4/closeout.m4 new file mode 100644 index 000000000..6442406ca --- /dev/null +++ b/m4/closeout.m4 @@ -0,0 +1,12 @@ +# closeout.m4 serial 6 +dnl Copyright (C) 2002-2003, 2005-2006, 2009-2018 Free Software Foundation, +dnl Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Prerequisites of lib/closeout.c. +AC_DEFUN([gl_CLOSEOUT], +[ + : +]) diff --git a/m4/fpending.m4 b/m4/fpending.m4 new file mode 100644 index 000000000..c897073de --- /dev/null +++ b/m4/fpending.m4 @@ -0,0 +1,36 @@ +# serial 22 + +# Copyright (C) 2000-2001, 2004-2018 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +dnl From Jim Meyering +dnl Using code from emacs, based on suggestions from Paul Eggert +dnl and Ulrich Drepper. + +dnl Find out how to determine the number of pending output bytes on a stream. +dnl glibc (2.1.93 and newer) and Solaris provide __fpending. On other systems, +dnl we have to grub around in the (possibly opaque) FILE struct. + +AC_DEFUN([gl_FUNC_FPENDING], +[ + AC_CHECK_HEADERS_ONCE([stdio_ext.h]) + fp_headers=' + #include + #if HAVE_STDIO_EXT_H + # include + #endif + ' + AC_CACHE_CHECK([for __fpending], [gl_cv_func___fpending], + [ + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([$fp_headers], + [[return ! __fpending (stdin);]])], + [gl_cv_func___fpending=yes], + [gl_cv_func___fpending=no]) + ]) + if test $gl_cv_func___fpending = yes; then + AC_CHECK_DECLS([__fpending], [], [], [$fp_headers]) + fi +]) diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 index 1193f6d99..3671db505 100644 --- a/m4/gnulib-cache.m4 +++ b/m4/gnulib-cache.m4 @@ -27,18 +27,20 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=tools --no-conditional-dependencies --libtool --macro-prefix=gl --no-vc-files argmatch argp error isatty mkstemp mkstemps progname stpcpy strverscmp sys_wait +# gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=tools --no-conditional-dependencies --libtool --macro-prefix=gl --no-vc-files argmatch argp closeout error isatty mkstemp mkstemps progname secure_getenv stpcpy strverscmp sys_wait # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) gl_MODULES([ argmatch argp + closeout error isatty mkstemp mkstemps progname + secure_getenv stpcpy strverscmp sys_wait diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index 35e964e33..2a8efa8be 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -50,6 +50,8 @@ AC_DEFUN([gl_EARLY], # Code from module c-ctype: # Code from module c-strcase: # Code from module c-strcaseeq: + # Code from module close-stream: + # Code from module closeout: # Code from module configmake: # Code from module dirname-lgpl: # Code from module dosname: @@ -62,6 +64,7 @@ AC_DEFUN([gl_EARLY], # Code from module fcntl-h: # Code from module filename: # Code from module float: + # Code from module fpending: # Code from module getopt-gnu: # Code from module getopt-posix: # Code from module getprogname: @@ -97,6 +100,7 @@ AC_DEFUN([gl_EARLY], # Code from module quotearg: # Code from module quotearg-simple: # Code from module rawmemchr: + # Code from module secure_getenv: # Code from module size_max: # Code from module sleep: # Code from module snippet/_Noreturn: @@ -165,6 +169,9 @@ AC_SUBST([LTALLOCA]) m4_ifdef([AM_XGETTEXT_OPTION], [AM_][XGETTEXT_OPTION([--flag=argp_error:2:c-format]) AM_][XGETTEXT_OPTION([--flag=argp_failure:4:c-format])]) + gl_CLOSE_STREAM + gl_MODULE_INDICATOR([close-stream]) + gl_CLOSEOUT gl_CONFIGMAKE_PREP gl_DIRNAME_LGPL gl_DOUBLE_SLASH_ROOT @@ -186,6 +193,10 @@ AC_SUBST([LTALLOCA]) if test $REPLACE_ITOLD = 1; then AC_LIBOBJ([itold]) fi + gl_FUNC_FPENDING + if test $gl_cv_func___fpending = no; then + AC_LIBOBJ([fpending]) + fi gl_FUNC_GETOPT_GNU dnl Because of the way gl_FUNC_GETOPT_GNU is implemented (the gl_getopt_required dnl mechanism), there is no need to do any AC_LIBOBJ or AC_SUBST here; they are @@ -296,6 +307,12 @@ AC_SUBST([LTALLOCA]) gl_PREREQ_RAWMEMCHR fi gl_STRING_MODULE_INDICATOR([rawmemchr]) + gl_FUNC_SECURE_GETENV + if test $HAVE_SECURE_GETENV = 0; then + AC_LIBOBJ([secure_getenv]) + gl_PREREQ_SECURE_GETENV + fi + gl_STDLIB_MODULE_INDICATOR([secure_getenv]) gl_SIZE_MAX gl_FUNC_SLEEP if test $HAVE_SLEEP = 0 || test $REPLACE_SLEEP = 1; then @@ -557,6 +574,10 @@ AC_DEFUN([gl_FILE_LIST], [ lib/c-strcasecmp.c lib/c-strcaseeq.h lib/c-strncasecmp.c + lib/close-stream.c + lib/close-stream.h + lib/closeout.c + lib/closeout.h lib/config.charset lib/dirname-lgpl.c lib/dirname.h @@ -571,6 +592,8 @@ AC_DEFUN([gl_FILE_LIST], [ lib/float+.h lib/float.c lib/float.in.h + lib/fpending.c + lib/fpending.h lib/getopt-cdefs.in.h lib/getopt-core.h lib/getopt-ext.h @@ -624,6 +647,7 @@ AC_DEFUN([gl_FILE_LIST], [ lib/rawmemchr.valgrind lib/ref-add.sin lib/ref-del.sin + lib/secure_getenv.c lib/size_max.h lib/sleep.c lib/stat-time.c @@ -635,6 +659,7 @@ AC_DEFUN([gl_FILE_LIST], [ lib/stdbool.in.h lib/stddef.in.h lib/stdint.in.h + lib/stdio-impl.h lib/stdio.in.h lib/stdlib.in.h lib/stpcpy.c @@ -680,6 +705,8 @@ AC_DEFUN([gl_FILE_LIST], [ m4/absolute-header.m4 m4/alloca.m4 m4/argp.m4 + m4/close-stream.m4 + m4/closeout.m4 m4/codeset.m4 m4/configmake.m4 m4/dirname.m4 @@ -693,6 +720,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/fcntl-o.m4 m4/fcntl_h.m4 m4/float_h.m4 + m4/fpending.m4 m4/getopt.m4 m4/getprogname.m4 m4/gettimeofday.m4 @@ -734,6 +762,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/quote.m4 m4/quotearg.m4 m4/rawmemchr.m4 + m4/secure_getenv.m4 m4/size_max.m4 m4/sleep.m4 m4/ssize_t.m4 diff --git a/m4/secure_getenv.m4 b/m4/secure_getenv.m4 new file mode 100644 index 000000000..ad78eb180 --- /dev/null +++ b/m4/secure_getenv.m4 @@ -0,0 +1,26 @@ +# Look up an environment variable more securely. +dnl Copyright 2013-2018 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_SECURE_GETENV], +[ + dnl Persuade glibc to declare secure_getenv(). + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) + + AC_REQUIRE([gl_STDLIB_H_DEFAULTS]) + AC_CHECK_FUNCS_ONCE([secure_getenv]) + if test $ac_cv_func_secure_getenv = no; then + HAVE_SECURE_GETENV=0 + fi +]) + +# Prerequisites of lib/secure_getenv.c. +AC_DEFUN([gl_PREREQ_SECURE_GETENV], [ + AC_CHECK_FUNCS([__secure_getenv]) + if test $ac_cv_func___secure_getenv = no; then + AC_CHECK_FUNCS([issetugid]) + fi + AC_CHECK_FUNCS_ONCE([getuid geteuid getgid getegid]) +])