Annotation of src/usr.bin/tmux/cmd-run-shell.c, Revision 1.10
1.10 ! nicm 1: /* $OpenBSD: cmd-run-shell.c,v 1.9 2010/07/24 20:11:59 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
1.3 nicm 5: * Copyright (c) 2009 Nicholas Marriott <nicm@openbsd.org>
1.1 nicm 6: *
7: * Permission to use, copy, modify, and distribute this software for any
8: * purpose with or without fee is hereby granted, provided that the above
9: * copyright notice and this permission notice appear in all copies.
10: *
11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
16: * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
17: * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18: */
19:
20: #include <sys/types.h>
21: #include <sys/wait.h>
22:
23: #include <string.h>
24:
25: #include "tmux.h"
26:
27: /*
28: * Runs a command without a window.
29: */
30:
31: int cmd_run_shell_exec(struct cmd *, struct cmd_ctx *);
32:
1.2 nicm 33: void cmd_run_shell_callback(struct job *);
34: void cmd_run_shell_free(void *);
35:
1.1 nicm 36: const struct cmd_entry cmd_run_shell_entry = {
37: "run-shell", "run",
1.10 ! nicm 38: "", 1, 1,
1.1 nicm 39: "command",
1.10 ! nicm 40: 0,
! 41: NULL,
! 42: NULL,
! 43: cmd_run_shell_exec
1.1 nicm 44: };
45:
1.2 nicm 46: struct cmd_run_shell_data {
47: char *cmd;
48: struct cmd_ctx ctx;
49: };
50:
1.1 nicm 51: int
52: cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
53: {
1.10 ! nicm 54: struct args *args = self->args;
1.2 nicm 55: struct cmd_run_shell_data *cdata;
56: struct job *job;
57:
58: cdata = xmalloc(sizeof *cdata);
1.10 ! nicm 59: cdata->cmd = xstrdup(args->argv[0]);
1.2 nicm 60: memcpy(&cdata->ctx, ctx, sizeof cdata->ctx);
61:
62: if (ctx->cmdclient != NULL)
63: ctx->cmdclient->references++;
64: if (ctx->curclient != NULL)
65: ctx->curclient->references++;
66:
1.4 nicm 67: job = job_add(NULL, 0, NULL,
1.10 ! nicm 68: args->argv[0], cmd_run_shell_callback, cmd_run_shell_free, cdata);
1.2 nicm 69: job_run(job);
70:
71: return (1); /* don't let client exit */
72: }
1.1 nicm 73:
1.2 nicm 74: void
75: cmd_run_shell_callback(struct job *job)
76: {
77: struct cmd_run_shell_data *cdata = job->data;
78: struct cmd_ctx *ctx = &cdata->ctx;
1.5 nicm 79: char *cmd, *msg, *line;
80: size_t size;
1.2 nicm 81: int retcode;
1.5 nicm 82: u_int lines;
1.7 nicm 83:
84: if (ctx->cmdclient != NULL && ctx->cmdclient->flags & CLIENT_DEAD)
85: return;
86: if (ctx->curclient != NULL && ctx->curclient->flags & CLIENT_DEAD)
87: return;
1.2 nicm 88:
1.5 nicm 89: lines = 0;
90: do {
91: if ((line = evbuffer_readline(job->event->input)) != NULL) {
92: ctx->print(ctx, "%s", line);
93: lines++;
94: }
95: } while (line != NULL);
96:
97: size = EVBUFFER_LENGTH(job->event->input);
98: if (size != 0) {
99: line = xmalloc(size + 1);
100: memcpy(line, EVBUFFER_DATA(job->event->input), size);
101: line[size] = '\0';
1.2 nicm 102:
1.5 nicm 103: ctx->print(ctx, "%s", line);
104: lines++;
1.2 nicm 105:
1.5 nicm 106: xfree(line);
1.1 nicm 107: }
108:
1.5 nicm 109: cmd = cdata->cmd;
110:
1.1 nicm 111: msg = NULL;
1.2 nicm 112: if (WIFEXITED(job->status)) {
113: if ((retcode = WEXITSTATUS(job->status)) != 0)
114: xasprintf(&msg, "'%s' returned %d", cmd, retcode);
115: } else if (WIFSIGNALED(job->status)) {
116: retcode = WTERMSIG(job->status);
117: xasprintf(&msg, "'%s' terminated by signal %d", cmd, retcode);
1.1 nicm 118: }
119: if (msg != NULL) {
1.5 nicm 120: if (lines != 0)
1.1 nicm 121: ctx->print(ctx, "%s", msg);
122: else
123: ctx->info(ctx, "%s", msg);
124: xfree(msg);
125: }
1.2 nicm 126: }
127:
128: void
129: cmd_run_shell_free(void *data)
130: {
131: struct cmd_run_shell_data *cdata = data;
132: struct cmd_ctx *ctx = &cdata->ctx;
133:
134: if (ctx->cmdclient != NULL) {
135: ctx->cmdclient->references--;
1.9 nicm 136: ctx->cmdclient->flags |= CLIENT_EXIT;
1.2 nicm 137: }
138: if (ctx->curclient != NULL)
139: ctx->curclient->references--;
140:
141: xfree(cdata->cmd);
142: xfree(cdata);
1.1 nicm 143: }