X-Git-Url: http://git.madism.org/?a=blobdiff_plain;f=common.c;h=0d7671d9640dc692e719b76dcbb383de6c13323b;hb=c693c0b0d26eac89aef4e4c6740feca3627e2d26;hp=520e77f930547572e25333a386049d79c0be5545;hpb=2472ae9bd2a2a22a278ffe586fd381e70c881e8d;p=apps%2Fpfixtools.git diff --git a/common.c b/common.c index 520e77f..0d7671d 100644 --- a/common.c +++ b/common.c @@ -1,5 +1,5 @@ /******************************************************************************/ -/* postlicyd: a postfix policy daemon with a lot of features */ +/* pfixtools: a collection of postfix related tools */ /* ~~~~~~~~~ */ /* ________________________________________________________________________ */ /* */ @@ -33,9 +33,13 @@ * Copyright © 2007 Pierre Habouzit */ +#include +#include +#include +#include + #include "common.h" -sig_atomic_t cleanexit = false; sig_atomic_t sigint = false; sig_atomic_t sighup = false; @@ -55,19 +59,149 @@ void common_sighandler(int sig) } return; - case SIGTERM: - break; - case SIGHUP: sighup = true; return; default: - return; + syslog(LOG_ERR, "Killed (got signal %d)...", sig); + exit(-1); + } +} + +static int setnonblock(int sock) +{ + int res = fcntl(sock, F_GETFL); + + if (res < 0) { + UNIXERR("fcntl"); + return -1; + } + + if (fcntl(sock, F_SETFL, res | O_NONBLOCK) < 0) { + UNIXERR("fcntl"); + return -1; + } + + return 0; +} + +int tcp_listen_nonblock(const struct sockaddr *addr, socklen_t len) +{ + int sock; + + switch (addr->sa_family) { + case AF_UNIX: + unlink(((struct sockaddr_un *)addr)->sun_path); + sock = socket(PF_UNIX, SOCK_STREAM, 0); + break; + case AF_INET: + sock = socket(PF_INET, SOCK_STREAM, 0); + break; + case AF_INET6: + sock = socket(PF_INET6, SOCK_STREAM, 0); + break; + default: + errno = EINVAL; + return -1; + } + + if (sock < 0) { + UNIXERR("socket"); + return -1; + } + + if (addr->sa_family != AF_UNIX) { + int v = 1; + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v)) < 0) { + UNIXERR("setsockopt(SO_REUSEADDR)"); + close(sock); + return -1; + } + } + + if (bind(sock, addr, len) < 0) { + UNIXERR("bind"); + close(sock); + return -1; + } + + if (setnonblock(sock)) { + close(sock); + return -1; + } + + if (listen(sock, 0) < 0) { + UNIXERR("bind"); + close(sock); + return -1; + } + + return sock; +} + +int accept_nonblock(int fd) +{ + int sock = accept(fd, NULL, 0); + + if (sock < 0) { + UNIXERR("accept"); + return -1; + } + + if (setnonblock(sock)) { + close(sock); + return -1; + } + + return sock; +} + +int daemon_detach(void) +{ + pid_t pid; + + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + + open("/dev/null", O_RDWR); + open("/dev/null", O_RDWR); + open("/dev/null", O_RDWR); + + pid = fork(); + if (pid < 0) + return -1; + if (pid) + exit(0); + + setsid(); + return 0; +} + +int drop_privileges(const char *user, const char *group) +{ + if (!geteuid()) { + struct passwd *pw; + struct group *gr; + + if (group) { + gr = getgrnam(group); + if (!gr) + return -1; + setgid(gr->gr_gid); + } + + pw = getpwnam(user); + if (!pw) + return -1; + if (!group) { + setgid(pw->pw_gid); + } + setuid(pw->pw_uid); } - syslog(LOG_ERR, "Killed..."); - exit(-1); + return 0; } void common_initialize(void)