xref: /illumos-gate/usr/src/lib/libc/port/gen/err.c (revision 23a1ccea6aac035f084a7a4cdc968687d1b02daf)
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 #include "lint.h"
27 #include "file64.h"
28 #include "mtlib.h"
29 #include "thr_uberdata.h"
30 #include <sys/types.h>
31 #include <err.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <stdarg.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <dlfcn.h>
38 #include "stdiom.h"
39 
40 /* Function exit/warning functions and global variables. */
41 
42 const char *__progname;		/* GNU/Linux/BSD compatibility */
43 
44 #define	PROGNAMESIZE	128	/* buffer size for __progname */
45 
46 const char *
47 getprogname(void)
48 {
49 	return (__progname);
50 }
51 
52 void
53 setprogname(const char *argv0)
54 {
55 	uberdata_t *udp = curthread->ul_uberdata;
56 	const char *progname;
57 
58 	if ((progname = strrchr(argv0, '/')) == NULL)
59 		progname = argv0;
60 	else
61 		progname++;
62 
63 	if (udp->progname == NULL)
64 		udp->progname = lmalloc(PROGNAMESIZE);
65 	(void) strlcpy(udp->progname, progname, PROGNAMESIZE);
66 	__progname = udp->progname;
67 }
68 
69 /* called only from libc_init() */
70 void
71 init_progname(void)
72 {
73 	Dl_argsinfo_t args;
74 	const char *argv0;
75 
76 	if (dlinfo(RTLD_SELF, RTLD_DI_ARGSINFO, &args) < 0)
77 		argv0 = "UNKNOWN";
78 	else
79 		argv0 = args.dla_argv[0];
80 	setprogname(argv0);
81 }
82 
83 /*
84  * warncore() is the workhorse of these functions.  Everything else has
85  * a warncore() component in it.
86  */
87 static rmutex_t *
88 warncore(FILE *fp, const char *fmt, va_list args)
89 {
90 	rmutex_t *lk;
91 
92 	FLOCKFILE(lk, fp);
93 
94 	if (__progname != NULL)
95 		(void) fprintf(fp, "%s: ", __progname);
96 
97 	if (fmt != NULL) {
98 		(void) vfprintf(fp, fmt, args);
99 	}
100 
101 	return (lk);
102 }
103 
104 /* Finish a warning with a newline and a flush of stderr. */
105 static void
106 warnfinish(FILE *fp, rmutex_t *lk)
107 {
108 	(void) fputc('\n', fp);
109 	(void) fflush(fp);
110 	FUNLOCKFILE(lk);
111 }
112 
113 void
114 _vwarnxfp(FILE *fp, const char *fmt, va_list args)
115 {
116 	rmutex_t *lk;
117 
118 	lk = warncore(fp, fmt, args);
119 	warnfinish(fp, lk);
120 }
121 
122 void
123 vwarnx(const char *fmt, va_list args)
124 {
125 	_vwarnxfp(stderr, fmt, args);
126 }
127 
128 void
129 _vwarnfp(FILE *fp, const char *fmt, va_list args)
130 {
131 	int tmperr = errno;	/* Capture errno now. */
132 	rmutex_t *lk;
133 
134 	lk = warncore(fp, fmt, args);
135 	if (fmt != NULL) {
136 		(void) fputc(':', fp);
137 		(void) fputc(' ', fp);
138 	}
139 	(void) fputs(strerror(tmperr), fp);
140 	warnfinish(fp, lk);
141 }
142 
143 void
144 vwarn(const char *fmt, va_list args)
145 {
146 	_vwarnfp(stderr, fmt, args);
147 }
148 
149 /* PRINTFLIKE1 */
150 void
151 warnx(const char *fmt, ...)
152 {
153 	va_list args;
154 
155 	va_start(args, fmt);
156 	vwarnx(fmt, args);
157 	va_end(args);
158 }
159 
160 void
161 _warnfp(FILE *fp, const char *fmt, ...)
162 {
163 	va_list args;
164 
165 	va_start(args, fmt);
166 	_vwarnfp(fp, fmt, args);
167 	va_end(args);
168 }
169 
170 void
171 _warnxfp(FILE *fp, const char *fmt, ...)
172 {
173 	va_list args;
174 
175 	va_start(args, fmt);
176 	_vwarnxfp(fp, fmt, args);
177 	va_end(args);
178 }
179 
180 /* PRINTFLIKE1 */
181 void
182 warn(const char *fmt, ...)
183 {
184 	va_list args;
185 
186 	va_start(args, fmt);
187 	vwarn(fmt, args);
188 	va_end(args);
189 }
190 
191 /* PRINTFLIKE2 */
192 void
193 err(int status, const char *fmt, ...)
194 {
195 	va_list args;
196 
197 	va_start(args, fmt);
198 	vwarn(fmt, args);
199 	va_end(args);
200 	exit(status);
201 }
202 
203 void
204 _errfp(FILE *fp, int status, const char *fmt, ...)
205 {
206 	va_list args;
207 
208 	va_start(args, fmt);
209 	_vwarnfp(fp, fmt, args);
210 	va_end(args);
211 	exit(status);
212 }
213 
214 void
215 verr(int status, const char *fmt, va_list args)
216 {
217 	vwarn(fmt, args);
218 	exit(status);
219 }
220 
221 void
222 _verrfp(FILE *fp, int status, const char *fmt, va_list args)
223 {
224 	_vwarnfp(fp, fmt, args);
225 	exit(status);
226 }
227 
228 /* PRINTFLIKE2 */
229 void
230 errx(int status, const char *fmt, ...)
231 {
232 	va_list args;
233 
234 	va_start(args, fmt);
235 	vwarnx(fmt, args);
236 	va_end(args);
237 	exit(status);
238 }
239 
240 void
241 _errxfp(FILE *fp, int status, const char *fmt, ...)
242 {
243 	va_list args;
244 
245 	va_start(args, fmt);
246 	_vwarnxfp(fp, fmt, args);
247 	va_end(args);
248 	exit(status);
249 }
250 
251 void
252 verrx(int status, const char *fmt, va_list args)
253 {
254 	vwarnx(fmt, args);
255 	exit(status);
256 }
257 
258 void
259 _verrxfp(FILE *fp, int status, const char *fmt, va_list args)
260 {
261 	_vwarnxfp(fp, fmt, args);
262 	exit(status);
263 }
264