1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-29 11:41:21 +03:00

Add new function __libc_message which performs the printing and simple format string handling. The string is written to tty, stderr, syslog in this order, stopping after the first successful output.

This commit is contained in:
Ulrich Drepper
2004-11-13 03:09:30 +00:00
parent bfd259e0f6
commit 1327439fc6
2 changed files with 228 additions and 47 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1993, 1994, 1995, 1997, 2000 Free Software Foundation, Inc.
/* Copyright (C) 1993,1994,1995,1997,2000,2004 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
@ -16,44 +16,129 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sysdep.h>
#include <string.h>
#include <sysdep.h>
#include <unistd.h>
#include <sys/syslog.h>
#include <not-cancel.h>
#ifdef FATAL_PREPARE_INCLUDE
#include FATAL_PREPARE_INCLUDE
#endif
struct str_list
{
const char *str;
size_t len;
struct str_list *next;
};
/* Abort with an error message. */
void
__libc_fatal (message)
const char *message;
__libc_message (int do_abort, const char *fmt, ...)
{
size_t len = strlen (message);
va_list ap;
va_list ap_copy;
int fd = -1;
va_start (ap, fmt);
va_copy (ap_copy, ap);
#ifdef FATAL_PREPARE
FATAL_PREPARE;
#endif
while (len > 0)
/* Open a descriptor for /dev/tty unless the user explicitly
requests errors on standard error. */
const char *on_2 = __secure_getenv ("LIBC_FATAL_STDERR_");
if (on_2 == NULL || *on_2 == '\0')
fd = open_not_cancel_2 (_PATH_TTY, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
fd = STDERR_FILENO;
struct str_list *list = NULL;
int nlist = 0;
const char *cp = fmt;
while (*cp != '\0')
{
register int count = __write (STDERR_FILENO, message, len);
if (count > 0)
/* Find the next "%s" or the end of the string. */
char *next = cp;
while (next[0] != '%' || next[1] != 's')
{
message += count;
len -= count;
next = __strchrnul (next + 1, '%');
if (next[0] == '\0')
break;
}
else if (count < 0
#ifdef EINTR
&& errno != EINTR
#endif
)
break;
/* Determine what to print. */
const char *str;
size_t len;
if (cp[0] == '%' && cp[1] == 's')
{
str = va_arg (ap, const char *);
len = strlen (str);
cp += 2;
}
else
{
str = cp;
len = next - cp;
cp = next;
}
struct str_list *newp = alloca (sizeof (struct str_list));
newp->str = str;
newp->len = len;
newp->next = list;
list = newp;
++nlist;
}
abort ();
bool written = false;
if (nlist > 0)
{
struct iovec *iov = alloca (nlist * sizeof (struct iovec));
ssize_t total = 0;
for (int cnt = nlist - 1; cnt >= 0; --cnt)
{
iov[cnt].iov_base = list->str;
iov[cnt].iov_len = list->len;
total += list->len;
list = list->next;
}
if (TEMP_FAILURE_RETRY (__writev (fd, iov, nlist)) == total)
written = true;
}
va_end (ap);
/* If we had no success writing the message, use syslog. */
if (! written)
vsyslog (LOG_ERR, fmt, ap_copy);
if (do_abort()
/* Kill the application. */
abort ();
}
void
__libc_fatal (message)
const char *message;
{
__libc_message (1, "%s", message);
}
libc_hidden_def (__libc_fatal)