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