1/* $Id: cmd-if-shell.c,v 1.1.1.2 2011/08/17 18:40:04 jmmv Exp $ */
2
3/*
4 * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
5 * Copyright (c) 2009 Nicholas Marriott <nicm@openbsd.org>
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 * Executes a tmux command if a shell command returns true.
29 */
30
31int	cmd_if_shell_exec(struct cmd *, struct cmd_ctx *);
32
33void	cmd_if_shell_callback(struct job *);
34void	cmd_if_shell_free(void *);
35
36const struct cmd_entry cmd_if_shell_entry = {
37	"if-shell", "if",
38	"", 2, 2,
39	"shell-command command",
40	0,
41	NULL,
42	NULL,
43	cmd_if_shell_exec
44};
45
46struct cmd_if_shell_data {
47	char		*cmd;
48	struct cmd_ctx	 ctx;
49};
50
51int
52cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
53{
54	struct args			*args = self->args;
55	struct cmd_if_shell_data	*cdata;
56	const char			*shellcmd = args->argv[0];
57
58	cdata = xmalloc(sizeof *cdata);
59	cdata->cmd = xstrdup(args->argv[1]);
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
67	job_run(shellcmd, cmd_if_shell_callback, cmd_if_shell_free, cdata);
68
69	return (1);	/* don't let client exit */
70}
71
72void
73cmd_if_shell_callback(struct job *job)
74{
75	struct cmd_if_shell_data	*cdata = job->data;
76	struct cmd_ctx			*ctx = &cdata->ctx;
77	struct cmd_list			*cmdlist;
78	char				*cause;
79
80	if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0)
81		return;
82
83	if (cmd_string_parse(cdata->cmd, &cmdlist, &cause) != 0) {
84		if (cause != NULL) {
85			ctx->error(ctx, "%s", cause);
86			xfree(cause);
87		}
88		return;
89	}
90
91	cmd_list_exec(cmdlist, ctx);
92	cmd_list_free(cmdlist);
93}
94
95void
96cmd_if_shell_free(void *data)
97{
98	struct cmd_if_shell_data	*cdata = data;
99	struct cmd_ctx			*ctx = &cdata->ctx;
100	struct msg_exit_data		 exitdata;
101
102	if (ctx->cmdclient != NULL) {
103		ctx->cmdclient->references--;
104		exitdata.retcode = ctx->cmdclient->retcode;
105		ctx->cmdclient->flags |= CLIENT_EXIT;
106	}
107	if (ctx->curclient != NULL)
108		ctx->curclient->references--;
109
110	xfree(cdata->cmd);
111	xfree(cdata);
112}
113