gsasl  1.10.0
About: GNU SASL is an implementation of the Simple Authentication and Security Layer (SASL). Development version.
  Fossies Dox: gsasl-1.10.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

error.c
Go to the documentation of this file.
1 /* Error handler for noninteractive utilities
2  Copyright (C) 1990-1998, 2000-2007, 2009-2021 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_STANDARD(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
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
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 
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 
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
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. */
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
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
#define __attribute__(xyz)
Definition: cdefs.h:230
#define alloca(size)
Definition: getopt.c:56
#define __libc_use_alloca(size)
Definition: getopt.c:54
#define _GL_ARG_NONNULL(params)
Definition: arg-nonnull.h:24
static int is_open(int fd)
Definition: error.c:132
void error(int status, int errnum, const char *message,...)
Definition: error.c:295
static void _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD(3, 0)
Definition: error.c:205
#define _(String)
Definition: error.c:54
unsigned int error_message_count
Definition: error.c:63
static void print_errno_message(int errnum)
Definition: error.c:175
int error_one_per_line
Definition: error.c:336
void(* error_print_progname)(void)
Definition: error.c:60
this configure time declaration test was not run int strerror_r(int errnum, char *buf, size_t buflen)
Definition: strerror_r.c:144
void error_at_line(int status, int errnum, const char *file_name, unsigned int line_number, const char *message,...)
Definition: error.c:339
static void flush_stdout(void)
Definition: error.c:150
#define program_name
Definition: error.c:122
int fcntl(int fd, int action,...)
Definition: fcntl.c:202
#define NULL
Definition: stddef.in.h:72
char * strerror(int n)
Definition: strerror.c:36
#define STDOUT_FILENO
Definition: unistd.in.h:244
#define mbstate_t
Definition: wchar.in.h:143
#define PTHREAD_CANCEL_DISABLE
Definition: pthread.in.h:433
#define PTHREAD_CANCEL_ENABLE
Definition: pthread.in.h:432
static gss_OID_desc tmp
Definition: gss-extra.c:38
#define weak_alias(name, aliasname)
Definition: libc-config.h:179
return() size_t(-2)
int res
Definition: mbrtowc-impl.h:45
const char * p
Definition: mbrtowc-impl.h:42
char buf[4]
Definition: mbrtowc-impl.h:39
#define SIZE_MAX
Definition: quotearg.c:53