]>
Commit | Line | Data |
---|---|---|
a334319f | 1 | /* Copyright (C) 1993,1994,1995,1997,2000,2004 Free Software Foundation, Inc. |
ebbad4cc | 2 | This file is part of the GNU C Library. |
28f540f4 | 3 | |
ebbad4cc | 4 | The GNU C Library is free software; you can redistribute it and/or |
41bdb6e2 AJ |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either | |
7 | version 2.1 of the License, or (at your option) any later version. | |
28f540f4 | 8 | |
ebbad4cc UD |
9 | The GNU C Library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 12 | Lesser General Public License for more details. |
28f540f4 | 13 | |
41bdb6e2 AJ |
14 | You should have received a copy of the GNU Lesser General Public |
15 | License along with the GNU C Library; if not, write to the Free | |
16 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
17 | 02111-1307 USA. */ | |
28f540f4 | 18 | |
1327439f UD |
19 | #include <errno.h> |
20 | #include <fcntl.h> | |
21 | #include <paths.h> | |
22 | #include <stdarg.h> | |
23 | #include <stdbool.h> | |
28f540f4 | 24 | #include <stdio.h> |
ef52edfc | 25 | #include <stdlib.h> |
7f811679 | 26 | #include <string.h> |
1327439f UD |
27 | #include <sysdep.h> |
28 | #include <unistd.h> | |
29 | #include <sys/syslog.h> | |
579e2d6e | 30 | #include <sys/uio.h> |
1327439f | 31 | #include <not-cancel.h> |
28f540f4 RM |
32 | |
33 | #ifdef FATAL_PREPARE_INCLUDE | |
34 | #include FATAL_PREPARE_INCLUDE | |
35 | #endif | |
36 | ||
1327439f UD |
37 | struct str_list |
38 | { | |
39 | const char *str; | |
40 | size_t len; | |
41 | struct str_list *next; | |
42 | }; | |
43 | ||
44 | ||
28f540f4 RM |
45 | /* Abort with an error message. */ |
46 | void | |
1327439f | 47 | __libc_message (int do_abort, const char *fmt, ...) |
28f540f4 | 48 | { |
1327439f UD |
49 | va_list ap; |
50 | va_list ap_copy; | |
51 | int fd = -1; | |
52 | ||
53 | va_start (ap, fmt); | |
54 | va_copy (ap_copy, ap); | |
28f540f4 RM |
55 | |
56 | #ifdef FATAL_PREPARE | |
57 | FATAL_PREPARE; | |
58 | #endif | |
59 | ||
1327439f UD |
60 | /* Open a descriptor for /dev/tty unless the user explicitly |
61 | requests errors on standard error. */ | |
62 | const char *on_2 = __secure_getenv ("LIBC_FATAL_STDERR_"); | |
63 | if (on_2 == NULL || *on_2 == '\0') | |
64 | fd = open_not_cancel_2 (_PATH_TTY, O_RDWR | O_NOCTTY | O_NDELAY); | |
65 | ||
66 | if (fd == -1) | |
67 | fd = STDERR_FILENO; | |
68 | ||
69 | struct str_list *list = NULL; | |
70 | int nlist = 0; | |
71 | ||
72 | const char *cp = fmt; | |
73 | while (*cp != '\0') | |
28f540f4 | 74 | { |
1327439f | 75 | /* Find the next "%s" or the end of the string. */ |
a334319f | 76 | char *next = cp; |
1327439f | 77 | while (next[0] != '%' || next[1] != 's') |
28f540f4 | 78 | { |
1327439f UD |
79 | next = __strchrnul (next + 1, '%'); |
80 | ||
81 | if (next[0] == '\0') | |
82 | break; | |
28f540f4 | 83 | } |
1327439f UD |
84 | |
85 | /* Determine what to print. */ | |
86 | const char *str; | |
87 | size_t len; | |
88 | if (cp[0] == '%' && cp[1] == 's') | |
89 | { | |
90 | str = va_arg (ap, const char *); | |
91 | len = strlen (str); | |
92 | cp += 2; | |
93 | } | |
94 | else | |
95 | { | |
96 | str = cp; | |
97 | len = next - cp; | |
98 | cp = next; | |
99 | } | |
100 | ||
101 | struct str_list *newp = alloca (sizeof (struct str_list)); | |
102 | newp->str = str; | |
103 | newp->len = len; | |
104 | newp->next = list; | |
105 | list = newp; | |
106 | ++nlist; | |
107 | } | |
108 | ||
109 | bool written = false; | |
110 | if (nlist > 0) | |
111 | { | |
112 | struct iovec *iov = alloca (nlist * sizeof (struct iovec)); | |
113 | ssize_t total = 0; | |
114 | ||
115 | for (int cnt = nlist - 1; cnt >= 0; --cnt) | |
116 | { | |
a334319f | 117 | iov[cnt].iov_base = list->str; |
1327439f UD |
118 | iov[cnt].iov_len = list->len; |
119 | total += list->len; | |
120 | list = list->next; | |
121 | } | |
122 | ||
123 | if (TEMP_FAILURE_RETRY (__writev (fd, iov, nlist)) == total) | |
124 | written = true; | |
28f540f4 RM |
125 | } |
126 | ||
1327439f UD |
127 | va_end (ap); |
128 | ||
129 | /* If we had no success writing the message, use syslog. */ | |
130 | if (! written) | |
131 | vsyslog (LOG_ERR, fmt, ap_copy); | |
132 | ||
37fa1953 UD |
133 | va_end (ap_copy); |
134 | ||
f895670d UD |
135 | if (do_abort) |
136 | /* Kill the application. */ | |
137 | abort (); | |
1327439f UD |
138 | } |
139 | ||
140 | ||
141 | void | |
142 | __libc_fatal (message) | |
143 | const char *message; | |
144 | { | |
f895670d UD |
145 | /* The loop is added only to keep gcc happy. */ |
146 | while (1) | |
147 | __libc_message (1, "%s", message); | |
28f540f4 | 148 | } |
9d79e037 | 149 | libc_hidden_def (__libc_fatal) |