From b8e6286c25d8be71887d9786f8ae1038e8cd9fac Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 22 Feb 2021 08:18:13 +0000 Subject: [PATCH] Move config file path expansion much earlier, keep the list of paths around rather than freeing later, and add a config_files format variable containing it. Suggested by kn@ a while back. --- usr.bin/tmux/cfg.c | 32 ++++++++++++-------------------- usr.bin/tmux/format.c | 25 ++++++++++++++++++++++++- usr.bin/tmux/tmux.1 | 5 +++-- usr.bin/tmux/tmux.c | 39 ++++++++++++++++++++++++++------------- usr.bin/tmux/tmux.h | 8 ++++---- 5 files changed, 69 insertions(+), 40 deletions(-) diff --git a/usr.bin/tmux/cfg.c b/usr.bin/tmux/cfg.c index e0bd9a32904..204a3ab6d49 100644 --- a/usr.bin/tmux/cfg.c +++ b/usr.bin/tmux/cfg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cfg.c,v 1.81 2020/05/16 14:26:33 nicm Exp $ */ +/* $OpenBSD: cfg.c,v 1.82 2021/02/22 08:18:13 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott @@ -28,12 +28,15 @@ #include "tmux.h" struct client *cfg_client; -static char *cfg_file; int cfg_finished; static char **cfg_causes; static u_int cfg_ncauses; static struct cmdq_item *cfg_item; +int cfg_quiet = 1; +char **cfg_files; +u_int cfg_nfiles; + static enum cmd_retval cfg_client_done(__unused struct cmdq_item *item, __unused void *data) { @@ -60,19 +63,11 @@ cfg_done(__unused struct cmdq_item *item, __unused void *data) return (CMD_RETURN_NORMAL); } -void -set_cfg_file(const char *path) -{ - free(cfg_file); - cfg_file = xstrdup(path); -} - void start_cfg(void) { struct client *c; - char **paths; - u_int i, n; + u_int i; /* * Configuration files are loaded without a client, so commands are run @@ -90,15 +85,12 @@ start_cfg(void) cmdq_append(c, cfg_item); } - if (cfg_file == NULL) { - expand_paths(TMUX_CONF, &paths, &n); - for (i = 0; i < n; i++) { - load_cfg(paths[i], c, NULL, CMD_PARSE_QUIET, NULL); - free(paths[i]); - } - free(paths); - } else - load_cfg(cfg_file, c, NULL, 0, NULL); + for (i = 0; i < cfg_nfiles; i++) { + if (cfg_quiet) + load_cfg(cfg_files[i], c, NULL, CMD_PARSE_QUIET, NULL); + else + load_cfg(cfg_files[i], c, NULL, 0, NULL); + } cmdq_append(NULL, cmdq_get_callback(cfg_done, NULL)); } diff --git a/usr.bin/tmux/format.c b/usr.bin/tmux/format.c index d15c0cc513d..98bf7b02f41 100644 --- a/usr.bin/tmux/format.c +++ b/usr.bin/tmux/format.c @@ -1,4 +1,4 @@ -/* $OpenBSD: format.c,v 1.275 2021/02/22 07:09:06 nicm Exp $ */ +/* $OpenBSD: format.c,v 1.276 2021/02/22 08:18:13 nicm Exp $ */ /* * Copyright (c) 2011 Nicholas Marriott @@ -1412,6 +1412,26 @@ format_cb_client_written(struct format_tree *ft) return (NULL); } +/* Callback for config_files. */ +static void * +format_cb_config_files(__unused struct format_tree *ft) +{ + char *s = NULL; + size_t slen = 0; + u_int i; + size_t n; + + for (i = 0; i < cfg_nfiles; i++) { + n = strlen(cfg_files[i]) + 1; + s = xrealloc(s, slen + n + 1); + slen += xsnprintf(s + slen, n + 1, "%s,", cfg_files[i]); + } + if (s == NULL) + return (xstrdup("")); + s[slen - 1] = '\0'; + return (s); +} + /* Callback for cursor_flag. */ static void * format_cb_cursor_flag(struct format_tree *ft) @@ -2569,6 +2589,9 @@ static const struct format_table_entry format_table[] = { { "client_written", FORMAT_TABLE_STRING, format_cb_client_written }, + { "config_files", FORMAT_TABLE_STRING, + format_cb_config_files + }, { "cursor_character", FORMAT_TABLE_STRING, format_cb_cursor_character }, diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index 04ecb10de14..cf5a39006b7 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.822 2021/02/15 09:39:38 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.823 2021/02/22 08:18:13 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott .\" @@ -14,7 +14,7 @@ .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: February 15 2021 $ +.Dd $Mdocdate: February 22 2021 $ .Dt TMUX 1 .Os .Sh NAME @@ -4763,6 +4763,7 @@ The following variables are available, where appropriate: .It Li "buffer_name" Ta "" Ta "Name of buffer" .It Li "buffer_sample" Ta "" Ta "Sample of start of buffer" .It Li "buffer_size" Ta "" Ta "Size of the specified buffer in bytes" +.It Li "config_files" Ta "" Ta "List of configuration files loaded" .It Li "client_activity" Ta "" Ta "Time client last had activity" .It Li "client_cell_height" Ta "" Ta "Height of each client cell in pixels" .It Li "client_cell_width" Ta "" Ta "Width of each client cell in pixels" diff --git a/usr.bin/tmux/tmux.c b/usr.bin/tmux/tmux.c index 518d784c1d5..91c0e5dbd88 100644 --- a/usr.bin/tmux/tmux.c +++ b/usr.bin/tmux/tmux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.c,v 1.204 2021/01/17 16:17:41 nicm Exp $ */ +/* $OpenBSD: tmux.c,v 1.205 2021/02/22 08:18:13 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -142,11 +142,12 @@ expand_path(const char *path, const char *home) return (xstrdup(path)); } -void -expand_paths(const char *s, char ***paths, u_int *n) +static void +expand_paths(const char *s, char ***paths, u_int *n, int ignore_errors) { const char *home = find_home(); char *copy, *next, *tmp, resolved[PATH_MAX], *expanded; + char *path; u_int i; *paths = NULL; @@ -162,20 +163,26 @@ expand_paths(const char *s, char ***paths, u_int *n) if (realpath(expanded, resolved) == NULL) { log_debug("%s: realpath(\"%s\") failed: %s", __func__, expanded, strerror(errno)); + if (ignore_errors) { + free(expanded); + continue; + } + path = expanded; + } else { + path = xstrdup(resolved); free(expanded); - continue; } - free(expanded); for (i = 0; i < *n; i++) { - if (strcmp(resolved, (*paths)[i]) == 0) + if (strcmp(path, (*paths)[i]) == 0) break; } if (i != *n) { - log_debug("%s: duplicate path: %s", __func__, resolved); + log_debug("%s: duplicate path: %s", __func__, path); + free(path); continue; } *paths = xreallocarray(*paths, (*n) + 1, sizeof *paths); - (*paths)[(*n)++] = xstrdup(resolved); + (*paths)[(*n)++] = path; } free(copy); } @@ -193,7 +200,7 @@ make_label(const char *label, char **cause) label = "default"; uid = getuid(); - expand_paths(TMUX_SOCK, &paths, &n); + expand_paths(TMUX_SOCK, &paths, &n, 1); if (n == 0) { xasprintf(cause, "no suitable socket path"); return (NULL); @@ -330,10 +337,11 @@ main(int argc, char **argv) { char *path = NULL, *label = NULL; char *cause, **var; - const char *s, *shell, *cwd; + const char *s, *cwd; int opt, keys, feat = 0; uint64_t flags = 0; const struct options_table_entry *oe; + u_int i; if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL && setlocale(LC_CTYPE, "C.UTF-8") == NULL) { @@ -349,6 +357,7 @@ main(int argc, char **argv) if (**argv == '-') flags = CLIENT_LOGIN; + expand_paths(TMUX_CONF, &cfg_files, &cfg_nfiles, 1); while ((opt = getopt(argc, argv, "2c:CDdf:lL:NqS:T:uUvV")) != -1) { switch (opt) { @@ -368,7 +377,11 @@ main(int argc, char **argv) flags |= CLIENT_CONTROL; break; case 'f': - set_cfg_file(optarg); + for (i = 0; i < cfg_nfiles; i++) + free(cfg_files[i]); + free(cfg_files); + expand_paths(optarg, &cfg_files, &cfg_nfiles, 0); + cfg_quiet = 0; break; case 'V': printf("%s %s\n", getprogname(), getversion()); @@ -460,8 +473,8 @@ main(int argc, char **argv) * The default shell comes from SHELL or from the user's passwd entry * if available. */ - shell = getshell(); - options_set_string(global_s_options, "default-shell", 0, "%s", shell); + options_set_string(global_s_options, "default-shell", 0, "%s", + getshell()); /* Override keys to vi if VISUAL or EDITOR are set. */ if ((s = getenv("VISUAL")) != NULL || (s = getenv("EDITOR")) != NULL) { diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 48bb0b75dc8..49cf210c05a 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.1094 2021/02/22 07:09:06 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.1095 2021/02/22 08:18:13 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -1887,7 +1887,6 @@ const char *sig2name(int); const char *find_cwd(void); const char *find_home(void); const char *getversion(void); -void expand_paths(const char *, char ***, u_int *); /* proc.c */ struct imsg; @@ -1907,13 +1906,14 @@ pid_t proc_fork_and_daemon(int *); /* cfg.c */ extern int cfg_finished; extern struct client *cfg_client; +extern char **cfg_files; +extern u_int cfg_nfiles; +extern int cfg_quiet; void start_cfg(void); int load_cfg(const char *, struct client *, struct cmdq_item *, int, struct cmdq_item **); int load_cfg_from_buffer(const void *, size_t, const char *, struct client *, struct cmdq_item *, int, struct cmdq_item **); -void set_cfg_file(const char *); -const char *get_cfg_file(void); void printflike(1, 2) cfg_add_cause(const char *, ...); void cfg_print_causes(struct cmdq_item *); void cfg_show_causes(struct session *); -- 2.20.1