Disable logging to stderr if it is not a tty
[public/pyceo-broken.git] / src / util.c
1 #include <unistd.h>
2 #include <sys/wait.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <stdarg.h>
6 #include <syslog.h>
7 #include <errno.h>
8
9 #include "util.h"
10
11 static char message[4096];
12
13 static int log_stderr = 1;
14
15 void init_log(const char *ident, int option, int facility) {
16     openlog(ident, option, facility);
17     log_stderr = isatty(STDERR_FILENO);
18 }
19
20 static void errmsg(int prio, const char *prefix, const char *fmt, va_list args) {
21     char *msgp = message;
22
23     msgp +=  snprintf(msgp, sizeof(message) - 2 - (msgp - message), "%s: ", prefix);
24     if (msgp - message > sizeof(message) - 2)
25         fatal("error message overflowed");
26
27     msgp += vsnprintf(msgp, sizeof(message) - 2 - (msgp - message), fmt, args);
28     if (msgp - message > sizeof(message) - 2)
29         fatal("error message overflowed");
30
31     *msgp++ = '\n';
32     *msgp++ = '\0';
33
34     syslog(prio, "%s", message);
35     if (log_stderr)
36         fputs(message, stderr);
37 }
38
39 static void errmsgpe(int prio, const char *prefix, const char *fmt, va_list args) {
40     char *msgp = message;
41
42     msgp += snprintf(msgp, sizeof(message) - 2 - (msgp - message), "%s: ", prefix);
43     if (msgp - message > sizeof(message) - 2)
44         fatal("error message overflowed");
45
46     msgp += vsnprintf(msgp, sizeof(message) - 2 - (msgp - message), fmt, args);
47     if (msgp - message > sizeof(message) - 2)
48         fatal("error message overflowed");
49
50     msgp += snprintf(msgp, sizeof(message) - 2 - (msgp - message), ": %s", strerror(errno));
51     if (msgp - message > sizeof(message) - 2)
52         fatal("error message overflowed");
53
54     *msgp++ = '\n';
55     *msgp++ = '\0';
56
57     syslog(prio, "%s", message);
58     if (log_stderr)
59         fputs(message, stderr);
60 }
61
62 NORETURN static void die(int prio, const char *prefix, const char *msg, va_list args) {
63     errmsg(prio, prefix, msg, args);
64     exit(1);
65 }
66
67 NORETURN static void diepe(int prio, const char *prefix, const char *msg, va_list args) {
68     errmsgpe(prio, prefix, msg, args);
69     exit(1);
70 }
71
72 NORETURN void fatal(const char *msg, ...) {
73     va_list args;
74     va_start(args, msg);
75     die(LOG_CRIT, "fatal", msg, args);
76     va_end(args);
77 }
78
79 void error(const char *msg, ...) {
80     va_list args;
81     va_start(args, msg);
82     errmsg(LOG_ERR, "error", msg, args);
83     va_end(args);
84 }
85
86 void warn(const char *msg, ...) {
87     va_list args;
88     va_start(args, msg);
89     errmsg(LOG_WARNING, "warning", msg, args);
90     va_end(args);
91 }
92
93 void logmsg(const char *msg, ...) {
94     va_list args;
95     va_start(args, msg);
96     vsyslog(LOG_ERR, msg, args);
97     va_end(args);
98 }
99
100 NORETURN void deny(const char *msg, ...) {
101     va_list args;
102     va_start(args, msg);
103     die(LOG_ERR, "denied", msg, args);
104     va_end(args);
105 }
106
107 NORETURN void badconf(const char *msg, ...) {
108     va_list args;
109     va_start(args, msg);
110     die(LOG_CRIT, "configuration error", msg, args);
111     va_end(args);
112 }
113
114 NORETURN void fatalpe(const char *msg, ...) {
115     va_list args;
116     va_start(args, msg);
117     diepe(LOG_CRIT, "fatal", msg, args);
118     va_end(args);
119 }
120
121 void errorpe(const char *msg, ...) {
122     va_list args;
123     va_start(args, msg);
124     errmsgpe(LOG_ERR, "error", msg, args);
125     va_end(args);
126 }
127
128 void warnpe(const char *msg, ...) {
129     va_list args;
130     va_start(args, msg);
131     errmsgpe(LOG_WARNING, "warning", msg, args);
132     va_end(args);
133 }
134
135 int spawnv(const char *path, char *argv[]) {
136     int pid, status;
137     pid = fork();
138     if (pid == -1)
139         fatalpe("fork");
140     else if (pid)
141         waitpid(pid, &status, 0);
142     else
143         exit(execv(path, argv));
144     return status;
145 }