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