118fd37a7SXin LI /* Error handler for noninteractive utilities
218fd37a7SXin LI Copyright (C) 1990-1998, 2000-2002, 2003 Free Software Foundation, Inc.
318fd37a7SXin LI This file is part of the GNU C Library.
418fd37a7SXin LI
518fd37a7SXin LI This program is free software; you can redistribute it and/or modify
618fd37a7SXin LI it under the terms of the GNU General Public License as published by
718fd37a7SXin LI the Free Software Foundation; either version 2, or (at your option)
818fd37a7SXin LI any later version.
918fd37a7SXin LI
1018fd37a7SXin LI This program is distributed in the hope that it will be useful,
1118fd37a7SXin LI but WITHOUT ANY WARRANTY; without even the implied warranty of
1218fd37a7SXin LI MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1318fd37a7SXin LI GNU General Public License for more details.
1418fd37a7SXin LI
1518fd37a7SXin LI You should have received a copy of the GNU General Public License along
1618fd37a7SXin LI with this program; if not, write to the Free Software Foundation,
1718fd37a7SXin LI Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
1818fd37a7SXin LI
1918fd37a7SXin LI /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
2018fd37a7SXin LI
2118fd37a7SXin LI #ifdef HAVE_CONFIG_H
2218fd37a7SXin LI # include <config.h>
2318fd37a7SXin LI #endif
2418fd37a7SXin LI
2518fd37a7SXin LI #include "error.h"
2618fd37a7SXin LI
2718fd37a7SXin LI #include <stdarg.h>
2818fd37a7SXin LI #include <stdio.h>
2918fd37a7SXin LI #include <stdlib.h>
3018fd37a7SXin LI #include <string.h>
3118fd37a7SXin LI
3218fd37a7SXin LI #ifdef _LIBC
3318fd37a7SXin LI # include <libintl.h>
3418fd37a7SXin LI #else
3518fd37a7SXin LI # include "gettext.h"
3618fd37a7SXin LI #endif
3718fd37a7SXin LI
3818fd37a7SXin LI #ifdef _LIBC
3918fd37a7SXin LI # include <wchar.h>
4018fd37a7SXin LI # define mbsrtowcs __mbsrtowcs
4118fd37a7SXin LI #endif
4218fd37a7SXin LI
4318fd37a7SXin LI #if !_LIBC
4418fd37a7SXin LI # include "unlocked-io.h"
4518fd37a7SXin LI #endif
4618fd37a7SXin LI
4718fd37a7SXin LI #ifndef _
4818fd37a7SXin LI # define _(String) String
4918fd37a7SXin LI #endif
5018fd37a7SXin LI
5118fd37a7SXin LI /* If NULL, error will flush stdout, then print on stderr the program
5218fd37a7SXin LI name, a colon and a space. Otherwise, error will call this
5318fd37a7SXin LI function without parameters instead. */
5418fd37a7SXin LI void (*error_print_progname) (void);
5518fd37a7SXin LI
5618fd37a7SXin LI /* This variable is incremented each time `error' is called. */
5718fd37a7SXin LI unsigned int error_message_count;
5818fd37a7SXin LI
5918fd37a7SXin LI #ifdef _LIBC
6018fd37a7SXin LI /* In the GNU C library, there is a predefined variable for this. */
6118fd37a7SXin LI
6218fd37a7SXin LI # define program_name program_invocation_name
6318fd37a7SXin LI # include <errno.h>
6418fd37a7SXin LI # include <libio/libioP.h>
6518fd37a7SXin LI
6618fd37a7SXin LI /* In GNU libc we want do not want to use the common name `error' directly.
6718fd37a7SXin LI Instead make it a weak alias. */
6818fd37a7SXin LI extern void __error (int status, int errnum, const char *message, ...)
6918fd37a7SXin LI __attribute__ ((__format__ (__printf__, 3, 4)));
7018fd37a7SXin LI extern void __error_at_line (int status, int errnum, const char *file_name,
7118fd37a7SXin LI unsigned int line_number, const char *message,
7218fd37a7SXin LI ...)
7318fd37a7SXin LI __attribute__ ((__format__ (__printf__, 5, 6)));;
7418fd37a7SXin LI # define error __error
7518fd37a7SXin LI # define error_at_line __error_at_line
7618fd37a7SXin LI
7718fd37a7SXin LI # include <libio/iolibio.h>
7818fd37a7SXin LI # define fflush(s) INTUSE(_IO_fflush) (s)
7918fd37a7SXin LI # undef putc
8018fd37a7SXin LI # define putc(c, fp) INTUSE(_IO_putc) (c, fp)
8118fd37a7SXin LI
8218fd37a7SXin LI # include <bits/libc-lock.h>
8318fd37a7SXin LI
8418fd37a7SXin LI #else /* not _LIBC */
8518fd37a7SXin LI
8618fd37a7SXin LI # if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
8718fd37a7SXin LI # ifndef HAVE_DECL_STRERROR_R
8818fd37a7SXin LI "this configure-time declaration test was not run"
8918fd37a7SXin LI # endif
9018fd37a7SXin LI char *strerror_r ();
9118fd37a7SXin LI # endif
9218fd37a7SXin LI
9318fd37a7SXin LI # ifndef SIZE_MAX
9418fd37a7SXin LI # define SIZE_MAX ((size_t) -1)
9518fd37a7SXin LI # endif
9618fd37a7SXin LI
9718fd37a7SXin LI /* The calling program should define program_name and set it to the
9818fd37a7SXin LI name of the executing program. */
9918fd37a7SXin LI extern char *program_name;
10018fd37a7SXin LI
10118fd37a7SXin LI # if HAVE_STRERROR_R || defined strerror_r
10218fd37a7SXin LI # define __strerror_r strerror_r
10318fd37a7SXin LI # endif
10418fd37a7SXin LI #endif /* not _LIBC */
10518fd37a7SXin LI
10618fd37a7SXin LI static void
print_errno_message(int errnum)10718fd37a7SXin LI print_errno_message (int errnum)
10818fd37a7SXin LI {
10918fd37a7SXin LI char const *s;
11018fd37a7SXin LI
11118fd37a7SXin LI #if defined HAVE_STRERROR_R || _LIBC
11218fd37a7SXin LI char errbuf[1024];
11318fd37a7SXin LI # if STRERROR_R_CHAR_P || _LIBC
11418fd37a7SXin LI s = __strerror_r (errnum, errbuf, sizeof errbuf);
11518fd37a7SXin LI # else
11618fd37a7SXin LI if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
11718fd37a7SXin LI s = errbuf;
11818fd37a7SXin LI else
11918fd37a7SXin LI s = 0;
12018fd37a7SXin LI # endif
12118fd37a7SXin LI #else
12218fd37a7SXin LI s = strerror (errnum);
12318fd37a7SXin LI #endif
12418fd37a7SXin LI
12518fd37a7SXin LI #if !_LIBC
12618fd37a7SXin LI if (! s)
12718fd37a7SXin LI s = _("Unknown system error");
12818fd37a7SXin LI #endif
12918fd37a7SXin LI
13018fd37a7SXin LI #if _LIBC
13118fd37a7SXin LI if (_IO_fwide (stderr, 0) > 0)
13218fd37a7SXin LI {
13318fd37a7SXin LI __fwprintf (stderr, L": %s", s);
13418fd37a7SXin LI return;
13518fd37a7SXin LI }
13618fd37a7SXin LI #endif
13718fd37a7SXin LI
13818fd37a7SXin LI fprintf (stderr, ": %s", s);
13918fd37a7SXin LI }
14018fd37a7SXin LI
14118fd37a7SXin LI static void
error_tail(int status,int errnum,const char * message,va_list args)14218fd37a7SXin LI error_tail (int status, int errnum, const char *message, va_list args)
14318fd37a7SXin LI {
14418fd37a7SXin LI #if _LIBC
14518fd37a7SXin LI if (_IO_fwide (stderr, 0) > 0)
14618fd37a7SXin LI {
14718fd37a7SXin LI # define ALLOCA_LIMIT 2000
14818fd37a7SXin LI size_t len = strlen (message) + 1;
14918fd37a7SXin LI const wchar_t *wmessage = L"out of memory";
15018fd37a7SXin LI wchar_t *wbuf = (len < ALLOCA_LIMIT
15118fd37a7SXin LI ? alloca (len * sizeof *wbuf)
15218fd37a7SXin LI : len <= SIZE_MAX / sizeof *wbuf
15318fd37a7SXin LI ? malloc (len * sizeof *wbuf)
15418fd37a7SXin LI : NULL);
15518fd37a7SXin LI
15618fd37a7SXin LI if (wbuf)
15718fd37a7SXin LI {
15818fd37a7SXin LI size_t res;
15918fd37a7SXin LI mbstate_t st;
16018fd37a7SXin LI const char *tmp = message;
16118fd37a7SXin LI memset (&st, '\0', sizeof (st));
16218fd37a7SXin LI res = mbsrtowcs (wbuf, &tmp, len, &st);
16318fd37a7SXin LI wmessage = res == (size_t) -1 ? L"???" : wbuf;
16418fd37a7SXin LI }
16518fd37a7SXin LI
16618fd37a7SXin LI __vfwprintf (stderr, wmessage, args);
16718fd37a7SXin LI if (! (len < ALLOCA_LIMIT))
16818fd37a7SXin LI free (wbuf);
16918fd37a7SXin LI }
17018fd37a7SXin LI else
17118fd37a7SXin LI #endif
17218fd37a7SXin LI vfprintf (stderr, message, args);
17318fd37a7SXin LI va_end (args);
17418fd37a7SXin LI
17518fd37a7SXin LI ++error_message_count;
17618fd37a7SXin LI if (errnum)
17718fd37a7SXin LI print_errno_message (errnum);
17818fd37a7SXin LI #if _LIBC
17918fd37a7SXin LI if (_IO_fwide (stderr, 0) > 0)
18018fd37a7SXin LI putwc (L'\n', stderr);
18118fd37a7SXin LI else
18218fd37a7SXin LI #endif
18318fd37a7SXin LI putc ('\n', stderr);
18418fd37a7SXin LI fflush (stderr);
18518fd37a7SXin LI if (status)
18618fd37a7SXin LI exit (status);
18718fd37a7SXin LI }
18818fd37a7SXin LI
18918fd37a7SXin LI
19018fd37a7SXin LI /* Print the program name and error message MESSAGE, which is a printf-style
19118fd37a7SXin LI format string with optional args.
19218fd37a7SXin LI If ERRNUM is nonzero, print its corresponding system error message.
19318fd37a7SXin LI Exit with status STATUS if it is nonzero. */
19418fd37a7SXin LI void
error(int status,int errnum,const char * message,...)19518fd37a7SXin LI error (int status, int errnum, const char *message, ...)
19618fd37a7SXin LI {
19718fd37a7SXin LI va_list args;
19818fd37a7SXin LI
19918fd37a7SXin LI #if defined _LIBC && defined __libc_ptf_call
20018fd37a7SXin LI /* We do not want this call to be cut short by a thread
20118fd37a7SXin LI cancellation. Therefore disable cancellation for now. */
20218fd37a7SXin LI int state = PTHREAD_CANCEL_ENABLE;
20318fd37a7SXin LI __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
20418fd37a7SXin LI 0);
20518fd37a7SXin LI #endif
20618fd37a7SXin LI
20718fd37a7SXin LI fflush (stdout);
20818fd37a7SXin LI #ifdef _LIBC
20918fd37a7SXin LI _IO_flockfile (stderr);
21018fd37a7SXin LI #endif
21118fd37a7SXin LI if (error_print_progname)
21218fd37a7SXin LI (*error_print_progname) ();
21318fd37a7SXin LI else
21418fd37a7SXin LI {
21518fd37a7SXin LI #if _LIBC
21618fd37a7SXin LI if (_IO_fwide (stderr, 0) > 0)
21718fd37a7SXin LI __fwprintf (stderr, L"%s: ", program_name);
21818fd37a7SXin LI else
21918fd37a7SXin LI #endif
22018fd37a7SXin LI fprintf (stderr, "%s: ", program_name);
22118fd37a7SXin LI }
22218fd37a7SXin LI
22318fd37a7SXin LI va_start (args, message);
22418fd37a7SXin LI error_tail (status, errnum, message, args);
22518fd37a7SXin LI
22618fd37a7SXin LI #ifdef _LIBC
22718fd37a7SXin LI _IO_funlockfile (stderr);
22818fd37a7SXin LI # ifdef __libc_ptf_call
22918fd37a7SXin LI __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
23018fd37a7SXin LI # endif
23118fd37a7SXin LI #endif
23218fd37a7SXin LI }
23318fd37a7SXin LI
23418fd37a7SXin LI /* Sometimes we want to have at most one error per line. This
23518fd37a7SXin LI variable controls whether this mode is selected or not. */
23618fd37a7SXin LI int error_one_per_line;
23718fd37a7SXin LI
23818fd37a7SXin LI void
error_at_line(int status,int errnum,const char * file_name,unsigned int line_number,const char * message,...)23918fd37a7SXin LI error_at_line (int status, int errnum, const char *file_name,
24018fd37a7SXin LI unsigned int line_number, const char *message, ...)
24118fd37a7SXin LI {
24218fd37a7SXin LI va_list args;
24318fd37a7SXin LI
24418fd37a7SXin LI if (error_one_per_line)
24518fd37a7SXin LI {
24618fd37a7SXin LI static const char *old_file_name;
24718fd37a7SXin LI static unsigned int old_line_number;
24818fd37a7SXin LI
24918fd37a7SXin LI if (old_line_number == line_number
25018fd37a7SXin LI && (file_name == old_file_name
25118fd37a7SXin LI || strcmp (old_file_name, file_name) == 0))
25218fd37a7SXin LI /* Simply return and print nothing. */
25318fd37a7SXin LI return;
25418fd37a7SXin LI
25518fd37a7SXin LI old_file_name = file_name;
25618fd37a7SXin LI old_line_number = line_number;
25718fd37a7SXin LI }
25818fd37a7SXin LI
25918fd37a7SXin LI #if defined _LIBC && defined __libc_ptf_call
26018fd37a7SXin LI /* We do not want this call to be cut short by a thread
26118fd37a7SXin LI cancellation. Therefore disable cancellation for now. */
26218fd37a7SXin LI int state = PTHREAD_CANCEL_ENABLE;
26318fd37a7SXin LI __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
26418fd37a7SXin LI 0);
26518fd37a7SXin LI #endif
26618fd37a7SXin LI
26718fd37a7SXin LI fflush (stdout);
26818fd37a7SXin LI #ifdef _LIBC
26918fd37a7SXin LI _IO_flockfile (stderr);
27018fd37a7SXin LI #endif
27118fd37a7SXin LI if (error_print_progname)
27218fd37a7SXin LI (*error_print_progname) ();
27318fd37a7SXin LI else
27418fd37a7SXin LI {
27518fd37a7SXin LI #if _LIBC
27618fd37a7SXin LI if (_IO_fwide (stderr, 0) > 0)
27718fd37a7SXin LI __fwprintf (stderr, L"%s: ", program_name);
27818fd37a7SXin LI else
27918fd37a7SXin LI #endif
28018fd37a7SXin LI fprintf (stderr, "%s:", program_name);
28118fd37a7SXin LI }
28218fd37a7SXin LI
28318fd37a7SXin LI if (file_name != NULL)
28418fd37a7SXin LI {
28518fd37a7SXin LI #if _LIBC
28618fd37a7SXin LI if (_IO_fwide (stderr, 0) > 0)
28718fd37a7SXin LI __fwprintf (stderr, L"%s:%d: ", file_name, line_number);
28818fd37a7SXin LI else
28918fd37a7SXin LI #endif
29018fd37a7SXin LI fprintf (stderr, "%s:%d: ", file_name, line_number);
29118fd37a7SXin LI }
29218fd37a7SXin LI
29318fd37a7SXin LI va_start (args, message);
29418fd37a7SXin LI error_tail (status, errnum, message, args);
29518fd37a7SXin LI
29618fd37a7SXin LI #ifdef _LIBC
29718fd37a7SXin LI _IO_funlockfile (stderr);
29818fd37a7SXin LI # ifdef __libc_ptf_call
29918fd37a7SXin LI __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
30018fd37a7SXin LI # endif
30118fd37a7SXin LI #endif
30218fd37a7SXin LI }
30318fd37a7SXin LI
30418fd37a7SXin LI #ifdef _LIBC
30518fd37a7SXin LI /* Make the weak alias. */
30618fd37a7SXin LI # undef error
30718fd37a7SXin LI # undef error_at_line
30818fd37a7SXin LI weak_alias (__error, error)
30918fd37a7SXin LI weak_alias (__error_at_line, error_at_line)
31018fd37a7SXin LI #endif
311