From 2a99c5a093737b7905d71ee2df24d3a17b1d83e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 12 Feb 2021 09:25:29 +0100 Subject: [PATCH 01/11] =?UTF-8?q?user-notification:=20add=20new=20function?= =?UTF-8?q?=20=E2=80=98user=5Fnotification=5Fadd()=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- meson.build | 2 +- user-notification.c | 38 ++++++++++++++++++++++++++++++++++++++ user-notification.h | 7 +++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 user-notification.c diff --git a/meson.build b/meson.build index 1465fa3e..f17ab7ef 100644 --- a/meson.build +++ b/meson.build @@ -181,7 +181,7 @@ executable( 'spawn.c', 'spawn.h', 'tokenize.c', 'tokenize.h', 'url-mode.c', 'url-mode.h', - 'user-notification.h', + 'user-notification.c', 'user-notification.h', 'wayland.c', 'wayland.h', wl_proto_src + wl_proto_headers, version, dependencies: [math, threads, libepoll, pixman, wayland_client, wayland_cursor, xkb, fontconfig, diff --git a/user-notification.c b/user-notification.c new file mode 100644 index 00000000..497aa08c --- /dev/null +++ b/user-notification.c @@ -0,0 +1,38 @@ +#include "user-notification.h" +#include +#include + +static bool +user_notification_add_va(user_notifications_t *notifications, + enum user_notification_kind kind, const char *fmt, + va_list ap) +{ + va_list ap2; + va_copy(ap2, ap); + int cnt = vsnprintf(NULL, 0, fmt, ap2); + va_end(ap2); + + if (cnt < 0) + return false; + + char *text = malloc(cnt + 1); + vsnprintf(text, cnt + 1, fmt, ap); + + struct user_notification not = { + .kind = kind, + .text = text, + }; + tll_push_back(*notifications, not); + return true; +} + +bool +user_notification_add(user_notifications_t *notifications, + enum user_notification_kind kind, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + bool ret = user_notification_add_va(notifications, kind, fmt, ap); + va_end(ap); + return ret; +} diff --git a/user-notification.h b/user-notification.h index f184871e..507c1791 100644 --- a/user-notification.h +++ b/user-notification.h @@ -1,7 +1,10 @@ #pragma once +#include #include +#include "macros.h" + enum user_notification_kind { USER_NOTIFICATION_DEPRECATED, USER_NOTIFICATION_WARNING, @@ -22,3 +25,7 @@ user_notifications_free(user_notifications_t *notifications) free(it->item.text); tll_free(*notifications); } + +bool user_notification_add(user_notifications_t *notifications, + enum user_notification_kind kind, + const char *fmt, ...) PRINTF(3); From 64a60d12f0f8b8cec55795818b0b7d008b66ae3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 12 Feb 2021 09:39:20 +0100 Subject: [PATCH 02/11] server: send exit-code -1 when we fail to instantiate a new terminal --- server.c | 1 + 1 file changed, 1 insertion(+) diff --git a/server.c b/server.c index 7a4101ea..6fbfaee6 100644 --- a/server.c +++ b/server.c @@ -275,6 +275,7 @@ fdm_client(struct fdm *fdm, int fd, int events, void *data) if (client->term == NULL) { LOG_ERR("failed to instantiate new terminal"); + client_send_exit_code(client, -1); goto shutdown; } From 19868c9c8d29cba0f22dafcf9b92ffffc76bd1e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 12 Feb 2021 09:39:44 +0100 Subject: [PATCH 03/11] main/client: add -D,--working-directory=DIR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This overrides the CWD the slave process chdir()’s into before exec:ing the client application. --- client.c | 21 +++++++++++++++------ main.c | 26 ++++++++++++++++++-------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/client.c b/client.c index 73b243f7..125b4cfa 100644 --- a/client.c +++ b/client.c @@ -54,6 +54,7 @@ print_usage(const char *prog_name) " -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" " -d,---log-level={info|warning|error} log level (info)\n" @@ -77,6 +78,7 @@ main(int argc, char *const *argv) {"maximized", no_argument, NULL, 'm'}, {"fullscreen", no_argument, NULL, 'F'}, {"login-shell", no_argument, NULL, 'L'}, + {"working-directory", required_argument, NULL, 'D'}, {"server-socket", required_argument, NULL, 's'}, {"hold", no_argument, NULL, 'H'}, {"log-level", required_argument, NULL, 'd'}, @@ -89,6 +91,7 @@ main(int argc, char *const *argv) const char *term = ""; const char *title = ""; const char *app_id = ""; + const char *custom_cwd = NULL; unsigned size_type = 0; // enum conf_size_type (without pulling in tllist/fcft via config.h) unsigned width = 0; unsigned height = 0; @@ -101,7 +104,7 @@ main(int argc, char *const *argv) bool hold = false; while (true) { - int c = getopt_long(argc, argv, "+t:T:a:w:W:mFLs:Hd:l::vh", longopts, NULL); + int c = getopt_long(argc, argv, "+t:T:a:w:W:mFLD:s:Hd:l::vh", longopts, NULL); if (c == -1) break; @@ -122,6 +125,10 @@ main(int argc, char *const *argv) login_shell = true; break; + case 'D': + custom_cwd = optarg; + break; + case 'w': if (sscanf(optarg, "%ux%u", &width, &height) != 2 || width == 0 || height == 0) { fprintf(stderr, "error: invalid window-size-pixels: %s\n", optarg); @@ -202,7 +209,7 @@ main(int argc, char *const *argv) log_init(log_colorize, false, LOG_FACILITY_USER, log_level); /* malloc:ed and needs to be in scope of all goto's */ - char *cwd = NULL; + char *_cwd = NULL; struct client_argv *cargv = NULL; int fd = socket(AF_UNIX, SOCK_STREAM, 0); @@ -247,17 +254,19 @@ main(int argc, char *const *argv) } } - { + const char *cwd = custom_cwd; + if (cwd == NULL) { errno = 0; size_t buf_len = 1024; do { - cwd = xrealloc(cwd, buf_len); - if (getcwd(cwd, buf_len) == NULL && errno != ERANGE) { + _cwd = xrealloc(_cwd, buf_len); + if (getcwd(_cwd, buf_len) == NULL && errno != ERANGE) { LOG_ERRNO("failed to get current working directory"); goto err; } buf_len *= 2; } while (errno == ERANGE); + cwd = _cwd; } /* String lengths, including NULL terminator */ @@ -356,7 +365,7 @@ main(int argc, char *const *argv) err: free(cargv); - free(cwd); + free(_cwd); if (fd != -1) close(fd); log_deinit(); diff --git a/main.c b/main.c index b0ae8650..2b9d3186 100644 --- a/main.c +++ b/main.c @@ -67,6 +67,7 @@ print_usage(const char *prog_name) " -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" " -w,--window-size-pixels=WIDTHxHEIGHT initial width and height, in pixels\n" " -W,--window-size-chars=WIDTHxHEIGHT initial width and height, in characters\n" " -s,--server[=PATH] run as a server (use 'footclient' to start terminals).\n" @@ -163,6 +164,7 @@ main(int argc, char *const *argv) {"title", required_argument, NULL, 'T'}, {"app-id", required_argument, NULL, 'a'}, {"login-shell", no_argument, NULL, 'L'}, + {"working-directory", required_argument, NULL, 'D'}, {"font", required_argument, NULL, 'f'}, {"window-size-pixels", required_argument, NULL, 'w'}, {"window-size-chars", required_argument, NULL, 'W'}, @@ -185,6 +187,7 @@ main(int argc, char *const *argv) const char *conf_term = NULL; const char *conf_title = NULL; const char *conf_app_id = NULL; + const char *custom_cwd = NULL; bool login_shell = false; tll(char *) conf_fonts = tll_init(); enum conf_size_type conf_size_type = CONF_SIZE_PX; @@ -204,7 +207,7 @@ main(int argc, char *const *argv) user_notifications_t user_notifications = tll_init(); while (true) { - int c = getopt_long(argc, argv, "+c:Ct:T:a:Lf:w:W:s::HmFPp:d:l::Svh", longopts, NULL); + int c = getopt_long(argc, argv, "+c:Ct:T:a:LD:f:w:W:s::HmFPp:d:l::Svh", longopts, NULL); if (c == -1) break; @@ -233,6 +236,10 @@ main(int argc, char *const *argv) conf_app_id = optarg; break; + case 'D': + custom_cwd = optarg; + break; + case 'f': tll_free_and_free(conf_fonts, free); for (char *font = strtok(optarg, ","); font != NULL; font = strtok(NULL, ",")) { @@ -443,18 +450,21 @@ main(int argc, char *const *argv) struct server *server = NULL; struct shutdown_context shutdown_ctx = {.term = &term, .exit_code = EXIT_FAILURE}; - char *cwd = NULL; - { + const char *cwd = custom_cwd; + char *_cwd = NULL; + + if (cwd == NULL) { errno = 0; size_t buf_len = 1024; do { - cwd = xrealloc(cwd, buf_len); - if (getcwd(cwd, buf_len) == NULL && errno != ERANGE) { + _cwd = xrealloc(_cwd, buf_len); + if (getcwd(_cwd, buf_len) == NULL && errno != ERANGE) { LOG_ERRNO("failed to get current working directory"); goto out; } buf_len *= 2; } while (errno == ERANGE); + cwd = _cwd; } shm_set_max_pool_size(conf.tweak.max_shm_pool_size); @@ -476,8 +486,8 @@ main(int argc, char *const *argv) &term_shutdown_cb, &shutdown_ctx)) == NULL) { goto out; } - free(cwd); - cwd = NULL; + free(_cwd); + _cwd = NULL; if (as_server && (server = server_init(&conf, fdm, reaper, wayl)) == NULL) goto out; @@ -510,7 +520,7 @@ main(int argc, char *const *argv) ret = aborted || tll_length(wayl->terms) == 0 ? EXIT_SUCCESS : EXIT_FAILURE; out: - free(cwd); + free(_cwd); server_destroy(server); term_destroy(term); From a2020ad6e821b9a7b0e061d2b7c59f22d25c6f58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 12 Feb 2021 09:43:05 +0100 Subject: [PATCH 04/11] doc: foot.1: add missing short option to --login-shell --- doc/foot.1.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/foot.1.scd b/doc/foot.1.scd index 71071dac..4ca378f6 100644 --- a/doc/foot.1.scd +++ b/doc/foot.1.scd @@ -69,7 +69,7 @@ the foot command line Start in fullscreen mode. If both *--maximized* and *--fullscreen* are specified, the _last_ one takes precedence. -*--login-shell* +*-L*,*--login-shell* Start a login shell, by prepending a '-' to argv[0]. *-s*,*--server*[=_PATH_] From 38b138bb14ec814e21f2c5cda8c133bff135bb20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 12 Feb 2021 09:43:20 +0100 Subject: [PATCH 05/11] doc: foot.1: add -D,--working-directory=DIR --- doc/foot.1.scd | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/foot.1.scd b/doc/foot.1.scd index 4ca378f6..199ca562 100644 --- a/doc/foot.1.scd +++ b/doc/foot.1.scd @@ -72,6 +72,10 @@ the foot command line *-L*,*--login-shell* Start a login shell, by prepending a '-' to argv[0]. +*-D*,*--working-directory*=_DIR_ + Initial working directory for the client application. Default: + _CWD of foot_. + *-s*,*--server*[=_PATH_] Run as a server. In this mode, a single foot instance hosts multiple terminals (windows). Use *footclient*(1) to launch new From 0de3340d368c760499d02742e6615735f84ebf7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 12 Feb 2021 09:43:30 +0100 Subject: [PATCH 06/11] doc: footclient.1: add -D,--working-directory=DIR --- doc/footclient.1.scd | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/footclient.1.scd b/doc/footclient.1.scd index 374a9a3a..107e6eaa 100644 --- a/doc/footclient.1.scd +++ b/doc/footclient.1.scd @@ -49,6 +49,10 @@ terminal has terminated). *-L*,*--login-shell* Start a login shell, by prepending a '-' to argv[0]. +*-D*,*--working-directory*=_DIR_ + Initial working directory for the client application. Default: + _CWD of footclient_. + *-s*,*--server-socket*=_PATH_ Connect to _PATH_ instead of *$XDG\_RUNTIME\_DIR/foot-$WAYLAND\_DISPLAY.sock*. From 60e67b9c21f523e2a9e50408563d57b0a57dc91b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 12 Feb 2021 09:46:22 +0100 Subject: [PATCH 07/11] completions: zsh: add -D,--working-directory --- completions/zsh/_foot | 1 + completions/zsh/_footclient | 1 + 2 files changed, 2 insertions(+) diff --git a/completions/zsh/_foot b/completions/zsh/_foot index b706ea2d..d87ad919 100644 --- a/completions/zsh/_foot +++ b/completions/zsh/_foot @@ -11,6 +11,7 @@ _arguments \ '(-m --maximized)'{-m,--maximized}'[start in maximized mode]' \ '(-F --fullscreen)'{-F,--fullscreen}'[start in fullscreen mode]' \ '(-L --login-shell)'{-L,--login-shell}'[start shell as a login shell]' \ + '(-D --working-directory)'{-D,--working-directory}'[initial working directory for the client application (CWD)]:working_directory:_files' \ '(-w --window-size-pixels)'{-w,--window-size-pixels}'[window WIDTHxHEIGHT, in pixels (700x500)]:size_pixels:()' \ '(-W --window-size-chars)'{-W,--window-size-chars}'[window WIDTHxHEIGHT, in characters (not set)]:size_chars:()' \ '(-s --server)'{-s,--server}'[run as server; open terminals by running footclient]:server:_files' \ diff --git a/completions/zsh/_footclient b/completions/zsh/_footclient index df9b7f25..f8537748 100644 --- a/completions/zsh/_footclient +++ b/completions/zsh/_footclient @@ -8,6 +8,7 @@ _arguments \ '(-m --maximized)'{-m,--maximized}'[start in maximized mode]' \ '(-F --fullscreen)'{-F,--fullscreen}'[start in fullscreen mode]' \ '(-L --login-shell)'{-L,--login-shell}'[start shell as a login shell]' \ + '(-D --working-directory)'{-D,--working-directory}'[initial working directory for the client application (CWD)]:working_directory:_files' \ '(-w --window-size-pixels)'{-w,--window-size-pixels}'[window WIDTHxHEIGHT, in pixels (700x500)]:size_pixels:()' \ '(-W --window-size-chars)'{-W,--window-size-chars}'[window WIDTHxHEIGHT, in characters (not set)]:size_chars:()' \ '(-s --server-socket)'{-s,--server-socket}'[override the default path to the foot server socket ($XDG_RUNTIME_DIR/foot-$WAYLAND_DISPLAY.sock)]:server:_files' \ From fc070dbdf1acde544ac50ce8ccb6c77c84c930a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 12 Feb 2021 09:47:50 +0100 Subject: [PATCH 08/11] completions: fish: add -D,--working-directory --- completions/fish/foot.fish | 1 + completions/fish/footclient.fish | 1 + 2 files changed, 2 insertions(+) diff --git a/completions/fish/foot.fish b/completions/fish/foot.fish index de31c547..58ae8f11 100644 --- a/completions/fish/foot.fish +++ b/completions/fish/foot.fish @@ -8,6 +8,7 @@ complete -c foot -x -s a -l app-id complete -c foot -s m -l maximized -d "start in maximized mode" complete -c foot -s F -l fullscreen -d "start in fullscreen mode" complete -c foot -s L -l login-shell -d "start shell as a login shell" +complete -c foot -F -s D -l working-directory -d "initial working directory for the client application (CWD)" complete -c foot -x -s w -l window-size-pixels -d "window WIDTHxHEIGHT, in pixels (700x500)" complete -c foot -x -s W -l window-size-chars -d "window WIDTHxHEIGHT, in characters (not set)" complete -c foot -F -s s -l server -d "run as server; open terminals by running footclient" diff --git a/completions/fish/footclient.fish b/completions/fish/footclient.fish index 880aaed7..09dc7305 100644 --- a/completions/fish/footclient.fish +++ b/completions/fish/footclient.fish @@ -5,6 +5,7 @@ complete -c footclient -x -s a -l app-id complete -c footclient -s m -l maximized -d "start in maximized mode" complete -c footclient -s F -l fullscreen -d "start in fullscreen mode" complete -c footclient -s L -l login-shell -d "start shell as a login shell" +complete -c footclient -F -s D -l working-directory -d "initial working directory for the client application (CWD)" complete -c footclient -x -s w -l window-size-pixels -d "window WIDTHxHEIGHT, in pixels (700x500)" complete -c footclient -x -s W -l window-size-chars -d "window WIDTHxHEIGHT, in characters (not set)" complete -c footclient -F -s s -l server-socket -d "override the default path to the foot server socket ($XDG_RUNTIME_DIR/foot-$WAYLAND_DISPLAY.sock)" From 37c4917e8e1decc13c4b27f6d974548bb5afc65c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 12 Feb 2021 09:48:32 +0100 Subject: [PATCH 09/11] changelog: -D,--working-directory=DIR --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0c18059..ba20e9e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,8 @@ (https://codeberg.org/dnkl/foot/issues/14). * `-d,--log-level={info|warning|error}` to both `foot` and `footclient` (https://codeberg.org/dnkl/foot/issues/337). +* `-D,--working-directory=DIR` to both `foot` and `footclient` + (https://codeberg.org/dnkl/foot/issues/347) ### Changed From f896f12967086cde054d02a0e5b4af1eb8eeb898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 13 Feb 2021 10:48:31 +0100 Subject: [PATCH 10/11] main: -D,--working-directory: check path exists and is a directory --- main.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index 2b9d3186..87f7a058 100644 --- a/main.c +++ b/main.c @@ -236,9 +236,15 @@ main(int argc, char *const *argv) conf_app_id = optarg; break; - case 'D': + case 'D': { + struct stat st; + if (stat(optarg, &st) < 0 || !(st.st_mode & S_IFDIR)) { + fprintf(stderr, "error: %s: not a directory\n", optarg); + return EXIT_FAILURE; + } custom_cwd = optarg; break; + } case 'f': tll_free_and_free(conf_fonts, free); From 5b0ebee290393394d18337f9d707f6b532d3f2a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 13 Feb 2021 10:48:58 +0100 Subject: [PATCH 11/11] client: -D,--working-directory: check path exists and is a directory --- client.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/client.c b/client.c index 125b4cfa..c012555c 100644 --- a/client.c +++ b/client.c @@ -10,6 +10,7 @@ #include #include +#include #define LOG_MODULE "foot-client" #define LOG_ENABLE_DBG 0 @@ -125,9 +126,15 @@ main(int argc, char *const *argv) login_shell = true; break; - case 'D': + case 'D': { + struct stat st; + if (stat(optarg, &st) < 0 || !(st.st_mode & S_IFDIR)) { + fprintf(stderr, "error: %s: not a directory\n", optarg); + return EXIT_FAILURE; + } custom_cwd = optarg; break; + } case 'w': if (sscanf(optarg, "%ux%u", &width, &height) != 2 || width == 0 || height == 0) {