1: /* Error handler for noninteractive utilities
2: Copyright (C) 1990-1998, 2000-2007, 2009-2019 Free Software Foundation, Inc.
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 <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(a, b)
44: # define _GL_ARG_NONNULL(a)
45: #else
46: # include "getprogname.h"
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:
62: /* This variable is incremented each time 'error' is called. */
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:
73: /* In GNU libc we want do not want to use the common name 'error' directly.
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,
78: unsigned int line_number, const char *message,
79: ...)
80: __attribute__ ((__format__ (__printf__, 5, 6)));
81: # define error __error
82: # define error_at_line __error_at_line
83:
84: # include <libio/iolibio.h>
85: # define fflush(s) _IO_fflush (s)
86: # undef putc
87: # define putc(c, fp) _IO_putc (c, fp)
88:
89: # include <bits/libc-lock.h>
90:
91: #else /* not _LIBC */
92:
93: # include <fcntl.h>
94: # include <unistd.h>
95:
96: # if defined _WIN32 && ! defined __CYGWIN__
97: /* Get declarations of the native Windows API functions. */
98: # define WIN32_LEAN_AND_MEAN
99: # include <windows.h>
100: /* Get _get_osfhandle. */
101: # if GNULIB_MSVC_NOTHROW
102: # include "msvc-nothrow.h"
103: # else
104: # include <io.h>
105: # endif
106: # endif
107:
108: /* The gnulib override of fcntl is not needed in this file. */
109: # undef fcntl
110:
111: # if !(GNULIB_STRERROR_R_POSIX || HAVE_DECL_STRERROR_R)
112: # ifndef HAVE_DECL_STRERROR_R
113: "this configure-time declaration test was not run"
114: # endif
115: # if STRERROR_R_CHAR_P
116: char *strerror_r (int errnum, char *buf, size_t buflen);
117: # else
118: int strerror_r (int errnum, char *buf, size_t buflen);
119: # endif
120: # endif
121:
122: #define program_name getprogname ()
123:
124: # if GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r
125: # define __strerror_r strerror_r
126: # endif /* GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r */
127: #endif /* not _LIBC */
128:
129: #if !_LIBC
130: /* Return non-zero if FD is open. */
131: static int
132: is_open (int fd)
133: {
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. */
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:
149: static void
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: }
173:
174: static void
175: print_errno_message (int errnum)
176: {
177: char const *s;
178:
179: #if _LIBC || GNULIB_STRERROR_R_POSIX || defined HAVE_STRERROR_R
180: char errbuf[1024];
181: # if _LIBC || (!GNULIB_STRERROR_R_POSIX && STRERROR_R_CHAR_P)
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:
205: static void _GL_ATTRIBUTE_FORMAT_PRINTF (3, 0) _GL_ARG_NONNULL ((3))
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)
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:
246: if (__builtin_expect (len >= SIZE_MAX / sizeof (wchar_t) / 2, 0))
247: {
248: /* This really should not happen if everything is fine. */
249: res = (size_t) -1;
250: break;
251: }
252:
253: len *= 2;
254: }
255:
256: if (res == (size_t) -1)
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: }
266:
267: __vfwprintf (stderr, wmessage, args);
268:
269: if (use_malloc)
270: free (wmessage);
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),
304: 0);
305: #endif
306:
307: flush_stdout ();
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);
324: va_end (args);
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,
340: unsigned int line_number, const char *message, ...)
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
350: && (file_name == old_file_name
351: || (old_file_name != NULL
352: && file_name != NULL
353: && strcmp (old_file_name, file_name) == 0)))
354:
355: /* Simply return and print nothing. */
356: return;
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),
367: 0);
368: #endif
369:
370: flush_stdout ();
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
386: __fxprintf (NULL, file_name != NULL ? "%s:%u: " : " ",
387: file_name, line_number);
388: #else
389: fprintf (stderr, file_name != NULL ? "%s:%u: " : " ",
390: file_name, line_number);
391: #endif
392:
393: va_start (args, message);
394: error_tail (status, errnum, message, args);
395: va_end (args);
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>