/* 4.4BSD utility functions for error messages. Copyright (C) 1995,1996,1998,2001,2002,2011 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ #include <stdarg.h> #include <err.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <stdio.h> #include <wchar.h> #define flockfile(s) _IO_flockfile (s) #define funlockfile(s) _IO_funlockfile (s) extern char *__progname; #define VA(call) \ { \ va_list ap; \ va_start (ap, format); \ call; \ va_end (ap); \ } static void convert_and_print (const char *format, __gnuc_va_list ap) { #define ALLOCA_LIMIT 2000 size_t len; wchar_t *wformat = NULL; mbstate_t st; size_t res; const char *tmp; if (format == NULL) return; len = strlen (format) + 1; do { if (len < ALLOCA_LIMIT) wformat = (wchar_t *) alloca (len * sizeof (wchar_t)); else { if (wformat != NULL && len / 2 < ALLOCA_LIMIT) wformat = NULL; wformat = (wchar_t *) realloc (wformat, len * sizeof (wchar_t)); if (wformat == NULL) { fputws_unlocked (L"out of memory\n", stderr); return; } } memset (&st, '\0', sizeof (st)); tmp =format; } while ((res = __mbsrtowcs (wformat, &tmp, len, &st)) == len); if (res == (size_t) -1) /* The string cannot be converted. */ wformat = (wchar_t *) L"???"; __vfwprintf (stderr, wformat, ap); } void vwarnx (const char *format, __gnuc_va_list ap) { flockfile (stderr); if (_IO_fwide (stderr, 0) > 0) { __fwprintf (stderr, L"%s: ", __progname); convert_and_print (format, ap); putwc_unlocked (L'\n', stderr); } else { fprintf (stderr, "%s: ", __progname); if (format) vfprintf (stderr, format, ap); putc_unlocked ('\n', stderr); } funlockfile (stderr); } libc_hidden_def (vwarnx) void vwarn (const char *format, __gnuc_va_list ap) { int error = errno; flockfile (stderr); if (_IO_fwide (stderr, 0) > 0) { __fwprintf (stderr, L"%s: ", __progname); if (format) { convert_and_print (format, ap); fputws_unlocked (L": ", stderr); } __set_errno (error); __fwprintf (stderr, L"%m\n"); } else { fprintf (stderr, "%s: ", __progname); if (format) { vfprintf (stderr, format, ap); fputs_unlocked (": ", stderr); } __set_errno (error); fprintf (stderr, "%m\n"); } funlockfile (stderr); } libc_hidden_def (vwarn) void warn (const char *format, ...) { VA (vwarn (format, ap)) } libc_hidden_def (warn) void warnx (const char *format, ...) { VA (vwarnx (format, ap)) } libc_hidden_def (warnx) void verr (int status, const char *format, __gnuc_va_list ap) { vwarn (format, ap); exit (status); } libc_hidden_def (verr) void verrx (int status, const char *format, __gnuc_va_list ap) { vwarnx (format, ap); exit (status); } libc_hidden_def (verrx) void err (int status, const char *format, ...) { VA (verr (status, format, ap)) } void errx (int status, const char *format, ...) { VA (verrx (status, format, ap)) }