Blame lib/error.c

Packit Service fdd496
/* Error handler for noninteractive utilities
Packit Service fdd496
   Copyright (C) 1990-1998, 2000-2007, 2009-2017 Free Software Foundation, Inc.
Packit Service fdd496
   This file is part of the GNU C Library.
Packit Service fdd496
Packit Service fdd496
   This program is free software: you can redistribute it and/or modify
Packit Service fdd496
   it under the terms of the GNU General Public License as published by
Packit Service fdd496
   the Free Software Foundation; either version 3 of the License, or
Packit Service fdd496
   (at your option) any later version.
Packit Service fdd496
Packit Service fdd496
   This program is distributed in the hope that it will be useful,
Packit Service fdd496
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service fdd496
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service fdd496
   GNU General Public License for more details.
Packit Service fdd496
Packit Service fdd496
   You should have received a copy of the GNU General Public License
Packit Service fdd496
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit Service fdd496
Packit Service fdd496
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>.  */
Packit Service fdd496
Packit Service fdd496
#if !_LIBC
Packit Service fdd496
# include <config.h>
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#include "error.h"
Packit Service fdd496
Packit Service fdd496
#include <stdarg.h>
Packit Service fdd496
#include <stdio.h>
Packit Service fdd496
#include <stdlib.h>
Packit Service fdd496
#include <string.h>
Packit Service fdd496
Packit Service fdd496
#if !_LIBC && ENABLE_NLS
Packit Service fdd496
# include "gettext.h"
Packit Service fdd496
# define _(msgid) gettext (msgid)
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#ifdef _LIBC
Packit Service fdd496
# include <libintl.h>
Packit Service fdd496
# include <stdbool.h>
Packit Service fdd496
# include <stdint.h>
Packit Service fdd496
# include <wchar.h>
Packit Service fdd496
# define mbsrtowcs __mbsrtowcs
Packit Service fdd496
# define USE_UNLOCKED_IO 0
Packit Service fdd496
# define _GL_ATTRIBUTE_FORMAT_PRINTF(a, b)
Packit Service fdd496
# define _GL_ARG_NONNULL(a)
Packit Service fdd496
#else
Packit Service fdd496
# include "getprogname.h"
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#if USE_UNLOCKED_IO
Packit Service fdd496
# include "unlocked-io.h"
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#ifndef _
Packit Service fdd496
# define _(String) String
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
/* If NULL, error will flush stdout, then print on stderr the program
Packit Service fdd496
   name, a colon and a space.  Otherwise, error will call this
Packit Service fdd496
   function without parameters instead.  */
Packit Service fdd496
void (*error_print_progname) (void);
Packit Service fdd496
Packit Service fdd496
/* This variable is incremented each time 'error' is called.  */
Packit Service fdd496
unsigned int error_message_count;
Packit Service fdd496
Packit Service fdd496
#ifdef _LIBC
Packit Service fdd496
/* In the GNU C library, there is a predefined variable for this.  */
Packit Service fdd496
Packit Service fdd496
# define program_name program_invocation_name
Packit Service fdd496
# include <errno.h>
Packit Service fdd496
# include <limits.h>
Packit Service fdd496
# include <libio/libioP.h>
Packit Service fdd496
Packit Service fdd496
/* In GNU libc we want do not want to use the common name 'error' directly.
Packit Service fdd496
   Instead make it a weak alias.  */
Packit Service fdd496
extern void __error (int status, int errnum, const char *message, ...)
Packit Service fdd496
     __attribute__ ((__format__ (__printf__, 3, 4)));
Packit Service fdd496
extern void __error_at_line (int status, int errnum, const char *file_name,
Packit Service fdd496
                             unsigned int line_number, const char *message,
Packit Service fdd496
                             ...)
Packit Service fdd496
     __attribute__ ((__format__ (__printf__, 5, 6)));
