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 34 int log_type = LOG_TYPE_OFF; 35 36 /* Log file, if needed. */ 37 FILE *log_file; 38 39 /* Debug level. */ 40 int log_level; 41 42 void log_vwrite(int, const char *, va_list); 43 __dead void log_vfatal(const char *, va_list); 44 45 /* Open logging to tty. */ 46 void 47 log_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. */ 59 void 60 log_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. */ 75 void 76 log_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. */ 85 void 86 log_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. */ 108 void printflike1 109 log_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. */ 123 void printflike1 124 log_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. */ 134 void printflike1 135 log_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. */ 147 void printflike1 148 log_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. */ 160 void printflike1 161 log_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 174 log_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 194 log_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 204 log_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