From 51ac2a3202d55c439976ecce49229e35865c7ebd Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Thu, 21 Mar 2013 16:54:37 +0000 Subject: Fix a couple of memory leaks, from Romain Francoise. --- cfg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'cfg.c') diff --git a/cfg.c b/cfg.c index f9ad300f..aa2ceea4 100644 --- a/cfg.c +++ b/cfg.c @@ -131,8 +131,10 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes) buf = copy; while (isspace((u_char)*buf)) buf++; - if (*buf == '\0') + if (*buf == '\0') { + free(copy); continue; + } if (cmd_string_parse(buf, &cmdlist, &cause) != 0) { free(copy); -- cgit From 8d59b189cc9e83ac0049fc3108de1b822fa7b4ce Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Fri, 22 Mar 2013 10:31:22 +0000 Subject: No more lint means no more ARGSUSED. --- cfg.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'cfg.c') diff --git a/cfg.c b/cfg.c index aa2ceea4..1967fe99 100644 --- a/cfg.c +++ b/cfg.c @@ -40,13 +40,11 @@ int cfg_finished; int cfg_references; struct causelist cfg_causes; -/* ARGSUSED */ void printflike2 cfg_print(unused struct cmd_ctx *ctx, unused const char *fmt, ...) { } -/* ARGSUSED */ void printflike2 cfg_error(unused struct cmd_ctx *ctx, const char *fmt, ...) { -- cgit From 8c545bbfa8a9fd984437a61c3f0556822ad6ad92 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Fri, 22 Mar 2013 10:41:57 +0000 Subject: Don't try to print unterminated strings when loading configuration file. --- cfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cfg.c') diff --git a/cfg.c b/cfg.c index 1967fe99..92e0bb45 100644 --- a/cfg.c +++ b/cfg.c @@ -97,7 +97,7 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes) /* Trim \n. */ if (buf[len - 1] == '\n') len--; - log_debug ("%s: %s", path, buf); + log_debug("%s: %.*s", path, (int)len, buf); /* Current line is the continuation of the previous one. */ if (line != NULL) { -- cgit From 0ff9275ad75e7ef8933d290bb274d5420a625b4f Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Fri, 22 Mar 2013 15:50:13 +0000 Subject: load_cfg can actually use the same context now they are reference counted. --- cfg.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'cfg.c') diff --git a/cfg.c b/cfg.c index 92e0bb45..1548fb14 100644 --- a/cfg.c +++ b/cfg.c @@ -73,14 +73,13 @@ cfg_add_cause(struct causelist *causes, const char *fmt, ...) * causes. Note that causes must be initialised by the caller! */ enum cmd_retval -load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes) +load_cfg(const char *path, struct cmd_ctx *ctx, struct causelist *causes) { FILE *f; u_int n; char *buf, *copy, *line, *cause; size_t len, oldlen; struct cmd_list *cmdlist; - struct cmd_ctx ctx; enum cmd_retval retval; if ((f = fopen(path, "rb")) == NULL) { @@ -90,6 +89,15 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes) cfg_references++; + if (ctx != NULL) + cmd_ref_ctx(ctx); + else { + ctx = cmd_get_ctx(); + ctx->error = cfg_error; + ctx->print = cfg_print; + ctx->info = cfg_print; + } + n = 0; line = NULL; retval = CMD_RETURN_NORMAL; @@ -146,22 +154,8 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes) if (cmdlist == NULL) continue; - if (ctxin == NULL) { - ctx.msgdata = NULL; - ctx.curclient = NULL; - ctx.cmdclient = NULL; - } else { - ctx.msgdata = ctxin->msgdata; - ctx.curclient = ctxin->curclient; - ctx.cmdclient = ctxin->cmdclient; - } - - ctx.error = cfg_error; - ctx.print = cfg_print; - ctx.info = cfg_print; - cfg_cause = NULL; - switch (cmd_list_exec(cmdlist, &ctx)) { + switch (cmd_list_exec(cmdlist, ctx)) { case CMD_RETURN_YIELD: if (retval != CMD_RETURN_ATTACH) retval = CMD_RETURN_YIELD; @@ -186,6 +180,8 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes) } fclose(f); + cmd_free_ctx(ctx); + cfg_references--; return (retval); -- cgit From 2243cfbe7559e6cf48194ff95dcd7eb6df5fe41d Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Fri, 22 Mar 2013 15:54:29 +0000 Subject: Need to set clients in context before changing their reference count. --- cfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cfg.c') diff --git a/cfg.c b/cfg.c index 1548fb14..b7b0ec78 100644 --- a/cfg.c +++ b/cfg.c @@ -92,7 +92,7 @@ load_cfg(const char *path, struct cmd_ctx *ctx, struct causelist *causes) if (ctx != NULL) cmd_ref_ctx(ctx); else { - ctx = cmd_get_ctx(); + ctx = cmd_get_ctx(NULL, NULL); ctx->error = cfg_error; ctx->print = cfg_print; ctx->info = cfg_print; -- cgit From 20636d956dd36c1f14152569a4d44a50eea9083d Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Sun, 24 Mar 2013 09:54:10 +0000 Subject: Add a command queue to standardize and simplify commands that call other commands and allow a command to block execution of subsequent commands. This allows run-shell and if-shell to be synchronous which has been much requested. Each client has a default command queue and commands are consumed one at a time from it. A command may suspend execution from the queue by returning CMD_RETURN_WAIT and then resume it by calling cmd_continue() - for example run-shell does this from the callback that is fired after the job is freed. When the command queue becomes empty, command clients are automatically exited (unless attaching). A callback is also fired - this is used for nested commands in, for example, if-shell which can block execution of the client's cmdq until a new cmdq becomes empty. Also merge all the old error/info/print functions together and lose the old curclient/cmdclient distinction - a cmdq is bound to one client (or none if in the configuration file), this is a command client if c->session is NULL otherwise an attached client. --- cfg.c | 126 ++++++++++++++++++------------------------------------------------ 1 file changed, 33 insertions(+), 93 deletions(-) (limited to 'cfg.c') diff --git a/cfg.c b/cfg.c index b7b0ec78..e4069d68 100644 --- a/cfg.c +++ b/cfg.c @@ -27,80 +27,27 @@ #include "tmux.h" -/* - * Config file parser. Pretty quick and simple, each line is parsed into a - * argv array and executed as a command. - */ - -void printflike2 cfg_print(struct cmd_ctx *, const char *, ...); -void printflike2 cfg_error(struct cmd_ctx *, const char *, ...); - -char *cfg_cause; +struct cmd_q *cfg_cmd_q; int cfg_finished; -int cfg_references; +int cfg_references; struct causelist cfg_causes; -void printflike2 -cfg_print(unused struct cmd_ctx *ctx, unused const char *fmt, ...) -{ -} - -void printflike2 -cfg_error(unused struct cmd_ctx *ctx, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - xvasprintf(&cfg_cause, fmt, ap); - va_end(ap); -} - -void printflike2 -cfg_add_cause(struct causelist *causes, const char *fmt, ...) -{ - char *cause; - va_list ap; - - va_start(ap, fmt); - xvasprintf(&cause, fmt, ap); - va_end(ap); - - ARRAY_ADD(causes, cause); -} - -/* - * Load configuration file. Returns -1 for an error with a list of messages in - * causes. Note that causes must be initialised by the caller! - */ -enum cmd_retval -load_cfg(const char *path, struct cmd_ctx *ctx, struct causelist *causes) +int +load_cfg(const char *path, struct cmd_q *cmdq, char **cause) { FILE *f; - u_int n; - char *buf, *copy, *line, *cause; + u_int n, found; + char *buf, *copy, *line, *cause1, *msg; size_t len, oldlen; struct cmd_list *cmdlist; - enum cmd_retval retval; if ((f = fopen(path, "rb")) == NULL) { - cfg_add_cause(causes, "%s: %s", path, strerror(errno)); - return (CMD_RETURN_ERROR); - } - - cfg_references++; - - if (ctx != NULL) - cmd_ref_ctx(ctx); - else { - ctx = cmd_get_ctx(NULL, NULL); - ctx->error = cfg_error; - ctx->print = cfg_print; - ctx->info = cfg_print; + xasprintf(cause, "%s: %s", path, strerror(errno)); + return (-1); } - n = 0; + n = found = 0; line = NULL; - retval = CMD_RETURN_NORMAL; while ((buf = fgetln(f, &len))) { /* Trim \n. */ if (buf[len - 1] == '\n') @@ -142,53 +89,47 @@ load_cfg(const char *path, struct cmd_ctx *ctx, struct causelist *causes) continue; } - if (cmd_string_parse(buf, &cmdlist, &cause) != 0) { + /* Parse and run the command. */ + if (cmd_string_parse(buf, &cmdlist, path, n, &cause1) != 0) { free(copy); - if (cause == NULL) + if (cause1 == NULL) continue; - cfg_add_cause(causes, "%s: %u: %s", path, n, cause); - free(cause); + xasprintf(&msg, "%s:%u: %s", path, n, cause1); + ARRAY_ADD(&cfg_causes, msg); + free(cause1); continue; } free(copy); + if (cmdlist == NULL) continue; - - cfg_cause = NULL; - switch (cmd_list_exec(cmdlist, ctx)) { - case CMD_RETURN_YIELD: - if (retval != CMD_RETURN_ATTACH) - retval = CMD_RETURN_YIELD; - break; - case CMD_RETURN_ATTACH: - retval = CMD_RETURN_ATTACH; - break; - case CMD_RETURN_ERROR: - case CMD_RETURN_NORMAL: - break; - } + cmdq_append(cmdq, cmdlist); cmd_list_free(cmdlist); - if (cfg_cause != NULL) { - cfg_add_cause(causes, "%s: %d: %s", path, n, cfg_cause); - free(cfg_cause); - } + found++; } - if (line != NULL) { - cfg_add_cause(causes, - "%s: %d: line continuation at end of file", path, n); + if (line != NULL) free(line); - } fclose(f); - cmd_free_ctx(ctx); + return (found); +} + +void +cfg_default_done(unused struct cmd_q *cmdq) +{ + if (--cfg_references != 0) + return; + cfg_finished = 1; - cfg_references--; + if (!RB_EMPTY(&sessions)) + cfg_show_causes(RB_MIN(sessions, &sessions)); - return (retval); + cmdq_free(cfg_cmd_q); + cfg_cmd_q = NULL; } void -show_cfg_causes(struct session *s) +cfg_show_causes(struct session *s) { struct window_pane *wp; char *cause; @@ -196,7 +137,6 @@ show_cfg_causes(struct session *s) if (s == NULL || ARRAY_EMPTY(&cfg_causes)) return; - wp = s->curw->window->active; window_pane_set_mode(wp, &window_copy_mode); -- cgit From ebd9c615c8137e68f8831d4dbfd968a2f6a10a72 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Mon, 25 Mar 2013 10:06:13 +0000 Subject: Add some additional debug logging. --- cfg.c | 1 + 1 file changed, 1 insertion(+) (limited to 'cfg.c') diff --git a/cfg.c b/cfg.c index e4069d68..c625a2fb 100644 --- a/cfg.c +++ b/cfg.c @@ -41,6 +41,7 @@ load_cfg(const char *path, struct cmd_q *cmdq, char **cause) size_t len, oldlen; struct cmd_list *cmdlist; + log_debug("loading %s", path); if ((f = fopen(path, "rb")) == NULL) { xasprintf(cause, "%s: %s", path, strerror(errno)); return (-1); -- cgit