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