diff options
| -rw-r--r-- | include/server.h | 2 | ||||
| -rw-r--r-- | meson.build | 1 | ||||
| -rw-r--r-- | seatd/seatd.c | 125 | ||||
| -rw-r--r-- | seatd/server.c | 96 | 
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;  } | 
