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.
This commit is contained in:
nicm 2021-02-22 08:18:13 +00:00
parent e858270006
commit 6876381276
5 changed files with 63 additions and 34 deletions

30
cfg.c
View File

@ -28,12 +28,15 @@
#include "tmux.h" #include "tmux.h"
struct client *cfg_client; struct client *cfg_client;
static char *cfg_file;
int cfg_finished; int cfg_finished;
static char **cfg_causes; static char **cfg_causes;
static u_int cfg_ncauses; static u_int cfg_ncauses;
static struct cmdq_item *cfg_item; static struct cmdq_item *cfg_item;
int cfg_quiet = 1;
char **cfg_files;
u_int cfg_nfiles;
static enum cmd_retval static enum cmd_retval
cfg_client_done(__unused struct cmdq_item *item, __unused void *data) 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); return (CMD_RETURN_NORMAL);
} }
void
set_cfg_file(const char *path)
{
free(cfg_file);
cfg_file = xstrdup(path);
}
void void
start_cfg(void) start_cfg(void)
{ {
struct client *c; struct client *c;
char **paths; u_int i;
u_int i, n;
/* /*
* Configuration files are loaded without a client, so commands are run * Configuration files are loaded without a client, so commands are run
@ -90,15 +85,12 @@ start_cfg(void)
cmdq_append(c, cfg_item); cmdq_append(c, cfg_item);
} }
if (cfg_file == NULL) { for (i = 0; i < cfg_nfiles; i++) {
expand_paths(TMUX_CONF, &paths, &n); if (cfg_quiet)
for (i = 0; i < n; i++) { load_cfg(cfg_files[i], c, NULL, CMD_PARSE_QUIET, NULL);
load_cfg(paths[i], c, NULL, CMD_PARSE_QUIET, NULL); else
free(paths[i]); load_cfg(cfg_files[i], c, NULL, 0, NULL);
} }
free(paths);
} else
load_cfg(cfg_file, c, NULL, 0, NULL);
cmdq_append(NULL, cmdq_get_callback(cfg_done, NULL)); cmdq_append(NULL, cmdq_get_callback(cfg_done, NULL));
} }

View File

@ -1412,6 +1412,26 @@ format_cb_client_written(struct format_tree *ft)
return (NULL); 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. */ /* Callback for cursor_flag. */
static void * static void *
format_cb_cursor_flag(struct format_tree *ft) 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, { "client_written", FORMAT_TABLE_STRING,
format_cb_client_written format_cb_client_written
}, },
{ "config_files", FORMAT_TABLE_STRING,
format_cb_config_files
},
{ "cursor_character", FORMAT_TABLE_STRING, { "cursor_character", FORMAT_TABLE_STRING,
format_cb_cursor_character format_cb_cursor_character
}, },

1
tmux.1
View File

@ -4763,6 +4763,7 @@ The following variables are available, where appropriate:
.It Li "buffer_name" Ta "" Ta "Name of buffer" .It Li "buffer_name" Ta "" Ta "Name of buffer"
.It Li "buffer_sample" Ta "" Ta "Sample of start 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 "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_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_height" Ta "" Ta "Height of each client cell in pixels"
.It Li "client_cell_width" Ta "" Ta "Width of each client cell in pixels" .It Li "client_cell_width" Ta "" Ta "Width of each client cell in pixels"

37
tmux.c
View File

@ -142,11 +142,12 @@ expand_path(const char *path, const char *home)
return (xstrdup(path)); return (xstrdup(path));
} }
void static void
expand_paths(const char *s, char ***paths, u_int *n) expand_paths(const char *s, char ***paths, u_int *n, int ignore_errors)
{ {
const char *home = find_home(); const char *home = find_home();
char *copy, *next, *tmp, resolved[PATH_MAX], *expanded; char *copy, *next, *tmp, resolved[PATH_MAX], *expanded;
char *path;
u_int i; u_int i;
*paths = NULL; *paths = NULL;
@ -162,20 +163,26 @@ expand_paths(const char *s, char ***paths, u_int *n)
if (realpath(expanded, resolved) == NULL) { if (realpath(expanded, resolved) == NULL) {
log_debug("%s: realpath(\"%s\") failed: %s", __func__, log_debug("%s: realpath(\"%s\") failed: %s", __func__,
expanded, strerror(errno)); expanded, strerror(errno));
if (ignore_errors) {
free(expanded);
continue;
}
path = expanded;
} else {
path = xstrdup(resolved);
free(expanded); free(expanded);
continue;
} }
free(expanded);
for (i = 0; i < *n; i++) { for (i = 0; i < *n; i++) {
if (strcmp(resolved, (*paths)[i]) == 0) if (strcmp(path, (*paths)[i]) == 0)
break; break;
} }
if (i != *n) { if (i != *n) {
log_debug("%s: duplicate path: %s", __func__, resolved); log_debug("%s: duplicate path: %s", __func__, path);
free(path);
continue; continue;
} }
*paths = xreallocarray(*paths, (*n) + 1, sizeof *paths); *paths = xreallocarray(*paths, (*n) + 1, sizeof *paths);
(*paths)[(*n)++] = xstrdup(resolved); (*paths)[(*n)++] = path;
} }
free(copy); free(copy);
} }
@ -193,7 +200,7 @@ make_label(const char *label, char **cause)
label = "default"; label = "default";
uid = getuid(); uid = getuid();
expand_paths(TMUX_SOCK, &paths, &n); expand_paths(TMUX_SOCK, &paths, &n, 1);
if (n == 0) { if (n == 0) {
xasprintf(cause, "no suitable socket path"); xasprintf(cause, "no suitable socket path");
return (NULL); return (NULL);
@ -330,10 +337,11 @@ main(int argc, char **argv)
{ {
char *path = NULL, *label = NULL; char *path = NULL, *label = NULL;
char *cause, **var; char *cause, **var;
const char *s, *shell, *cwd; const char *s, *cwd;
int opt, keys, feat = 0; int opt, keys, feat = 0;
uint64_t flags = 0; uint64_t flags = 0;
const struct options_table_entry *oe; const struct options_table_entry *oe;
u_int i;
if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL && if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL &&
setlocale(LC_CTYPE, "C.UTF-8") == NULL) { setlocale(LC_CTYPE, "C.UTF-8") == NULL) {
@ -349,6 +357,7 @@ main(int argc, char **argv)
if (**argv == '-') if (**argv == '-')
flags = CLIENT_LOGIN; flags = CLIENT_LOGIN;
expand_paths(TMUX_CONF, &cfg_files, &cfg_nfiles, 1);
while ((opt = getopt(argc, argv, "2c:CDdf:lL:NqS:T:uUvV")) != -1) { while ((opt = getopt(argc, argv, "2c:CDdf:lL:NqS:T:uUvV")) != -1) {
switch (opt) { switch (opt) {
@ -368,7 +377,11 @@ main(int argc, char **argv)
flags |= CLIENT_CONTROL; flags |= CLIENT_CONTROL;
break; break;
case 'f': 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; break;
case 'V': case 'V':
printf("%s %s\n", getprogname(), getversion()); 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 * The default shell comes from SHELL or from the user's passwd entry
* if available. * if available.
*/ */
shell = getshell(); options_set_string(global_s_options, "default-shell", 0, "%s",
options_set_string(global_s_options, "default-shell", 0, "%s", shell); getshell());
/* Override keys to vi if VISUAL or EDITOR are set. */ /* Override keys to vi if VISUAL or EDITOR are set. */
if ((s = getenv("VISUAL")) != NULL || (s = getenv("EDITOR")) != NULL) { if ((s = getenv("VISUAL")) != NULL || (s = getenv("EDITOR")) != NULL) {

6
tmux.h
View File

@ -1887,7 +1887,6 @@ const char *sig2name(int);
const char *find_cwd(void); const char *find_cwd(void);
const char *find_home(void); const char *find_home(void);
const char *getversion(void); const char *getversion(void);
void expand_paths(const char *, char ***, u_int *);
/* proc.c */ /* proc.c */
struct imsg; struct imsg;
@ -1907,13 +1906,14 @@ pid_t proc_fork_and_daemon(int *);
/* cfg.c */ /* cfg.c */
extern int cfg_finished; extern int cfg_finished;
extern struct client *cfg_client; extern struct client *cfg_client;
extern char **cfg_files;
extern u_int cfg_nfiles;
extern int cfg_quiet;
void start_cfg(void); void start_cfg(void);
int load_cfg(const char *, struct client *, struct cmdq_item *, int, int load_cfg(const char *, struct client *, struct cmdq_item *, int,
struct cmdq_item **); struct cmdq_item **);
int load_cfg_from_buffer(const void *, size_t, const char *, int load_cfg_from_buffer(const void *, size_t, const char *,
struct client *, struct cmdq_item *, int, struct cmdq_item **); 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 printflike(1, 2) cfg_add_cause(const char *, ...);
void cfg_print_causes(struct cmdq_item *); void cfg_print_causes(struct cmdq_item *);
void cfg_show_causes(struct session *); void cfg_show_causes(struct session *);