From 293e331d69def60110bdc49b6453af905e0509b3 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Mon, 18 Feb 2013 23:20:21 +0000 Subject: [PATCH] Add functions to allocate and free command contexts rather than doing it all on the stack. --- cfg.c | 35 ++++++++++++++++++--------------- cmd-command-prompt.c | 19 +++++++++--------- cmd-confirm-before.c | 19 +++++++++--------- cmd-if-shell.c | 20 +++++++------------ cmd-list.c | 5 +++-- cmd-run-shell.c | 22 ++++++++------------- cmd.c | 46 +++++++++++++++++++++++++++++++------------- control.c | 18 +++++++++-------- key-bindings.c | 21 ++++++++++---------- server-client.c | 25 +++++++++++++----------- tmux.h | 11 +++++++---- window-choose.c | 19 +++++++++--------- 12 files changed, 142 insertions(+), 118 deletions(-) diff --git a/cfg.c b/cfg.c index c5c8c657..55922299 100644 --- a/cfg.c +++ b/cfg.c @@ -80,7 +80,7 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes) char *buf, *copy, *line, *cause; size_t len, oldlen; struct cmd_list *cmdlist; - struct cmd_ctx ctx; + struct cmd_ctx *ctx; enum cmd_retval retval; if ((f = fopen(path, "rb")) == NULL) { @@ -90,6 +90,21 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes) cfg_references++; + ctx = cmd_get_ctx(); + 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; + n = 0; line = NULL; retval = CMD_RETURN_NORMAL; @@ -146,22 +161,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 +187,8 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes) } fclose(f); + cmd_free_ctx(ctx); + cfg_references--; return (retval); diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c index ea380353..2a0e1aa7 100644 --- a/cmd-command-prompt.c +++ b/cmd-command-prompt.c @@ -150,7 +150,7 @@ cmd_command_prompt_callback(void *data, const char *s) struct cmd_command_prompt_cdata *cdata = data; struct client *c = cdata->c; struct cmd_list *cmdlist; - struct cmd_ctx ctx; + struct cmd_ctx *ctx; char *cause, *new_template, *prompt, *ptr; char *input = NULL; @@ -184,17 +184,18 @@ cmd_command_prompt_callback(void *data, const char *s) return (0); } - ctx.msgdata = NULL; - ctx.curclient = c; + ctx = cmd_get_ctx(); + ctx->msgdata = NULL; + ctx->curclient = c; + ctx->cmdclient = NULL; - ctx.error = key_bindings_error; - ctx.print = key_bindings_print; - ctx.info = key_bindings_info; + ctx->error = key_bindings_error; + ctx->print = key_bindings_print; + ctx->info = key_bindings_info; - ctx.cmdclient = NULL; - - cmd_list_exec(cmdlist, &ctx); + cmd_list_exec(cmdlist, ctx); cmd_list_free(cmdlist); + cmd_free_ctx(ctx); if (c->prompt_callbackfn != (void *) &cmd_command_prompt_callback) return (1); diff --git a/cmd-confirm-before.c b/cmd-confirm-before.c index 329027cc..33733c33 100644 --- a/cmd-confirm-before.c +++ b/cmd-confirm-before.c @@ -108,7 +108,7 @@ cmd_confirm_before_callback(void *data, const char *s) struct cmd_confirm_before_data *cdata = data; struct client *c = cdata->c; struct cmd_list *cmdlist; - struct cmd_ctx ctx; + struct cmd_ctx *ctx; char *cause; if (s == NULL || *s == '\0') @@ -125,17 +125,18 @@ cmd_confirm_before_callback(void *data, const char *s) return (0); } - ctx.msgdata = NULL; - ctx.curclient = c; + ctx = cmd_get_ctx(); + ctx->msgdata = NULL; + ctx->curclient = c; + ctx->cmdclient = NULL; - ctx.error = key_bindings_error; - ctx.print = key_bindings_print; - ctx.info = key_bindings_info; + ctx->error = key_bindings_error; + ctx->print = key_bindings_print; + ctx->info = key_bindings_info; - ctx.cmdclient = NULL; - - cmd_list_exec(cmdlist, &ctx); + cmd_list_exec(cmdlist, ctx); cmd_list_free(cmdlist); + cmd_free_ctx(ctx); return (0); } diff --git a/cmd-if-shell.c b/cmd-if-shell.c index 636cf805..6f0b151a 100644 --- a/cmd-if-shell.c +++ b/cmd-if-shell.c @@ -47,7 +47,7 @@ const struct cmd_entry cmd_if_shell_entry = { struct cmd_if_shell_data { char *cmd_if; char *cmd_else; - struct cmd_ctx ctx; + struct cmd_ctx *ctx; }; enum cmd_retval @@ -63,12 +63,9 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx) cdata->cmd_else = xstrdup(args->argv[2]); else cdata->cmd_else = NULL; - memcpy(&cdata->ctx, ctx, sizeof cdata->ctx); - if (ctx->cmdclient != NULL) - ctx->cmdclient->references++; - if (ctx->curclient != NULL) - ctx->curclient->references++; + cdata->ctx = ctx; + cmd_ref_ctx(ctx); job_run(shellcmd, cmd_if_shell_callback, cmd_if_shell_free, cdata); @@ -79,7 +76,7 @@ void cmd_if_shell_callback(struct job *job) { struct cmd_if_shell_data *cdata = job->data; - struct cmd_ctx *ctx = &cdata->ctx; + struct cmd_ctx *ctx = cdata->ctx; struct cmd_list *cmdlist; char *cause, *cmd; @@ -105,14 +102,11 @@ void cmd_if_shell_free(void *data) { struct cmd_if_shell_data *cdata = data; - struct cmd_ctx *ctx = &cdata->ctx; + struct cmd_ctx *ctx = cdata->ctx; - if (ctx->cmdclient != NULL) { - ctx->cmdclient->references--; + if (ctx->cmdclient != NULL) ctx->cmdclient->flags |= CLIENT_EXIT; - } - if (ctx->curclient != NULL) - ctx->curclient->references--; + cmd_free_ctx(ctx); free(cdata->cmd_else); free(cdata->cmd_if); diff --git a/cmd-list.c b/cmd-list.c index 1717ec3b..6820d007 100644 --- a/cmd-list.c +++ b/cmd-list.c @@ -97,7 +97,7 @@ cmd_list_exec(struct cmd_list *cmdlist, struct cmd_ctx *ctx) TAILQ_FOREACH(cmd, &cmdlist->list, qentry) { if (guards) ctx->print(ctx, "%%begin"); - n = cmd_exec(cmd, ctx); + n = cmd->entry->exec(cmd, ctx); if (guards) ctx->print(ctx, "%%end"); @@ -146,7 +146,8 @@ cmd_list_free(struct cmd_list *cmdlist) while (!TAILQ_EMPTY(&cmdlist->list)) { cmd = TAILQ_FIRST(&cmdlist->list); TAILQ_REMOVE(&cmdlist->list, cmd, qentry); - cmd_free(cmd); + args_free(cmd->args); + free(cmd); } free(cmdlist); } diff --git a/cmd-run-shell.c b/cmd-run-shell.c index 44e796df..03cbc292 100644 --- a/cmd-run-shell.c +++ b/cmd-run-shell.c @@ -47,7 +47,7 @@ const struct cmd_entry cmd_run_shell_entry = { struct cmd_run_shell_data { char *cmd; - struct cmd_ctx ctx; + struct cmd_ctx *ctx; u_int wp_id; }; @@ -55,7 +55,7 @@ void cmd_run_shell_print(struct job *job, const char *msg) { struct cmd_run_shell_data *cdata = job->data; - struct cmd_ctx *ctx = &cdata->ctx; + struct cmd_ctx *ctx = cdata->ctx; struct window_pane *wp; wp = window_pane_find_by_id(cdata->wp_id); @@ -84,12 +84,9 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx) cdata = xmalloc(sizeof *cdata); cdata->cmd = xstrdup(args->argv[0]); cdata->wp_id = wp->id; - memcpy(&cdata->ctx, ctx, sizeof cdata->ctx); - if (ctx->cmdclient != NULL) - ctx->cmdclient->references++; - if (ctx->curclient != NULL) - ctx->curclient->references++; + cdata->ctx = ctx; + cmd_ref_ctx(ctx); job_run(shellcmd, cmd_run_shell_callback, cmd_run_shell_free, cdata); @@ -100,7 +97,7 @@ void cmd_run_shell_callback(struct job *job) { struct cmd_run_shell_data *cdata = job->data; - struct cmd_ctx *ctx = &cdata->ctx; + struct cmd_ctx *ctx = cdata->ctx; char *cmd, *msg, *line; size_t size; int retcode; @@ -154,14 +151,11 @@ void cmd_run_shell_free(void *data) { struct cmd_run_shell_data *cdata = data; - struct cmd_ctx *ctx = &cdata->ctx; + struct cmd_ctx *ctx = cdata->ctx; - if (ctx->cmdclient != NULL) { - ctx->cmdclient->references--; + if (ctx->cmdclient != NULL) ctx->cmdclient->flags |= CLIENT_EXIT; - } - if (ctx->curclient != NULL) - ctx->curclient->references--; + cmd_free_ctx(ctx); free(cdata->cmd); free(cdata); diff --git a/cmd.c b/cmd.c index 52c1a303..23e86cff 100644 --- a/cmd.c +++ b/cmd.c @@ -132,6 +132,39 @@ struct winlink *cmd_find_window_offset(const char *, struct session *, int *); int cmd_find_index_offset(const char *, struct session *, int *); struct window_pane *cmd_find_pane_offset(const char *, struct winlink *); +struct cmd_ctx * +cmd_get_ctx(void) +{ + struct cmd_ctx *ctx; + + ctx = xcalloc(1, sizeof *ctx); + ctx->references = 0; + + cmd_ref_ctx(ctx); + return (ctx); +} + +void +cmd_free_ctx(struct cmd_ctx *ctx) +{ + if (ctx->cmdclient != NULL) + ctx->cmdclient->references--; + if (ctx->curclient != NULL) + ctx->curclient->references--; + if (--ctx->references == 0) + free(ctx); +} + +void +cmd_ref_ctx(struct cmd_ctx *ctx) +{ + ctx->references++; + if (ctx->cmdclient != NULL) + ctx->cmdclient->references++; + if (ctx->curclient != NULL) + ctx->curclient->references++; +} + int cmd_pack_argv(int argc, char **argv, char *buf, size_t len) { @@ -281,19 +314,6 @@ usage: return (NULL); } -enum cmd_retval -cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx) -{ - return (cmd->entry->exec(cmd, ctx)); -} - -void -cmd_free(struct cmd *cmd) -{ - args_free(cmd->args); - free(cmd); -} - size_t cmd_print(struct cmd *cmd, char *buf, size_t len) { diff --git a/control.c b/control.c index b5ec6bdb..f00f57f9 100644 --- a/control.c +++ b/control.c @@ -93,7 +93,7 @@ void control_callback(struct client *c, int closed, unused void *data) { char *line, *cause; - struct cmd_ctx ctx; + struct cmd_ctx *ctx; struct cmd_list *cmdlist; if (closed) @@ -108,22 +108,24 @@ control_callback(struct client *c, int closed, unused void *data) break; } - ctx.msgdata = NULL; - ctx.cmdclient = NULL; - ctx.curclient = c; + ctx = cmd_get_ctx(); + ctx->msgdata = NULL; + ctx->cmdclient = NULL; + ctx->curclient = c; - ctx.error = control_msg_error; - ctx.print = control_msg_print; - ctx.info = control_msg_info; + ctx->error = control_msg_error; + ctx->print = control_msg_print; + ctx->info = control_msg_info; if (cmd_string_parse(line, &cmdlist, &cause) != 0) { control_write(c, "%%error in line \"%s\": %s", line, cause); free(cause); } else { - cmd_list_exec(cmdlist, &ctx); + cmd_list_exec(cmdlist, ctx); cmd_list_free(cmdlist); } + cmd_free_ctx(ctx); free(line); } diff --git a/key-bindings.c b/key-bindings.c index cf5237d4..a25d3700 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -262,18 +262,18 @@ key_bindings_info(struct cmd_ctx *ctx, const char *fmt, ...) void key_bindings_dispatch(struct key_binding *bd, struct client *c) { - struct cmd_ctx ctx; + struct cmd_ctx *ctx; struct cmd *cmd; int readonly; - ctx.msgdata = NULL; - ctx.curclient = c; + ctx = cmd_get_ctx(); + ctx->msgdata = NULL; + ctx->cmdclient = NULL; + ctx->curclient = c; - ctx.error = key_bindings_error; - ctx.print = key_bindings_print; - ctx.info = key_bindings_info; - - ctx.cmdclient = NULL; + ctx->error = key_bindings_error; + ctx->print = key_bindings_print; + ctx->info = key_bindings_info; readonly = 1; TAILQ_FOREACH(cmd, &bd->cmdlist->list, qentry) { @@ -281,9 +281,10 @@ key_bindings_dispatch(struct key_binding *bd, struct client *c) readonly = 0; } if (!readonly && c->flags & CLIENT_READONLY) { - key_bindings_info(&ctx, "Client is read-only"); + key_bindings_info(ctx, "client is read-only"); return; } - cmd_list_exec(bd->cmdlist, &ctx); + cmd_list_exec(bd->cmdlist, ctx); + cmd_free_ctx(ctx); } diff --git a/server-client.c b/server-client.c index d4449a50..1500419c 100644 --- a/server-client.c +++ b/server-client.c @@ -864,24 +864,24 @@ server_client_msg_info(struct cmd_ctx *ctx, const char *fmt, ...) void server_client_msg_command(struct client *c, struct msg_command_data *data) { - struct cmd_ctx ctx; + struct cmd_ctx *ctx; struct cmd_list *cmdlist = NULL; int argc; char **argv, *cause; - ctx.error = server_client_msg_error; - ctx.print = server_client_msg_print; - ctx.info = server_client_msg_info; + ctx = cmd_get_ctx(); + ctx->msgdata = data; + ctx->curclient = NULL; + ctx->cmdclient = c; - ctx.msgdata = data; - ctx.curclient = NULL; - - ctx.cmdclient = c; + ctx->error = server_client_msg_error; + ctx->print = server_client_msg_print; + ctx->info = server_client_msg_info; argc = data->argc; data->argv[(sizeof data->argv) - 1] = '\0'; if (cmd_unpack_argv(data->argv, sizeof data->argv, argc, &argv) != 0) { - server_client_msg_error(&ctx, "command too long"); + server_client_msg_error(ctx, "command too long"); goto error; } @@ -892,13 +892,13 @@ server_client_msg_command(struct client *c, struct msg_command_data *data) } if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) { - server_client_msg_error(&ctx, "%s", cause); + server_client_msg_error(ctx, "%s", cause); cmd_free_argv(argc, argv); goto error; } cmd_free_argv(argc, argv); - switch (cmd_list_exec(cmdlist, &ctx)) + switch (cmd_list_exec(cmdlist, ctx)) { case CMD_RETURN_ERROR: case CMD_RETURN_NORMAL: @@ -909,11 +909,14 @@ server_client_msg_command(struct client *c, struct msg_command_data *data) break; } cmd_list_free(cmdlist); + cmd_free_ctx(ctx); return; error: if (cmdlist != NULL) cmd_list_free(cmdlist); + cmd_free_ctx(ctx); + c->flags |= CLIENT_EXIT; } diff --git a/tmux.h b/tmux.h index d602b145..df47cdb3 100644 --- a/tmux.h +++ b/tmux.h @@ -1362,8 +1362,10 @@ struct cmd_ctx { * cmdclient and curclient may both be NULL if the command is in the * configuration file. */ - struct client *curclient; - struct client *cmdclient; + struct client *curclient; + struct client *cmdclient; + + int references; struct msg_command_data *msgdata; @@ -1710,13 +1712,14 @@ long long args_strtonum( struct args *, u_char, long long, long long, char **); /* cmd.c */ +struct cmd_ctx *cmd_get_ctx(void); +void cmd_free_ctx(struct cmd_ctx *); +void cmd_ref_ctx(struct cmd_ctx *); int cmd_pack_argv(int, char **, char *, size_t); int cmd_unpack_argv(char *, size_t, int, char ***); char **cmd_copy_argv(int, char *const *); void cmd_free_argv(int, char **); struct cmd *cmd_parse(int, char **, char **); -enum cmd_retval cmd_exec(struct cmd *, struct cmd_ctx *); -void cmd_free(struct cmd *); size_t cmd_print(struct cmd *, char *, size_t); struct session *cmd_current_session(struct cmd_ctx *, int); struct client *cmd_current_client(struct cmd_ctx *); diff --git a/window-choose.c b/window-choose.c index d37527de..e48db7e5 100644 --- a/window-choose.c +++ b/window-choose.c @@ -200,7 +200,7 @@ window_choose_data_free(struct window_choose_data *wcd) void window_choose_data_run(struct window_choose_data *cdata) { - struct cmd_ctx ctx; + struct cmd_ctx *ctx; struct cmd_list *cmdlist; char *cause; @@ -220,17 +220,18 @@ window_choose_data_run(struct window_choose_data *cdata) return; } - ctx.msgdata = NULL; - ctx.curclient = cdata->start_client; + ctx = cmd_get_ctx(); + ctx->msgdata = NULL; + ctx->curclient = cdata->start_client; + ctx->cmdclient = NULL; - ctx.error = key_bindings_error; - ctx.print = key_bindings_print; - ctx.info = key_bindings_info; + ctx->error = key_bindings_error; + ctx->print = key_bindings_print; + ctx->info = key_bindings_info; - ctx.cmdclient = NULL; - - cmd_list_exec(cmdlist, &ctx); + cmd_list_exec(cmdlist, ctx); cmd_list_free(cmdlist); + cmd_free_ctx(ctx); } void