diff options
Diffstat (limited to '')
-rw-r--r-- | src/common.h | 10 | ||||
-rw-r--r-- | src/satd.c | 35 |
2 files changed, 37 insertions, 8 deletions
diff --git a/src/common.h b/src/common.h index 2f8ac86..55a0837 100644 --- a/src/common.h +++ b/src/common.h @@ -48,7 +48,7 @@ usage(void) \ { \ fprintf(stderr, "usage: %s%s%s\n", \ strrchr(argv0, '/') ? (strrchr(argv0, '/') + 1) : argv0, \ - (synopsis) ? " " : "", synopsis ? synopsis : ""); \ + synopsis ? " " : "", synopsis ? synopsis : ""); \ exit(2); \ } @@ -68,12 +68,14 @@ char *argv0 = name; * that is an option. */ #define NO_OPTIONS \ - int i; +do { \ + int i; \ if (!strcmp(argv[1], "--")) \ argv++, argc--; \ for (i = 1; i < argc; i++) \ if (strchr("-", argv[i][0])) \ - usage() + usage(); \ +} while (0) /** @@ -100,7 +102,7 @@ do { \ t (errno); \ free(msg); \ return 3; \ - } + } \ } while (0) @@ -24,6 +24,7 @@ #include <sys/stat.h> #include <sys/socket.h> #include <sys/un.h> +#include <sys/file.h> #include "daemonise.h" #include "common.h" @@ -58,19 +59,40 @@ create_socket(struct sockaddr_un *address) char *dir; int saved_errno; + /* Get scoket address. */ dir = getenv("XDG_RUNTIME_DIR"), dir = (dir ? dir : "/run"); t (snprintf(NULL, 0, "%s/satd.socket%zn", dir, &len) == -1); if ((len < 0) || ((size_t)len >= sizeof(address->sun_path))) t ((errno = ENAMETOOLONG)); sprintf(address->sun_path, "%s/satd.socket", dir); address->sun_family = AF_UNIX; - /* TODO test flock */ + + /* Check that no living process owns the socket. */ + fd = open(address->sun_path, O_RDONLY); + if (fd == -1) { + t (errno != ENOENT); + goto does_not_exist; + } else { + if (flock(fd, LOCK_EX | LOCK_NB) == -1) { + t (errno != EWOULDBLOCK); + fprintf(stderr, "%s: the daemon's socket file is already in use.\n", argv0); + errno = 0; + goto fail; + } + flock(fd, LOCK_UN); + close(fd), fd = -1; + } + + /* Create socket. */ unlink(address->sun_path); +does_not_exist: t ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1); t (fchmod(fd, S_IRWXU) == -1); t (fchown(fd, getuid(), getgid()) == -1); t (bind(fd, (struct sockaddr *)address, sizeof(*address)) == -1); - /* TODO flock */ + + /* Mark the socket as owned by a living process. */ + t (flock(fd, LOCK_SH)); return fd; fail: @@ -98,21 +120,25 @@ main(int argc, char *argv[]) struct sockaddr_un address; int sock = -1, foreground = 0; + /* Parse command line. */ if (argc > 0) argv0 = argv[0]; if (argc > 2) usage(); if (argc == 2) if (!(foreground = !strcmp(argv[1], "-f"))) usage(); + /* Daemonise. */ t (foreground ? 0 : daemonise("satd", 0)); + /* Create socket. */ t (sock = create_socket(&address), sock == -1); if (sock != 3) { t (dup2(sock, 3) == -1); close(sock), sock = 3; } -#ifdef SOMAXCONN < SATD_BACKLOG + /* Listen for incoming conections. */ +#if SOMAXCONN < SATD_BACKLOG t (listen(sock, SOMAXCONN)); #else t (listen(sock, SATD_BACKLOG)); @@ -124,7 +150,8 @@ main(int argc, char *argv[]) return 0; fail: - perror(argv0); + if (errno) + perror(argv0); if (sock >= 0) { close(sock); unlink(address.sun_path); |