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

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

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