aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenny Levinsen <kl@kl.wtf>2020-08-07 15:48:24 +0200
committerKenny Levinsen <kl@kl.wtf>2020-08-07 15:50:27 +0200
commita98e0c4ce90347d37370f2debcbed8ae9678a990 (patch)
tree47f3d10b51f6329103c8878e5a53da10b192600c
parent420f97300489f9fa10cea036c0d0f6d893c343d6 (diff)
seatd: Add command-line arguments
-rw-r--r--include/server.h2
-rw-r--r--meson.build1
-rw-r--r--seatd/seatd.c125
-rw-r--r--seatd/server.c96
4 files changed, 129 insertions, 95 deletions
diff --git a/include/server.h b/include/server.h
index f280993..a225668 100644
--- a/include/server.h
+++ b/include/server.h
@@ -20,7 +20,7 @@ void server_finish(struct server *server);
struct seat *server_get_seat(struct server *server, const char *seat_name);
-int server_listen(struct server *server, const char *path);
+int server_handle_connection(int fd, uint32_t mask, void *data);
int server_add_client(struct server *server, int fd);
#endif
diff --git a/meson.build b/meson.build
index 6d54a2b..49bd049 100644
--- a/meson.build
+++ b/meson.build
@@ -27,6 +27,7 @@ add_project_arguments(
'-Wl,--exclude-libs=ALL',
'-D_XOPEN_SOURCE=700',
'-D__BSD_VISIBLE',
+ '-DSEATD_VERSION="@0@"'.format(meson.project_version()),
],
language: 'c',
)
diff --git a/seatd/seatd.c b/seatd/seatd.c
index 2dba9ba..30b0c27 100644
--- a/seatd/seatd.c
+++ b/seatd/seatd.c
@@ -1,5 +1,7 @@
#include <errno.h>
+#include <grp.h>
#include <poll.h>
+#include <pwd.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
@@ -13,10 +15,44 @@
#include "poller.h"
#include "server.h"
-int main(int argc, char *argv[]) {
- (void)argc;
- (void)argv;
+#define LISTEN_BACKLOG 16
+
+static int open_socket(char *path, int uid, int gid) {
+ union {
+ struct sockaddr_un unix;
+ struct sockaddr generic;
+ } addr = {{0}};
+ int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
+ if (fd == -1) {
+ log_errorf("could not create socket: %s", strerror(errno));
+ return -1;
+ }
+ addr.unix.sun_family = AF_UNIX;
+ strncpy(addr.unix.sun_path, path, sizeof addr.unix.sun_path - 1);
+ socklen_t size = offsetof(struct sockaddr_un, sun_path) + strlen(addr.unix.sun_path);
+ if (bind(fd, &addr.generic, size) == -1) {
+ log_errorf("could not bind socket: %s", strerror(errno));
+ close(fd);
+ return -1;
+ }
+ if (listen(fd, LISTEN_BACKLOG) == -1) {
+ log_errorf("could not listen on socket: %s", strerror(errno));
+ close(fd);
+ return -1;
+ }
+ if (uid != 0 || gid != 0) {
+ if (fchown(fd, uid, gid) == -1) {
+ log_errorf("could not chown socket to uid %d, gid %d: %s", uid, gid,
+ strerror(errno));
+ } else if (fchmod(fd, 0770) == -1) {
+ log_errorf("could not chmod socket: %s", strerror(errno));
+ }
+ }
+ return fd;
+}
+
+int main(int argc, char *argv[]) {
char *loglevel = getenv("SEATD_LOGLEVEL");
enum log_level level = LOGLEVEL_ERROR;
if (loglevel != NULL) {
@@ -30,23 +66,82 @@ int main(int argc, char *argv[]) {
}
log_init(level);
- struct server server = {0};
- if (server_init(&server) == -1) {
- log_errorf("server_create failed: %s", strerror(errno));
- return 1;
+ const char *usage = "Usage: seatd [options]\n"
+ "\n"
+ " -h Show this help message\n"
+ " -u <user> User to own the seatd socket\n"
+ " -g <group> Group to own the seatd socket\n"
+ " -s <path> Where to create the seatd socket\n"
+ " -v Show the version number\n"
+ "\n";
+
+ int c;
+ int uid = 0, gid = 0;
+ char *socket_path = getenv("SEATD_SOCK");
+ while ((c = getopt(argc, argv, "vhs:g:u:")) != -1) {
+ switch (c) {
+ case 's':
+ socket_path = optarg;
+ break;
+ case 'u': {
+ struct passwd *pw = getpwnam(optarg);
+ if (pw == NULL) {
+ fprintf(stderr, "Could not find user by name '%s'.\n", optarg);
+ return 1;
+ } else {
+ uid = pw->pw_uid;
+ }
+ break;
+ }
+ case 'g': {
+ struct group *gr = getgrnam(optarg);
+ if (gr == NULL) {
+ fprintf(stderr, "Could not find group by name '%s'.\n", optarg);
+ return 1;
+ } else {
+ gid = gr->gr_gid;
+ }
+ break;
+ }
+ case 'v':
+ printf("seatd version %s\n", SEATD_VERSION);
+ return 0;
+ case 'h':
+ printf("%s", usage);
+ return 0;
+ case '?':
+ fprintf(stderr, "Try '%s -h' for more information.\n", argv[0]);
+ return 1;
+ default:
+ abort();
+ }
}
- char *path = getenv("SEATD_SOCK");
- if (path == NULL) {
- path = "/run/seatd.sock";
+
+ if (socket_path == NULL) {
+ socket_path = "/run/seatd.sock";
struct stat st;
- if (stat(path, &st) == 0) {
+ if (stat(socket_path, &st) == 0) {
log_info("removing leftover seatd socket");
- unlink(path);
+ unlink(socket_path);
}
}
- if (server_listen(&server, path) == -1) {
- log_errorf("server_listen failed: %s", strerror(errno));
+ struct server server = {0};
+ if (server_init(&server) == -1) {
+ log_errorf("server_create failed: %s", strerror(errno));
+ return 1;
+ }
+
+ int socket_fd = open_socket(socket_path, uid, gid);
+ if (socket_fd == -1) {
+ log_errorf("could not create server socket: %s", strerror(errno));
+ server_finish(&server);
+ return 1;
+ }
+ if (poller_add_fd(&server.poller, socket_fd, EVENT_READABLE, server_handle_connection,
+ &server) == NULL) {
+ log_errorf("could not add socket to poller: %s", strerror(errno));
+ close(socket_fd);
server_finish(&server);
return 1;
}
@@ -61,6 +156,6 @@ int main(int argc, char *argv[]) {
}
server_finish(&server);
- unlink(path);
+ unlink(socket_path);
return 0;
}
diff --git a/seatd/server.c b/seatd/server.c
index 799fda0..7368ea3 100644
--- a/seatd/server.c
+++ b/seatd/server.c
@@ -1,7 +1,6 @@
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
-#include <grp.h>
#include <signal.h>
#include <stddef.h>
#include <stdlib.h>
@@ -20,8 +19,6 @@
#include "server.h"
#include "terminal.h"
-#define LISTEN_BACKLOG 16
-
static int server_handle_vt_acq(int signal, void *data);
static int server_handle_vt_rel(int signal, void *data);
static int server_handle_kill(int signal, void *data);
@@ -117,42 +114,6 @@ static int set_nonblock(int fd) {
return 0;
}
-static int server_handle_connection(int fd, uint32_t mask, void *data) {
- struct server *server = data;
- if (mask & (EVENT_ERROR | EVENT_HANGUP)) {
- shutdown(fd, SHUT_RDWR);
- server->running = false;
- log_errorf("server socket recieved an error: %s", strerror(errno));
- return -1;
- }
-
- if (mask & EVENT_READABLE) {
- int new_fd = accept(fd, NULL, NULL);
- if (fd == -1) {
- log_errorf("could not accept client connection: %s", strerror(errno));
- return 0;
- }
-
- if (set_nonblock(new_fd) != 0) {
- close(new_fd);
- log_errorf("could not prepare new client socket: %s", strerror(errno));
- return 0;
- }
-
- struct client *client = client_create(server, new_fd);
- client->event_source = poller_add_fd(&server->poller, new_fd, EVENT_READABLE,
- client_handle_connection, client);
- if (client->event_source == NULL) {
- client_destroy(client);
- log_errorf("could not add client socket to poller: %s", strerror(errno));
- return 0;
- }
- log_infof("new client connected (pid: %d, uid: %d, gid: %d)", client->pid,
- client->uid, client->gid);
- }
- return 0;
-}
-
int server_add_client(struct server *server, int fd) {
if (set_nonblock(fd) != 0) {
close(fd);
@@ -168,53 +129,30 @@ int server_add_client(struct server *server, int fd) {
log_errorf("could not add client socket to poller: %s", strerror(errno));
return -1;
}
+ log_infof("new client connected (pid: %d, uid: %d, gid: %d)", client->pid, client->uid,
+ client->gid);
return 0;
}
-int server_listen(struct server *server, const char *path) {
- union {
- struct sockaddr_un unix;
- struct sockaddr generic;
- } addr = {{0}};
- int fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (fd == -1) {
- log_errorf("could not create socket: %s", strerror(errno));
- return -1;
- }
- if (set_nonblock(fd) == -1) {
- close(fd);
- log_errorf("could not prepare socket: %s", strerror(errno));
+int server_handle_connection(int fd, uint32_t mask, void *data) {
+ struct server *server = data;
+ if (mask & (EVENT_ERROR | EVENT_HANGUP)) {
+ shutdown(fd, SHUT_RDWR);
+ server->running = false;
+ log_errorf("server socket recieved an error: %s", strerror(errno));
return -1;
}
- addr.unix.sun_family = AF_UNIX;
- strncpy(addr.unix.sun_path, path, sizeof addr.unix.sun_path - 1);
- socklen_t size = offsetof(struct sockaddr_un, sun_path) + strlen(addr.unix.sun_path);
- if (bind(fd, &addr.generic, size) == -1) {
- log_errorf("could not bind socket: %s", strerror(errno));
- close(fd);
- return -1;
- }
- if (listen(fd, LISTEN_BACKLOG) == -1) {
- log_errorf("could not listen on socket: %s", strerror(errno));
- close(fd);
- return -1;
- }
- struct group *videogrp = getgrnam("video");
- if (videogrp != NULL) {
- if (chown(path, 0, videogrp->gr_gid) == -1) {
- log_errorf("could not chown socket to video group: %s", strerror(errno));
- } else if (chmod(path, 0770) == -1) {
- log_errorf("could not chmod socket: %s", strerror(errno));
+ if (mask & EVENT_READABLE) {
+ int new_fd = accept(fd, NULL, NULL);
+ if (fd == -1) {
+ log_errorf("could not accept client connection: %s", strerror(errno));
+ return 0;
+ }
+
+ if (server_add_client(server, new_fd) == -1) {
+ return 0;
}
- } else {
- log_errorf("could not get video group: %s", strerror(errno));
- }
- if (poller_add_fd(&server->poller, fd, EVENT_READABLE, server_handle_connection, server) ==
- NULL) {
- log_errorf("could not add socket to poller: %s", strerror(errno));
- close(fd);
- return -1;
}
return 0;
}