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