diff options
Diffstat (limited to 'sbusd.c')
-rw-r--r-- | sbusd.c | 309 |
1 files changed, 9 insertions, 300 deletions
@@ -3,24 +3,15 @@ #include <sys/socket.h> #include <sys/stat.h> #include <sys/un.h> -#include <sys/wait.h> #include <alloca.h> #include <ctype.h> #include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <pwd.h> -#include <stdarg.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> -#include <time.h> #include <unistd.h> #include "arg.h" - -#define STYPE_MAX(T) (long long int)((1ULL << (8 * sizeof(T) - 1)) - 1) -#define eprintf(...) (weprintf(__VA_ARGS__), exit(1)) +#include "libsbusd.h" enum blocking_mode { BLOCKING_QUEUE, @@ -56,7 +47,7 @@ static int epfd; static int had_client = 0; static struct sockaddr_un addr; static uid_t *users; -static size_t nusers; +static size_t nusers = 0; static const char *pidfile = "/run/sbus.pid"; static void @@ -67,19 +58,6 @@ usage(void) } static void -weprintf(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - vfprintf(stderr, fmt, args); - if (strchr(fmt, '\0')[-1] == ':') { - fputc(' ', stderr); - perror(NULL); - } - va_end(args); -} - -static void sigexit(int signo) { if (*addr.sun_path) @@ -162,39 +140,6 @@ cred_ok: } static int -is_subscription_match(const char *sub, const char *key) -{ - const char *sub_start = sub; - for (;;) { - while (*sub && *sub == *key) { - sub++; - key++; - } - if (!*key) - return !*sub; - if (!*sub) - return sub == sub_start || sub[-1] == '/'; - if (*sub == '*') { - sub++; - while (*key && *key != '/') - key++; - continue; - } - return 0; - } -} - -static int -is_subscribed(const struct client *cl, const char *key) -{ - size_t i = cl->nsubs; - while (i--) - if (is_subscription_match(cl->subs[i], key)) - return 1; - return 0; -} - -static int is_subscription_acceptable(struct client *cl, const char *key) { struct ucred cred; @@ -235,7 +180,7 @@ add_subscription(struct client *cl, const char *key) remove_client(cl); return; case 0: - weprintf("client subscribed unacceptable routing key\n"); + weprintf("client subscribed to unacceptable routing key\n"); remove_client(cl); return; default: @@ -303,7 +248,7 @@ handle_cmsg(struct client *cl, char *buf, size_t n) n += (size_t)sprintf(&buf[n], "!/cred/%lli/%lli/%lli", (long long int)cred.gid, (long long int)cred.uid, - (long long int)cred.gid); + (long long int)cred.pid); if (send_packet(cl, buf, n)) { weprintf("send <client>:"); remove_client(cl); @@ -336,7 +281,7 @@ broadcast(const char *msg, size_t n) { struct client *cl = head.next, *tmp; for (; cl->next; cl = cl->next) { - if (!is_subscribed(cl, &msg[4])) + if (!libsbusd_issubed(cl->subs, cl->nsubs, &msg[4])) continue; if (send_packet(cl, msg, n)) { cl = (tmp = cl)->prev; @@ -375,214 +320,6 @@ handle_message(struct client *cl) } } -static void -randomise(void *buf, size_t n) -{ - char *p = buf; - while (n--) - *p++ = rand(); -} - -static void -print_address(void) -{ - char buf[2 * sizeof(addr.sun_path) + 1]; - char *p = buf; - const unsigned char *a = (const unsigned char *)addr.sun_path; - size_t n = sizeof(addr.sun_path); - - for (; n--; p += 2, a += 1) { - p[0] = "0123456789abcdef"[(int)*a >> 4]; - p[1] = "0123456789abcdef"[(int)*a & 15]; - } - *p = '\0'; - - printf("/dev/unix/abstract/%s\n", buf); - if (fflush(stdout) || ferror(stdout)) - eprintf("failed print generated address:"); -} - -static int -make_socket(const char *address, int reuse, mode_t mode) -{ - int fd = -1, randaddr = 0, hi, lo, listening = 0; - long int tmp; - size_t n; - const char *p, *q; - char *a; - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - - if (strstr(address, "/dev/fd/") == address) { - p = &address[sizeof("/dev/fd/") - 1]; - if (!isdigit(*p)) - goto def; - errno = 0; - tmp = strtol(p, &a, 10); - if (errno || *a || tmp < 0) { - errno = 0; - goto def; - } - if (tmp > INT_MAX) { - errno = EBADF; - goto bad_address; - } - fd = (int)tmp; - reuse = 0; - } else if (!strcmp(address, "/dev/unix/abstract")) { - randaddr = 1; - reuse = 0; - } else if (strstr(address, "/dev/unix/abstract/") == address) { - p = &address[sizeof("/dev/unix/abstract/") - 1]; - n = strlen(p); - if (n & 1) - goto def; - for (q = p; *q; q++) - if (!isxdigit(*q)) - goto def; - if (n > sizeof(addr.sun_path) * 2) { - errno = ENAMETOOLONG; - goto bad_address; - } - a = addr.sun_path; - for (; *p; p += 2) { - hi = (p[0] & 15) + 9 * !isdigit(p[0]); - lo = (p[1] & 15) + 9 * !isdigit(p[1]); - *a++ = (hi << 4) | lo; - } - reuse = 0; - } else { - def: - if (strlen(address) >= sizeof(addr.sun_path)) { - errno = ENAMETOOLONG; - goto bad_address; - } - strcpy(addr.sun_path, address); - } - - if (reuse) - unlink(addr.sun_path); - - if (fd < 0) { - fd = socket(PF_UNIX, SOCK_SEQPACKET, 0); - if (fd < 0) - eprintf("socket PF_UNIX SOCK_SEQPACKET:"); - if (fchmod(fd, mode)) - eprintf("fchmod <socket> %o:", mode); - if (randaddr) { - srand((unsigned)time(NULL)); - for (;;) { - randomise(&addr.sun_path[1], sizeof(addr.sun_path) - 1); - if (!bind(fd, (void *)&addr, sizeof(addr))) - break; - else if (errno != EADDRINUSE) - eprintf("bind <random abstract address>:"); - } - print_address(); - } else { - if (bind(fd, (void *)&addr, sizeof(addr))) { - if (*addr.sun_path) - eprintf("bind %s:", addr.sun_path); - else - eprintf("bind <abstract:%s>:", &address[sizeof("/dev/unix/abstract/") - 1]); - } - } - } else { - if (mode & 0070) - weprintf("ignoring -g due to using passed down socket\n"); - if (mode & 0007) - weprintf("ignoring -o due to using passed down socket\n"); - if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &listening, &(socklen_t){sizeof(listening)})) - eprintf("getsockopt SOL_SOCKET SO_ACCEPTCONN:"); - } - - if (!listening && listen(fd, SOMAXCONN)) - eprintf("listen:"); - - return fd; - -bad_address: - eprintf("bad unix socket address:"); - exit(1); -} - -static void -daemonise(void) -{ - pid_t pid; - int rw[2], status = 0, fd; - FILE *fp; - - if (pipe(rw)) - eprintf("pipe:"); - - switch ((pid = fork())) { - case -1: - eprintf("fork:"); - - case 0: - close(rw[0]); - setsid(); - switch (fork()) { - case -1: - eprintf("fork:"); - - case 0: - if (signal(SIGHUP, SIG_IGN) == SIG_ERR) - weprintf("signal SIGHUP SIG_IGN:"); - if (signal(SIGINT, sigexit) == SIG_ERR) - weprintf("signal SIGINT <exit>:"); - if (pidfile) { - pid = getpid(); - fd = open(pidfile, O_WRONLY | O_CREAT | O_EXCL, 0644); - if (fd < 0) - eprintf("open %s O_WRONLY O_CREAT O_EXCL:", pidfile); - fp = fdopen(fd, "w"); - fprintf(fp, "%li\n", (long int)pid); - if (fflush(fp) || ferror(fp)) - eprintf("fprintf %s:", pidfile); - fclose(fp); - } - if (chdir("/")) - eprintf("chdir /:"); - close(STDIN_FILENO); - close(STDOUT_FILENO); - if (isatty(STDERR_FILENO)) { - fd = open("/dev/null", O_WRONLY); - if (fd) - eprintf("open /dev/null O_WRONLY:"); - if (dup2(fd, STDERR_FILENO) != STDERR_FILENO) - eprintf("dup2 /dev/null /dev/stderr:"); - close(fd); - } - if (write(rw[1], &status, 1) < 1) - eprintf("write <pipe>:"); - close(rw[1]); - break; - - default: - exit(0); - } - break; - - default: - close(rw[1]); - if (waitpid(pid, &status, 0) != pid) - eprintf("waitpid:"); - if (status) - exit(1); - switch (read(rw[0], &status, 1)) { - case -1: - eprintf("read <pipe>:"); - case 0: - exit(1); - default: - exit(0); - } - } -} - int main(int argc, char *argv[]) { @@ -592,10 +329,7 @@ main(int argc, char *argv[]) int foreground = 0; mode_t mode = 0700; int reuse_address = 0; - struct passwd *user; int server, n; - long long int tmp; - char *arg; users = alloca(argc * sizeof(*users)); @@ -622,19 +356,7 @@ main(int argc, char *argv[]) reuse_address = 1; break; case 'u': - arg = EARGF(); - if (!isdigit(*arg)) - goto user_by_name; - errno = 0; - tmp = strtoll(arg, &arg, 10); - if (errno || *arg || tmp < 0 || tmp > STYPE_MAX(uid_t)) - goto user_by_name; - users[nusers++] = (uid_t)tmp; - user_by_name: - user = getpwnam(arg); - if (!user) - eprintf("getpwnam %s:", arg); - users[nusers++] = user->pw_uid; + libsbusd_adduser(users, &nusers, EARGF()); break; default: usage(); @@ -643,24 +365,11 @@ main(int argc, char *argv[]) usage(); umask(0); - server = make_socket(address, reuse_address, mode); - if (foreground) { - close(STDIN_FILENO); - close(STDOUT_FILENO); - if (signal(SIGHUP, sigexit) == SIG_ERR) - weprintf("signal SIGHUP <exit>:"); - if (signal(SIGINT, sigexit) == SIG_ERR) - weprintf("signal SIGINT <exit>:"); - pidfile = NULL; - } else { - if (!strcmp(pidfile, "/dev/null")) - pidfile = NULL; - daemonise(); - } - + server = libsbusd_mksocket(&addr, address, reuse_address, mode); + libsbusd_initalise(foreground, &pidfile, sigexit); if (nusers) users[nusers++] = getuid(); - + head.next = &tail; tail.prev = &head; |