mirror of
https://github.com/tmate-io/tmate.git
synced 2024-11-27 02:23:15 +01:00
Add functions to allocate and free command contexts rather than doing it all on
the stack.
This commit is contained in:
parent
2a91025581
commit
293e331d69
35
cfg.c
35
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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
46
cmd.c
46
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)
|
||||
{
|
||||
|
18
control.c
18
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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
11
tmux.h
11
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 *);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user