Packit Service fdd496
# define error __error
Packit Service fdd496
# define error_at_line __error_at_line
Packit Service fdd496
Packit Service fdd496
# include <libio/iolibio.h>
Packit Service fdd496
# define fflush(s) _IO_fflush (s)
Packit Service fdd496
# undef putc
Packit Service fdd496
# define putc(c, fp) _IO_putc (c, fp)
Packit Service fdd496
Packit Service fdd496
# include <bits/libc-lock.h>
Packit Service fdd496
Packit Service fdd496
#else /* not _LIBC */
Packit Service fdd496
Packit Service fdd496
# include <fcntl.h>
Packit Service fdd496
# include <unistd.h>
Packit Service fdd496
Packit Service fdd496
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
Packit Service fdd496
/* Get declarations of the native Windows API functions.  */
Packit Service fdd496
#  define WIN32_LEAN_AND_MEAN
Packit Service fdd496
#  include <windows.h>
Packit Service fdd496
/* Get _get_osfhandle.  */
Packit Service fdd496
#  if GNULIB_MSVC_NOTHROW
Packit Service fdd496
#   include "msvc-nothrow.h"
Packit Service fdd496
#  else
Packit Service fdd496
#   include <io.h>
Packit Service fdd496
#  endif
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
/* The gnulib override of fcntl is not needed in this file.  */
Packit Service fdd496
# undef fcntl
Packit Service fdd496
Packit Service fdd496
# if !(GNULIB_STRERROR_R_POSIX || HAVE_DECL_STRERROR_R)
Packit Service fdd496
#  ifndef HAVE_DECL_STRERROR_R
Packit Service fdd496
"this configure-time declaration test was not run"
Packit Service fdd496
#  endif
Packit Service fdd496
#  if STRERROR_R_CHAR_P
Packit Service fdd496
char *strerror_r (int errnum, char *buf, size_t buflen);
Packit Service fdd496
#  else
Packit Service fdd496
int strerror_r (int errnum, char *buf, size_t buflen);
Packit Service fdd496
#  endif
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
#define program_name getprogname ()
Packit Service fdd496
Packit Service fdd496
# if GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r
Packit Service fdd496
#  define __strerror_r strerror_r
Packit Service fdd496
# endif /* GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r */
Packit Service fdd496
#endif  /* not _LIBC */
Packit Service fdd496
Packit Service fdd496
#if !_LIBC
Packit Service fdd496
/* Return non-zero if FD is open.  */
Packit Service fdd496
static int
Packit Service fdd496
is_open (int fd)
Packit Service fdd496
{
Packit Service fdd496
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
Packit Service fdd496
  /* On native Windows: The initial state of unassigned standard file
Packit Service fdd496
     descriptors is that they are open but point to an INVALID_HANDLE_VALUE.
Packit Service fdd496
     There is no fcntl, and the gnulib replacement fcntl does not support
Packit Service fdd496
     F_GETFL.  */
Packit Service fdd496
  return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
Packit Service fdd496
# else
Packit Service fdd496
#  ifndef F_GETFL
Packit Service fdd496
#   error Please port fcntl to your platform
Packit Service fdd496
#  endif
Packit Service fdd496
  return 0 <= fcntl (fd, F_GETFL);
Packit Service fdd496
# endif
Packit Service fdd496
}
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
static void
Packit Service fdd496
flush_stdout (void)
Packit Service fdd496
{
Packit Service fdd496
#if !_LIBC
Packit Service fdd496
  int stdout_fd;
Packit Service fdd496
Packit Service fdd496
# if GNULIB_FREOPEN_SAFER
Packit Service fdd496
  /* Use of gnulib's freopen-safer module normally ensures that
Packit Service fdd496
       fileno (stdout) == 1
Packit Service fdd496
     whenever stdout is open.  */
Packit Service fdd496
  stdout_fd = STDOUT_FILENO;
Packit Service fdd496
# else
Packit Service fdd496
  /* POSIX states that fileno (stdout) after fclose is unspecified.  But in
Packit Service fdd496
     practice it is not a problem, because stdout is statically allocated and
Packit Service fdd496
     the fd of a FILE stream is stored as a field in its allocated memory.  */
Packit Service fdd496
  stdout_fd = fileno (stdout);
Packit Service fdd496
# endif
Packit Service fdd496
  /* POSIX states that fflush (stdout) after fclose is unspecified; it
Packit Service fdd496
     is safe in glibc, but not on all other platforms.  fflush (NULL)
Packit Service fdd496
     is always defined, but too draconian.  */
Packit Service fdd496
  if (0 <= stdout_fd && is_open (stdout_fd))
Packit Service fdd496
#endif
Packit Service fdd496
    fflush (stdout);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
static void
Packit Service fdd496
print_errno_message (int errnum)
Packit Service fdd496
{
Packit Service fdd496
  char const *s;
Packit Service fdd496
Packit Service fdd496
#if _LIBC || GNULIB_STRERROR_R_POSIX || defined HAVE_STRERROR_R
Packit Service fdd496
  char errbuf[1024];
Packit Service fdd496
# if _LIBC || (!GNULIB_STRERROR_R_POSIX && STRERROR_R_CHAR_P)
Packit Service fdd496
  s = __strerror_r (errnum, errbuf, sizeof errbuf);
Packit Service fdd496
# else
Packit Service fdd496
  if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
Packit Service fdd496
    s = errbuf;
Packit Service fdd496
  else
Packit Service fdd496
    s = 0;
Packit Service fdd496
# endif
Packit Service fdd496
#else
Packit Service fdd496
  s = strerror (errnum);
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#if !_LIBC
Packit Service fdd496
  if (! s)
Packit Service fdd496
    s = _("Unknown system error");
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#if _LIBC
Packit Service fdd496
  __fxprintf (NULL, ": %s", s);
Packit Service fdd496
#else
Packit Service fdd496
  fprintf (stderr, ": %s", s);
Packit Service fdd496
#endif
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
static void _GL_ATTRIBUTE_FORMAT_PRINTF (3, 0) _GL_ARG_NONNULL ((3))
Packit Service fdd496
error_tail (int status, int errnum, const char *message, va_list args)
Packit Service fdd496
{
Packit Service fdd496
#if _LIBC
Packit Service fdd496
  if (_IO_fwide (stderr, 0) > 0)
Packit Service fdd496
    {
Packit Service fdd496
      size_t len = strlen (message) + 1;
Packit Service fdd496
      wchar_t *wmessage = NULL;
Packit Service fdd496
      mbstate_t st;
Packit Service fdd496
      size_t res;
Packit Service fdd496
      const char *tmp;
Packit Service fdd496
      bool use_malloc = false;
Packit Service fdd496
Packit Service fdd496
      while (1)
Packit Service fdd496
        {
Packit Service fdd496
          if (__libc_use_alloca (len * sizeof (wchar_t)))
Packit Service fdd496
            wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
Packit Service fdd496
          else
Packit Service fdd496
            {
Packit Service fdd496
              if (!use_malloc)
Packit Service fdd496
                wmessage = NULL;
Packit Service fdd496
Packit Service fdd496
              wchar_t *p = (wchar_t *) realloc (wmessage,
Packit Service fdd496
                                                len * sizeof (wchar_t));
Packit Service fdd496
              if (p == NULL)
Packit Service fdd496
                {
Packit Service fdd496
                  free (wmessage);
Packit Service fdd496
                  fputws_unlocked (L"out of memory\n", stderr);
Packit Service fdd496
                  return;
Packit Service fdd496
                }
Packit Service fdd496
              wmessage = p;
Packit Service fdd496
              use_malloc = true;
Packit Service fdd496
            }
Packit Service fdd496
Packit Service fdd496
          memset (&st, '\0', sizeof (st));
Packit Service fdd496
          tmp = message;
Packit Service fdd496
Packit Service fdd496
          res = mbsrtowcs (wmessage, &tmp, len, &st);
Packit Service fdd496
          if (res != len)
Packit Service fdd496
            break;
Packit Service fdd496
Packit Service fdd496
          if (__builtin_expect (len >= SIZE_MAX / sizeof (wchar_t) / 2, 0))
Packit Service fdd496
            {
Packit Service fdd496
              /* This really should not happen if everything is fine.  */
Packit Service fdd496
              res = (size_t) -1;
Packit Service fdd496
              break;
Packit Service fdd496
            }
Packit Service fdd496
Packit Service fdd496
          len *= 2;
Packit Service fdd496
        }
Packit Service fdd496
Packit Service fdd496
      if (res == (size_t) -1)
Packit Service fdd496
        {
Packit Service fdd496
          /* The string cannot be converted.  */
Packit Service fdd496
          if (use_malloc)
Packit Service fdd496
            {
Packit Service fdd496
              free (wmessage);
Packit Service fdd496
              use_malloc = false;
Packit Service fdd496
            }
Packit Service fdd496
          wmessage = (wchar_t *) L"???";
Packit Service fdd496
        }
Packit Service fdd496
Packit Service fdd496
      __vfwprintf (stderr, wmessage, args);
Packit Service fdd496
Packit Service fdd496
      if (use_malloc)
Packit Service fdd496
        free (wmessage);
Packit Service fdd496
    }
Packit Service fdd496
  else
Packit Service fdd496
#endif
Packit Service fdd496
    vfprintf (stderr, message, args);
Packit Service fdd496
  va_end (args);
Packit Service fdd496
Packit Service fdd496
  ++error_message_count;
Packit Service fdd496
  if (errnum)
Packit Service fdd496
    print_errno_message (errnum);
Packit Service fdd496
#if _LIBC
Packit Service fdd496
  __fxprintf (NULL, "\n");
Packit Service fdd496
#else
Packit Service fdd496
  putc ('\n', stderr);
Packit Service fdd496
#endif
Packit Service fdd496
  fflush (stderr);
Packit Service fdd496
  if (status)
Packit Service fdd496
    exit (status);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
Packit Service fdd496
/* Print the program name and error message MESSAGE, which is a printf-style
Packit Service fdd496
   format string with optional args.
Packit Service fdd496
   If ERRNUM is nonzero, print its corresponding system error message.
Packit Service fdd496
   Exit with status STATUS if it is nonzero.  */
Packit Service fdd496
void
Packit Service fdd496
error (int status, int errnum, const char *message, ...)
Packit Service fdd496
{
Packit Service fdd496
  va_list args;
Packit Service fdd496
Packit Service fdd496
#if defined _LIBC && defined __libc_ptf_call
Packit Service fdd496
  /* We do not want this call to be cut short by a thread
Packit Service fdd496
     cancellation.  Therefore disable cancellation for now.  */
Packit Service fdd496
  int state = PTHREAD_CANCEL_ENABLE;
Packit Service fdd496
  __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
Packit Service fdd496
                   0);
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
  flush_stdout ();
Packit Service fdd496
#ifdef _LIBC
Packit Service fdd496
  _IO_flockfile (stderr);
Packit Service fdd496
#endif
Packit Service fdd496
  if (error_print_progname)
Packit Service fdd496
    (*error_print_progname) ();
Packit Service fdd496
  else
Packit Service fdd496
    {
Packit Service fdd496
#if _LIBC
Packit Service fdd496
      __fxprintf (NULL, "%s: ", program_name);
Packit Service fdd496
#else
Packit Service fdd496
      fprintf (stderr, "%s: ", program_name);
Packit Service fdd496
#endif
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
  va_start (args, message);
Packit Service fdd496
  error_tail (status, errnum, message, args);
Packit Service fdd496
Packit Service fdd496
#ifdef _LIBC
Packit Service fdd496
  _IO_funlockfile (stderr);
Packit Service fdd496
# ifdef __libc_ptf_call
Packit Service fdd496
  __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
Packit Service fdd496
# endif
Packit Service fdd496
#endif
Packit Service fdd496
}
Packit Service fdd496

Packit Service fdd496
/* Sometimes we want to have at most one error per line.  This
Packit Service fdd496
   variable controls whether this mode is selected or not.  */
Packit Service fdd496
int error_one_per_line;
Packit Service fdd496
Packit Service fdd496
void
Packit Service fdd496
error_at_line (int status, int errnum, const char *file_name,
Packit Service fdd496
               unsigned int line_number, const char *message, ...)
Packit Service fdd496
{
Packit Service fdd496
  va_list args;
Packit Service fdd496
Packit Service fdd496
  if (error_one_per_line)
Packit Service fdd496
    {
Packit Service fdd496
      static const char *old_file_name;
Packit Service fdd496
      static unsigned int old_line_number;
Packit Service fdd496
Packit Service fdd496
      if (old_line_number == line_number
Packit Service fdd496
          && (file_name == old_file_name
Packit Service fdd496
              || (old_file_name != NULL
Packit Service fdd496
                  && file_name != NULL
Packit Service fdd496
                  && strcmp (old_file_name, file_name) == 0)))
Packit Service fdd496
Packit Service fdd496
        /* Simply return and print nothing.  */
Packit Service fdd496
        return;
Packit Service fdd496
Packit Service fdd496
      old_file_name = file_name;
Packit Service fdd496
      old_line_number = line_number;
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
#if defined _LIBC && defined __libc_ptf_call
Packit Service fdd496
  /* We do not want this call to be cut short by a thread
Packit Service fdd496
     cancellation.  Therefore disable cancellation for now.  */
Packit Service fdd496
  int state = PTHREAD_CANCEL_ENABLE;
Packit Service fdd496
  __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
Packit Service fdd496
                   0);
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
  flush_stdout ();
Packit Service fdd496
#ifdef _LIBC
Packit Service fdd496
  _IO_flockfile (stderr);
Packit Service fdd496
#endif
Packit Service fdd496
  if (error_print_progname)
Packit Service fdd496
    (*error_print_progname) ();
Packit Service fdd496
  else
Packit Service fdd496
    {
Packit Service fdd496
#if _LIBC
Packit Service fdd496
      __fxprintf (NULL, "%s:", program_name);
Packit Service fdd496
#else
Packit Service fdd496
      fprintf (stderr, "%s:", program_name);
Packit Service fdd496
#endif
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
#if _LIBC
Packit Service fdd496
  __fxprintf (NULL, file_name != NULL ? "%s:%u: " : " ",
Packit Service fdd496
              file_name, line_number);
Packit Service fdd496
#else
Packit Service fdd496
  fprintf (stderr, file_name != NULL ? "%s:%u: " : " ",
Packit Service fdd496
           file_name, line_number);
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
  va_start (args, message);
Packit Service fdd496
  error_tail (status, errnum, message, args);
Packit Service fdd496
Packit Service fdd496
#ifdef _LIBC
Packit Service fdd496
  _IO_funlockfile (stderr);
Packit Service fdd496
# ifdef __libc_ptf_call
Packit Service fdd496
  __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
Packit Service fdd496
# endif
Packit Service fdd496
#endif
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
#ifdef _LIBC
Packit Service fdd496
/* Make the weak alias.  */
Packit Service fdd496
# undef error
Packit Service fdd496
# undef error_at_line
Packit Service fdd496
weak_alias (__error, error)
Packit Service fdd496
weak_alias (__error_at_line, error_at_line)
Packit Service fdd496
#endif