=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/cmd-run-shell.c,v retrieving revision 1.1 retrieving revision 1.2 diff -c -r1.1 -r1.2 *** src/usr.bin/tmux/cmd-run-shell.c 2009/09/20 19:15:01 1.1 --- src/usr.bin/tmux/cmd-run-shell.c 2009/10/11 08:58:05 1.2 *************** *** 1,4 **** ! /* $OpenBSD: cmd-run-shell.c,v 1.1 2009/09/20 19:15:01 nicm Exp $ */ /* * Copyright (c) 2009 Tiago Cunha --- 1,4 ---- ! /* $OpenBSD: cmd-run-shell.c,v 1.2 2009/10/11 08:58:05 nicm Exp $ */ /* * Copyright (c) 2009 Tiago Cunha *************** *** 29,34 **** --- 29,37 ---- 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 = { "run-shell", "run", "command", *************** *** 40,96 **** cmd_target_print }; int cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx) { ! struct cmd_target_data *data = self->data; ! FILE *fp; ! char *buf, *lbuf, *msg; ! size_t len; ! int has_output, ret, status; ! if ((fp = popen(data->arg, "r")) == NULL) { ! ctx->error(ctx, "popen error"); ! return (-1); ! } ! has_output = 0; ! lbuf = NULL; ! while ((buf = fgetln(fp, &len)) != NULL) { ! if (buf[len - 1] == '\n') ! buf[len - 1] = '\0'; ! else { ! lbuf = xmalloc(len + 1); ! memcpy(lbuf, buf, len); ! lbuf[len] = '\0'; ! buf = lbuf; } ! ctx->print(ctx, "%s", buf); ! has_output = 1; } - if (lbuf != NULL) - xfree(lbuf); msg = NULL; ! status = pclose(fp); ! ! if (WIFEXITED(status)) { ! if ((ret = WEXITSTATUS(status)) == 0) ! return (0); ! xasprintf(&msg, "'%s' returned %d", data->arg, ret); ! } else if (WIFSIGNALED(status)) { ! xasprintf( ! &msg, "'%s' terminated by signal %d", data->arg, ! WTERMSIG(status)); } - if (msg != NULL) { ! if (has_output) ctx->print(ctx, "%s", msg); else ctx->info(ctx, "%s", msg); xfree(msg); } ! return (0); } --- 43,139 ---- cmd_target_print }; + struct cmd_run_shell_data { + char *cmd; + struct cmd_ctx ctx; + }; + int cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx) { ! struct cmd_target_data *data = self->data; ! struct cmd_run_shell_data *cdata; ! struct job *job; ! cdata = xmalloc(sizeof *cdata); ! cdata->cmd = xstrdup(data->arg); ! memcpy(&cdata->ctx, ctx, sizeof cdata->ctx); ! if (ctx->cmdclient != NULL) ! ctx->cmdclient->references++; ! if (ctx->curclient != NULL) ! ctx->curclient->references++; ! ! job = job_add(NULL, NULL, ! data->arg, cmd_run_shell_callback, cmd_run_shell_free, cdata); ! job_run(job); ! ! 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; ! } } ! llen = buf + len - line; ! if (llen > 0 && llen < INT_MAX) ! ctx->print(ctx, "%.*s", (int) llen, line); } msg = NULL; ! if (WIFEXITED(job->status)) { ! if ((retcode = WEXITSTATUS(job->status)) != 0) ! xasprintf(&msg, "'%s' returned %d", cmd, retcode); ! } else if (WIFSIGNALED(job->status)) { ! retcode = WTERMSIG(job->status); ! xasprintf(&msg, "'%s' terminated by signal %d", cmd, retcode); } if (msg != NULL) { ! if (len != 0) ctx->print(ctx, "%s", msg); else ctx->info(ctx, "%s", msg); xfree(msg); } ! 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); }