Annotation of embedaddon/libiconv/srclib/error.c, revision 1.1.1.3

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>