Annotation of src/usr.bin/tmux/cmd-run-shell.c, Revision 1.4
1.4 ! nicm 1: /* $OpenBSD: cmd-run-shell.c,v 1.3 2009/10/11 09:04:33 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",
38: "command",
39: CMD_ARG1, 0,
40: cmd_target_init,
41: cmd_target_parse,
42: cmd_run_shell_exec,
43: cmd_target_free,
44: cmd_target_print
45: };
46:
1.2 nicm 47: struct cmd_run_shell_data {
48: char *cmd;
49: struct cmd_ctx ctx;
50: };
51:
1.1 nicm 52: int
53: cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
54: {
1.2 nicm 55: struct cmd_target_data *data = self->data;
56: struct cmd_run_shell_data *cdata;
57: struct job *job;
58:
59: cdata = xmalloc(sizeof *cdata);
60: cdata->cmd = xstrdup(data->arg);
61: memcpy(&cdata->ctx, ctx, sizeof cdata->ctx);
62:
63: if (ctx->cmdclient != NULL)
64: ctx->cmdclient->references++;
65: if (ctx->curclient != NULL)
66: ctx->curclient->references++;
67:
1.4 ! nicm 68: job = job_add(NULL, 0, NULL,
1.2 nicm 69: data->arg, cmd_run_shell_callback, cmd_run_shell_free, cdata);
70: job_run(job);
71:
72: return (1); /* don't let client exit */
73: }
1.1 nicm 74:
1.2 nicm 75: void
76: cmd_run_shell_callback(struct job *job)
77: {
78: struct cmd_run_shell_data *cdata = job->data;
79: struct cmd_ctx *ctx = &cdata->ctx;
80: char *cmd, *msg, *line, *buf;
81: size_t off, len, llen;
82: int retcode;
83:
84: buf = BUFFER_OUT(job->out);
85: len = BUFFER_USED(job->out);
86:
87: cmd = cdata->cmd;
88:
89: if (len != 0) {
90: line = buf;
91: for (off = 0; off < len; off++) {
92: if (buf[off] == '\n') {
93: llen = buf + off - line;
94: if (llen > INT_MAX)
95: break;
96: ctx->print(ctx, "%.*s", (int) llen, line);
97: line = buf + off + 1;
98: }
1.1 nicm 99: }
1.2 nicm 100: llen = buf + len - line;
101: if (llen > 0 && llen < INT_MAX)
102: ctx->print(ctx, "%.*s", (int) llen, line);
1.1 nicm 103: }
104:
105: msg = NULL;
1.2 nicm 106: if (WIFEXITED(job->status)) {
107: if ((retcode = WEXITSTATUS(job->status)) != 0)
108: xasprintf(&msg, "'%s' returned %d", cmd, retcode);
109: } else if (WIFSIGNALED(job->status)) {
110: retcode = WTERMSIG(job->status);
111: xasprintf(&msg, "'%s' terminated by signal %d", cmd, retcode);
1.1 nicm 112: }
113: if (msg != NULL) {
1.2 nicm 114: if (len != 0)
1.1 nicm 115: ctx->print(ctx, "%s", msg);
116: else
117: ctx->info(ctx, "%s", msg);
118: xfree(msg);
119: }
1.2 nicm 120: }
121:
122: void
123: cmd_run_shell_free(void *data)
124: {
125: struct cmd_run_shell_data *cdata = data;
126: struct cmd_ctx *ctx = &cdata->ctx;
127:
128: if (ctx->cmdclient != NULL) {
129: ctx->cmdclient->references--;
130: server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
131: }
132: if (ctx->curclient != NULL)
133: ctx->curclient->references--;
134:
135: xfree(cdata->cmd);
136: xfree(cdata);
1.1 nicm 137: }