Make CEO non-SUID
[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
11 static char message[4096];
12
13 static void errmsg(int prio, const char *prefix, const char *fmt, va_list args) {
14     char *msgp = message;
15
16     msgp +=  snprintf(msgp, sizeof(message) - 2 - (msgp - message), "%s: ", prefix);
17     if (msgp - message > sizeof(message) - 2)
18         fatal("error message overflowed");
19
20     msgp += vsnprintf(msgp, sizeof(message) - 2 - (msgp - message), fmt, args);
21     if (msgp - message > sizeof(message) - 2)
22         fatal("error message overflowed");
23
24     *msgp++ = '\n';
25     *msgp++ = '\0';
26
27     syslog(prio, "%s", message);
28     fputs(message, stderr);
29 }
30
31 static void errmsgpe(int prio, const char *prefix, const char *fmt, va_list args) {
32     char *msgp = message;
33
34     msgp += snprintf(msgp, sizeof(message) - 2 - (msgp - message), "%s: ", prefix);
35     if (msgp - message > sizeof(message) - 2)
36         fatal("error message overflowed");
37
38     msgp += vsnprintf(msgp, sizeof(message) - 2 - (msgp - message), fmt, args);
39     if (msgp - message > sizeof(message) - 2)
40         fatal("error message overflowed");
41
42     msgp += snprintf(msgp, sizeof(message) - 2 - (msgp - message), ": %s", strerror(errno));
43     if (msgp - message > sizeof(message) - 2)
44         fatal("error message overflowed");
45
46     *msgp++ = '\n';
47     *msgp++ = '\0';
48
49     syslog(prio, "%s", message);
50     fputs(message, stderr);
51 }
52
53 NORETURN static void die(int prio, const char *prefix, const char *msg, va_list args) {
54     errmsg(prio, prefix, msg, args);
55     exit(1);
56 }
57
58 NORETURN static void diepe(int prio, const char *prefix, const char *msg, va_list args) {
59     errmsgpe(prio, prefix, msg, args);
60     exit(1);
61 }
62
63 NORETURN void fatal(const char *msg, ...) {
64     va_list args;
65     va_start(args, msg);
66     die(LOG_CRIT, "fatal", msg, args);
67     va_end(args);
68 }
69
70 void error(const char *msg, ...) {
71     va_list args;
72     va_start(args, msg);
73     errmsg(LOG_ERR, "error", msg, args);
74     va_end(args);
75 }
76
77 void warn(const char *msg, ...) {
78     va_list args;
79     va_start(args, msg);
80     errmsg(LOG_WARNING, "warning", msg, args);
81     va_end(args);
82 }
83
84 void logmsg(const char *msg, ...) {
85     va_list args;
86     va_start(args, msg);
87     vsyslog(LOG_ERR, msg, args);
88     va_end(args);
89 }
90
91 NORETURN void deny(const char *msg, ...) {
92     va_list args;
93     va_start(args, msg);
94     die(LOG_ERR, "denied", msg, args);
95     va_end(args);
96 }
97
98 NORETURN void badconf(const char *msg, ...) {
99     va_list args;
100     va_start(args, msg);
101     die(LOG_CRIT, "configuration error", msg, args);
102     va_end(args);
103 }
104
105 NORETURN void fatalpe(const char *msg, ...) {
106     va_list args;
107     va_start(args, msg);
108     diepe(LOG_CRIT, "fatal", msg, args);
109     va_end(args);
110 }
111
112 void errorpe(const char *msg, ...) {
113     va_list args;
114     va_start(args, msg);
115     errmsgpe(LOG_ERR, "error", msg, args);
116     va_end(args);
117 }
118
119 void warnpe(const char *msg, ...) {
120     va_list args;
121     va_start(args, msg);
122     errmsgpe(LOG_WARNING, "warning", msg, args);
123     va_end(args);
124 }
125
126 int spawnv(const char *path, char *argv[]) {
127     int pid, status;
128     pid = fork();
129     if (pid == -1)
130         fatalpe("fork");
131     else if (pid)
132         waitpid(pid, &status, 0);
133     else
134         exit(execv(path, argv));
135     return status;
136 }