mirror of
https://github.com/swaywm/sway.git
synced 2026-04-22 06:46:27 -04:00
Add sandbox_socket command
This command can be used to create a new listening socket (suitable for use in WAYLAND_DISPLAY) whose clients will all have a specific label. Co-authored-by: Mykola Orliuk <virkony@gmail.com>
This commit is contained in:
parent
b7f62c9d7a
commit
27c67cc2b3
4 changed files with 151 additions and 0 deletions
|
|
@ -307,4 +307,6 @@ sway_cmd cmd_ipc_cmd;
|
||||||
sway_cmd cmd_ipc_events;
|
sway_cmd cmd_ipc_events;
|
||||||
sway_cmd cmd_ipc_event_cmd;
|
sway_cmd cmd_ipc_event_cmd;
|
||||||
|
|
||||||
|
sway_cmd cmd_sandbox_socket;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ static const struct cmd_handler handlers[] = {
|
||||||
{ "no_focus", cmd_no_focus },
|
{ "no_focus", cmd_no_focus },
|
||||||
{ "output", cmd_output },
|
{ "output", cmd_output },
|
||||||
{ "popup_during_fullscreen", cmd_popup_during_fullscreen },
|
{ "popup_during_fullscreen", cmd_popup_during_fullscreen },
|
||||||
|
{ "sandbox_socket", cmd_sandbox_socket },
|
||||||
{ "seat", cmd_seat },
|
{ "seat", cmd_seat },
|
||||||
{ "set", cmd_set },
|
{ "set", cmd_set },
|
||||||
{ "show_marks", cmd_show_marks },
|
{ "show_marks", cmd_show_marks },
|
||||||
|
|
|
||||||
147
sway/commands/sandbox_socket.c
Normal file
147
sway/commands/sandbox_socket.c
Normal file
|
|
@ -0,0 +1,147 @@
|
||||||
|
#define _XOPEN_SOURCE 700 // for strdup
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
#include "sway/client_label.h"
|
||||||
|
#include "sway/commands.h"
|
||||||
|
#include "sway/tree/container.h"
|
||||||
|
#include "sway/tree/view.h"
|
||||||
|
#include "list.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
struct sandbox_socket {
|
||||||
|
char* path;
|
||||||
|
struct wl_event_source *src;
|
||||||
|
int fd;
|
||||||
|
char* label;
|
||||||
|
};
|
||||||
|
|
||||||
|
static list_t *sandbox_sockets;
|
||||||
|
|
||||||
|
static int fd_accept(int srv_fd, uint32_t mask, void *data) {
|
||||||
|
struct sandbox_socket *sock = data;
|
||||||
|
|
||||||
|
int cli_fd = accept(srv_fd, NULL, NULL);
|
||||||
|
if (cli_fd < 0) {
|
||||||
|
if (errno == EINTR || errno == ECONNABORTED || errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
int i;
|
||||||
|
wl_event_source_remove(sock->src);
|
||||||
|
unlink(sock->path);
|
||||||
|
free(sock->path);
|
||||||
|
close(srv_fd);
|
||||||
|
for(i = 0; i < sandbox_sockets->length; ++i) {
|
||||||
|
if (sock != sandbox_sockets->items[i])
|
||||||
|
continue;
|
||||||
|
list_del(sandbox_sockets, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(sock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sway_set_cloexec(cli_fd, true);
|
||||||
|
struct wl_client* client = wl_client_create(server.wl_display, cli_fd);
|
||||||
|
if (client) {
|
||||||
|
wl_client_label_set(client, strdup(sock->label));
|
||||||
|
} else {
|
||||||
|
close(cli_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cmd_results *cmd_sandbox_socket(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "sandbox_socket", EXPECTED_AT_LEAST, 2))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sandbox_sockets)
|
||||||
|
sandbox_sockets = create_list();
|
||||||
|
|
||||||
|
char* op = argv[0];
|
||||||
|
|
||||||
|
if (strcmp(op, "create") == 0) {
|
||||||
|
struct sockaddr_un name = {};
|
||||||
|
char* label = NULL;
|
||||||
|
int i = 1;
|
||||||
|
while (i < argc) {
|
||||||
|
if (strcmp(argv[i], "--label") == 0) {
|
||||||
|
if (i + 1 >= argc)
|
||||||
|
return cmd_results_new(CMD_INVALID, "--label requires an argument");
|
||||||
|
label = argv[i + 1];
|
||||||
|
i += 2;
|
||||||
|
} else if (strcmp(argv[i], "--") == 0) { // after this any argument should be treated as positional
|
||||||
|
++i;
|
||||||
|
break;
|
||||||
|
} else if (strncmp(argv[i], "-", 1) == 0) {
|
||||||
|
return cmd_results_new(CMD_INVALID, "Unknown option to sandbox_socket");
|
||||||
|
} else {
|
||||||
|
break; // end of options, now only positional arguments
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((error = checkarg(argc, "sandbox_socket", EXPECTED_EQUAL_TO, i + 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
char *path = argv[i];
|
||||||
|
size_t path_len = strlen(path) + 1;
|
||||||
|
|
||||||
|
if (path_len > sizeof(name.sun_path)) {
|
||||||
|
return cmd_results_new(CMD_INVALID, "Invalid socket path: %s", path);
|
||||||
|
}
|
||||||
|
unlink(path);
|
||||||
|
|
||||||
|
name.sun_family = AF_UNIX;
|
||||||
|
memcpy(name.sun_path, path, path_len);
|
||||||
|
size_t name_len = offsetof(struct sockaddr_un, sun_path) + path_len;
|
||||||
|
|
||||||
|
int srv_fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (srv_fd < 0 ||
|
||||||
|
!sway_set_cloexec(srv_fd, true) ||
|
||||||
|
fcntl(srv_fd, F_SETFL, O_NONBLOCK) != 0 ||
|
||||||
|
bind(srv_fd, (struct sockaddr *)&name, name_len) != 0 ||
|
||||||
|
listen(srv_fd, 5) != 0) {
|
||||||
|
close(srv_fd);
|
||||||
|
return cmd_results_new(CMD_FAILURE, "Error creating socket: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sandbox_socket *sock = calloc(1, sizeof(*sock));
|
||||||
|
sock->path = strdup(path);
|
||||||
|
sock->src = wl_event_loop_add_fd(server.wl_event_loop, srv_fd, WL_EVENT_READABLE, fd_accept, sock);
|
||||||
|
sock->fd = srv_fd;
|
||||||
|
if (label)
|
||||||
|
sock->label = strdup(label);
|
||||||
|
|
||||||
|
list_add(sandbox_sockets, sock);
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||||
|
} else if (strcmp(op, "delete") == 0) {
|
||||||
|
char* path = argv[1];
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < sandbox_sockets->length; ++i) {
|
||||||
|
struct sandbox_socket *sock = sandbox_sockets->items[i];
|
||||||
|
if (strcmp(sock->path, path) == 0) {
|
||||||
|
wl_event_source_remove(sock->src);
|
||||||
|
unlink(path);
|
||||||
|
close(sock->fd);
|
||||||
|
free(sock->path);
|
||||||
|
free(sock->label);
|
||||||
|
free(sock);
|
||||||
|
list_del(sandbox_sockets, i);
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cmd_results_new(CMD_FAILURE, "sandbox_socket: %s not found", path);
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, "Unknown command sandbox_socket %s", op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -86,6 +86,7 @@ sway_sources = files(
|
||||||
'commands/reload.c',
|
'commands/reload.c',
|
||||||
'commands/rename.c',
|
'commands/rename.c',
|
||||||
'commands/resize.c',
|
'commands/resize.c',
|
||||||
|
'commands/sandbox_socket.c',
|
||||||
'commands/scratchpad.c',
|
'commands/scratchpad.c',
|
||||||
'commands/seat.c',
|
'commands/seat.c',
|
||||||
'commands/seat/attach.c',
|
'commands/seat/attach.c',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue