1 /*-
2 * Copyright (c) 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #if defined(LIBC_SCCS) && !defined(lint)
31 static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
32 #endif /* LIBC_SCCS and not lint */
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include "namespace.h"
37 #include <err.h>
38 #include <errno.h>
39 #include <stdarg.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include "block_abi.h"
44 #include "un-namespace.h"
45
46 #include "libc_private.h"
47
48 static FILE *err_file; /* file to use for error output */
49 static void (*err_exit)(int);
50 typedef DECLARE_BLOCK(void, err_exit_block_t, int);
51
52 /*
53 * This is declared to take a `void *' so that the caller is not required
54 * to include <stdio.h> first. However, it is really a `FILE *', and the
55 * manual page documents it as such.
56 */
57 void
err_set_file(void * fp)58 err_set_file(void *fp)
59 {
60 if (fp)
61 err_file = fp;
62 else
63 err_file = stderr;
64 }
65
66 void
err_set_exit(void (* ef)(int))67 err_set_exit(void (*ef)(int))
68 {
69 err_exit = ef;
70 }
71
72 /*
73 * Register a block to be executed at error exit.
74 */
75 void
err_set_exit_b(err_exit_block_t block)76 err_set_exit_b(err_exit_block_t block)
77 {
78
79 if (_Block_copy != 0)
80 err_exit = (void(*)(int))GET_BLOCK_FUNCTION(_Block_copy(block));
81 }
82
83 __weak_reference(_err, err);
84
85 void
_err(int eval,const char * fmt,...)86 _err(int eval, const char *fmt, ...)
87 {
88 va_list ap;
89 va_start(ap, fmt);
90 verrc(eval, errno, fmt, ap);
91 va_end(ap);
92 }
93
94 void
verr(int eval,const char * fmt,va_list ap)95 verr(int eval, const char *fmt, va_list ap)
96 {
97 verrc(eval, errno, fmt, ap);
98 }
99
100 void
errc(int eval,int code,const char * fmt,...)101 errc(int eval, int code, const char *fmt, ...)
102 {
103 va_list ap;
104 va_start(ap, fmt);
105 verrc(eval, code, fmt, ap);
106 va_end(ap);
107 }
108
109 void
verrc(int eval,int code,const char * fmt,va_list ap)110 verrc(int eval, int code, const char *fmt, va_list ap)
111 {
112 if (err_file == 0)
113 err_set_file((FILE *)0);
114 fprintf(err_file, "%s: ", _getprogname());
115 if (fmt != NULL) {
116 vfprintf(err_file, fmt, ap);
117 fprintf(err_file, ": ");
118 }
119 fprintf(err_file, "%s\n", strerror(code));
120 if (err_exit)
121 err_exit(eval);
122 exit(eval);
123 }
124
125 void
errx(int eval,const char * fmt,...)126 errx(int eval, const char *fmt, ...)
127 {
128 va_list ap;
129 va_start(ap, fmt);
130 verrx(eval, fmt, ap);
131 va_end(ap);
132 }
133
134 void
verrx(int eval,const char * fmt,va_list ap)135 verrx(int eval, const char *fmt, va_list ap)
136 {
137 if (err_file == 0)
138 err_set_file((FILE *)0);
139 fprintf(err_file, "%s: ", _getprogname());
140 if (fmt != NULL)
141 vfprintf(err_file, fmt, ap);
142 fprintf(err_file, "\n");
143 if (err_exit)
144 err_exit(eval);
145 exit(eval);
146 }
147
148 __weak_reference(_warn, warn);
149
150 void
_warn(const char * fmt,...)151 _warn(const char *fmt, ...)
152 {
153 va_list ap;
154 va_start(ap, fmt);
155 vwarnc(errno, fmt, ap);
156 va_end(ap);
157 }
158
159 void
vwarn(const char * fmt,va_list ap)160 vwarn(const char *fmt, va_list ap)
161 {
162 vwarnc(errno, fmt, ap);
163 }
164
165 void
warnc(int code,const char * fmt,...)166 warnc(int code, const char *fmt, ...)
167 {
168 va_list ap;
169 va_start(ap, fmt);
170 vwarnc(code, fmt, ap);
171 va_end(ap);
172 }
173
174 void
vwarnc(int code,const char * fmt,va_list ap)175 vwarnc(int code, const char *fmt, va_list ap)
176 {
177 if (err_file == 0)
178 err_set_file((FILE *)0);
179 fprintf(err_file, "%s: ", _getprogname());
180 if (fmt != NULL) {
181 vfprintf(err_file, fmt, ap);
182 fprintf(err_file, ": ");
183 }
184 fprintf(err_file, "%s\n", strerror(code));
185 }
186
187 void
warnx(const char * fmt,...)188 warnx(const char *fmt, ...)
189 {
190 va_list ap;
191 va_start(ap, fmt);
192 vwarnx(fmt, ap);
193 va_end(ap);
194 }
195
196 void
vwarnx(const char * fmt,va_list ap)197 vwarnx(const char *fmt, va_list ap)
198 {
199 if (err_file == 0)
200 err_set_file((FILE *)0);
201 fprintf(err_file, "%s: ", _getprogname());
202 if (fmt != NULL)
203 vfprintf(err_file, fmt, ap);
204 fprintf(err_file, "\n");
205 }
206