1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Author: Tatu Ylonen <ylo@cs.hut.fi> 3*0Sstevel@tonic-gate * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4*0Sstevel@tonic-gate * All rights reserved 5*0Sstevel@tonic-gate * 6*0Sstevel@tonic-gate * As far as I am concerned, the code I have written for this software 7*0Sstevel@tonic-gate * can be used freely for any purpose. Any derived versions of this 8*0Sstevel@tonic-gate * software must be clearly marked as such, and if the derived work is 9*0Sstevel@tonic-gate * incompatible with the protocol description in the RFC file, it must be 10*0Sstevel@tonic-gate * called by a name other than "ssh" or "Secure Shell". 11*0Sstevel@tonic-gate */ 12*0Sstevel@tonic-gate /* 13*0Sstevel@tonic-gate * Copyright (c) 2000 Markus Friedl. All rights reserved. 14*0Sstevel@tonic-gate * 15*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 16*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 17*0Sstevel@tonic-gate * are met: 18*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 19*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 20*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 21*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 22*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 23*0Sstevel@tonic-gate * 24*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25*0Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26*0Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27*0Sstevel@tonic-gate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 28*0Sstevel@tonic-gate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29*0Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30*0Sstevel@tonic-gate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31*0Sstevel@tonic-gate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32*0Sstevel@tonic-gate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33*0Sstevel@tonic-gate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34*0Sstevel@tonic-gate */ 35*0Sstevel@tonic-gate /* 36*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 37*0Sstevel@tonic-gate * Use is subject to license terms. 38*0Sstevel@tonic-gate */ 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate #include "includes.h" 41*0Sstevel@tonic-gate RCSID("$OpenBSD: log.c,v 1.24 2002/07/19 15:43:33 markus Exp $"); 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gate #include "log.h" 46*0Sstevel@tonic-gate #include "xmalloc.h" 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate #include <syslog.h> 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate static LogLevel log_level = SYSLOG_LEVEL_INFO; 51*0Sstevel@tonic-gate static int log_on_stderr = 1; 52*0Sstevel@tonic-gate static int log_facility = LOG_AUTH; 53*0Sstevel@tonic-gate static char *argv0; 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate extern char *__progname; 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate static const char *log_txt_prefix = ""; 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate /* textual representation of log-facilities/levels */ 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gate static struct { 62*0Sstevel@tonic-gate const char *name; 63*0Sstevel@tonic-gate SyslogFacility val; 64*0Sstevel@tonic-gate } log_facilities[] = { 65*0Sstevel@tonic-gate { "DAEMON", SYSLOG_FACILITY_DAEMON }, 66*0Sstevel@tonic-gate { "USER", SYSLOG_FACILITY_USER }, 67*0Sstevel@tonic-gate { "AUTH", SYSLOG_FACILITY_AUTH }, 68*0Sstevel@tonic-gate #ifdef LOG_AUTHPRIV 69*0Sstevel@tonic-gate { "AUTHPRIV", SYSLOG_FACILITY_AUTHPRIV }, 70*0Sstevel@tonic-gate #endif 71*0Sstevel@tonic-gate { "LOCAL0", SYSLOG_FACILITY_LOCAL0 }, 72*0Sstevel@tonic-gate { "LOCAL1", SYSLOG_FACILITY_LOCAL1 }, 73*0Sstevel@tonic-gate { "LOCAL2", SYSLOG_FACILITY_LOCAL2 }, 74*0Sstevel@tonic-gate { "LOCAL3", SYSLOG_FACILITY_LOCAL3 }, 75*0Sstevel@tonic-gate { "LOCAL4", SYSLOG_FACILITY_LOCAL4 }, 76*0Sstevel@tonic-gate { "LOCAL5", SYSLOG_FACILITY_LOCAL5 }, 77*0Sstevel@tonic-gate { "LOCAL6", SYSLOG_FACILITY_LOCAL6 }, 78*0Sstevel@tonic-gate { "LOCAL7", SYSLOG_FACILITY_LOCAL7 }, 79*0Sstevel@tonic-gate { NULL, SYSLOG_FACILITY_NOT_SET } 80*0Sstevel@tonic-gate }; 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate static struct { 83*0Sstevel@tonic-gate const char *name; 84*0Sstevel@tonic-gate LogLevel val; 85*0Sstevel@tonic-gate } log_levels[] = 86*0Sstevel@tonic-gate { 87*0Sstevel@tonic-gate { "QUIET", SYSLOG_LEVEL_QUIET }, 88*0Sstevel@tonic-gate { "FATAL", SYSLOG_LEVEL_FATAL }, 89*0Sstevel@tonic-gate { "ERROR", SYSLOG_LEVEL_ERROR }, 90*0Sstevel@tonic-gate { "NOTICE", SYSLOG_LEVEL_NOTICE }, 91*0Sstevel@tonic-gate { "INFO", SYSLOG_LEVEL_INFO }, 92*0Sstevel@tonic-gate { "VERBOSE", SYSLOG_LEVEL_VERBOSE }, 93*0Sstevel@tonic-gate { "DEBUG", SYSLOG_LEVEL_DEBUG1 }, 94*0Sstevel@tonic-gate { "DEBUG1", SYSLOG_LEVEL_DEBUG1 }, 95*0Sstevel@tonic-gate { "DEBUG2", SYSLOG_LEVEL_DEBUG2 }, 96*0Sstevel@tonic-gate { "DEBUG3", SYSLOG_LEVEL_DEBUG3 }, 97*0Sstevel@tonic-gate { NULL, SYSLOG_LEVEL_NOT_SET } 98*0Sstevel@tonic-gate }; 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate SyslogFacility 101*0Sstevel@tonic-gate log_facility_number(char *name) 102*0Sstevel@tonic-gate { 103*0Sstevel@tonic-gate int i; 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate if (name != NULL) 106*0Sstevel@tonic-gate for (i = 0; log_facilities[i].name; i++) 107*0Sstevel@tonic-gate if (strcasecmp(log_facilities[i].name, name) == 0) 108*0Sstevel@tonic-gate return log_facilities[i].val; 109*0Sstevel@tonic-gate return SYSLOG_FACILITY_NOT_SET; 110*0Sstevel@tonic-gate } 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate LogLevel 113*0Sstevel@tonic-gate log_level_number(char *name) 114*0Sstevel@tonic-gate { 115*0Sstevel@tonic-gate int i; 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate if (name != NULL) 118*0Sstevel@tonic-gate for (i = 0; log_levels[i].name; i++) 119*0Sstevel@tonic-gate if (strcasecmp(log_levels[i].name, name) == 0) 120*0Sstevel@tonic-gate return log_levels[i].val; 121*0Sstevel@tonic-gate return SYSLOG_LEVEL_NOT_SET; 122*0Sstevel@tonic-gate } 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate void 125*0Sstevel@tonic-gate set_log_txt_prefix(const char *txt) 126*0Sstevel@tonic-gate { 127*0Sstevel@tonic-gate log_txt_prefix = txt; 128*0Sstevel@tonic-gate } 129*0Sstevel@tonic-gate 130*0Sstevel@tonic-gate /* Error messages that should be logged. */ 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gate void 133*0Sstevel@tonic-gate error(const char *fmt,...) 134*0Sstevel@tonic-gate { 135*0Sstevel@tonic-gate va_list args; 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate va_start(args, fmt); 138*0Sstevel@tonic-gate do_log(SYSLOG_LEVEL_ERROR, fmt, args); 139*0Sstevel@tonic-gate va_end(args); 140*0Sstevel@tonic-gate } 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate void 143*0Sstevel@tonic-gate notice(const char *fmt,...) 144*0Sstevel@tonic-gate { 145*0Sstevel@tonic-gate va_list args; 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate va_start(args, fmt); 148*0Sstevel@tonic-gate do_log(SYSLOG_LEVEL_NOTICE, fmt, args); 149*0Sstevel@tonic-gate va_end(args); 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate /* Log this message (information that usually should go to the log). */ 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate void 155*0Sstevel@tonic-gate log(const char *fmt,...) 156*0Sstevel@tonic-gate { 157*0Sstevel@tonic-gate va_list args; 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate va_start(args, fmt); 160*0Sstevel@tonic-gate do_log(SYSLOG_LEVEL_INFO, fmt, args); 161*0Sstevel@tonic-gate va_end(args); 162*0Sstevel@tonic-gate } 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate /* More detailed messages (information that does not need to go to the log). */ 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate void 167*0Sstevel@tonic-gate verbose(const char *fmt,...) 168*0Sstevel@tonic-gate { 169*0Sstevel@tonic-gate va_list args; 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate va_start(args, fmt); 172*0Sstevel@tonic-gate do_log(SYSLOG_LEVEL_VERBOSE, fmt, args); 173*0Sstevel@tonic-gate va_end(args); 174*0Sstevel@tonic-gate } 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate /* Debugging messages that should not be logged during normal operation. */ 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gate void 179*0Sstevel@tonic-gate debug(const char *fmt,...) 180*0Sstevel@tonic-gate { 181*0Sstevel@tonic-gate va_list args; 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate va_start(args, fmt); 184*0Sstevel@tonic-gate do_log(SYSLOG_LEVEL_DEBUG1, fmt, args); 185*0Sstevel@tonic-gate va_end(args); 186*0Sstevel@tonic-gate } 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate void 189*0Sstevel@tonic-gate debug2(const char *fmt,...) 190*0Sstevel@tonic-gate { 191*0Sstevel@tonic-gate va_list args; 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate va_start(args, fmt); 194*0Sstevel@tonic-gate do_log(SYSLOG_LEVEL_DEBUG2, fmt, args); 195*0Sstevel@tonic-gate va_end(args); 196*0Sstevel@tonic-gate } 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate void 199*0Sstevel@tonic-gate debug3(const char *fmt,...) 200*0Sstevel@tonic-gate { 201*0Sstevel@tonic-gate va_list args; 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate va_start(args, fmt); 204*0Sstevel@tonic-gate do_log(SYSLOG_LEVEL_DEBUG3, fmt, args); 205*0Sstevel@tonic-gate va_end(args); 206*0Sstevel@tonic-gate } 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate /* Fatal cleanup */ 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate struct fatal_cleanup { 211*0Sstevel@tonic-gate struct fatal_cleanup *next; 212*0Sstevel@tonic-gate void (*proc) (void *); 213*0Sstevel@tonic-gate void *context; 214*0Sstevel@tonic-gate }; 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate static struct fatal_cleanup *fatal_cleanups = NULL; 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate /* Registers a cleanup function to be called by fatal() before exiting. */ 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate void 221*0Sstevel@tonic-gate fatal_add_cleanup(void (*proc) (void *), void *context) 222*0Sstevel@tonic-gate { 223*0Sstevel@tonic-gate struct fatal_cleanup *cu; 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate cu = xmalloc(sizeof(*cu)); 226*0Sstevel@tonic-gate cu->proc = proc; 227*0Sstevel@tonic-gate cu->context = context; 228*0Sstevel@tonic-gate cu->next = fatal_cleanups; 229*0Sstevel@tonic-gate fatal_cleanups = cu; 230*0Sstevel@tonic-gate } 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate /* Removes a cleanup frunction to be called at fatal(). */ 233*0Sstevel@tonic-gate 234*0Sstevel@tonic-gate void 235*0Sstevel@tonic-gate fatal_remove_cleanup(void (*proc) (void *context), void *context) 236*0Sstevel@tonic-gate { 237*0Sstevel@tonic-gate struct fatal_cleanup **cup, *cu; 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate for (cup = &fatal_cleanups; *cup; cup = &cu->next) { 240*0Sstevel@tonic-gate cu = *cup; 241*0Sstevel@tonic-gate if (cu->proc == proc && cu->context == context) { 242*0Sstevel@tonic-gate *cup = cu->next; 243*0Sstevel@tonic-gate xfree(cu); 244*0Sstevel@tonic-gate return; 245*0Sstevel@tonic-gate } 246*0Sstevel@tonic-gate } 247*0Sstevel@tonic-gate debug3("fatal_remove_cleanup: no such cleanup function: 0x%lx 0x%lx", 248*0Sstevel@tonic-gate (u_long) proc, (u_long) context); 249*0Sstevel@tonic-gate } 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate /* Remove all cleanups, to be called after fork() */ 252*0Sstevel@tonic-gate void 253*0Sstevel@tonic-gate fatal_remove_all_cleanups(void) 254*0Sstevel@tonic-gate { 255*0Sstevel@tonic-gate struct fatal_cleanup *cu, *next_cu; 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate for (cu = fatal_cleanups; cu; cu = next_cu) { 258*0Sstevel@tonic-gate next_cu = cu->next; 259*0Sstevel@tonic-gate xfree(cu); 260*0Sstevel@tonic-gate } 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate fatal_cleanups = NULL; 263*0Sstevel@tonic-gate } 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate /* Cleanup and exit */ 266*0Sstevel@tonic-gate void 267*0Sstevel@tonic-gate fatal_cleanup(void) 268*0Sstevel@tonic-gate { 269*0Sstevel@tonic-gate struct fatal_cleanup *cu, *next_cu; 270*0Sstevel@tonic-gate static int called = 0; 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate if (called) 273*0Sstevel@tonic-gate exit(255); 274*0Sstevel@tonic-gate called = 1; 275*0Sstevel@tonic-gate /* Call cleanup functions. */ 276*0Sstevel@tonic-gate for (cu = fatal_cleanups; cu; cu = next_cu) { 277*0Sstevel@tonic-gate next_cu = cu->next; 278*0Sstevel@tonic-gate debug("Calling cleanup 0x%lx(0x%lx)", 279*0Sstevel@tonic-gate (u_long) cu->proc, (u_long) cu->context); 280*0Sstevel@tonic-gate (*cu->proc) (cu->context); 281*0Sstevel@tonic-gate } 282*0Sstevel@tonic-gate exit(255); 283*0Sstevel@tonic-gate } 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gate 286*0Sstevel@tonic-gate /* 287*0Sstevel@tonic-gate * Initialize the log. 288*0Sstevel@tonic-gate */ 289*0Sstevel@tonic-gate 290*0Sstevel@tonic-gate void 291*0Sstevel@tonic-gate log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr) 292*0Sstevel@tonic-gate { 293*0Sstevel@tonic-gate argv0 = av0; 294*0Sstevel@tonic-gate 295*0Sstevel@tonic-gate switch (level) { 296*0Sstevel@tonic-gate case SYSLOG_LEVEL_QUIET: 297*0Sstevel@tonic-gate case SYSLOG_LEVEL_FATAL: 298*0Sstevel@tonic-gate case SYSLOG_LEVEL_ERROR: 299*0Sstevel@tonic-gate case SYSLOG_LEVEL_NOTICE: 300*0Sstevel@tonic-gate case SYSLOG_LEVEL_INFO: 301*0Sstevel@tonic-gate case SYSLOG_LEVEL_VERBOSE: 302*0Sstevel@tonic-gate case SYSLOG_LEVEL_DEBUG1: 303*0Sstevel@tonic-gate case SYSLOG_LEVEL_DEBUG2: 304*0Sstevel@tonic-gate case SYSLOG_LEVEL_DEBUG3: 305*0Sstevel@tonic-gate log_level = level; 306*0Sstevel@tonic-gate break; 307*0Sstevel@tonic-gate default: 308*0Sstevel@tonic-gate fprintf(stderr, "Unrecognized internal syslog level code %d\n", 309*0Sstevel@tonic-gate (int) level); 310*0Sstevel@tonic-gate exit(1); 311*0Sstevel@tonic-gate } 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate log_on_stderr = on_stderr; 314*0Sstevel@tonic-gate if (on_stderr) 315*0Sstevel@tonic-gate return; 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate switch (facility) { 318*0Sstevel@tonic-gate case SYSLOG_FACILITY_DAEMON: 319*0Sstevel@tonic-gate log_facility = LOG_DAEMON; 320*0Sstevel@tonic-gate break; 321*0Sstevel@tonic-gate case SYSLOG_FACILITY_USER: 322*0Sstevel@tonic-gate log_facility = LOG_USER; 323*0Sstevel@tonic-gate break; 324*0Sstevel@tonic-gate case SYSLOG_FACILITY_AUTH: 325*0Sstevel@tonic-gate log_facility = LOG_AUTH; 326*0Sstevel@tonic-gate break; 327*0Sstevel@tonic-gate #ifdef LOG_AUTHPRIV 328*0Sstevel@tonic-gate case SYSLOG_FACILITY_AUTHPRIV: 329*0Sstevel@tonic-gate log_facility = LOG_AUTHPRIV; 330*0Sstevel@tonic-gate break; 331*0Sstevel@tonic-gate #endif 332*0Sstevel@tonic-gate case SYSLOG_FACILITY_LOCAL0: 333*0Sstevel@tonic-gate log_facility = LOG_LOCAL0; 334*0Sstevel@tonic-gate break; 335*0Sstevel@tonic-gate case SYSLOG_FACILITY_LOCAL1: 336*0Sstevel@tonic-gate log_facility = LOG_LOCAL1; 337*0Sstevel@tonic-gate break; 338*0Sstevel@tonic-gate case SYSLOG_FACILITY_LOCAL2: 339*0Sstevel@tonic-gate log_facility = LOG_LOCAL2; 340*0Sstevel@tonic-gate break; 341*0Sstevel@tonic-gate case SYSLOG_FACILITY_LOCAL3: 342*0Sstevel@tonic-gate log_facility = LOG_LOCAL3; 343*0Sstevel@tonic-gate break; 344*0Sstevel@tonic-gate case SYSLOG_FACILITY_LOCAL4: 345*0Sstevel@tonic-gate log_facility = LOG_LOCAL4; 346*0Sstevel@tonic-gate break; 347*0Sstevel@tonic-gate case SYSLOG_FACILITY_LOCAL5: 348*0Sstevel@tonic-gate log_facility = LOG_LOCAL5; 349*0Sstevel@tonic-gate break; 350*0Sstevel@tonic-gate case SYSLOG_FACILITY_LOCAL6: 351*0Sstevel@tonic-gate log_facility = LOG_LOCAL6; 352*0Sstevel@tonic-gate break; 353*0Sstevel@tonic-gate case SYSLOG_FACILITY_LOCAL7: 354*0Sstevel@tonic-gate log_facility = LOG_LOCAL7; 355*0Sstevel@tonic-gate break; 356*0Sstevel@tonic-gate default: 357*0Sstevel@tonic-gate fprintf(stderr, 358*0Sstevel@tonic-gate "Unrecognized internal syslog facility code %d\n", 359*0Sstevel@tonic-gate (int) facility); 360*0Sstevel@tonic-gate exit(1); 361*0Sstevel@tonic-gate } 362*0Sstevel@tonic-gate } 363*0Sstevel@tonic-gate 364*0Sstevel@tonic-gate #define MSGBUFSIZ 1024 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate /* PRINTFLIKE2 */ 367*0Sstevel@tonic-gate void 368*0Sstevel@tonic-gate do_log(LogLevel level, const char *fmt, va_list args) 369*0Sstevel@tonic-gate { 370*0Sstevel@tonic-gate char msgbuf[MSGBUFSIZ]; 371*0Sstevel@tonic-gate char fmtbuf[MSGBUFSIZ]; 372*0Sstevel@tonic-gate char *txt = NULL; 373*0Sstevel@tonic-gate int pri = LOG_INFO; 374*0Sstevel@tonic-gate int do_gettext = log_on_stderr; /* 375*0Sstevel@tonic-gate * Localize user messages - not 376*0Sstevel@tonic-gate * syslog()ed messages. 377*0Sstevel@tonic-gate */ 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gate if (level > log_level) 380*0Sstevel@tonic-gate return; 381*0Sstevel@tonic-gate 382*0Sstevel@tonic-gate switch (level) { 383*0Sstevel@tonic-gate case SYSLOG_LEVEL_FATAL: 384*0Sstevel@tonic-gate if (!log_on_stderr) 385*0Sstevel@tonic-gate txt = "fatal"; 386*0Sstevel@tonic-gate pri = LOG_CRIT; 387*0Sstevel@tonic-gate break; 388*0Sstevel@tonic-gate case SYSLOG_LEVEL_ERROR: 389*0Sstevel@tonic-gate if (!log_on_stderr) 390*0Sstevel@tonic-gate txt = "error"; 391*0Sstevel@tonic-gate pri = LOG_ERR; 392*0Sstevel@tonic-gate break; 393*0Sstevel@tonic-gate case SYSLOG_LEVEL_NOTICE: 394*0Sstevel@tonic-gate pri = LOG_NOTICE; 395*0Sstevel@tonic-gate break; 396*0Sstevel@tonic-gate case SYSLOG_LEVEL_INFO: 397*0Sstevel@tonic-gate pri = LOG_INFO; 398*0Sstevel@tonic-gate break; 399*0Sstevel@tonic-gate case SYSLOG_LEVEL_VERBOSE: 400*0Sstevel@tonic-gate pri = LOG_INFO; 401*0Sstevel@tonic-gate break; 402*0Sstevel@tonic-gate case SYSLOG_LEVEL_DEBUG1: 403*0Sstevel@tonic-gate txt = "debug1"; 404*0Sstevel@tonic-gate pri = LOG_DEBUG; 405*0Sstevel@tonic-gate /* 406*0Sstevel@tonic-gate * Don't localize debug messages - such are not intended 407*0Sstevel@tonic-gate * for users but for support staff whose preferred 408*0Sstevel@tonic-gate * language is unknown, therefore we default to the 409*0Sstevel@tonic-gate * language used in the source code: English. 410*0Sstevel@tonic-gate */ 411*0Sstevel@tonic-gate do_gettext = 0; 412*0Sstevel@tonic-gate break; 413*0Sstevel@tonic-gate case SYSLOG_LEVEL_DEBUG2: 414*0Sstevel@tonic-gate txt = "debug2"; 415*0Sstevel@tonic-gate pri = LOG_DEBUG; 416*0Sstevel@tonic-gate do_gettext = 0; /* Don't localize debug messages. */ 417*0Sstevel@tonic-gate break; 418*0Sstevel@tonic-gate case SYSLOG_LEVEL_DEBUG3: 419*0Sstevel@tonic-gate txt = "debug3"; 420*0Sstevel@tonic-gate pri = LOG_DEBUG; 421*0Sstevel@tonic-gate do_gettext = 0; /* Don't localize debug messages. */ 422*0Sstevel@tonic-gate break; 423*0Sstevel@tonic-gate default: 424*0Sstevel@tonic-gate txt = "internal error"; 425*0Sstevel@tonic-gate pri = LOG_ERR; 426*0Sstevel@tonic-gate break; 427*0Sstevel@tonic-gate } 428*0Sstevel@tonic-gate if (txt != NULL) { 429*0Sstevel@tonic-gate snprintf(fmtbuf, sizeof(fmtbuf), "%s%s: %s", log_txt_prefix, 430*0Sstevel@tonic-gate do_gettext ? gettext(txt) : txt, 431*0Sstevel@tonic-gate do_gettext ? gettext(fmt) : fmt); 432*0Sstevel@tonic-gate vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args); 433*0Sstevel@tonic-gate } else { 434*0Sstevel@tonic-gate vsnprintf(msgbuf, sizeof(msgbuf), 435*0Sstevel@tonic-gate do_gettext ? gettext(fmt) : fmt, 436*0Sstevel@tonic-gate args); 437*0Sstevel@tonic-gate } 438*0Sstevel@tonic-gate if (log_on_stderr) { 439*0Sstevel@tonic-gate fprintf(stderr, "%s\r\n", msgbuf); 440*0Sstevel@tonic-gate } else { 441*0Sstevel@tonic-gate openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility); 442*0Sstevel@tonic-gate syslog(pri, "%.500s", msgbuf); 443*0Sstevel@tonic-gate closelog(); 444*0Sstevel@tonic-gate } 445*0Sstevel@tonic-gate } 446