mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-04-16 08:21:20 -04:00
client --auto-server: handle all socket paths
handle --server=<path>, as well as the default socket path lookup factorize code so that all client-side attempts (lookup of a listening socket) go through the same connect() call, and server socket path lookup follows the same sequence
This commit is contained in:
parent
f6011f8e06
commit
025153e2b5
1 changed files with 86 additions and 54 deletions
140
client.c
140
client.c
|
|
@ -139,7 +139,7 @@ send_string_list(int fd, const string_list_t *string_list)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
init_server_socket(const char *sock_path)
|
init_server_socket(const struct sockaddr_un *addr)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
|
@ -150,18 +150,15 @@ init_server_socket(const char *sock_path)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unlink(sock_path);
|
unlink(addr->sun_path);
|
||||||
|
|
||||||
struct sockaddr_un addr = {.sun_family = AF_UNIX};
|
if (bind(fd, (const struct sockaddr *)addr, sizeof(*addr)) < 0) {
|
||||||
strncpy(addr.sun_path, sock_path, sizeof(addr.sun_path) - 1);
|
LOG_ERRNO("%s: failed to bind", addr->sun_path);
|
||||||
|
|
||||||
if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
||||||
LOG_ERRNO("%s: failed to bind", addr.sun_path);
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listen(fd, 0) < 0) {
|
if (listen(fd, 0) < 0) {
|
||||||
LOG_ERRNO("%s: failed to listen", addr.sun_path);
|
LOG_ERRNO("%s: failed to listen", addr->sun_path);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,10 +169,84 @@ err:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
try_sockets(const char *server_socket_path, bool as_server)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (!as_server) {
|
||||||
|
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (fd < 0) {
|
||||||
|
LOG_ERRNO("failed to create socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum s_source {S_END, S_PARAM, S_XDG_DISPLAY, S_XDG_GENERIC, S_TMP};
|
||||||
|
enum s_source attempts[] = {S_PARAM, S_XDG_DISPLAY, S_XDG_GENERIC, S_TMP, S_END};
|
||||||
|
|
||||||
|
const char *xdg_runtime = getenv("XDG_RUNTIME_DIR");
|
||||||
|
struct sockaddr_un addr = {.sun_family = AF_UNIX};
|
||||||
|
|
||||||
|
for (int i = -1; attempts[++i] != S_END;) {
|
||||||
|
switch (attempts[i]) {
|
||||||
|
case S_PARAM:
|
||||||
|
if (server_socket_path == NULL)
|
||||||
|
continue;
|
||||||
|
/* If a path was provided, do not attempt further paths: */
|
||||||
|
attempts[i + 1] = S_END;
|
||||||
|
strncpy(addr.sun_path, server_socket_path, sizeof(addr.sun_path) - 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S_XDG_DISPLAY:
|
||||||
|
if (xdg_runtime == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const char *wayland_display = getenv("WAYLAND_DISPLAY");
|
||||||
|
if (wayland_display == NULL)
|
||||||
|
continue;
|
||||||
|
snprintf(addr.sun_path, sizeof(addr.sun_path),
|
||||||
|
"%s/foot-%s.sock", xdg_runtime, wayland_display);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S_XDG_GENERIC:
|
||||||
|
if (xdg_runtime == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
snprintf(addr.sun_path, sizeof(addr.sun_path),
|
||||||
|
"%s/foot.sock", xdg_runtime);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S_TMP:
|
||||||
|
strncpy(addr.sun_path, "/tmp/foot.sock", sizeof(addr.sun_path) - 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S_END:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
|
LOG_INFO("will now try %s", addr.sun_path);
|
||||||
|
|
||||||
|
if (as_server) {
|
||||||
|
return init_server_socket(&addr);
|
||||||
|
} else {
|
||||||
|
if (connect(fd, (const struct sockaddr *)&addr, sizeof(addr)) == 0)
|
||||||
|
return fd;
|
||||||
|
/* else attempt next socket path */
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_WARN("%s: failed to connect", addr.sun_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_ERRNO("failed to connect (is 'foot --server' running?)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
start_server(const char *server_socket_path)
|
start_server(const char *server_socket_path)
|
||||||
{
|
{
|
||||||
int socket_fd = init_server_socket(server_socket_path);
|
int socket_fd = try_sockets(server_socket_path, true);
|
||||||
if (socket_fd < 0)
|
if (socket_fd < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
|
@ -440,53 +511,14 @@ main(int argc, char *const *argv)
|
||||||
|
|
||||||
log_init(log_colorize, false, LOG_FACILITY_USER, log_level);
|
log_init(log_colorize, false, LOG_FACILITY_USER, log_level);
|
||||||
|
|
||||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
if ((fd = try_sockets(server_socket_path, false)) < 0) {
|
||||||
if (fd == -1) {
|
if (auto_server) {
|
||||||
LOG_ERRNO("failed to create socket");
|
LOG_INFO("will try to launch a server");
|
||||||
goto err;
|
if (start_server(server_socket_path) >= 0)
|
||||||
}
|
fd = try_sockets(server_socket_path, false);
|
||||||
|
|
||||||
struct sockaddr_un addr = {.sun_family = AF_UNIX};
|
|
||||||
bool connected = false;
|
|
||||||
int retries = 0;
|
|
||||||
|
|
||||||
retry:
|
|
||||||
if (server_socket_path != NULL) {
|
|
||||||
strncpy(addr.sun_path, server_socket_path, sizeof(addr.sun_path) - 1);
|
|
||||||
} else {
|
|
||||||
const char *xdg_runtime = getenv("XDG_RUNTIME_DIR");
|
|
||||||
if (xdg_runtime != NULL) {
|
|
||||||
const char *wayland_display = getenv("WAYLAND_DISPLAY");
|
|
||||||
if (wayland_display != NULL) {
|
|
||||||
snprintf(addr.sun_path, sizeof(addr.sun_path),
|
|
||||||
"%s/foot-%s.sock", xdg_runtime, wayland_display);
|
|
||||||
connected = (connect(fd, (const struct sockaddr *)&addr, sizeof(addr)) == 0);
|
|
||||||
}
|
|
||||||
if (!connected) {
|
|
||||||
LOG_WARN("%s: failed to connect, will now try %s/foot.sock",
|
|
||||||
addr.sun_path, xdg_runtime);
|
|
||||||
snprintf(addr.sun_path, sizeof(addr.sun_path),
|
|
||||||
"%s/foot.sock", xdg_runtime);
|
|
||||||
connected = (connect(fd, (const struct sockaddr *)&addr, sizeof(addr)) == 0);
|
|
||||||
}
|
|
||||||
if (!connected)
|
|
||||||
LOG_WARN("%s: failed to connect, will now try /tmp/foot.sock", addr.sun_path);
|
|
||||||
}
|
}
|
||||||
if (!connected)
|
if (fd < 0)
|
||||||
strncpy(addr.sun_path, "/tmp/foot.sock", sizeof(addr.sun_path) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!connected) {
|
|
||||||
if (connect(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
||||||
if (++retries < 2 && auto_server) {
|
|
||||||
if (start_server(server_socket_path) >= 0)
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
LOG_ERRNO("%s%sfailed to connect (is 'foot --server' running?)",
|
|
||||||
server_socket_path ? server_socket_path : "",
|
|
||||||
server_socket_path ? ": " : "");
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *cwd = custom_cwd;
|
const char *cwd = custom_cwd;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue