1 /* $OpenBSD: log.c,v 1.3 2009/07/21 18:40:30 nicm 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 char *fmt; 89 FILE *f = log_file; 90 91 switch (log_type) { 92 case LOG_TYPE_TTY: 93 if (pri == LOG_INFO) 94 f = stdout; 95 else 96 f = stderr; 97 /* FALLTHROUGH */ 98 case LOG_TYPE_FILE: 99 if (asprintf(&fmt, "%s\n", msg) == -1) 100 exit(1); 101 if (vfprintf(f, fmt, ap) == -1) 102 exit(1); 103 fflush(f); 104 free(fmt); 105 break; 106 } 107 } 108 109 /* Log a warning with error string. */ 110 void printflike1 111 log_warn(const char *msg, ...) 112 { 113 va_list ap; 114 char *fmt; 115 116 va_start(ap, msg); 117 if (asprintf(&fmt, "%s: %s", msg, strerror(errno)) == -1) 118 exit(1); 119 log_vwrite(LOG_CRIT, fmt, ap); 120 free(fmt); 121 va_end(ap); 122 } 123 124 /* Log a warning. */ 125 void printflike1 126 log_warnx(const char *msg, ...) 127 { 128 va_list ap; 129 130 va_start(ap, msg); 131 log_vwrite(LOG_CRIT, msg, ap); 132 va_end(ap); 133 } 134 135 /* Log an informational message. */ 136 void printflike1 137 log_info(const char *msg, ...) 138 { 139 va_list ap; 140 141 if (log_level > -1) { 142 va_start(ap, msg); 143 log_vwrite(LOG_INFO, msg, ap); 144 va_end(ap); 145 } 146 } 147 148 /* Log a debug message. */ 149 void printflike1 150 log_debug(const char *msg, ...) 151 { 152 va_list ap; 153 154 if (log_level > 0) { 155 va_start(ap, msg); 156 log_vwrite(LOG_DEBUG, msg, ap); 157 va_end(ap); 158 } 159 } 160 161 /* Log a debug message at level 2. */ 162 void printflike1 163 log_debug2(const char *msg, ...) 164 { 165 va_list ap; 166 167 if (log_level > 1) { 168 va_start(ap, msg); 169 log_vwrite(LOG_DEBUG, msg, ap); 170 va_end(ap); 171 } 172 } 173 174 /* Log a critical error, with error string if necessary, and die. */ 175 __dead void 176 log_vfatal(const char *msg, va_list ap) 177 { 178 char *fmt; 179 180 if (errno != 0) { 181 if (asprintf(&fmt, "fatal: %s: %s", msg, strerror(errno)) == -1) 182 exit(1); 183 log_vwrite(LOG_CRIT, fmt, ap); 184 } else { 185 if (asprintf(&fmt, "fatal: %s", msg) == -1) 186 exit(1); 187 log_vwrite(LOG_CRIT, fmt, ap); 188 } 189 free(fmt); 190 191 exit(1); 192 } 193 194 /* Log a critical error, with error string, and die. */ 195 __dead void printflike1 196 log_fatal(const char *msg, ...) 197 { 198 va_list ap; 199 200 va_start(ap, msg); 201 log_vfatal(msg, ap); 202 } 203 204 /* Log a critical error and die. */ 205 __dead void printflike1 206 log_fatalx(const char *msg, ...) 207 { 208 va_list ap; 209 210 errno = 0; 211 va_start(ap, msg); 212 log_vfatal(msg, ap); 213 } 214