4 * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
5 * Copyright (c) 2009 Nicholas Marriott <nicm@openbsd.org>
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.
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.
20 #include <sys/types.h>
30 * Executes a tmux command if a shell command returns true or false.
33 static enum args_parse_type
cmd_if_shell_args_parse(struct args
*, u_int
,
35 static enum cmd_retval
cmd_if_shell_exec(struct cmd
*,
38 static void cmd_if_shell_callback(struct job
*);
39 static void cmd_if_shell_free(void *);
41 const struct cmd_entry cmd_if_shell_entry
= {
45 .args
= { "bFt:", 2, 3, cmd_if_shell_args_parse
},
46 .usage
= "[-bF] " CMD_TARGET_PANE_USAGE
" shell-command command "
49 .target
= { 't', CMD_FIND_PANE
, CMD_FIND_CANFAIL
},
52 .exec
= cmd_if_shell_exec
55 struct cmd_if_shell_data
{
56 struct args_command_state
*cmd_if
;
57 struct args_command_state
*cmd_else
;
59 struct client
*client
;
60 struct cmdq_item
*item
;
63 static enum args_parse_type
64 cmd_if_shell_args_parse(__unused
struct args
*args
, u_int idx
,
65 __unused
char **cause
)
67 if (idx
== 1 || idx
== 2)
68 return (ARGS_PARSE_COMMANDS_OR_STRING
);
69 return (ARGS_PARSE_STRING
);
72 static enum cmd_retval
73 cmd_if_shell_exec(struct cmd
*self
, struct cmdq_item
*item
)
75 struct args
*args
= cmd_get_args(self
);
76 struct cmd_find_state
*target
= cmdq_get_target(item
);
77 struct cmd_if_shell_data
*cdata
;
78 struct cmdq_item
*new_item
;
80 struct client
*tc
= cmdq_get_target_client(item
);
81 struct session
*s
= target
->s
;
82 struct cmd_list
*cmdlist
;
83 u_int count
= args_count(args
);
84 int wait
= !args_has(args
, 'b');
86 shellcmd
= format_single_from_target(item
, args_string(args
, 0));
87 if (args_has(args
, 'F')) {
88 if (*shellcmd
!= '0' && *shellcmd
!= '\0')
89 cmdlist
= args_make_commands_now(self
, item
, 1, 0);
91 cmdlist
= args_make_commands_now(self
, item
, 2, 0);
94 return (CMD_RETURN_NORMAL
);
98 return (CMD_RETURN_ERROR
);
99 new_item
= cmdq_get_command(cmdlist
, cmdq_get_state(item
));
100 cmdq_insert_after(item
, new_item
);
101 return (CMD_RETURN_NORMAL
);
104 cdata
= xcalloc(1, sizeof *cdata
);
106 cdata
->cmd_if
= args_make_commands_prepare(self
, item
, 1, NULL
, wait
,
109 cdata
->cmd_else
= args_make_commands_prepare(self
, item
, 2,
114 cdata
->client
= cmdq_get_client(item
);
118 if (cdata
->client
!= NULL
)
119 cdata
->client
->references
++;
121 if (job_run(shellcmd
, 0, NULL
, NULL
, s
,
122 server_client_get_cwd(cmdq_get_client(item
), s
), NULL
,
123 cmd_if_shell_callback
, cmd_if_shell_free
, cdata
, 0, -1,
125 cmdq_error(item
, "failed to run command: %s", shellcmd
);
128 return (CMD_RETURN_ERROR
);
133 return (CMD_RETURN_NORMAL
);
134 return (CMD_RETURN_WAIT
);
138 cmd_if_shell_callback(struct job
*job
)
140 struct cmd_if_shell_data
*cdata
= job_get_data(job
);
141 struct client
*c
= cdata
->client
;
142 struct cmdq_item
*item
= cdata
->item
, *new_item
;
143 struct args_command_state
*state
;
144 struct cmd_list
*cmdlist
;
148 status
= job_get_status(job
);
149 if (!WIFEXITED(status
) || WEXITSTATUS(status
) != 0)
150 state
= cdata
->cmd_else
;
152 state
= cdata
->cmd_if
;
156 cmdlist
= args_make_commands(state
, 0, NULL
, &error
);
157 if (cmdlist
== NULL
) {
158 if (cdata
->item
== NULL
) {
159 *error
= toupper((u_char
)*error
);
160 status_message_set(c
, -1, 1, 0, "%s", error
);
162 cmdq_error(cdata
->item
, "%s", error
);
164 } else if (item
== NULL
) {
165 new_item
= cmdq_get_command(cmdlist
, NULL
);
166 cmdq_append(c
, new_item
);
168 new_item
= cmdq_get_command(cmdlist
, cmdq_get_state(item
));
169 cmdq_insert_after(item
, new_item
);
173 if (cdata
->item
!= NULL
)
174 cmdq_continue(cdata
->item
);
178 cmd_if_shell_free(void *data
)
180 struct cmd_if_shell_data
*cdata
= data
;
182 if (cdata
->client
!= NULL
)
183 server_client_unref(cdata
->client
);
185 if (cdata
->cmd_else
!= NULL
)
186 args_make_commands_free(cdata
->cmd_else
);
187 args_make_commands_free(cdata
->cmd_if
);