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);
|
||||
|
||||
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
|
||||
|
|
|
@ -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',
|
||||
)
|
||||
|
|
125
seatd/seatd.c
125
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);
|
||||
|
||||
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};
|
||||
if (server_init(&server) == -1) {
|
||||
log_errorf("server_create failed: %s", strerror(errno));
|
||||
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) {
|
||||
log_errorf("server_listen failed: %s", strerror(errno));
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue