Don't forget to flush
[mspang/pyceo.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 #include "strbuf.h"
11
12 static int log_stderr = 1;
13
14 void init_log(const char *ident, int option, int facility) {
15     openlog(ident, option, facility);
16     log_stderr = isatty(STDERR_FILENO);
17 }
18
19 static void errmsg(int prio, const char *prefix, const char *fmt, va_list args) {
20     struct strbuf msg = STRBUF_INIT;
21
22     strbuf_addf(&msg, "%s: ", prefix);
23     strbuf_vaddf(&msg, fmt, args);
24     strbuf_addch(&msg, '\n');
25
26     syslog(prio, "%s", msg.buf);
27     if (log_stderr)
28         fputs(msg.buf, stderr);
29 }
30
31 static void errmsgpe(int prio, const char *prefix, const char *fmt, va_list args) {
32     struct strbuf msg = STRBUF_INIT;
33
34     strbuf_addf(&msg, "%s: ", prefix);
35     strbuf_vaddf(&msg, fmt, args);
36     strbuf_addf(&msg, ": %s\n", strerror(errno));
37
38     syslog(prio, "%s", msg.buf);
39     if (log_stderr)
40         fputs(msg.buf, stderr);
41 }
42
43 NORETURN static void die(int prio, const char *prefix, const char *msg, va_list args) {
44     errmsg(prio, prefix, msg, args);
45     exit(1);
46 }
47
48 NORETURN static void diepe(int prio, const char *prefix, const char *msg, va_list args) {
49     errmsgpe(prio, prefix, msg, args);
50     exit(1);
51 }
52
53 NORETURN void fatal(const char *msg, ...) {
54     va_list args;
55     va_start(args, msg);
56     die(LOG_CRIT, "fatal", msg, args);
57     va_end(args);
58 }
59
60 void error(const char *msg, ...) {
61     va_list args;
62     va_start(args, msg);
63     errmsg(LOG_ERR, "error", msg, args);
64     va_end(args);
65 }
66
67 void warn(const char *msg, ...) {
68     va_list args;
69     va_start(args, msg);
70     errmsg(LOG_WARNING, "warning", msg, args);
71     va_end(args);
72 }
73
74 void notice(const char *msg, ...) {
75     va_list args;
76     va_start(args, msg);
77     errmsg(LOG_NOTICE, "notice", msg, args);
78     va_end(args);
79 }
80
81 void debug(const char *msg, ...) {
82     va_list args;
83     va_start(args, msg);
84     errmsg(LOG_DEBUG, "debug", msg, args);
85     va_end(args);
86 }
87
88 void logmsg(int priority, const char *msg, ...) {
89     va_list args;
90     va_start(args, msg);
91     vsyslog(priority, msg, args);
92     va_end(args);
93     va_start(args, msg);
94     if (log_stderr) {
95         vfprintf(stderr, msg, args);
96         fputc('\n', stderr);
97     }
98     va_end(args);
99 }
100
101 NORETURN void deny(const char *msg, ...) {
102     va_list args;
103     va_start(args, msg);
104     die(LOG_ERR, "denied", msg, args);
105     va_end(args);
106 }
107
108 NORETURN void badconf(const char *msg, ...) {
109     va_list args;
110     va_start(args, msg);
111     die(LOG_CRIT, "configuration error", msg, args);
112     va_end(args);
113 }
114
115 NORETURN void fatalpe(const char *msg, ...) {
116     va_list args;
117     va_start(args, msg);
118     diepe(LOG_CRIT, "fatal", msg, args);
119     va_end(args);
120 }
121
122 void errorpe(const char *msg, ...) {
123     va_list args;
124     va_start(args, msg);
125     errmsgpe(LOG_ERR, "error", msg, args);
126     va_end(args);
127 }
128
129 void warnpe(const char *msg, ...) {
130     va_list args;
131     va_start(args, msg);
132     errmsgpe(LOG_WARNING, "warning", msg, args);
133     va_end(args);
134 }
135
136 int spawnv(const char *path, char *const argv[]) {
137     int pid, status;
138
139     fflush(stdout);
140     fflush(stderr);
141
142     pid = fork();
143     if (pid < 0)
144         fatalpe("fork");
145     else if (pid)
146         waitpid(pid, &status, 0);
147     else
148         exit(execv(path, argv));
149     return status;
150 }