1 /* $OpenBSD: log.c,v 1.8 2012/05/30 15:01:21 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 /* Log file, if needed. */ 31 FILE *log_file; 32 33 /* Debug level. */ 34 int log_level = 0; 35 36 void log_event_cb(int, const char *); 37 void log_vwrite(const char *, va_list); 38 __dead void log_vfatal(const char *, va_list); 39 40 /* Log callback for libevent. */ 41 void 42 log_event_cb(unused int severity, const char *msg) 43 { 44 log_warnx("%s", msg); 45 } 46 47 /* Open logging to file. */ 48 void 49 log_open(int level, const char *path) 50 { 51 log_file = fopen(path, "w"); 52 if (log_file == NULL) 53 return; 54 log_level = level; 55 56 setlinebuf(log_file); 57 event_set_log_callback(log_event_cb); 58 59 tzset(); 60 } 61 62 /* Close logging. */ 63 void 64 log_close(void) 65 { 66 if (log_file != NULL) 67 fclose(log_file); 68 69 event_set_log_callback(NULL); 70 } 71 72 /* Write a log message. */ 73 void 74 log_vwrite(const char *msg, va_list ap) 75 { 76 char *fmt; 77 78 if (log_file == NULL) 79 return; 80 81 if (asprintf(&fmt, "%s\n", msg) == -1) 82 exit(1); 83 if (vfprintf(log_file, fmt, ap) == -1) 84 exit(1); 85 fflush(log_file); 86 free(fmt); 87 } 88 89 /* Log a warning with error string. */ 90 void printflike1 91 log_warn(const char *msg, ...) 92 { 93 va_list ap; 94 char *fmt; 95 96 va_start(ap, msg); 97 if (asprintf(&fmt, "%s: %s", msg, strerror(errno)) == -1) 98 exit(1); 99 log_vwrite(fmt, ap); 100 free(fmt); 101 va_end(ap); 102 } 103 104 /* Log a warning. */ 105 void printflike1 106 log_warnx(const char *msg, ...) 107 { 108 va_list ap; 109 110 va_start(ap, msg); 111 log_vwrite(msg, ap); 112 va_end(ap); 113 } 114 115 /* Log an informational message. */ 116 void printflike1 117 log_info(const char *msg, ...) 118 { 119 va_list ap; 120 121 if (log_level > -1) { 122 va_start(ap, msg); 123 log_vwrite(msg, ap); 124 va_end(ap); 125 } 126 } 127 128 /* Log a debug message. */ 129 void printflike1 130 log_debug(const char *msg, ...) 131 { 132 va_list ap; 133 134 if (log_level > 0) { 135 va_start(ap, msg); 136 log_vwrite(msg, ap); 137 va_end(ap); 138 } 139 } 140 141 /* Log a debug message at level 2. */ 142 void printflike1 143 log_debug2(const char *msg, ...) 144 { 145 va_list ap; 146 147 if (log_level > 1) { 148 va_start(ap, msg); 149 log_vwrite(msg, ap); 150 va_end(ap); 151 } 152 } 153 154 /* Log a critical error, with error string if necessary, and die. */ 155 __dead void 156 log_vfatal(const char *msg, va_list ap) 157 { 158 char *fmt; 159 160 if (errno != 0) { 161 if (asprintf(&fmt, "fatal: %s: %s", msg, strerror(errno)) == -1) 162 exit(1); 163 log_vwrite(fmt, ap); 164 } else { 165 if (asprintf(&fmt, "fatal: %s", msg) == -1) 166 exit(1); 167 log_vwrite(fmt, ap); 168 } 169 free(fmt); 170 171 exit(1); 172 } 173 174 /* Log a critical error, with error string, and die. */ 175 __dead void printflike1 176 log_fatal(const char *msg, ...) 177 { 178 va_list ap; 179 180 va_start(ap, msg); 181 log_vfatal(msg, ap); 182 } 183 184 /* Log a critical error and die. */ 185 __dead void printflike1 186 log_fatalx(const char *msg, ...) 187 { 188 va_list ap; 189 190 errno = 0; 191 va_start(ap, msg); 192 log_vfatal(msg, ap); 193 } 194