4 * Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
26 /* Create new command queue. */
28 cmdq_new(struct client
*c
)
32 cmdq
= xcalloc(1, sizeof *cmdq
);
37 cmdq
->client_exit
= 0;
39 TAILQ_INIT(&cmdq
->queue
);
46 /* Free command queue */
48 cmdq_free(struct cmd_q
*cmdq
)
50 if (--cmdq
->references
!= 0)
58 /* Show message from command. */
60 cmdq_print(struct cmd_q
*cmdq
, const char *fmt
, ...)
62 struct client
*c
= cmdq
->client
;
70 else if (c
->session
== NULL
|| (c
->flags
& CLIENT_CONTROL
)) {
72 evbuffer_add_vprintf(c
->stdout_data
, fmt
, ap
);
75 evbuffer_add(c
->stdout_data
, "\n", 1);
76 server_push_stdout(c
);
78 w
= c
->session
->curw
->window
;
79 if (w
->active
->mode
!= &window_copy_mode
) {
80 window_pane_reset_mode(w
->active
);
81 window_pane_set_mode(w
->active
, &window_copy_mode
);
82 window_copy_init_for_output(w
->active
);
84 window_copy_vadd(w
->active
, fmt
, ap
);
90 /* Show info from command. */
92 cmdq_info(struct cmd_q
*cmdq
, const char *fmt
, ...)
94 struct client
*c
= cmdq
->client
;
98 if (options_get_number(&global_options
, "quiet"))
105 else if (c
->session
== NULL
|| (c
->flags
& CLIENT_CONTROL
)) {
107 evbuffer_add_vprintf(c
->stdout_data
, fmt
, ap
);
110 evbuffer_add(c
->stdout_data
, "\n", 1);
111 server_push_stdout(c
);
113 xvasprintf(&msg
, fmt
, ap
);
114 *msg
= toupper((u_char
) *msg
);
115 status_message_set(c
, "%s", msg
);
123 /* Show error from command. */
125 cmdq_error(struct cmd_q
*cmdq
, const char *fmt
, ...)
127 struct client
*c
= cmdq
->client
;
128 struct cmd
*cmd
= cmdq
->cmd
;
134 msglen
= xvasprintf(&msg
, fmt
, ap
);
138 xasprintf(&cause
, "%s:%u: %s", cmd
->file
, cmd
->line
, msg
);
139 ARRAY_ADD(&cfg_causes
, cause
);
140 } else if (c
->session
== NULL
|| (c
->flags
& CLIENT_CONTROL
)) {
141 evbuffer_add(c
->stderr_data
, msg
, msglen
);
142 evbuffer_add(c
->stderr_data
, "\n", 1);
144 server_push_stderr(c
);
147 *msg
= toupper((u_char
) *msg
);
148 status_message_set(c
, "%s", msg
);
154 /* Print a guard line. */
156 cmdq_guard(struct cmd_q
*cmdq
, const char *guard
)
158 struct client
*c
= cmdq
->client
;
160 if (c
== NULL
|| c
->session
== NULL
)
162 if (!(c
->flags
& CLIENT_CONTROL
))
165 evbuffer_add_printf(c
->stdout_data
, "%%%s %ld %u\n", guard
,
166 (long) cmdq
->time
, cmdq
->number
);
167 server_push_stdout(c
);
171 /* Add command list to queue and begin processing if needed. */
173 cmdq_run(struct cmd_q
*cmdq
, struct cmd_list
*cmdlist
)
175 cmdq_append(cmdq
, cmdlist
);
177 if (cmdq
->item
== NULL
) {
183 /* Add command list to queue. */
185 cmdq_append(struct cmd_q
*cmdq
, struct cmd_list
*cmdlist
)
187 struct cmd_q_item
*item
;
189 item
= xcalloc(1, sizeof *item
);
190 item
->cmdlist
= cmdlist
;
191 TAILQ_INSERT_TAIL(&cmdq
->queue
, item
, qentry
);
192 cmdlist
->references
++;
195 /* Continue processing command queue. Returns 1 if finishes empty. */
197 cmdq_continue(struct cmd_q
*cmdq
)
199 struct cmd_q_item
*next
;
200 enum cmd_retval retval
;
206 empty
= TAILQ_EMPTY(&cmdq
->queue
);
210 if (cmdq
->item
== NULL
) {
211 cmdq
->item
= TAILQ_FIRST(&cmdq
->queue
);
212 cmdq
->cmd
= TAILQ_FIRST(&cmdq
->item
->cmdlist
->list
);
214 cmdq
->cmd
= TAILQ_NEXT(cmdq
->cmd
, qentry
);
217 next
= TAILQ_NEXT(cmdq
->item
, qentry
);
219 while (cmdq
->cmd
!= NULL
) {
220 cmd_print(cmdq
->cmd
, s
, sizeof s
);
221 log_debug("cmdq %p: %s (client %d)", cmdq
, s
,
222 cmdq
->client
!= NULL
? cmdq
->client
->ibuf
.fd
: -1);
224 cmdq
->time
= time(NULL
);
227 guard
= cmdq_guard(cmdq
, "begin");
228 retval
= cmdq
->cmd
->entry
->exec(cmdq
->cmd
, cmdq
);
230 if (retval
== CMD_RETURN_ERROR
)
231 cmdq_guard(cmdq
, "error");
233 cmdq_guard(cmdq
, "end");
236 if (retval
== CMD_RETURN_ERROR
)
238 if (retval
== CMD_RETURN_WAIT
)
240 if (retval
== CMD_RETURN_STOP
) {
245 cmdq
->cmd
= TAILQ_NEXT(cmdq
->cmd
, qentry
);
248 TAILQ_REMOVE(&cmdq
->queue
, cmdq
->item
, qentry
);
249 cmd_list_free(cmdq
->item
->cmdlist
);
253 if (cmdq
->item
!= NULL
)
254 cmdq
->cmd
= TAILQ_FIRST(&cmdq
->item
->cmdlist
->list
);
255 } while (cmdq
->item
!= NULL
);
258 if (cmdq
->client_exit
)
259 cmdq
->client
->flags
|= CLIENT_EXIT
;
260 if (cmdq
->emptyfn
!= NULL
)
261 cmdq
->emptyfn(cmdq
); /* may free cmdq */
269 /* Flush command queue. */
271 cmdq_flush(struct cmd_q
*cmdq
)
273 struct cmd_q_item
*item
, *item1
;
275 TAILQ_FOREACH_SAFE(item
, &cmdq
->queue
, qentry
, item1
) {
276 TAILQ_REMOVE(&cmdq
->queue
, item
, qentry
);
277 cmd_list_free(item
->cmdlist
);