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