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