log.c revision 1.10
1/* 2 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * All rights reserved 5 * 6 * As far as I am concerned, the code I have written for this software 7 * can be used freely for any purpose. Any derived versions of this 8 * software must be clearly marked as such, and if the derived work is 9 * incompatible with the protocol description in the RFC file, it must be 10 * called by a name other than "ssh" or "Secure Shell". 11 */ 12/* 13 * Shared versions of debug(), log(), etc. 14 * 15 * Copyright (c) 2000 Markus Friedl. All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions 19 * are met: 20 * 1. Redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer. 22 * 2. Redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38#include "includes.h" 39RCSID("$OpenBSD: log.c,v 1.10 2000/09/12 20:53:10 markus Exp $"); 40 41#include "ssh.h" 42#include "xmalloc.h" 43 44/* Fatal messages. This function never returns. */ 45 46void 47fatal(const char *fmt,...) 48{ 49 va_list args; 50 va_start(args, fmt); 51 do_log(SYSLOG_LEVEL_FATAL, fmt, args); 52 va_end(args); 53 fatal_cleanup(); 54} 55 56/* Error messages that should be logged. */ 57 58void 59error(const char *fmt,...) 60{ 61 va_list args; 62 va_start(args, fmt); 63 do_log(SYSLOG_LEVEL_ERROR, fmt, args); 64 va_end(args); 65} 66 67/* Log this message (information that usually should go to the log). */ 68 69void 70log(const char *fmt,...) 71{ 72 va_list args; 73 va_start(args, fmt); 74 do_log(SYSLOG_LEVEL_INFO, fmt, args); 75 va_end(args); 76} 77 78/* More detailed messages (information that does not need to go to the log). */ 79 80void 81verbose(const char *fmt,...) 82{ 83 va_list args; 84 va_start(args, fmt); 85 do_log(SYSLOG_LEVEL_VERBOSE, fmt, args); 86 va_end(args); 87} 88 89/* Debugging messages that should not be logged during normal operation. */ 90 91void 92debug(const char *fmt,...) 93{ 94 va_list args; 95 va_start(args, fmt); 96 do_log(SYSLOG_LEVEL_DEBUG1, fmt, args); 97 va_end(args); 98} 99 100void 101debug2(const char *fmt,...) 102{ 103 va_list args; 104 va_start(args, fmt); 105 do_log(SYSLOG_LEVEL_DEBUG2, fmt, args); 106 va_end(args); 107} 108 109void 110debug3(const char *fmt,...) 111{ 112 va_list args; 113 va_start(args, fmt); 114 do_log(SYSLOG_LEVEL_DEBUG3, fmt, args); 115 va_end(args); 116} 117 118/* Fatal cleanup */ 119 120struct fatal_cleanup { 121 struct fatal_cleanup *next; 122 void (*proc) (void *); 123 void *context; 124}; 125 126static struct fatal_cleanup *fatal_cleanups = NULL; 127 128/* Registers a cleanup function to be called by fatal() before exiting. */ 129 130void 131fatal_add_cleanup(void (*proc) (void *), void *context) 132{ 133 struct fatal_cleanup *cu; 134 135 cu = xmalloc(sizeof(*cu)); 136 cu->proc = proc; 137 cu->context = context; 138 cu->next = fatal_cleanups; 139 fatal_cleanups = cu; 140} 141 142/* Removes a cleanup frunction to be called at fatal(). */ 143 144void 145fatal_remove_cleanup(void (*proc) (void *context), void *context) 146{ 147 struct fatal_cleanup **cup, *cu; 148 149 for (cup = &fatal_cleanups; *cup; cup = &cu->next) { 150 cu = *cup; 151 if (cu->proc == proc && cu->context == context) { 152 *cup = cu->next; 153 xfree(cu); 154 return; 155 } 156 } 157 fatal("fatal_remove_cleanup: no such cleanup function: 0x%lx 0x%lx\n", 158 (unsigned long) proc, (unsigned long) context); 159} 160 161/* Cleanup and exit */ 162void 163fatal_cleanup(void) 164{ 165 struct fatal_cleanup *cu, *next_cu; 166 static int called = 0; 167 168 if (called) 169 exit(255); 170 called = 1; 171 /* Call cleanup functions. */ 172 for (cu = fatal_cleanups; cu; cu = next_cu) { 173 next_cu = cu->next; 174 debug("Calling cleanup 0x%lx(0x%lx)", 175 (unsigned long) cu->proc, (unsigned long) cu->context); 176 (*cu->proc) (cu->context); 177 } 178 exit(255); 179} 180 181/* textual representation of log-facilities/levels */ 182 183static struct { 184 const char *name; 185 SyslogFacility val; 186} log_facilities[] = { 187 { "DAEMON", SYSLOG_FACILITY_DAEMON }, 188 { "USER", SYSLOG_FACILITY_USER }, 189 { "AUTH", SYSLOG_FACILITY_AUTH }, 190 { "LOCAL0", SYSLOG_FACILITY_LOCAL0 }, 191 { "LOCAL1", SYSLOG_FACILITY_LOCAL1 }, 192 { "LOCAL2", SYSLOG_FACILITY_LOCAL2 }, 193 { "LOCAL3", SYSLOG_FACILITY_LOCAL3 }, 194 { "LOCAL4", SYSLOG_FACILITY_LOCAL4 }, 195 { "LOCAL5", SYSLOG_FACILITY_LOCAL5 }, 196 { "LOCAL6", SYSLOG_FACILITY_LOCAL6 }, 197 { "LOCAL7", SYSLOG_FACILITY_LOCAL7 }, 198 { NULL, 0 } 199}; 200 201static struct { 202 const char *name; 203 LogLevel val; 204} log_levels[] = 205{ 206 { "QUIET", SYSLOG_LEVEL_QUIET }, 207 { "FATAL", SYSLOG_LEVEL_FATAL }, 208 { "ERROR", SYSLOG_LEVEL_ERROR }, 209 { "INFO", SYSLOG_LEVEL_INFO }, 210 { "VERBOSE", SYSLOG_LEVEL_VERBOSE }, 211 { "DEBUG1", SYSLOG_LEVEL_DEBUG1 }, 212 { "DEBUG2", SYSLOG_LEVEL_DEBUG2 }, 213 { "DEBUG3", SYSLOG_LEVEL_DEBUG3 }, 214 { NULL, 0 } 215}; 216 217SyslogFacility 218log_facility_number(char *name) 219{ 220 int i; 221 if (name != NULL) 222 for (i = 0; log_facilities[i].name; i++) 223 if (strcasecmp(log_facilities[i].name, name) == 0) 224 return log_facilities[i].val; 225 return (SyslogFacility) - 1; 226} 227 228LogLevel 229log_level_number(char *name) 230{ 231 int i; 232 if (name != NULL) 233 for (i = 0; log_levels[i].name; i++) 234 if (strcasecmp(log_levels[i].name, name) == 0) 235 return log_levels[i].val; 236 return (LogLevel) - 1; 237} 238