xref: /illumos-gate/usr/src/lib/libc/port/gen/err.c (revision 621b6cf75a027e4c06f2a1b3207abb5f24539b14)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /*
27  * Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
28  */
29 
30 #include "lint.h"
31 #include "file64.h"
32 #include "mtlib.h"
33 #include "thr_uberdata.h"
34 #include <sys/types.h>
35 #include <err.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <stdarg.h>
39 #include <string.h>
40 #include <errno.h>
41 #include <dlfcn.h>
42 #include "stdiom.h"
43 
44 /* Function exit/warning functions and global variables. */
45 
46 const char *__progname;		/* GNU/Linux/BSD compatibility */
47 
48 #define	PROGNAMESIZE	128	/* buffer size for __progname */
49 
50 const char *
getprogname(void)51 getprogname(void)
52 {
53 	return (__progname);
54 }
55 
56 void
setprogname(const char * argv0)57 setprogname(const char *argv0)
58 {
59 	uberdata_t *udp = curthread->ul_uberdata;
60 	const char *progname;
61 
62 	if ((progname = strrchr(argv0, '/')) == NULL)
63 		progname = argv0;
64 	else
65 		progname++;
66 
67 	if (udp->progname == NULL)
68 		udp->progname = lmalloc(PROGNAMESIZE);
69 	(void) strlcpy(udp->progname, progname, PROGNAMESIZE);
70 	__progname = udp->progname;
71 }
72 
73 /* called only from libc_init() */
74 void
init_progname(void)75 init_progname(void)
76 {
77 	Dl_argsinfo_t args;
78 	const char *argv0;
79 
80 	if (dlinfo(RTLD_SELF, RTLD_DI_ARGSINFO, &args) < 0 ||
81 	    args.dla_argc <= 0 ||
82 	    (argv0 = args.dla_argv[0]) == NULL)
83 		argv0 = "UNKNOWN";
84 
85 	setprogname(argv0);
86 }
87 
88 /*
89  * warncore() is the workhorse of these functions.  Everything else has
90  * a warncore() component in it.
91  */
92 static rmutex_t *
warncore(FILE * fp,const char * fmt,va_list args)93 warncore(FILE *fp, const char *fmt, va_list args)
94 {
95 	rmutex_t *lk;
96 
97 	FLOCKFILE(lk, fp);
98 
99 	if (__progname != NULL)
100 		(void) fprintf(fp, "%s: ", __progname);
101 
102 	if (fmt != NULL) {
103 		(void) vfprintf(fp, fmt, args);
104 	}
105 
106 	return (lk);
107 }
108 
109 /* Finish a warning with a newline and a flush of stderr. */
110 static void
warnfinish(FILE * fp,rmutex_t * lk)111 warnfinish(FILE *fp, rmutex_t *lk)
112 {
113 	(void) fputc('\n', fp);
114 	(void) fflush(fp);
115 	FUNLOCKFILE(lk);
116 }
117 
118 static void
vwarnfp(FILE * fp,int code,const char * fmt,va_list args)119 vwarnfp(FILE *fp, int code, const char *fmt, va_list args)
120 {
121 	rmutex_t *lk;
122 
123 	lk = warncore(fp, fmt, args);
124 	if (fmt != NULL) {
125 		(void) fputc(':', fp);
126 		(void) fputc(' ', fp);
127 	}
128 	(void) fputs(strerror(code), fp);
129 	warnfinish(fp, lk);
130 }
131 
132 void
vwarnx(const char * fmt,va_list args)133 vwarnx(const char *fmt, va_list args)
134 {
135 	rmutex_t *lk;
136 
137 	lk = warncore(stderr, fmt, args);
138 	warnfinish(stderr, lk);
139 }
140 
141 void
vwarn(const char * fmt,va_list args)142 vwarn(const char *fmt, va_list args)
143 {
144 	vwarnfp(stderr, errno, fmt, args);
145 }
146 
147 void
vwarnc(int code,const char * fmt,va_list args)148 vwarnc(int code, const char *fmt, va_list args)
149 {
150 	vwarnfp(stderr, code, fmt, args);
151 }
152 
153 void
warnx(const char * fmt,...)154 warnx(const char *fmt, ...)
155 {
156 	va_list args;
157 
158 	va_start(args, fmt);
159 	vwarnx(fmt, args);
160 	va_end(args);
161 }
162 
163 void
warn(const char * fmt,...)164 warn(const char *fmt, ...)
165 {
166 	va_list args;
167 
168 	va_start(args, fmt);
169 	vwarn(fmt, args);
170 	va_end(args);
171 }
172 
173 void
warnc(int code,const char * fmt,...)174 warnc(int code, const char *fmt, ...)
175 {
176 	va_list args;
177 
178 	va_start(args, fmt);
179 	vwarnc(code, fmt, args);
180 	va_end(args);
181 }
182 
183 void
err(int status,const char * fmt,...)184 err(int status, const char *fmt, ...)
185 {
186 	va_list args;
187 
188 	va_start(args, fmt);
189 	vwarn(fmt, args);
190 	va_end(args);
191 	exit(status);
192 }
193 
194 void
errc(int status,int code,const char * fmt,...)195 errc(int status, int code, const char *fmt, ...)
196 {
197 	va_list args;
198 
199 	va_start(args, fmt);
200 	vwarnc(code, fmt, args);
201 	va_end(args);
202 	exit(status);
203 }
204 
205 void
verr(int status,const char * fmt,va_list args)206 verr(int status, const char *fmt, va_list args)
207 {
208 	vwarn(fmt, args);
209 	exit(status);
210 }
211 
212 void
verrc(int status,int code,const char * fmt,va_list args)213 verrc(int status, int code, const char *fmt, va_list args)
214 {
215 	vwarnc(code, fmt, args);
216 	exit(status);
217 }
218 
219 void
errx(int status,const char * fmt,...)220 errx(int status, const char *fmt, ...)
221 {
222 	va_list args;
223 
224 	va_start(args, fmt);
225 	vwarnx(fmt, args);
226 	va_end(args);
227 	exit(status);
228 }
229 
230 void
verrx(int status,const char * fmt,va_list args)231 verrx(int status, const char *fmt, va_list args)
232 {
233 	vwarnx(fmt, args);
234 	exit(status);
235 }
236 
237 /*
238  * The following functions are here as the targets of filters in libipsecutil.
239  */
240 
241 void
_vwarnxfp(FILE * fp,const char * fmt,va_list args)242 _vwarnxfp(FILE *fp, const char *fmt, va_list args)
243 {
244 	rmutex_t *lk;
245 
246 	lk = warncore(fp, fmt, args);
247 	warnfinish(fp, lk);
248 }
249 
250 void
_vwarnfp(FILE * fp,const char * fmt,va_list args)251 _vwarnfp(FILE *fp, const char *fmt, va_list args)
252 {
253 	vwarnfp(fp, errno, fmt, args);
254 }
255 
256 void
_warnfp(FILE * fp,const char * fmt,...)257 _warnfp(FILE *fp, const char *fmt, ...)
258 {
259 	va_list args;
260 
261 	va_start(args, fmt);
262 	_vwarnfp(fp, fmt, args);
263 	va_end(args);
264 }
265 
266 void
_warnxfp(FILE * fp,const char * fmt,...)267 _warnxfp(FILE *fp, const char *fmt, ...)
268 {
269 	va_list args;
270 
271 	va_start(args, fmt);
272 	_vwarnxfp(fp, fmt, args);
273 	va_end(args);
274 }
275 
276 void
_errfp(FILE * fp,int status,const char * fmt,...)277 _errfp(FILE *fp, int status, const char *fmt, ...)
278 {
279 	va_list args;
280 
281 	va_start(args, fmt);
282 	_vwarnfp(fp, fmt, args);
283 	va_end(args);
284 	exit(status);
285 }
286 
287 void
_verrfp(FILE * fp,int status,const char * fmt,va_list args)288 _verrfp(FILE *fp, int status, const char *fmt, va_list args)
289 {
290 	_vwarnfp(fp, fmt, args);
291 	exit(status);
292 }
293 
294 void
_errxfp(FILE * fp,int status,const char * fmt,...)295 _errxfp(FILE *fp, int status, const char *fmt, ...)
296 {
297 	va_list args;
298 
299 	va_start(args, fmt);
300 	_vwarnxfp(fp, fmt, args);
301 	va_end(args);
302 	exit(status);
303 }
304 
305 void
_verrxfp(FILE * fp,int status,const char * fmt,va_list args)306 _verrxfp(FILE *fp, int status, const char *fmt, va_list args)
307 {
308 	_vwarnxfp(fp, fmt, args);
309 	exit(status);
310 }
311