1/* $Id: log.c,v 1.2 2011/08/25 16:41:51 joerg Exp $ */ 2 3/* 4 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#include <sys/types.h> 20 21#include <errno.h> 22#include <stdio.h> 23#include <stdlib.h> 24#include <string.h> 25#include <syslog.h> 26#include <time.h> 27 28#include "tmux.h" 29 30/* Logging type. */ 31#define LOG_TYPE_OFF 0 32#define LOG_TYPE_TTY 1 33#define LOG_TYPE_FILE 2 34int log_type = LOG_TYPE_OFF; 35 36/* Log file, if needed. */ 37FILE *log_file; 38 39/* Debug level. */ 40int log_level; 41 42void log_vwrite(int, const char *, va_list); 43__dead void log_vfatal(const char *, va_list); 44 45/* Open logging to tty. */ 46void 47log_open_tty(int level) 48{ 49 log_type = LOG_TYPE_TTY; 50 log_level = level; 51 52 setlinebuf(stderr); 53 setlinebuf(stdout); 54 55 tzset(); 56} 57 58/* Open logging to file. */ 59void 60log_open_file(int level, const char *path) 61{ 62 log_file = fopen(path, "w"); 63 if (log_file == NULL) 64 return; 65 66 log_type = LOG_TYPE_FILE; 67 log_level = level; 68 69 setlinebuf(log_file); 70 71 tzset(); 72} 73 74/* Close logging. */ 75void 76log_close(void) 77{ 78 if (log_type == LOG_TYPE_FILE) 79 fclose(log_file); 80 81 log_type = LOG_TYPE_OFF; 82} 83 84/* Write a log message. */ 85void 86log_vwrite(int pri, const char *msg, va_list ap) 87{ 88 FILE *f = log_file; 89 90 switch (log_type) { 91 case LOG_TYPE_TTY: 92 if (pri == LOG_INFO) 93 f = stdout; 94 else 95 f = stderr; 96 /* FALLTHROUGH */ 97 case LOG_TYPE_FILE: 98 if (vfprintf(f, msg, ap) == -1) 99 exit(1); 100 if (putc('\n', f) == -1) 101 exit(1); 102 fflush(f); 103 break; 104 } 105} 106 107/* Log a warning with error string. */ 108void printflike1 109log_warn(const char *msg, ...) 110{ 111 va_list ap; 112 char *fmt; 113 114 va_start(ap, msg); 115 if (asprintf(&fmt, "%s: %s", msg, strerror(errno)) == -1) 116 exit(1); 117 log_vwrite(LOG_CRIT, fmt, ap); 118 free(fmt); 119 va_end(ap); 120} 121 122/* Log a warning. */ 123void printflike1 124log_warnx(const char *msg, ...) 125{ 126 va_list ap; 127 128 va_start(ap, msg); 129 log_vwrite(LOG_CRIT, msg, ap); 130 va_end(ap); 131} 132 133/* Log an informational message. */ 134void printflike1 135log_info(const char *msg, ...) 136{ 137 va_list ap; 138 139 if (log_level > -1) { 140 va_start(ap, msg); 141 log_vwrite(LOG_INFO, msg, ap); 142 va_end(ap); 143 } 144} 145 146/* Log a debug message. */ 147void printflike1 148log_debug(const char *msg, ...) 149{ 150 va_list ap; 151 152 if (log_level > 0) { 153 va_start(ap, msg); 154 log_vwrite(LOG_DEBUG, msg, ap); 155 va_end(ap); 156 } 157} 158 159/* Log a debug message at level 2. */ 160void printflike1 161log_debug2(const char *msg, ...) 162{ 163 va_list ap; 164 165 if (log_level > 1) { 166 va_start(ap, msg); 167 log_vwrite(LOG_DEBUG, msg, ap); 168 va_end(ap); 169 } 170} 171 172/* Log a critical error, with error string if necessary, and die. */ 173__dead void 174log_vfatal(const char *msg, va_list ap) 175{ 176 char *fmt; 177 178 if (errno != 0) { 179 if (asprintf(&fmt, "fatal: %s: %s", msg, strerror(errno)) == -1) 180 exit(1); 181 log_vwrite(LOG_CRIT, fmt, ap); 182 } else { 183 if (asprintf(&fmt, "fatal: %s", msg) == -1) 184 exit(1); 185 log_vwrite(LOG_CRIT, fmt, ap); 186 } 187 free(fmt); 188 189 exit(1); 190} 191 192/* Log a critical error, with error string, and die. */ 193__dead void printflike1 194log_fatal(const char *msg, ...) 195{ 196 va_list ap; 197 198 va_start(ap, msg); 199 log_vfatal(msg, ap); 200} 201 202/* Log a critical error and die. */ 203__dead void printflike1 204log_fatalx(const char *msg, ...) 205{ 206 va_list ap; 207 208 errno = 0; 209 va_start(ap, msg); 210 log_vfatal(msg, ap); 211} 212