2019-11-01 20:39:34 +01:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <getopt.h>
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
|
|
#include <sys/socket.h>
|
2021-01-19 14:34:30 +00:00
|
|
|
#include <sys/un.h>
|
2021-02-13 10:48:58 +01:00
|
|
|
#include <sys/stat.h>
|
2019-11-01 20:39:34 +01:00
|
|
|
|
2021-06-23 14:22:18 +02:00
|
|
|
#include <tllist.h>
|
|
|
|
|
|
2019-11-01 20:39:34 +01:00
|
|
|
#define LOG_MODULE "foot-client"
|
2019-11-02 00:01:08 +01:00
|
|
|
#define LOG_ENABLE_DBG 0
|
2019-11-01 20:39:34 +01:00
|
|
|
#include "log.h"
|
2020-11-21 20:21:18 +01:00
|
|
|
#include "client-protocol.h"
|
2021-01-15 20:39:45 +00:00
|
|
|
#include "debug.h"
|
2020-12-04 18:57:49 +01:00
|
|
|
#include "foot-features.h"
|
2021-02-11 11:08:18 +00:00
|
|
|
#include "macros.h"
|
2021-02-09 21:07:30 +01:00
|
|
|
#include "util.h"
|
2019-11-01 20:39:34 +01:00
|
|
|
#include "version.h"
|
2020-08-08 20:34:30 +01:00
|
|
|
#include "xmalloc.h"
|
2019-11-01 20:39:34 +01:00
|
|
|
|
2022-04-11 13:24:27 +02:00
|
|
|
extern char **environ;
|
|
|
|
|
|
2022-04-11 12:19:40 +02:00
|
|
|
struct string {
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
size_t len;
|
|
|
|
|
char *str;
|
|
|
|
|
};
|
2022-04-11 12:19:40 +02:00
|
|
|
typedef tll(struct string) string_list_t;
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
|
2019-11-01 20:39:34 +01:00
|
|
|
static volatile sig_atomic_t aborted = 0;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
sig_handler(int signo)
|
|
|
|
|
{
|
|
|
|
|
aborted = 1;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-29 21:42:57 +02:00
|
|
|
static ssize_t
|
|
|
|
|
sendall(int sock, const void *_buf, size_t len)
|
|
|
|
|
{
|
|
|
|
|
const uint8_t *buf = _buf;
|
|
|
|
|
size_t left = len;
|
|
|
|
|
|
|
|
|
|
while (left > 0) {
|
2021-10-30 18:07:06 +02:00
|
|
|
ssize_t r = send(sock, buf, left, MSG_NOSIGNAL);
|
2021-10-29 21:42:57 +02:00
|
|
|
if (r < 0) {
|
|
|
|
|
if (errno == EINTR)
|
|
|
|
|
continue;
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buf += r;
|
|
|
|
|
left -= r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-04 18:57:49 +01:00
|
|
|
static const char *
|
|
|
|
|
version_and_features(void)
|
|
|
|
|
{
|
|
|
|
|
static char buf[256];
|
2023-06-26 18:00:01 +02:00
|
|
|
snprintf(buf, sizeof(buf),
|
2023-06-29 16:12:54 +02:00
|
|
|
"version: %s %cpgo %cime %cgraphemes %cfractional-scaling %ccursor-shape %cassertions",
|
2021-03-26 20:30:13 +01:00
|
|
|
FOOT_VERSION,
|
2021-06-24 17:50:44 +02:00
|
|
|
feature_pgo() ? '+' : '-',
|
2021-03-26 20:30:13 +01:00
|
|
|
feature_ime() ? '+' : '-',
|
2021-10-23 15:40:54 +02:00
|
|
|
feature_graphemes() ? '+' : '-',
|
2023-06-26 18:00:01 +02:00
|
|
|
feature_fractional_scaling() ? '+' : ':',
|
2023-06-29 16:12:54 +02:00
|
|
|
feature_cursor_shape() ? '+' : '-',
|
2021-10-23 15:40:54 +02:00
|
|
|
feature_assertions() ? '+' : '-');
|
2020-12-04 18:57:49 +01:00
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-01 20:39:34 +01:00
|
|
|
static void
|
|
|
|
|
print_usage(const char *prog_name)
|
|
|
|
|
{
|
2021-09-18 19:44:04 +01:00
|
|
|
static const char options[] =
|
|
|
|
|
"\nOptions:\n"
|
|
|
|
|
" -t,--term=TERM value to set the environment variable TERM to (" FOOT_DEFAULT_TERM ")\n"
|
|
|
|
|
" -T,--title=TITLE initial window title (foot)\n"
|
|
|
|
|
" -a,--app-id=ID window application ID (foot)\n"
|
|
|
|
|
" -w,--window-size-pixels=WIDTHxHEIGHT initial width and height, in pixels\n"
|
|
|
|
|
" -W,--window-size-chars=WIDTHxHEIGHT initial width and height, in characters\n"
|
|
|
|
|
" -m,--maximized start in maximized mode\n"
|
|
|
|
|
" -F,--fullscreen start in fullscreen mode\n"
|
|
|
|
|
" -L,--login-shell start shell as a login shell\n"
|
|
|
|
|
" -D,--working-directory=DIR directory to start in (CWD)\n"
|
|
|
|
|
" -s,--server-socket=PATH path to the server UNIX domain socket (default=$XDG_RUNTIME_DIR/foot-$WAYLAND_DISPLAY.sock)\n"
|
|
|
|
|
" -H,--hold remain open after child process exits\n"
|
|
|
|
|
" -N,--no-wait detach the client process from the running terminal, exiting immediately\n"
|
|
|
|
|
" -o,--override=[section.]key=value override configuration option\n"
|
2022-04-11 12:19:40 +02:00
|
|
|
" -E, --client-environment exec shell using footclient's environment, instead of the server's\n"
|
change default log level to WARNING
The default foot output looks like this, in Debian testing "bookworm"
at the time of writing:
anarcat@angela:pubpaste$ foot true
info: main.c:421: version: 1.13.1 +pgo +ime +graphemes -assertions
info: main.c:428: arch: Linux x86_64/64-bit
info: main.c:440: locale: fr_CA.UTF-8
info: config.c:3003: loading configuration from /home/anarcat/.config/foot/foot.ini
info: fcft.c:338: fcft: 3.1.5 +graphemes -runs +svg(nanosvg) -assertions
info: fcft.c:377: fontconfig: 2.13.1, freetype: 2.12.1, harfbuzz: 5.2.0
info: fcft.c:838: /home/anarcat/.local/share/fonts/Fira-4.202/otf/FiraMono-Regular.otf: size=8.00pt/8px, dpi=75.00
info: wayland.c:1353: eDP-1: 2256x1504+0x0@60Hz 0x095F 13.32" scale=2 PPI=205x214 (physical) PPI=136x143 (logical), DPI=271.31
info: wayland.c:1509: requesting SSD decorations
info: fcft.c:838: /home/anarcat/.local/share/fonts/Fira-4.202/otf/FiraMono-Bold.otf: size=24.00pt/32px, dpi=96.00
info: fcft.c:838: /home/anarcat/.local/share/fonts/Fira-4.202/otf/FiraMono-Regular.otf: size=24.00pt/32px, dpi=96.00
info: fcft.c:838: /home/anarcat/.local/share/fonts/Fira-4.202/otf/FiraMono-Bold.otf: size=24.00pt/32px, dpi=96.00
info: fcft.c:838: /home/anarcat/.local/share/fonts/Fira-4.202/otf/FiraMono-Regular.otf: size=24.00pt/32px, dpi=96.00
info: terminal.c:700: cell width=19, height=39
info: terminal.c:588: using 16 rendering threads
info: wayland.c:859: using SSD decorations
info: main.c:680: goodbye
anarcat@angela:pubpaste$
That's 17 lines of output that are *mostly* useless for most use
cases. I might understand having this output during the project's
startup, when it's helpful for diagnostics, but now Foot just mostly
works everywhere, and I've never had a use for any of that stuff in
the (arguably short) time I've been using Foot so far.
And if I do, there's the `--log-level` commandline option to tweak
this. At first, I looked at tweaking the log level through the config
file. But as explained in this issue:
https://codeberg.org/dnkl/foot/issues/1142
... there's a chicken and egg problem there that makes it hard to
implement and possibly confusing for users as well.
There's also the possibility for users to change the shortcut with
which they start foot, for example a `.desktop` file so that menu
systems that support those start foot properly. But that only works in
that environment, and not through the so many things that will just
call `foot` and hope it will do the right thing.
In my case, I have `foot` hardcoded in a lot of places now, between
sway and waybar, and this is only going to grow. Others have suggested
adding the flag to a $TERMINAL global variable, but that won't help
.desktop users.
So, instead of playing whack-a-mole with the log levels, just make it
so that, by default, foot is silent. This is actually one of the
[basics of UNIX philosophy][1]:
> Rule of Silence: When a program has nothing surprising to say, it
> should say nothing.
And yes, I am aware I am severely violating that principle by writing
a way too long commit log for a one-line patch, but there you go, I
figured it was good to document the why of this properly.
[1]: https://web.archive.org/web/20031102053334/http://www.faqs.org/docs/artu/ch01s06.html
2022-11-18 11:07:16 -05:00
|
|
|
" -d,--log-level={info|warning|error|none} log level (warning)\n"
|
2021-09-18 19:44:04 +01:00
|
|
|
" -l,--log-colorize=[{never|always|auto}] enable/disable colorization of log output on stderr\n"
|
2021-09-18 23:40:40 +01:00
|
|
|
" -v,--version show the version number and quit\n"
|
|
|
|
|
" -e ignored (for compatibility with xterm -e)\n";
|
2021-09-18 19:44:04 +01:00
|
|
|
|
2021-03-12 21:53:11 +01:00
|
|
|
printf("Usage: %s [OPTIONS...]\n", prog_name);
|
|
|
|
|
printf("Usage: %s [OPTIONS...] command [ARGS...]\n", prog_name);
|
2021-09-18 19:44:04 +01:00
|
|
|
puts(options);
|
2019-11-01 20:39:34 +01:00
|
|
|
}
|
|
|
|
|
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
static bool NOINLINE
|
2022-04-11 12:19:40 +02:00
|
|
|
push_string(string_list_t *string_list, const char *s, uint64_t *total_len)
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
{
|
|
|
|
|
size_t len = strlen(s) + 1;
|
2022-04-11 12:19:40 +02:00
|
|
|
if (len >= 1 << (8 * sizeof(uint16_t))) {
|
|
|
|
|
LOG_ERR("string length overflow");
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-11 12:19:40 +02:00
|
|
|
struct string o = {len, xstrdup(s)};
|
|
|
|
|
tll_push_back(*string_list, o);
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
*total_len += sizeof(struct client_string) + o.len;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-11 12:19:40 +02:00
|
|
|
static void
|
|
|
|
|
free_string_list(string_list_t *string_list)
|
|
|
|
|
{
|
|
|
|
|
tll_foreach(*string_list, it) {
|
|
|
|
|
free(it->item.str);
|
|
|
|
|
tll_remove(*string_list, it);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-11 12:38:36 +02:00
|
|
|
static bool
|
|
|
|
|
send_string_list(int fd, const string_list_t *string_list)
|
|
|
|
|
{
|
|
|
|
|
tll_foreach(*string_list, it) {
|
|
|
|
|
const struct client_string s = {it->item.len};
|
|
|
|
|
if (sendall(fd, &s, sizeof(s)) < 0 ||
|
|
|
|
|
sendall(fd, it->item.str, s.len) < 0)
|
|
|
|
|
{
|
|
|
|
|
LOG_ERRNO("failed to send setup packet to server");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-01 20:39:34 +01:00
|
|
|
int
|
|
|
|
|
main(int argc, char *const *argv)
|
|
|
|
|
{
|
2021-04-30 22:47:16 +02:00
|
|
|
/* Custom exit code, to enable users to differentiate between foot
|
|
|
|
|
* itself failing, and the client application failiing */
|
2021-05-01 10:46:40 +02:00
|
|
|
static const int foot_exit_failure = -36;
|
2021-04-30 22:47:16 +02:00
|
|
|
int ret = foot_exit_failure;
|
2019-11-01 20:39:34 +01:00
|
|
|
|
2022-01-01 21:11:31 +01:00
|
|
|
const char *const prog_name = argc > 0 ? argv[0] : "<nullptr>";
|
2019-11-01 20:39:34 +01:00
|
|
|
|
2019-11-01 20:50:00 +01:00
|
|
|
static const struct option longopts[] = {
|
2020-11-22 00:12:23 +00:00
|
|
|
{"term", required_argument, NULL, 't'},
|
|
|
|
|
{"title", required_argument, NULL, 'T'},
|
|
|
|
|
{"app-id", required_argument, NULL, 'a'},
|
|
|
|
|
{"window-size-pixels", required_argument, NULL, 'w'},
|
|
|
|
|
{"window-size-chars", required_argument, NULL, 'W'},
|
|
|
|
|
{"maximized", no_argument, NULL, 'm'},
|
|
|
|
|
{"fullscreen", no_argument, NULL, 'F'},
|
|
|
|
|
{"login-shell", no_argument, NULL, 'L'},
|
2021-02-12 09:39:44 +01:00
|
|
|
{"working-directory", required_argument, NULL, 'D'},
|
2020-11-22 00:12:23 +00:00
|
|
|
{"server-socket", required_argument, NULL, 's'},
|
|
|
|
|
{"hold", no_argument, NULL, 'H'},
|
2021-03-12 20:46:55 -03:00
|
|
|
{"no-wait", no_argument, NULL, 'N'},
|
2021-06-23 14:34:36 +02:00
|
|
|
{"override", required_argument, NULL, 'o'},
|
2022-04-11 12:19:40 +02:00
|
|
|
{"client-environment", no_argument, NULL, 'E'},
|
2021-02-09 21:07:30 +01:00
|
|
|
{"log-level", required_argument, NULL, 'd'},
|
2020-11-22 00:12:23 +00:00
|
|
|
{"log-colorize", optional_argument, NULL, 'l'},
|
|
|
|
|
{"version", no_argument, NULL, 'v'},
|
|
|
|
|
{"help", no_argument, NULL, 'h'},
|
|
|
|
|
{NULL, no_argument, NULL, 0},
|
2019-11-01 20:50:00 +01:00
|
|
|
};
|
|
|
|
|
|
2021-02-12 09:39:44 +01:00
|
|
|
const char *custom_cwd = NULL;
|
2019-12-14 13:00:48 +01:00
|
|
|
const char *server_socket_path = NULL;
|
change default log level to WARNING
The default foot output looks like this, in Debian testing "bookworm"
at the time of writing:
anarcat@angela:pubpaste$ foot true
info: main.c:421: version: 1.13.1 +pgo +ime +graphemes -assertions
info: main.c:428: arch: Linux x86_64/64-bit
info: main.c:440: locale: fr_CA.UTF-8
info: config.c:3003: loading configuration from /home/anarcat/.config/foot/foot.ini
info: fcft.c:338: fcft: 3.1.5 +graphemes -runs +svg(nanosvg) -assertions
info: fcft.c:377: fontconfig: 2.13.1, freetype: 2.12.1, harfbuzz: 5.2.0
info: fcft.c:838: /home/anarcat/.local/share/fonts/Fira-4.202/otf/FiraMono-Regular.otf: size=8.00pt/8px, dpi=75.00
info: wayland.c:1353: eDP-1: 2256x1504+0x0@60Hz 0x095F 13.32" scale=2 PPI=205x214 (physical) PPI=136x143 (logical), DPI=271.31
info: wayland.c:1509: requesting SSD decorations
info: fcft.c:838: /home/anarcat/.local/share/fonts/Fira-4.202/otf/FiraMono-Bold.otf: size=24.00pt/32px, dpi=96.00
info: fcft.c:838: /home/anarcat/.local/share/fonts/Fira-4.202/otf/FiraMono-Regular.otf: size=24.00pt/32px, dpi=96.00
info: fcft.c:838: /home/anarcat/.local/share/fonts/Fira-4.202/otf/FiraMono-Bold.otf: size=24.00pt/32px, dpi=96.00
info: fcft.c:838: /home/anarcat/.local/share/fonts/Fira-4.202/otf/FiraMono-Regular.otf: size=24.00pt/32px, dpi=96.00
info: terminal.c:700: cell width=19, height=39
info: terminal.c:588: using 16 rendering threads
info: wayland.c:859: using SSD decorations
info: main.c:680: goodbye
anarcat@angela:pubpaste$
That's 17 lines of output that are *mostly* useless for most use
cases. I might understand having this output during the project's
startup, when it's helpful for diagnostics, but now Foot just mostly
works everywhere, and I've never had a use for any of that stuff in
the (arguably short) time I've been using Foot so far.
And if I do, there's the `--log-level` commandline option to tweak
this. At first, I looked at tweaking the log level through the config
file. But as explained in this issue:
https://codeberg.org/dnkl/foot/issues/1142
... there's a chicken and egg problem there that makes it hard to
implement and possibly confusing for users as well.
There's also the possibility for users to change the shortcut with
which they start foot, for example a `.desktop` file so that menu
systems that support those start foot properly. But that only works in
that environment, and not through the so many things that will just
call `foot` and hope it will do the right thing.
In my case, I have `foot` hardcoded in a lot of places now, between
sway and waybar, and this is only going to grow. Others have suggested
adding the flag to a $TERMINAL global variable, but that won't help
.desktop users.
So, instead of playing whack-a-mole with the log levels, just make it
so that, by default, foot is silent. This is actually one of the
[basics of UNIX philosophy][1]:
> Rule of Silence: When a program has nothing surprising to say, it
> should say nothing.
And yes, I am aware I am severely violating that principle by writing
a way too long commit log for a one-line patch, but there you go, I
figured it was good to document the why of this properly.
[1]: https://web.archive.org/web/20031102053334/http://www.faqs.org/docs/artu/ch01s06.html
2022-11-18 11:07:16 -05:00
|
|
|
enum log_class log_level = LOG_CLASS_WARNING;
|
2020-02-05 19:54:16 +01:00
|
|
|
enum log_colorize log_colorize = LOG_COLORIZE_AUTO;
|
2020-05-26 20:11:38 +02:00
|
|
|
bool hold = false;
|
2022-04-11 12:19:40 +02:00
|
|
|
bool client_environment = false;
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
|
|
|
|
|
/* Used to format overrides */
|
2021-03-12 20:46:55 -03:00
|
|
|
bool no_wait = false;
|
2019-11-01 21:10:47 +01:00
|
|
|
|
2021-10-28 17:51:44 -07:00
|
|
|
/* For XDG activation */
|
|
|
|
|
const char *token = getenv("XDG_ACTIVATION_TOKEN");
|
|
|
|
|
bool xdga_token = token != NULL;
|
|
|
|
|
size_t token_len = xdga_token ? strlen(token) + 1 : 0;
|
|
|
|
|
|
2021-06-23 14:22:18 +02:00
|
|
|
char buf[1024];
|
|
|
|
|
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
/* Total packet length, not (yet) including overrides or argv[] */
|
|
|
|
|
uint64_t total_len = 0;
|
|
|
|
|
|
2021-06-23 14:22:18 +02:00
|
|
|
/* malloc:ed and needs to be in scope of all goto's */
|
2021-06-23 15:32:03 +02:00
|
|
|
int fd = -1;
|
2021-06-23 14:22:18 +02:00
|
|
|
char *_cwd = NULL;
|
|
|
|
|
struct client_string *cargv = NULL;
|
2022-04-11 12:19:40 +02:00
|
|
|
string_list_t overrides = tll_init();
|
|
|
|
|
string_list_t envp = tll_init();
|
2021-06-23 14:22:18 +02:00
|
|
|
|
2019-11-01 20:39:34 +01:00
|
|
|
while (true) {
|
2022-04-11 12:19:40 +02:00
|
|
|
int c = getopt_long(argc, argv, "+t:T:a:w:W:mFLD:s:HNo:Ed:l::veh", longopts, NULL);
|
2019-11-01 20:39:34 +01:00
|
|
|
if (c == -1)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
switch (c) {
|
2019-11-01 21:10:47 +01:00
|
|
|
case 't':
|
2021-06-23 14:22:18 +02:00
|
|
|
snprintf(buf, sizeof(buf), "term=%s", optarg);
|
2022-04-11 12:19:40 +02:00
|
|
|
if (!push_string(&overrides, buf, &total_len))
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
goto err;
|
2019-12-14 13:07:33 +01:00
|
|
|
break;
|
2019-12-14 13:00:48 +01:00
|
|
|
|
2020-04-01 19:59:47 +02:00
|
|
|
case 'T':
|
2021-06-23 14:22:18 +02:00
|
|
|
snprintf(buf, sizeof(buf), "title=%s", optarg);
|
2022-04-11 12:19:40 +02:00
|
|
|
if (!push_string(&overrides, buf, &total_len))
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
goto err;
|
2020-04-01 19:59:47 +02:00
|
|
|
break;
|
|
|
|
|
|
2020-04-01 18:40:51 +02:00
|
|
|
case 'a':
|
2021-06-23 14:22:18 +02:00
|
|
|
snprintf(buf, sizeof(buf), "app-id=%s", optarg);
|
2022-04-11 12:19:40 +02:00
|
|
|
if (!push_string(&overrides, buf, &total_len))
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
goto err;
|
2020-04-01 18:40:51 +02:00
|
|
|
break;
|
|
|
|
|
|
2020-02-20 18:34:51 +01:00
|
|
|
case 'L':
|
2022-04-11 12:19:40 +02:00
|
|
|
if (!push_string(&overrides, "login-shell=yes", &total_len))
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
goto err;
|
2020-02-20 18:34:51 +01:00
|
|
|
break;
|
|
|
|
|
|
2021-02-13 10:48:58 +01:00
|
|
|
case 'D': {
|
|
|
|
|
struct stat st;
|
|
|
|
|
if (stat(optarg, &st) < 0 || !(st.st_mode & S_IFDIR)) {
|
|
|
|
|
fprintf(stderr, "error: %s: not a directory\n", optarg);
|
2021-06-23 14:22:18 +02:00
|
|
|
goto err;
|
2021-02-13 10:48:58 +01:00
|
|
|
}
|
2021-02-12 09:39:44 +01:00
|
|
|
custom_cwd = optarg;
|
|
|
|
|
break;
|
2021-02-13 10:48:58 +01:00
|
|
|
}
|
2021-02-12 09:39:44 +01:00
|
|
|
|
2021-06-23 14:22:18 +02:00
|
|
|
case 'w': {
|
|
|
|
|
unsigned width, height;
|
2020-11-22 00:12:23 +00:00
|
|
|
if (sscanf(optarg, "%ux%u", &width, &height) != 2 || width == 0 || height == 0) {
|
|
|
|
|
fprintf(stderr, "error: invalid window-size-pixels: %s\n", optarg);
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
goto err;
|
2020-11-22 00:12:23 +00:00
|
|
|
}
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
|
2021-06-23 14:22:18 +02:00
|
|
|
snprintf(buf, sizeof(buf), "initial-window-size-pixels=%ux%u", width, height);
|
2022-04-11 12:19:40 +02:00
|
|
|
if (!push_string(&overrides, buf, &total_len))
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
goto err;
|
2020-11-22 00:12:23 +00:00
|
|
|
break;
|
2021-06-23 14:22:18 +02:00
|
|
|
}
|
2020-11-22 00:12:23 +00:00
|
|
|
|
2021-06-23 14:22:18 +02:00
|
|
|
case 'W': {
|
|
|
|
|
unsigned width, height;
|
2020-11-22 00:12:23 +00:00
|
|
|
if (sscanf(optarg, "%ux%u", &width, &height) != 2 || width == 0 || height == 0) {
|
|
|
|
|
fprintf(stderr, "error: invalid window-size-chars: %s\n", optarg);
|
2021-06-23 14:22:18 +02:00
|
|
|
goto err;
|
2020-11-22 00:12:23 +00:00
|
|
|
}
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
|
2021-06-23 14:22:18 +02:00
|
|
|
snprintf(buf, sizeof(buf), "initial-window-size-chars=%ux%u", width, height);
|
2022-04-11 12:19:40 +02:00
|
|
|
if (!push_string(&overrides, buf, &total_len))
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
goto err;
|
2020-11-22 00:12:23 +00:00
|
|
|
break;
|
2021-06-23 14:22:18 +02:00
|
|
|
}
|
2020-11-22 00:12:23 +00:00
|
|
|
|
2020-11-22 16:40:15 +00:00
|
|
|
case 'm':
|
2022-04-11 12:19:40 +02:00
|
|
|
if (!push_string(&overrides, "initial-window-mode=maximized", &total_len))
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
goto err;
|
2020-03-27 21:14:49 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'F':
|
2022-04-11 12:19:40 +02:00
|
|
|
if (!push_string(&overrides, "initial-window-mode=fullscreen", &total_len))
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
goto err;
|
2020-03-27 21:14:49 +01:00
|
|
|
break;
|
|
|
|
|
|
2019-12-14 13:00:48 +01:00
|
|
|
case 's':
|
|
|
|
|
server_socket_path = optarg;
|
2019-11-01 21:10:47 +01:00
|
|
|
break;
|
|
|
|
|
|
2020-05-26 20:11:38 +02:00
|
|
|
case 'H':
|
|
|
|
|
hold = true;
|
|
|
|
|
break;
|
|
|
|
|
|
2021-03-12 20:46:55 -03:00
|
|
|
case 'N':
|
|
|
|
|
no_wait = true;
|
|
|
|
|
break;
|
|
|
|
|
|
2021-06-23 14:34:36 +02:00
|
|
|
case 'o':
|
2022-04-11 12:19:40 +02:00
|
|
|
if (!push_string(&overrides, optarg, &total_len))
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
goto err;
|
2021-06-23 14:34:36 +02:00
|
|
|
break;
|
|
|
|
|
|
2022-04-11 12:19:40 +02:00
|
|
|
case 'E':
|
|
|
|
|
client_environment = true;
|
|
|
|
|
break;
|
|
|
|
|
|
2021-02-09 21:07:30 +01:00
|
|
|
case 'd': {
|
2021-02-11 11:08:18 +00:00
|
|
|
int lvl = log_level_from_string(optarg);
|
|
|
|
|
if (unlikely(lvl < 0)) {
|
2021-02-09 21:07:30 +01:00
|
|
|
fprintf(
|
2021-02-11 11:08:18 +00:00
|
|
|
stderr,
|
|
|
|
|
"-d,--log-level: %s: argument must be one of %s\n",
|
|
|
|
|
optarg,
|
|
|
|
|
log_level_string_hint());
|
2021-06-23 14:22:18 +02:00
|
|
|
goto err;
|
2021-02-09 21:07:30 +01:00
|
|
|
}
|
2021-02-11 11:08:18 +00:00
|
|
|
log_level = lvl;
|
2021-02-09 21:07:30 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-05 19:54:16 +01:00
|
|
|
case 'l':
|
|
|
|
|
if (optarg == NULL || strcmp(optarg, "auto") == 0)
|
|
|
|
|
log_colorize = LOG_COLORIZE_AUTO;
|
|
|
|
|
else if (strcmp(optarg, "never") == 0)
|
|
|
|
|
log_colorize = LOG_COLORIZE_NEVER;
|
|
|
|
|
else if (strcmp(optarg, "always") == 0)
|
|
|
|
|
log_colorize = LOG_COLORIZE_ALWAYS;
|
|
|
|
|
else {
|
|
|
|
|
fprintf(stderr, "%s: argument must be one of 'never', 'always' or 'auto'\n", optarg);
|
2021-06-23 14:22:18 +02:00
|
|
|
goto err;
|
2020-02-05 19:54:16 +01:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2019-11-01 20:39:34 +01:00
|
|
|
case 'v':
|
2020-12-04 18:57:49 +01:00
|
|
|
printf("footclient %s\n", version_and_features());
|
2021-06-23 14:22:18 +02:00
|
|
|
ret = EXIT_SUCCESS;
|
|
|
|
|
goto err;
|
2019-11-01 20:39:34 +01:00
|
|
|
|
|
|
|
|
case 'h':
|
|
|
|
|
print_usage(prog_name);
|
2021-06-23 14:22:18 +02:00
|
|
|
ret = EXIT_SUCCESS;
|
|
|
|
|
goto err;
|
2019-11-01 20:39:34 +01:00
|
|
|
|
2021-09-18 23:40:40 +01:00
|
|
|
case 'e':
|
|
|
|
|
break;
|
|
|
|
|
|
2019-11-01 20:39:34 +01:00
|
|
|
case '?':
|
2021-06-23 14:22:18 +02:00
|
|
|
goto err;
|
2019-11-01 20:39:34 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-01 21:11:31 +01:00
|
|
|
if (argc > 0) {
|
|
|
|
|
argc -= optind;
|
|
|
|
|
argv += optind;
|
|
|
|
|
}
|
2019-11-01 20:39:34 +01:00
|
|
|
|
2021-02-09 21:07:30 +01:00
|
|
|
log_init(log_colorize, false, LOG_FACILITY_USER, log_level);
|
2020-02-05 19:54:16 +01:00
|
|
|
|
2021-06-23 15:32:03 +02:00
|
|
|
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
2019-11-01 20:39:34 +01:00
|
|
|
if (fd == -1) {
|
|
|
|
|
LOG_ERRNO("failed to create socket");
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct sockaddr_un addr = {.sun_family = AF_UNIX};
|
|
|
|
|
|
2019-12-14 13:00:48 +01:00
|
|
|
if (server_socket_path != NULL) {
|
2019-12-14 13:14:24 +01:00
|
|
|
strncpy(addr.sun_path, server_socket_path, sizeof(addr.sun_path) - 1);
|
2019-11-01 20:39:34 +01:00
|
|
|
if (connect(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
2019-12-14 13:00:48 +01:00
|
|
|
LOG_ERR("%s: failed to connect (is 'foot --server' running?)", server_socket_path);
|
2019-11-01 20:39:34 +01:00
|
|
|
goto err;
|
|
|
|
|
}
|
2019-12-14 13:00:48 +01:00
|
|
|
} else {
|
|
|
|
|
bool connected = false;
|
|
|
|
|
|
|
|
|
|
const char *xdg_runtime = getenv("XDG_RUNTIME_DIR");
|
|
|
|
|
if (xdg_runtime != NULL) {
|
2020-08-02 13:10:31 +02:00
|
|
|
const char *wayland_display = getenv("WAYLAND_DISPLAY");
|
2023-03-09 14:13:57 +01:00
|
|
|
if (wayland_display != NULL) {
|
2020-08-02 13:10:31 +02:00
|
|
|
snprintf(addr.sun_path, sizeof(addr.sun_path),
|
|
|
|
|
"%s/foot-%s.sock", xdg_runtime, wayland_display);
|
2023-03-09 14:13:57 +01:00
|
|
|
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);
|
2020-08-02 13:10:31 +02:00
|
|
|
snprintf(addr.sun_path, sizeof(addr.sun_path),
|
|
|
|
|
"%s/foot.sock", xdg_runtime);
|
2023-03-09 14:13:57 +01:00
|
|
|
connected = (connect(fd, (const struct sockaddr *)&addr, sizeof(addr)) == 0);
|
|
|
|
|
}
|
|
|
|
|
if (!connected)
|
2020-03-10 18:02:57 +01:00
|
|
|
LOG_WARN("%s: failed to connect, will now try /tmp/foot.sock", addr.sun_path);
|
2019-12-14 13:00:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!connected) {
|
|
|
|
|
strncpy(addr.sun_path, "/tmp/foot.sock", sizeof(addr.sun_path) - 1);
|
|
|
|
|
if (connect(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
|
|
|
LOG_ERRNO("failed to connect (is 'foot --server' running?)");
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-01 20:39:34 +01:00
|
|
|
}
|
|
|
|
|
|
2021-02-12 09:39:44 +01:00
|
|
|
const char *cwd = custom_cwd;
|
|
|
|
|
if (cwd == NULL) {
|
2020-02-20 18:45:42 +01:00
|
|
|
errno = 0;
|
|
|
|
|
size_t buf_len = 1024;
|
|
|
|
|
do {
|
2021-02-12 09:39:44 +01:00
|
|
|
_cwd = xrealloc(_cwd, buf_len);
|
|
|
|
|
if (getcwd(_cwd, buf_len) == NULL && errno != ERANGE) {
|
2020-02-20 18:45:42 +01:00
|
|
|
LOG_ERRNO("failed to get current working directory");
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
buf_len *= 2;
|
|
|
|
|
} while (errno == ERANGE);
|
2021-02-12 09:39:44 +01:00
|
|
|
cwd = _cwd;
|
2020-02-20 18:45:42 +01:00
|
|
|
}
|
2019-11-05 10:08:30 +01:00
|
|
|
|
2022-09-26 19:09:33 +02:00
|
|
|
const char *pwd = getenv("PWD");
|
|
|
|
|
if (pwd != NULL) {
|
|
|
|
|
char *resolved_path_cwd = realpath(cwd, NULL);
|
|
|
|
|
char *resolved_path_pwd = realpath(pwd, NULL);
|
|
|
|
|
|
|
|
|
|
if (resolved_path_cwd != NULL &&
|
|
|
|
|
resolved_path_pwd != NULL &&
|
|
|
|
|
strcmp(resolved_path_cwd, resolved_path_pwd) == 0)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* The resolved path of $PWD matches the resolved path of
|
|
|
|
|
* the *actual* working directory - use $PWD.
|
|
|
|
|
*
|
|
|
|
|
* This makes a difference when $PWD refers to a symlink.
|
|
|
|
|
*/
|
|
|
|
|
cwd = pwd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(resolved_path_cwd);
|
|
|
|
|
free(resolved_path_pwd);
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-11 12:19:40 +02:00
|
|
|
if (client_environment) {
|
|
|
|
|
for (char **e = environ; *e != NULL; e++) {
|
|
|
|
|
if (!push_string(&envp, *e, &total_len))
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-21 20:21:18 +01:00
|
|
|
/* String lengths, including NULL terminator */
|
|
|
|
|
const size_t cwd_len = strlen(cwd) + 1;
|
2021-06-23 14:22:18 +02:00
|
|
|
const size_t override_count = tll_length(overrides);
|
2022-04-11 12:19:40 +02:00
|
|
|
const size_t env_count = tll_length(envp);
|
2020-11-21 20:21:18 +01:00
|
|
|
|
|
|
|
|
const struct client_data data = {
|
|
|
|
|
.hold = hold,
|
2021-03-12 20:46:55 -03:00
|
|
|
.no_wait = no_wait,
|
2021-10-28 17:51:44 -07:00
|
|
|
.xdga_token = xdga_token,
|
|
|
|
|
.token_len = token_len,
|
2020-11-21 20:21:18 +01:00
|
|
|
.cwd_len = cwd_len,
|
2021-06-23 14:22:18 +02:00
|
|
|
.override_count = override_count,
|
2020-11-21 20:21:18 +01:00
|
|
|
.argc = argc,
|
2022-04-11 12:19:40 +02:00
|
|
|
.env_count = env_count,
|
2020-11-21 20:21:18 +01:00
|
|
|
};
|
2019-11-05 10:08:30 +01:00
|
|
|
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
/* Total packet length, not (yet) including argv[] */
|
2021-10-28 17:51:44 -07:00
|
|
|
total_len += sizeof(data) + cwd_len + token_len;
|
2019-12-21 19:56:37 +01:00
|
|
|
|
2020-11-21 20:21:18 +01:00
|
|
|
/* Add argv[] size to total packet length */
|
client: add and use function push_override()
We now track override data (length + malloc:ed string) in a struct,
and push this struct to our overrides linked list.
There’s a new function, push_override() that takes a string,
calculates its length, strdup() it and pushes it to the linked
list. This function also length-checks the string, to ensure we don’t
overflow.
This way, we don’t have to loop the overrides list twice; once when
calculating the total length of all overrides, and once when sending
the overrides to the server.
Now, we can update the total length as we add overrides (i.e while
parsing the command line, instead of afterwards).
This means we only have to loop the list once, and that’s when sending
it. This also means there’s no longer any need to malloc an array
holding the lengths of each override.
2021-06-23 15:04:09 +02:00
|
|
|
cargv = xmalloc(argc * sizeof(cargv[0]));
|
2020-11-21 20:21:18 +01:00
|
|
|
for (size_t i = 0; i < argc; i++) {
|
|
|
|
|
const size_t arg_len = strlen(argv[i]) + 1;
|
|
|
|
|
|
|
|
|
|
if (arg_len >= 1 << (8 * sizeof(cargv[i].len))) {
|
|
|
|
|
LOG_ERR("argv length overflow");
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cargv[i].len = arg_len;
|
|
|
|
|
total_len += sizeof(cargv[i]) + cargv[i].len;
|
2019-11-01 21:10:47 +01:00
|
|
|
}
|
|
|
|
|
|
2020-11-21 20:21:18 +01:00
|
|
|
/* Check for size overflows */
|
|
|
|
|
if (total_len >= 1llu << (8 * sizeof(uint32_t)) ||
|
|
|
|
|
cwd_len >= 1 << (8 * sizeof(data.cwd_len)) ||
|
2021-10-28 17:51:44 -07:00
|
|
|
token_len >= 1 << (8 * sizeof(data.token_len)) ||
|
2021-06-23 14:22:18 +02:00
|
|
|
override_count > (size_t)(unsigned int)data.override_count ||
|
2022-04-11 12:19:40 +02:00
|
|
|
argc > (int)(unsigned int)data.argc ||
|
|
|
|
|
env_count > (size_t)(unsigned int)data.env_count)
|
2020-04-01 19:59:47 +02:00
|
|
|
{
|
2020-11-21 20:21:18 +01:00
|
|
|
LOG_ERR("size overflow");
|
2020-04-01 19:59:47 +02:00
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-21 20:21:18 +01:00
|
|
|
/* Send everything except argv[] */
|
2021-10-29 21:42:57 +02:00
|
|
|
if (sendall(fd, &(uint32_t){total_len}, sizeof(uint32_t)) < 0 ||
|
|
|
|
|
sendall(fd, &data, sizeof(data)) < 0 ||
|
|
|
|
|
sendall(fd, cwd, cwd_len) < 0)
|
2020-04-01 18:40:51 +02:00
|
|
|
{
|
2020-11-21 20:21:18 +01:00
|
|
|
LOG_ERRNO("failed to send setup packet to server");
|
2020-03-27 21:14:49 +01:00
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-28 17:51:44 -07:00
|
|
|
/* Send XDGA token, if we have one */
|
|
|
|
|
if (xdga_token) {
|
|
|
|
|
if (sendall(fd, token, token_len) != token_len)
|
|
|
|
|
{
|
|
|
|
|
LOG_ERRNO("failed to send xdg activation token to server");
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-23 14:22:18 +02:00
|
|
|
/* Send overrides */
|
2022-04-11 12:38:36 +02:00
|
|
|
if (!send_string_list(fd, &overrides))
|
|
|
|
|
goto err;
|
2021-06-23 14:22:18 +02:00
|
|
|
|
2020-11-21 20:21:18 +01:00
|
|
|
/* Send argv[] */
|
|
|
|
|
for (size_t i = 0; i < argc; i++) {
|
2021-10-29 21:42:57 +02:00
|
|
|
if (sendall(fd, &cargv[i], sizeof(cargv[i])) < 0 ||
|
|
|
|
|
sendall(fd, argv[i], cargv[i].len) < 0)
|
2019-11-01 20:39:34 +01:00
|
|
|
{
|
2021-06-23 14:22:18 +02:00
|
|
|
LOG_ERRNO("failed to send setup packet (argv) to server");
|
2019-11-01 20:39:34 +01:00
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-11 12:19:40 +02:00
|
|
|
/* Send environment */
|
2022-04-11 12:38:36 +02:00
|
|
|
if (!send_string_list(fd, &envp))
|
|
|
|
|
goto err;
|
2022-04-11 12:19:40 +02:00
|
|
|
|
Explicitly initialize sigaction::sa_mask members with sigemptyset(3)
Not doing so before calling sigaction(3) is "undefined" according to
POSIX[1]:
> Applications shall call either sigemptyset() or sigfillset() at least
> once for each object of type sigset_t prior to any other use of that
> object. If such an object is not initialized in this way, but is
> nonetheless supplied as an argument to any of pthread_sigmask(),
> sigaction(), sigaddset(), sigdelset(), sigismember(), sigpending(),
> sigprocmask(), sigsuspend(), sigtimedwait(), sigwait(), or
> sigwaitinfo(), the results are undefined.
The use of designated initializers means that sa_mask members were
still being initialized, but sigset_t is an opaque type and implicit
initialization doesn't necessarily produce the same results as using
sigemptyset(3) (although it typically does on most implementations).
[1]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaddset.html
2022-02-12 12:04:57 +00:00
|
|
|
struct sigaction sa = {.sa_handler = &sig_handler};
|
|
|
|
|
sigemptyset(&sa.sa_mask);
|
2019-11-01 21:13:37 +01:00
|
|
|
if (sigaction(SIGINT, &sa, NULL) < 0 || sigaction(SIGTERM, &sa, NULL) < 0) {
|
2019-11-01 20:39:34 +01:00
|
|
|
LOG_ERRNO("failed to register signal handlers");
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int exit_code;
|
|
|
|
|
ssize_t rcvd = recv(fd, &exit_code, sizeof(exit_code), 0);
|
|
|
|
|
|
|
|
|
|
if (rcvd == -1 && errno == EINTR)
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(aborted);
|
2019-11-01 20:39:34 +01:00
|
|
|
else if (rcvd != sizeof(exit_code))
|
|
|
|
|
LOG_ERRNO("failed to read server response");
|
|
|
|
|
else
|
|
|
|
|
ret = exit_code;
|
|
|
|
|
|
|
|
|
|
err:
|
2022-04-11 12:19:40 +02:00
|
|
|
free_string_list(&envp);
|
|
|
|
|
free_string_list(&overrides);
|
2020-11-21 20:21:18 +01:00
|
|
|
free(cargv);
|
2021-02-12 09:39:44 +01:00
|
|
|
free(_cwd);
|
2019-11-01 20:39:34 +01:00
|
|
|
if (fd != -1)
|
|
|
|
|
close(fd);
|
2019-12-14 13:01:21 +01:00
|
|
|
log_deinit();
|
2019-11-01 20:39:34 +01:00
|
|
|
return ret;
|
|
|
|
|
}
|