1
0
mirror of https://github.com/tmux/tmux.git synced 2025-04-29 01:08:49 +00:00

Sync OpenBSD patchset 384:

Switch run-shell over to queue the command in the background like #().
This commit is contained in:
Tiago Cunha 2009-10-12 00:25:25 +00:00
parent c8d0608369
commit 197f8b88bf
4 changed files with 94 additions and 47 deletions

View File

@ -1,4 +1,4 @@
/* $Id: cmd-run-shell.c,v 1.1 2009-09-20 22:20:10 tcunha Exp $ */ /* $Id: cmd-run-shell.c,v 1.2 2009-10-12 00:25:25 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@ -29,6 +29,9 @@
int cmd_run_shell_exec(struct cmd *, struct cmd_ctx *); int cmd_run_shell_exec(struct cmd *, struct cmd_ctx *);
void cmd_run_shell_callback(struct job *);
void cmd_run_shell_free(void *);
const struct cmd_entry cmd_run_shell_entry = { const struct cmd_entry cmd_run_shell_entry = {
"run-shell", "run", "run-shell", "run",
"command", "command",
@ -40,57 +43,97 @@ const struct cmd_entry cmd_run_shell_entry = {
cmd_target_print cmd_target_print
}; };
struct cmd_run_shell_data {
char *cmd;
struct cmd_ctx ctx;
};
int int
cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_target_data *data = self->data;
FILE *fp; struct cmd_run_shell_data *cdata;
char *buf, *lbuf, *msg; struct job *job;
size_t len;
int has_output, ret, status;
if ((fp = popen(data->arg, "r")) == NULL) { cdata = xmalloc(sizeof *cdata);
ctx->error(ctx, "popen error"); cdata->cmd = xstrdup(data->arg);
return (-1); memcpy(&cdata->ctx, ctx, sizeof cdata->ctx);
}
has_output = 0; if (ctx->cmdclient != NULL)
lbuf = NULL; ctx->cmdclient->references++;
while ((buf = fgetln(fp, &len)) != NULL) { if (ctx->curclient != NULL)
if (buf[len - 1] == '\n') ctx->curclient->references++;
buf[len - 1] = '\0';
else { job = job_add(NULL, NULL,
lbuf = xmalloc(len + 1); data->arg, cmd_run_shell_callback, cmd_run_shell_free, cdata);
memcpy(lbuf, buf, len); job_run(job);
lbuf[len] = '\0';
buf = lbuf; return (1); /* don't let client exit */
}
void
cmd_run_shell_callback(struct job *job)
{
struct cmd_run_shell_data *cdata = job->data;
struct cmd_ctx *ctx = &cdata->ctx;
char *cmd, *msg, *line, *buf;
size_t off, len, llen;
int retcode;
buf = BUFFER_OUT(job->out);
len = BUFFER_USED(job->out);
cmd = cdata->cmd;
if (len != 0) {
line = buf;
for (off = 0; off < len; off++) {
if (buf[off] == '\n') {
llen = buf + off - line;
if (llen > INT_MAX)
break;
ctx->print(ctx, "%.*s", (int) llen, line);
line = buf + off + 1;
}
} }
ctx->print(ctx, "%s", buf); llen = buf + len - line;
has_output = 1; if (llen > 0 && llen < INT_MAX)
ctx->print(ctx, "%.*s", (int) llen, line);
} }
if (lbuf != NULL)
xfree(lbuf);
msg = NULL; msg = NULL;
status = pclose(fp); if (WIFEXITED(job->status)) {
if ((retcode = WEXITSTATUS(job->status)) != 0)
if (WIFEXITED(status)) { xasprintf(&msg, "'%s' returned %d", cmd, retcode);
if ((ret = WEXITSTATUS(status)) == 0) } else if (WIFSIGNALED(job->status)) {
return (0); retcode = WTERMSIG(job->status);
xasprintf(&msg, "'%s' returned %d", data->arg, ret); xasprintf(&msg, "'%s' terminated by signal %d", cmd, retcode);
} else if (WIFSIGNALED(status)) {
xasprintf(
&msg, "'%s' terminated by signal %d", data->arg,
WTERMSIG(status));
} }
if (msg != NULL) { if (msg != NULL) {
if (has_output) if (len != 0)
ctx->print(ctx, "%s", msg); ctx->print(ctx, "%s", msg);
else else
ctx->info(ctx, "%s", msg); ctx->info(ctx, "%s", msg);
xfree(msg); xfree(msg);
} }
return (0); job_free(job); /* calls cmd_run_shell_free */
}
void
cmd_run_shell_free(void *data)
{
struct cmd_run_shell_data *cdata = data;
struct cmd_ctx *ctx = &cdata->ctx;
return;
if (ctx->cmdclient != NULL) {
ctx->cmdclient->references--;
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
}
if (ctx->curclient != NULL)
ctx->curclient->references--;
xfree(cdata->cmd);
xfree(cdata);
} }

