X-Git-Url: http://git.madism.org/?a=blobdiff_plain;f=common.c;h=d00461b827761c2d526fb9f4cd075b1b6a2319eb;hb=002766b52f65c43202f6649c5cd1e4a7e4dea885;hp=7ede07b8483e4fa269fccaf3f1a290c7650d4a0a;hpb=e3d9a582b6ff0bef16a6c1e7f506d9088379c77a;p=apps%2Fpfixtools.git diff --git a/common.c b/common.c index 7ede07b..d00461b 100644 --- a/common.c +++ b/common.c @@ -33,26 +33,23 @@ * 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; +sig_atomic_t sigint = false; +sig_atomic_t sighup = false; + +static FILE *pidfile = NULL; void common_sighandler(int sig) { - static time_t lastintr = 0; - time_t now = time(NULL); - switch (sig) { case SIGINT: - if (sigint) { - if (now - lastintr >= 1) - break; - } else { - lastintr = now; - sigint = true; - } + sigint = true; return; case SIGHUP: @@ -65,22 +62,226 @@ void common_sighandler(int sig) } } -void common_initialize(void) +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_bind(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; + } + + return sock; +} + +int tcp_listen(const struct sockaddr *addr, socklen_t len) +{ + int sock = tcp_bind(addr, len); + if (listen(sock, 0) < 0) { + UNIXERR("bind"); + close(sock); + return -1; + } + return sock; +} + +int tcp_listen_nonblock(const struct sockaddr *addr, socklen_t len) +{ + int sock = tcp_bind(addr, len); + 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 xwrite(int fd, const char *s, size_t l) +{ + while (l > 0) { + int nb = write(fd, s, l); + if (nb < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + return -1; + } + l -= nb; + } + return 0; +} + +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); + } + + return 0; +} + +int pidfile_open(const char *name) +{ + if (name) { + pidfile = fopen(name, "w"); + if (!pidfile) + return -1; + fprintf(pidfile, "%d\n", getpid()); + return fflush(pidfile); + } + return 0; +} + +int pidfile_refresh(void) +{ + if (pidfile) { + rewind(pidfile); + ftruncate(fileno(pidfile), 0); + fprintf(pidfile, "%d\n", getpid()); + return fflush(pidfile); + } + return 0; +} + +static void pidfile_close(void) +{ + if (pidfile) { + rewind(pidfile); + ftruncate(fileno(pidfile), 0); + fclose(pidfile); + pidfile = NULL; + } +} + +extern initcall_t __madinit[], __madexit[]; + +static void common_shutdown(void) { - extern initcall_t __madinit_start, __madinit_end; + pidfile_close(); - initcall_t *call_p = &__madinit_start; - while (call_p < &__madinit_end) { - (*call_p++)(); + for (int i = -1; __madexit[i]; i--) { + (*__madexit[i])(); } } -void common_shutdown(void) +static void __attribute__((__constructor__,__used__)) +common_initialize(void) { - extern exitcall_t __madexit_start, __madexit_end; + if (atexit(common_shutdown)) { + fputs("Cannot hook my atexit function, quitting !\n", stderr); + abort(); + } - exitcall_t *call_p = &__madexit_end; - while (call_p > &__madexit_start) { - (*--call_p)(); + for (int i = 0; __madinit[i]; i++) { + if ((*__madinit[i])()) { + exit(EXIT_FAILURE); + } } } +