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 * 51 getprogname(void) 52 { 53 return (__progname); 54 } 55 56 void 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 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 * 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 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 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 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 142 vwarn(const char *fmt, va_list args) 143 { 144 vwarnfp(stderr, errno, fmt, args); 145 } 146 147 void 148 vwarnc(int code, const char *fmt, va_list args) 149 { 150 vwarnfp(stderr, code, fmt, args); 151 } 152 153 void 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 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 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 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 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 206 verr(int status, const char *fmt, va_list args) 207 { 208 vwarn(fmt, args); 209 exit(status); 210 } 211 212 void 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 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 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 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 251 _vwarnfp(FILE *fp, const char *fmt, va_list args) 252 { 253 vwarnfp(fp, errno, fmt, args); 254 } 255 256 void 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 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 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 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 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 306 _verrxfp(FILE *fp, int status, const char *fmt, va_list args) 307 { 308 _vwarnxfp(fp, fmt, args); 309 exit(status); 310 } 311