1/* 2 * Routines for logging error messages or other informative messages. 3 * 4 * Log messages can easily contain the program name, a time stamp, system 5 * error messages, and arbitrary printf-style strings, and can be directed 6 * to stderr or a log file. 7 * 8 * Author: Stephen McKay 9 * 10 * NOTICE: This is free software. I hope you get some use from this program. 11 * In return you should think about all the nice people who give away software. 12 * Maybe you should write some free software too. 13 */ 14 15#ifndef lint 16static const char rcsid[] = 17 "$FreeBSD$"; 18#endif /* not lint */ 19 20#include <stdio.h> 21#include <string.h> 22#include <stdarg.h> 23#include <time.h> 24#include <errno.h> 25#include "error.h" 26 27static FILE *error_fp = NULL; 28static char *prog = NULL; 29 30 31/* 32 * Log errors to the given file. 33 */ 34void 35err_set_log(char *log_file) 36 { 37 FILE *fp; 38 39 if ((fp = fopen(log_file, "a")) == NULL) 40 err("cannot log to '%s'", log_file); 41 else 42 error_fp = fp; 43 } 44 45 46/* 47 * Set the error prefix if not logging to a file. 48 */ 49void 50err_prog_name(char *name) 51 { 52 if ((prog = strrchr(name, '/')) == NULL) 53 prog = name; 54 else 55 prog++; 56 } 57 58 59/* 60 * Log an error. 61 * 62 * A leading '*' in the message format means we want the system errno 63 * decoded and appended. 64 */ 65void 66err(const char *fmt, ...) 67 { 68 va_list ap; 69 time_t now; 70 struct tm *tm; 71 FILE *fp; 72 int x = errno; 73 int want_errno; 74 75 if ((fp = error_fp) == NULL) 76 { 77 fp = stderr; 78 if (prog != NULL) 79 fprintf(fp, "%s: ", prog); 80 } 81 else 82 { 83 time(&now); 84 tm = localtime(&now); 85 fprintf(fp, "%04d-%02d-%02d %02d:%02d ", tm->tm_year+1900, 86 tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min); 87 } 88 89 want_errno = 0; 90 if (*fmt == '*') 91 want_errno++, fmt++; 92 93 va_start(ap, fmt); 94 vfprintf(fp, fmt, ap); 95 va_end(ap); 96 97 if (want_errno) 98 fprintf(fp, ": %s", strerror(x)); 99 100 fprintf(fp, "\n"); 101 fflush(fp); 102 } 103