(root)/
diffutils-3.10/
lib/
error.c
       1  /* Error handler for noninteractive utilities
       2     Copyright (C) 1990-1998, 2000-2007, 2009-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     This file is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU Lesser General Public License as
       7     published by the Free Software Foundation; either version 2.1 of the
       8     License, or (at your option) any later version.
       9  
      10     This file is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  /* Written by David MacKenzie <djm@gnu.ai.mit.edu>.  */
      19  
      20  #if !_LIBC
      21  # include <config.h>
      22  #endif
      23  
      24  #include "error.h"
      25  
      26  #include <stdarg.h>
      27  #include <stdio.h>
      28  #include <stdlib.h>
      29  #include <string.h>
      30  
      31  #if !_LIBC && ENABLE_NLS
      32  # include "gettext.h"
      33  # define _(msgid) gettext (msgid)
      34  #endif
      35  
      36  #ifdef _LIBC
      37  # include <libintl.h>
      38  # include <stdbool.h>
      39  # include <stdint.h>
      40  # include <wchar.h>
      41  # define mbsrtowcs __mbsrtowcs
      42  # define USE_UNLOCKED_IO 0
      43  # define _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD(a, b)
      44  # define _GL_ARG_NONNULL(a)
      45  #endif
      46  
      47  #if USE_UNLOCKED_IO
      48  # include "unlocked-io.h"
      49  #endif
      50  
      51  #ifndef _
      52  # define _(String) String
      53  #endif
      54  
      55  /* If NULL, error will flush stdout, then print on stderr the program
      56     name, a colon and a space.  Otherwise, error will call this
      57     function without parameters instead.  */
      58  void (*error_print_progname) (void);
      59  
      60  /* This variable is incremented each time 'error' is called.  */
      61  unsigned int error_message_count;
      62  
      63  #ifdef _LIBC
      64  /* In the GNU C library, there is a predefined variable for this.  */
      65  
      66  # define program_name program_invocation_name
      67  # include <errno.h>
      68  # include <limits.h>
      69  # include <libio/libioP.h>
      70  
      71  /* In GNU libc we want do not want to use the common name 'error' directly.
      72     Instead make it a weak alias.  */
      73  extern void __error (int status, int errnum, const char *message, ...)
      74       __attribute__ ((__format__ (__printf__, 3, 4)));
      75  extern void __error_at_line (int status, int errnum, const char *file_name,
      76                               unsigned int line_number, const char *message,
      77                               ...)
      78       __attribute__ ((__format__ (__printf__, 5, 6)));
      79  # define error __error
      80  # define error_at_line __error_at_line
      81  
      82  # include <libio/iolibio.h>
      83  # define fflush(s) _IO_fflush (s)
      84  # undef putc
      85  # define putc(c, fp) _IO_putc (c, fp)
      86  
      87  # include <bits/libc-lock.h>
      88  
      89  #else /* not _LIBC */
      90  
      91  # include <fcntl.h>
      92  # include <unistd.h>
      93  
      94  # if defined _WIN32 && ! defined __CYGWIN__
      95  /* Get declarations of the native Windows API functions.  */
      96  #  define WIN32_LEAN_AND_MEAN
      97  #  include <windows.h>
      98  /* Get _get_osfhandle.  */
      99  #  if GNULIB_MSVC_NOTHROW
     100  #   include "msvc-nothrow.h"
     101  #  else
     102  #   include <io.h>
     103  #  endif
     104  # endif
     105  
     106  /* The gnulib override of fcntl is not needed in this file.  */
     107  # undef fcntl
     108  
     109  # if !(GNULIB_STRERROR_R_POSIX || HAVE_DECL_STRERROR_R)
     110  #  ifndef HAVE_DECL_STRERROR_R
     111  "this configure-time declaration test was not run"
     112  #  endif
     113  #  if STRERROR_R_CHAR_P
     114  char *strerror_r (int errnum, char *buf, size_t buflen);
     115  #  else
     116  int strerror_r (int errnum, char *buf, size_t buflen);
     117  #  endif
     118  # endif
     119  
     120  # define program_name getprogname ()
     121  
     122  # if GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r
     123  #  define __strerror_r strerror_r
     124  # endif /* GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r */
     125  #endif  /* not _LIBC */
     126  
     127  #if !_LIBC
     128  /* Return non-zero if FD is open.  */
     129  static int
     130  is_open (int fd)
     131  {
     132  # if defined _WIN32 && ! defined __CYGWIN__
     133    /* On native Windows: The initial state of unassigned standard file
     134       descriptors is that they are open but point to an INVALID_HANDLE_VALUE.
     135       There is no fcntl, and the gnulib replacement fcntl does not support
     136       F_GETFL.  */
     137    return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
     138  # else
     139  #  ifndef F_GETFL
     140  #   error Please port fcntl to your platform
     141  #  endif
     142    return 0 <= fcntl (fd, F_GETFL);
     143  # endif
     144  }
     145  #endif
     146  
     147  static void
     148  flush_stdout (void)
     149  {
     150  #if !_LIBC
     151    int stdout_fd;
     152  
     153  # if GNULIB_FREOPEN_SAFER
     154    /* Use of gnulib's freopen-safer module normally ensures that
     155         fileno (stdout) == 1
     156       whenever stdout is open.  */
     157    stdout_fd = STDOUT_FILENO;
     158  # else
     159    /* POSIX states that fileno (stdout) after fclose is unspecified.  But in
     160       practice it is not a problem, because stdout is statically allocated and
     161       the fd of a FILE stream is stored as a field in its allocated memory.  */
     162    stdout_fd = fileno (stdout);
     163  # endif
     164    /* POSIX states that fflush (stdout) after fclose is unspecified; it
     165       is safe in glibc, but not on all other platforms.  fflush (NULL)
     166       is always defined, but too draconian.  */
     167    if (0 <= stdout_fd && is_open (stdout_fd))
     168  #endif
     169      fflush (stdout);
     170  }
     171  
     172  static void
     173  print_errno_message (int errnum)
     174  {
     175    char const *s;
     176  
     177  #if _LIBC || GNULIB_STRERROR_R_POSIX || defined HAVE_STRERROR_R
     178    char errbuf[1024];
     179  # if _LIBC || (!GNULIB_STRERROR_R_POSIX && STRERROR_R_CHAR_P)
     180    s = __strerror_r (errnum, errbuf, sizeof errbuf);
     181  # else
     182    if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
     183      s = errbuf;
     184    else
     185      s = 0;
     186  # endif
     187  #else
     188    s = strerror (errnum);
     189  #endif
     190  
     191  #if !_LIBC
     192    if (! s)
     193      s = _("Unknown system error");
     194  #endif
     195  
     196  #if _LIBC
     197    __fxprintf (NULL, ": %s", s);
     198  #else
     199    fprintf (stderr, ": %s", s);
     200  #endif
     201  }
     202  
     203  static void _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 0) _GL_ARG_NONNULL ((3))
     204  error_tail (int status, int errnum, const char *message, va_list args)
     205  {
     206  #if _LIBC
     207    if (_IO_fwide (stderr, 0) > 0)
     208      {
     209        size_t len = strlen (message) + 1;
     210        wchar_t *wmessage = NULL;
     211        mbstate_t st;
     212        size_t res;
     213        const char *tmp;
     214        bool use_malloc = false;
     215  
     216        while (1)
     217          {
     218            if (__libc_use_alloca (len * sizeof (wchar_t)))
     219              wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
     220            else
     221              {
     222                if (!use_malloc)
     223                  wmessage = NULL;
     224  
     225                wchar_t *p = (wchar_t *) realloc (wmessage,
     226                                                  len * sizeof (wchar_t));
     227                if (p == NULL)
     228                  {
     229                    free (wmessage);
     230                    fputws_unlocked (L"out of memory\n", stderr);
     231                    return;
     232                  }
     233                wmessage = p;
     234                use_malloc = true;
     235              }
     236  
     237            memset (&st, '\0', sizeof (st));
     238            tmp = message;
     239  
     240            res = mbsrtowcs (wmessage, &tmp, len, &st);
     241            if (res != len)
     242              break;
     243  
     244            if (__builtin_expect (len >= SIZE_MAX / sizeof (wchar_t) / 2, 0))
     245              {
     246                /* This really should not happen if everything is fine.  */
     247                res = (size_t) -1;
     248                break;
     249              }
     250  
     251            len *= 2;
     252          }
     253  
     254        if (res == (size_t) -1)
     255          {
     256            /* The string cannot be converted.  */
     257            if (use_malloc)
     258              {
     259                free (wmessage);
     260                use_malloc = false;
     261              }
     262            wmessage = (wchar_t *) L"???";
     263          }
     264  
     265        __vfwprintf (stderr, wmessage, args);
     266  
     267        if (use_malloc)
     268          free (wmessage);
     269      }
     270    else
     271  #endif
     272      vfprintf (stderr, message, args);
     273  
     274    ++error_message_count;
     275    if (errnum)
     276      print_errno_message (errnum);
     277  #if _LIBC
     278    __fxprintf (NULL, "\n");
     279  #else
     280    putc ('\n', stderr);
     281  #endif
     282    fflush (stderr);
     283    if (status)
     284      exit (status);
     285  }
     286  
     287  
     288  /* Print the program name and error message MESSAGE, which is a printf-style
     289     format string with optional args.
     290     If ERRNUM is nonzero, print its corresponding system error message.
     291     Exit with status STATUS if it is nonzero.  */
     292  void
     293  error (int status, int errnum, const char *message, ...)
     294  {
     295    va_list args;
     296  
     297  #if defined _LIBC && defined __libc_ptf_call
     298    /* We do not want this call to be cut short by a thread
     299       cancellation.  Therefore disable cancellation for now.  */
     300    int state = PTHREAD_CANCEL_ENABLE;
     301    __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
     302                     0);
     303  #endif
     304  
     305    flush_stdout ();
     306  #ifdef _LIBC
     307    _IO_flockfile (stderr);
     308  #endif
     309    if (error_print_progname)
     310      (*error_print_progname) ();
     311    else
     312      {
     313  #if _LIBC
     314        __fxprintf (NULL, "%s: ", program_name);
     315  #else
     316        fprintf (stderr, "%s: ", program_name);
     317  #endif
     318      }
     319  
     320    va_start (args, message);
     321    error_tail (status, errnum, message, args);
     322    va_end (args);
     323  
     324  #ifdef _LIBC
     325    _IO_funlockfile (stderr);
     326  # ifdef __libc_ptf_call
     327    __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
     328  # endif
     329  #endif
     330  }
     331  
     332  /* Sometimes we want to have at most one error per line.  This
     333     variable controls whether this mode is selected or not.  */
     334  int error_one_per_line;
     335  
     336  void
     337  error_at_line (int status, int errnum, const char *file_name,
     338                 unsigned int line_number, const char *message, ...)
     339  {
     340    va_list args;
     341  
     342    if (error_one_per_line)
     343      {
     344        static const char *old_file_name;
     345        static unsigned int old_line_number;
     346  
     347        if (old_line_number == line_number
     348            && (file_name == old_file_name
     349                || (old_file_name != NULL
     350                    && file_name != NULL
     351                    && strcmp (old_file_name, file_name) == 0)))
     352  
     353          /* Simply return and print nothing.  */
     354          return;
     355  
     356        old_file_name = file_name;
     357        old_line_number = line_number;
     358      }
     359  
     360  #if defined _LIBC && defined __libc_ptf_call
     361    /* We do not want this call to be cut short by a thread
     362       cancellation.  Therefore disable cancellation for now.  */
     363    int state = PTHREAD_CANCEL_ENABLE;
     364    __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
     365                     0);
     366  #endif
     367  
     368    flush_stdout ();
     369  #ifdef _LIBC
     370    _IO_flockfile (stderr);
     371  #endif
     372    if (error_print_progname)
     373      (*error_print_progname) ();
     374    else
     375      {
     376  #if _LIBC
     377        __fxprintf (NULL, "%s:", program_name);
     378  #else
     379        fprintf (stderr, "%s:", program_name);
     380  #endif
     381      }
     382  
     383  #if _LIBC
     384    __fxprintf (NULL, file_name != NULL ? "%s:%u: " : " ",
     385                file_name, line_number);
     386  #else
     387    fprintf (stderr, file_name != NULL ? "%s:%u: " : " ",
     388             file_name, line_number);
     389  #endif
     390  
     391    va_start (args, message);
     392    error_tail (status, errnum, message, args);
     393    va_end (args);
     394  
     395  #ifdef _LIBC
     396    _IO_funlockfile (stderr);
     397  # ifdef __libc_ptf_call
     398    __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
     399  # endif
     400  #endif
     401  }
     402  
     403  #ifdef _LIBC
     404  /* Make the weak alias.  */
     405  # undef error
     406  # undef error_at_line
     407  weak_alias (__error, error)
     408  weak_alias (__error_at_line, error_at_line)
     409  #endif