1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate * 26*7c478bd9Sstevel@tonic-gate * out.c -- some basic output routines 27*7c478bd9Sstevel@tonic-gate * 28*7c478bd9Sstevel@tonic-gate */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate #include <stdio.h> 33*7c478bd9Sstevel@tonic-gate #include <fm/fmd_api.h> 34*7c478bd9Sstevel@tonic-gate #include <unistd.h> 35*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 36*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 37*7c478bd9Sstevel@tonic-gate #include <string.h> 38*7c478bd9Sstevel@tonic-gate #include <strings.h> 39*7c478bd9Sstevel@tonic-gate #include <errno.h> 40*7c478bd9Sstevel@tonic-gate #include <time.h> 41*7c478bd9Sstevel@tonic-gate #include "out.h" 42*7c478bd9Sstevel@tonic-gate #include "stats.h" 43*7c478bd9Sstevel@tonic-gate #include "io.h" 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate /* stats we keep for "out" module */ 46*7c478bd9Sstevel@tonic-gate static struct stats *Outcount; 47*7c478bd9Sstevel@tonic-gate static struct stats *Errcount; 48*7c478bd9Sstevel@tonic-gate static struct stats *Warncount; 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate static int Exitcode; 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate static const char *Myname; 53*7c478bd9Sstevel@tonic-gate static FILE *Altfp; 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate /* buffer used to format all prints */ 56*7c478bd9Sstevel@tonic-gate #define MAXOUT 8192 57*7c478bd9Sstevel@tonic-gate static char Outbuf[MAXOUT]; 58*7c478bd9Sstevel@tonic-gate static int Outidx; /* next unused char in Outbuf[] */ 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate /* 61*7c478bd9Sstevel@tonic-gate * out_init -- initialize this module 62*7c478bd9Sstevel@tonic-gate */ 63*7c478bd9Sstevel@tonic-gate void 64*7c478bd9Sstevel@tonic-gate out_init(const char *myname) 65*7c478bd9Sstevel@tonic-gate { 66*7c478bd9Sstevel@tonic-gate Outcount = stats_new_counter("output.calls", "total calls", 1); 67*7c478bd9Sstevel@tonic-gate Errcount = stats_new_counter("output.errors", "total errors", 0); 68*7c478bd9Sstevel@tonic-gate Warncount = stats_new_counter("output.warnings", "total warnings", 0); 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate if (myname == NULL) 71*7c478bd9Sstevel@tonic-gate return; 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate if ((Myname = strrchr(myname, '/')) == NULL && 74*7c478bd9Sstevel@tonic-gate (Myname = strrchr(myname, '\\')) == NULL) 75*7c478bd9Sstevel@tonic-gate Myname = myname; 76*7c478bd9Sstevel@tonic-gate else 77*7c478bd9Sstevel@tonic-gate Myname++; 78*7c478bd9Sstevel@tonic-gate } 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate void 81*7c478bd9Sstevel@tonic-gate out_fini(void) 82*7c478bd9Sstevel@tonic-gate { 83*7c478bd9Sstevel@tonic-gate stats_delete(Outcount); 84*7c478bd9Sstevel@tonic-gate Outcount = NULL; 85*7c478bd9Sstevel@tonic-gate stats_delete(Errcount); 86*7c478bd9Sstevel@tonic-gate Errcount = NULL; 87*7c478bd9Sstevel@tonic-gate stats_delete(Warncount); 88*7c478bd9Sstevel@tonic-gate Warncount = NULL; 89*7c478bd9Sstevel@tonic-gate } 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate /* 92*7c478bd9Sstevel@tonic-gate * out_altfp -- store an alternate fp for O_ALTFP 93*7c478bd9Sstevel@tonic-gate */ 94*7c478bd9Sstevel@tonic-gate void 95*7c478bd9Sstevel@tonic-gate out_altfp(FILE *fp) 96*7c478bd9Sstevel@tonic-gate { 97*7c478bd9Sstevel@tonic-gate Altfp = fp; 98*7c478bd9Sstevel@tonic-gate } 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate /* 101*7c478bd9Sstevel@tonic-gate * voutbufprintf -- like vprintf, but appends to Outbuf 102*7c478bd9Sstevel@tonic-gate */ 103*7c478bd9Sstevel@tonic-gate static void 104*7c478bd9Sstevel@tonic-gate voutbufprintf(const char *fmt, va_list ap) 105*7c478bd9Sstevel@tonic-gate { 106*7c478bd9Sstevel@tonic-gate int len = vsnprintf(&Outbuf[Outidx], MAXOUT - Outidx, fmt, ap); 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate Outidx += len; 109*7c478bd9Sstevel@tonic-gate if (Outidx >= MAXOUT) 110*7c478bd9Sstevel@tonic-gate Outidx = MAXOUT - 1; 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate /* 114*7c478bd9Sstevel@tonic-gate * outbufprintf -- like printf, but appends to Outbuf 115*7c478bd9Sstevel@tonic-gate */ 116*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/ 117*7c478bd9Sstevel@tonic-gate static void 118*7c478bd9Sstevel@tonic-gate outbufprintf(const char *fmt, ...) 119*7c478bd9Sstevel@tonic-gate { 120*7c478bd9Sstevel@tonic-gate va_list ap; 121*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 122*7c478bd9Sstevel@tonic-gate voutbufprintf(fmt, ap); 123*7c478bd9Sstevel@tonic-gate va_end(ap); 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate /* 127*7c478bd9Sstevel@tonic-gate * vout -- va_list version of out() 128*7c478bd9Sstevel@tonic-gate * 129*7c478bd9Sstevel@tonic-gate * all the output processing work is done here. 130*7c478bd9Sstevel@tonic-gate */ 131*7c478bd9Sstevel@tonic-gate static void 132*7c478bd9Sstevel@tonic-gate vout(int flags, const char *fmt, va_list ap) 133*7c478bd9Sstevel@tonic-gate { 134*7c478bd9Sstevel@tonic-gate int safe_errno = errno; 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate stats_counter_bump(Outcount); 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate /* 139*7c478bd9Sstevel@tonic-gate * just return if called with a disabled output type. this 140*7c478bd9Sstevel@tonic-gate * prevents debug prints when Debug is off, verbose prints 141*7c478bd9Sstevel@tonic-gate * when Verbose is off, and language warnings when warnings 142*7c478bd9Sstevel@tonic-gate * are quenched (which they are when we're loading a .eft file). 143*7c478bd9Sstevel@tonic-gate * 144*7c478bd9Sstevel@tonic-gate */ 145*7c478bd9Sstevel@tonic-gate if ((flags & O_DEBUG) && Debug == 0) 146*7c478bd9Sstevel@tonic-gate return; 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate if ((flags & O_VERB) && Verbose == 0) 149*7c478bd9Sstevel@tonic-gate return; 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate if ((flags & O_VERB2) && Verbose < 2) 152*7c478bd9Sstevel@tonic-gate return; 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate if ((flags & O_VERB3) && Verbose < 3) 155*7c478bd9Sstevel@tonic-gate return; 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate if ((flags & O_WARN) && Warn == 0) 158*7c478bd9Sstevel@tonic-gate return; 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate if ((flags & O_ALTFP) && Altfp == NULL) 161*7c478bd9Sstevel@tonic-gate return; 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate /* some things only happen at the beginning of a print */ 164*7c478bd9Sstevel@tonic-gate if (Outidx == 0) { 165*7c478bd9Sstevel@tonic-gate if (flags & O_USAGE) { 166*7c478bd9Sstevel@tonic-gate Exitcode++; 167*7c478bd9Sstevel@tonic-gate outbufprintf("usage: %s ", Myname); 168*7c478bd9Sstevel@tonic-gate } else { 169*7c478bd9Sstevel@tonic-gate if (Myname && flags & (O_DIE|O_ERR|O_WARN|O_PROG)) 170*7c478bd9Sstevel@tonic-gate outbufprintf("%s: ", Myname); 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate if (flags & O_DIE) { 173*7c478bd9Sstevel@tonic-gate Exitcode++; 174*7c478bd9Sstevel@tonic-gate outbufprintf("fatal error: "); 175*7c478bd9Sstevel@tonic-gate } else if (flags & O_ERR) { 176*7c478bd9Sstevel@tonic-gate Exitcode++; 177*7c478bd9Sstevel@tonic-gate stats_counter_bump(Errcount); 178*7c478bd9Sstevel@tonic-gate outbufprintf("error: "); 179*7c478bd9Sstevel@tonic-gate } else if (flags & O_WARN) { 180*7c478bd9Sstevel@tonic-gate stats_counter_bump(Warncount); 181*7c478bd9Sstevel@tonic-gate outbufprintf("warning: "); 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate } 184*7c478bd9Sstevel@tonic-gate } 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate /* fmt can be NULL if the caller just wanted flags processed */ 187*7c478bd9Sstevel@tonic-gate if (fmt != NULL) 188*7c478bd9Sstevel@tonic-gate voutbufprintf(fmt, ap); 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate /* O_SYS means convert errno to a string and append it */ 191*7c478bd9Sstevel@tonic-gate if (flags & O_SYS) { 192*7c478bd9Sstevel@tonic-gate const char *msg = strerror(safe_errno); 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate if (Outidx != 0) 195*7c478bd9Sstevel@tonic-gate outbufprintf(": "); 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate if (msg) 198*7c478bd9Sstevel@tonic-gate outbufprintf("%s", msg); 199*7c478bd9Sstevel@tonic-gate else 200*7c478bd9Sstevel@tonic-gate outbufprintf("(error %d)", safe_errno); 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate /* O_STAMP means convert add a timestamp */ 204*7c478bd9Sstevel@tonic-gate if (flags & O_STAMP) { 205*7c478bd9Sstevel@tonic-gate time_t clock; 206*7c478bd9Sstevel@tonic-gate char *tmsg; 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate (void) time(&clock); 209*7c478bd9Sstevel@tonic-gate tmsg = ctime(&clock); 210*7c478bd9Sstevel@tonic-gate if (tmsg && *tmsg) { 211*7c478bd9Sstevel@tonic-gate tmsg[strlen(tmsg) - 1] = '\0'; 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate if (Outidx != 0) 214*7c478bd9Sstevel@tonic-gate outbufprintf(" "); 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate outbufprintf("%s", tmsg); 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate } 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate if (flags & O_NONL) 221*7c478bd9Sstevel@tonic-gate return; /* not done filling Outbuf */ 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate /* done filling Outbuf, platform calls will add newline */ 224*7c478bd9Sstevel@tonic-gate if (flags & O_ALTFP) 225*7c478bd9Sstevel@tonic-gate (void) fprintf(Altfp, "%s\n", Outbuf); 226*7c478bd9Sstevel@tonic-gate else if (flags & O_ABORT) 227*7c478bd9Sstevel@tonic-gate io_abort(Outbuf); 228*7c478bd9Sstevel@tonic-gate else if (flags & O_DIE) 229*7c478bd9Sstevel@tonic-gate io_die(Outbuf); 230*7c478bd9Sstevel@tonic-gate else if (flags & O_ERR) 231*7c478bd9Sstevel@tonic-gate io_err(Outbuf); 232*7c478bd9Sstevel@tonic-gate else 233*7c478bd9Sstevel@tonic-gate io_out(Outbuf); 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate /* reset output buffer */ 236*7c478bd9Sstevel@tonic-gate Outidx = 0; 237*7c478bd9Sstevel@tonic-gate Outbuf[0] = '\0'; 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate /* 241*7c478bd9Sstevel@tonic-gate * out -- spew a line of output, with various options 242*7c478bd9Sstevel@tonic-gate */ 243*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 244*7c478bd9Sstevel@tonic-gate void 245*7c478bd9Sstevel@tonic-gate out(int flags, const char *fmt, ...) 246*7c478bd9Sstevel@tonic-gate { 247*7c478bd9Sstevel@tonic-gate va_list ap; 248*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 249*7c478bd9Sstevel@tonic-gate vout(flags, fmt, ap); 250*7c478bd9Sstevel@tonic-gate va_end(ap); 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate /* 254*7c478bd9Sstevel@tonic-gate * outfl -- spew a filename:linenumber message 255*7c478bd9Sstevel@tonic-gate */ 256*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE4*/ 257*7c478bd9Sstevel@tonic-gate void 258*7c478bd9Sstevel@tonic-gate outfl(int flags, const char *fname, int line, const char *fmt, ...) 259*7c478bd9Sstevel@tonic-gate { 260*7c478bd9Sstevel@tonic-gate va_list ap; 261*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate if (fname) 264*7c478bd9Sstevel@tonic-gate out(flags|O_NONL, "%s:%d: ", fname, line); 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate vout(flags, fmt, ap); 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate va_end(ap); 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate /* 272*7c478bd9Sstevel@tonic-gate * out_exit -- exit the program 273*7c478bd9Sstevel@tonic-gate */ 274*7c478bd9Sstevel@tonic-gate void 275*7c478bd9Sstevel@tonic-gate out_exit(int code) 276*7c478bd9Sstevel@tonic-gate { 277*7c478bd9Sstevel@tonic-gate io_exit(Exitcode + code); 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate /* 281*7c478bd9Sstevel@tonic-gate * out_errcount -- return the number of O_ERR messages issued so far 282*7c478bd9Sstevel@tonic-gate */ 283*7c478bd9Sstevel@tonic-gate int 284*7c478bd9Sstevel@tonic-gate out_errcount(void) 285*7c478bd9Sstevel@tonic-gate { 286*7c478bd9Sstevel@tonic-gate return (stats_counter_value(Errcount)); 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate /* 290*7c478bd9Sstevel@tonic-gate * out_warncount -- return the number of O_WARN messages issued so far 291*7c478bd9Sstevel@tonic-gate */ 292*7c478bd9Sstevel@tonic-gate int 293*7c478bd9Sstevel@tonic-gate out_warncount(void) 294*7c478bd9Sstevel@tonic-gate { 295*7c478bd9Sstevel@tonic-gate return (stats_counter_value(Warncount)); 296*7c478bd9Sstevel@tonic-gate } 297