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 args.dla_argc <= 0 || 78 (argv0 = args.dla_argv[0]) == NULL) 79 argv0 = "UNKNOWN"; 80 81 setprogname(argv0); 82 } 83 84 /* 85 * warncore() is the workhorse of these functions. Everything else has 86 * a warncore() component in it. 87 */ 88 static rmutex_t * 89 warncore(FILE *fp, const char *fmt, va_list args) 90 { 91 rmutex_t *lk; 92 93 FLOCKFILE(lk, fp); 94 95 if (__progname != NULL) 96 (void) fprintf(fp, "%s: ", __progname); 97 98 if (fmt != NULL) { 99 (void) vfprintf(fp, fmt, args); 100 } 101 102 return (lk); 103 } 104 105 /* Finish a warning with a newline and a flush of stderr. */ 106 static void 107 warnfinish(FILE *fp, rmutex_t *lk) 108 { 109 (void) fputc('\n', fp); 110 (void) fflush(fp); 111 FUNLOCKFILE(lk); 112 } 113 114 void 115 _vwarnxfp(FILE *fp, const char *fmt, va_list args) 116 { 117 rmutex_t *lk; 118 119 lk = warncore(fp, fmt, args); 120 warnfinish(fp, lk); 121 } 122 123 void 124 vwarnx(const char *fmt, va_list args) 125 { 126 _vwarnxfp(stderr, fmt, args); 127 } 128 129 void 130 _vwarnfp(FILE *fp, const char *fmt, va_list args) 131 { 132 int tmperr = errno; /* Capture errno now. */ 133 rmutex_t *lk; 134 135 lk = warncore(fp, fmt, args); 136 if (fmt != NULL) { 137 (void) fputc(':', fp); 138 (void) fputc(' ', fp); 139 } 140 (void) fputs(strerror(tmperr), fp); 141 warnfinish(fp, lk); 142 } 143 144 void 145 vwarn(const char *fmt, va_list args) 146 { 147 _vwarnfp(stderr, fmt, args); 148 } 149 150 /* PRINTFLIKE1 */ 151 void 152 warnx(const char *fmt, ...) 153 { 154 va_list args; 155 156 va_start(args, fmt); 157 vwarnx(fmt, args); 158 va_end(args); 159 } 160 161 void 162 _warnfp(FILE *fp, const char *fmt, ...) 163 { 164 va_list args; 165 166 va_start(args, fmt); 167 _vwarnfp(fp, fmt, args); 168 va_end(args); 169 } 170 171 void 172 _warnxfp(FILE *fp, const char *fmt, ...) 173 { 174 va_list args; 175 176 va_start(args, fmt); 177 _vwarnxfp(fp, fmt, args); 178 va_end(args); 179 } 180 181 /* PRINTFLIKE1 */ 182 void 183 warn(const char *fmt, ...) 184 { 185 va_list args; 186 187 va_start(args, fmt); 188 vwarn(fmt, args); 189 va_end(args); 190 } 191 192 /* PRINTFLIKE2 */ 193 void 194 err(int status, const char *fmt, ...) 195 { 196 va_list args; 197 198 va_start(args, fmt); 199 vwarn(fmt, args); 200 va_end(args); 201 exit(status); 202 } 203 204 void 205 _errfp(FILE *fp, int status, const char *fmt, ...) 206 { 207 va_list args; 208 209 va_start(args, fmt); 210 _vwarnfp(fp, fmt, args); 211 va_end(args); 212 exit(status); 213 } 214 215 void 216 verr(int status, const char *fmt, va_list args) 217 { 218 vwarn(fmt, args); 219 exit(status); 220 } 221 222 void 223 _verrfp(FILE *fp, int status, const char *fmt, va_list args) 224 { 225 _vwarnfp(fp, fmt, args); 226 exit(status); 227 } 228 229 /* PRINTFLIKE2 */ 230 void 231 errx(int status, const char *fmt, ...) 232 { 233 va_list args; 234 235 va_start(args, fmt); 236 vwarnx(fmt, args); 237 va_end(args); 238 exit(status); 239 } 240 241 void 242 _errxfp(FILE *fp, int status, const char *fmt, ...) 243 { 244 va_list args; 245 246 va_start(args, fmt); 247 _vwarnxfp(fp, fmt, args); 248 va_end(args); 249 exit(status); 250 } 251 252 void 253 verrx(int status, const char *fmt, va_list args) 254 { 255 vwarnx(fmt, args); 256 exit(status); 257 } 258 259 void 260 _verrxfp(FILE *fp, int status, const char *fmt, va_list args) 261 { 262 _vwarnxfp(fp, fmt, args); 263 exit(status); 264 } 265