seatd: Add command-line arguments
This commit is contained in:
parent
420f973004
commit
a98e0c4ce9
4 changed files with 129 additions and 95 deletions
|
@ -20,7 +20,7 @@ void server_finish(struct server *server);
|
||||||
|
|
||||||
struct seat *server_get_seat(struct server *server, const char *seat_name);
|
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);
|
int server_add_client(struct server *server, int fd);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -27,6 +27,7 @@ add_project_arguments(
|
||||||
'-Wl,--exclude-libs=ALL',
|
'-Wl,--exclude-libs=ALL',
|
||||||
'-D_XOPEN_SOURCE=700',
|
'-D_XOPEN_SOURCE=700',
|
||||||
'-D__BSD_VISIBLE',
|
'-D__BSD_VISIBLE',
|
||||||
|
'-DSEATD_VERSION="@0@"'.format(meson.project_version()),
|
||||||
],
|
],
|
||||||
language: 'c',
|
language: 'c',
|
||||||
)
|
)
|
||||||
|
|
125
seatd/seatd.c
125
seatd/seatd.c
|
@ -1,5 +1,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <grp.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
#include <pwd.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -13,10 +15,44 @@
|
||||||
#include "poller.h"
|
#include "poller.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
#define LISTEN_BACKLOG 16
|
||||||
(void)argc;
|
|
||||||
(void)argv;
|
|
||||||
|
|
||||||
|
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");
|
char *loglevel = getenv("SEATD_LOGLEVEL");
|
||||||
enum log_level level = LOGLEVEL_ERROR;
|
enum log_level level = LOGLEVEL_ERROR;
|
||||||
if (loglevel != NULL) {
|
if (loglevel != NULL) {
|
||||||
|
@ -30,23 +66,82 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
log_init(level);
|
log_init(level);
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (socket_path == NULL) {
|
||||||
|
socket_path = "/run/seatd.sock";
|
||||||
|
struct stat st;
|
||||||
|
if (stat(socket_path, &st) == 0) {
|
||||||
|
log_info("removing leftover seatd socket");
|
||||||
|
unlink(socket_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct server server = {0};
|
struct server server = {0};
|
||||||
if (server_init(&server) == -1) {
|
if (server_init(&server) == -1) {
|
||||||
log_errorf("server_create failed: %s", strerror(errno));
|
log_errorf("server_create failed: %s", strerror(errno));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
char *path = getenv("SEATD_SOCK");
|
|
||||||
if (path == NULL) {
|
|
||||||
path = "/run/seatd.sock";
|
|
||||||
struct stat st;
|
|
||||||
if (stat(path, &st) == 0) {
|
|
||||||
log_info("removing leftover seatd socket");
|
|
||||||
unlink(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server_listen(&server, path) == -1) {
|
int socket_fd = open_socket(socket_path, uid, gid);
|
||||||
log_errorf("server_listen failed: %s", strerror(errno));
|
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);
|
server_finish(&server);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -61,6 +156,6 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
server_finish(&server);
|
server_finish(&server);
|
||||||
unlink(path);
|
unlink(socket_path);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <grp.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -20,8 +19,6 @@
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
|
|
||||||
#define LISTEN_BACKLOG 16
|
|
||||||
|
|
||||||
static int server_handle_vt_acq(int signal, void *data);
|
static int server_handle_vt_acq(int signal, void *data);
|
||||||
static int server_handle_vt_rel(int signal, void *data);
|
static int server_handle_vt_rel(int signal, void *data);
|
||||||
static int server_handle_kill(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;
|
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) {
|
int server_add_client(struct server *server, int fd) {
|
||||||
if (set_nonblock(fd) != 0) {
|
if (set_nonblock(fd) != 0) {
|
||||||
close(fd);
|
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));
|
log_errorf("could not add client socket to poller: %s", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
log_infof("new client connected (pid: %d, uid: %d, gid: %d)", client->pid, client->uid,
|
||||||
|
client->gid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int server_listen(struct server *server, const char *path) {
|
int server_handle_connection(int fd, uint32_t mask, void *data) {
|
||||||
union {
|
struct server *server = data;
|
||||||
struct sockaddr_un unix;
|
if (mask & (EVENT_ERROR | EVENT_HANGUP)) {
|
||||||
struct sockaddr generic;
|
shutdown(fd, SHUT_RDWR);
|
||||||
} addr = {{0}};
|
server->running = false;
|
||||||
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
log_errorf("server socket recieved an error: %s", strerror(errno));
|
||||||
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));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr.unix.sun_family = AF_UNIX;
|
if (mask & EVENT_READABLE) {
|
||||||
strncpy(addr.unix.sun_path, path, sizeof addr.unix.sun_path - 1);
|
int new_fd = accept(fd, NULL, NULL);
|
||||||
socklen_t size = offsetof(struct sockaddr_un, sun_path) + strlen(addr.unix.sun_path);
|
if (fd == -1) {
|
||||||
if (bind(fd, &addr.generic, size) == -1) {
|
log_errorf("could not accept client connection: %s", strerror(errno));
|
||||||
log_errorf("could not bind socket: %s", strerror(errno));
|
return 0;
|
||||||
close(fd);
|
}
|
||||||
return -1;
|
|
||||||
}
|
if (server_add_client(server, new_fd) == -1) {
|
||||||
if (listen(fd, LISTEN_BACKLOG) == -1) {
|
return 0;
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
} 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue