16 static int log_stderr = 1;
17 static int log_maxprio = LOG_DEBUG;
19 void init_log(const char *ident, int option, int facility, int lstderr) {
20 openlog(ident, option, facility);
21 log_stderr = lstderr || isatty(STDERR_FILENO);
24 void log_set_maxprio(int prio) {
28 static void errmsg(int prio, const char *prefix, const char *fmt, va_list args) {
29 struct strbuf msg = STRBUF_INIT;
31 strbuf_addf(&msg, "%s: ", prefix);
32 strbuf_vaddf(&msg, fmt, args);
33 strbuf_addch(&msg, '\n');
35 syslog(prio, "%s", msg.buf);
36 if (log_stderr && prio <= log_maxprio)
37 fputs(msg.buf, stderr);
42 static void errmsgpe(int prio, const char *prefix, const char *fmt, va_list args) {
43 struct strbuf msg = STRBUF_INIT;
45 strbuf_addf(&msg, "%s: ", prefix);
46 strbuf_vaddf(&msg, fmt, args);
47 strbuf_addf(&msg, ": %s\n", strerror(errno));
49 syslog(prio, "%s", msg.buf);
50 if (log_stderr && prio <= log_maxprio)
51 fputs(msg.buf, stderr);
56 NORETURN static void die(int prio, const char *prefix, const char *msg, va_list args) {
57 errmsg(prio, prefix, msg, args);
61 NORETURN static void diepe(int prio, const char *prefix, const char *msg, va_list args) {
62 errmsgpe(prio, prefix, msg, args);
66 NORETURN void fatal(const char *msg, ...) {
69 die(LOG_CRIT, "fatal", msg, args);
73 void error(const char *msg, ...) {
76 errmsg(LOG_ERR, "error", msg, args);
80 void warn(const char *msg, ...) {
83 errmsg(LOG_WARNING, "warning", msg, args);
87 void notice(const char *msg, ...) {
90 errmsg(LOG_NOTICE, "notice", msg, args);
94 void debug(const char *msg, ...) {
97 errmsg(LOG_DEBUG, "debug", msg, args);
101 void logmsg(int priority, const char *msg, ...) {
104 vsyslog(priority, msg, args);
107 if (log_stderr && priority <= log_maxprio) {
108 vfprintf(stderr, msg, args);
114 NORETURN void deny(const char *msg, ...) {
117 die(LOG_ERR, "denied", msg, args);
121 NORETURN void badconf(const char *msg, ...) {
124 die(LOG_CRIT, "configuration error", msg, args);
128 NORETURN void fatalpe(const char *msg, ...) {
131 diepe(LOG_CRIT, "fatal", msg, args);
135 void errorpe(const char *msg, ...) {
138 errmsgpe(LOG_ERR, "error", msg, args);
142 void warnpe(const char *msg, ...) {
145 errmsgpe(LOG_WARNING, "warning", msg, args);
149 int spawnv(const char *path, char *const argv[]) {
159 waitpid(pid, &status, 0);
161 exit(execv(path, argv));
165 int full_write(int fd, const void *buf, size_t count) {
168 while (total < count) {
169 ssize_t wcount = write(fd, (char *)buf + total, count - total);
178 int spawnvem(const char *path, char *const *argv, char *const *envp, const struct strbuf *output, struct strbuf *input, int cap_stderr) {
179 return spawnvemu(path, argv, envp, output, input, cap_stderr, NULL);
182 int spawnvemu(const char *path, char *const *argv, char *const *envp, const struct strbuf *output, struct strbuf *input, int cap_stderr, char *user) {
183 int pid, wpid, status;
199 dup2(tochild[0], STDIN_FILENO);
200 dup2(fmchild[1], STDOUT_FILENO);
202 dup2(STDOUT_FILENO, STDERR_FILENO);
209 struct passwd *pw = getpwnam(user);
211 fatalpe("getpwnam: %s", user);
212 if (initgroups(user, pw->pw_gid))
213 fatalpe("initgroups: %s", user);
214 if (setregid(pw->pw_gid, pw->pw_gid))
215 fatalpe("setregid: %s", user);
216 if (setreuid(pw->pw_uid, pw->pw_uid))
219 execve(path, argv, envp);
224 full_write(tochild[1], output->buf, output->len);
228 strbuf_read(input, fmchild[0], 0);
232 wpid = waitpid(pid, &status, 0);
235 else if (wpid != pid)
236 fatal("waitpid is broken");
238 if (WIFEXITED(status) && WEXITSTATUS(status))
239 notice("child %s exited with status %d", path, WEXITSTATUS(status));
240 else if (WIFSIGNALED(status))
241 notice("child %s killed by signal %d", path, WTERMSIG(status));
246 int spawnv_msg(const char *path, char *const *argv, const struct strbuf *output) {
247 return spawnvem(path, argv, environ, output, NULL, 0);
250 int check_group(char *username, char *group) {
251 struct group *grp = getgrnam(group);
255 for (members = grp->gr_mem; *members; members++)
256 if (!strcmp(username, *members))
262 FILE *fopenat(DIR *d, const char *path, int flags) {
266 int fd = openat(dfd, path, flags);
269 return fdopen(fd, flags & O_RDWR ? "r+" :
270 flags & O_WRONLY ? "w" :
274 void make_env(char **envp, ...) {
275 const size_t len = 4096;
278 char *buf = xmalloc(len);
283 while ((name = va_arg(ap, char *))) {
284 val = va_arg(ap, char *);
287 int n = snprintf(buf + used, len - used, "%s=%s", name, val);
291 fatal("environment too big");
293 envp[args++] = buf + used;
303 void free_env(char **envp) {