4
job.c
View File

@ -1,4 +1,4 @@
/* $Id: job.c,v 1.5 2009-10-12 00:22:17 tcunha Exp $ */ /* $Id: job.c,v 1.6 2009-10-12 00:25:25 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -69,7 +69,6 @@ job_tree_free(struct jobs *jobs)
while (!RB_EMPTY(jobs)) { while (!RB_EMPTY(jobs)) {
job = RB_ROOT(jobs); job = RB_ROOT(jobs);
RB_REMOVE(jobs, jobs, job); RB_REMOVE(jobs, jobs, job);
SLIST_REMOVE(&all_jobs, job, job, lentry);
job_free(job); job_free(job);
} }
} }
@ -119,6 +118,7 @@ job_free(struct job *job)
{ {
job_kill(job); job_kill(job);
SLIST_REMOVE(&all_jobs, job, job, lentry);
xfree(job->cmd); xfree(job->cmd);
if (job->freefn != NULL && job->data != NULL) if (job->freefn != NULL && job->data != NULL)

View File

@ -1,4 +1,4 @@
/* $Id: server.c,v 1.204 2009-10-12 00:21:08 tcunha Exp $ */ /* $Id: server.c,v 1.205 2009-10-12 00:25:25 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -813,13 +813,17 @@ void
server_check_jobs(void) server_check_jobs(void)
{ {
struct job *job; struct job *job;
restart:
SLIST_FOREACH(job, &all_jobs, lentry) { SLIST_FOREACH(job, &all_jobs, lentry) {
if (job->flags & JOB_DONE || job->fd != -1 || job->pid != -1) if (job->flags & JOB_DONE || job->fd != -1 || job->pid != -1)
continue; continue;
if (job->callbackfn != NULL)
job->callbackfn(job);
job->flags |= JOB_DONE; job->flags |= JOB_DONE;
if (job->callbackfn != NULL) {
job->callbackfn(job);
goto restart; /* could be freed by callback */
}
} }
} }

8
tmux.1
View File

@ -1,4 +1,4 @@
.\" $Id: tmux.1,v 1.187 2009-10-12 00:09:48 tcunha Exp $ .\" $Id: tmux.1,v 1.188 2009-10-12 00:25:25 tcunha Exp $
.\" .\"
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> .\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
.\" .\"
@ -14,7 +14,7 @@
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: October 10 2009 $ .Dd $Mdocdate: October 11 2009 $
.Dt TMUX 1 .Dt TMUX 1
.Os .Os
.Sh NAME .Sh NAME
@ -2068,8 +2068,8 @@ option.
.D1 (alias: Ic run ) .D1 (alias: Ic run )
Execute Execute
.Ar command .Ar command
without creating a window. in the background without creating a window.
Any output to stdout is displayed in output mode. After the command finishes, any output to stdout is displayed in output mode.
If If
.Ar command .Ar command
doesn't return success, the exit status is also displayed. doesn't return success, the exit status is also displayed.