xref: /openbsd-src/usr.bin/tmux/control.c (revision ac9b4aacc1da35008afea06a5d23c2f2dea9b93e)
1 /* $OpenBSD: control.c,v 1.3 2012/09/03 09:32:38 nicm Exp $ */
2 
3 /*
4  * Copyright (c) 2012 Nicholas Marriott <nicm@users.sourceforge.net>
5  * Copyright (c) 2012 George Nachman <tmux@georgester.com>
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 
22 #include <event.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include "tmux.h"
27 
28 void printflike2 control_msg_error(struct cmd_ctx *, const char *, ...);
29 void printflike2 control_msg_print(struct cmd_ctx *, const char *, ...);
30 void printflike2 control_msg_info(struct cmd_ctx *, const char *, ...);
31 
32 /* Command error callback. */
33 void printflike2
34 control_msg_error(struct cmd_ctx *ctx, const char *fmt, ...)
35 {
36 	struct client	*c = ctx->curclient;
37 	va_list		 ap;
38 
39 	va_start(ap, fmt);
40 	evbuffer_add_vprintf(c->stdout_data, fmt, ap);
41 	va_end(ap);
42 
43 	evbuffer_add(c->stdout_data, "\n", 1);
44 	server_push_stdout(c);
45 }
46 
47 /* Command print callback. */
48 void printflike2
49 control_msg_print(struct cmd_ctx *ctx, const char *fmt, ...)
50 {
51 	struct client	*c = ctx->curclient;
52 	va_list		 ap;
53 
54 	va_start(ap, fmt);
55 	evbuffer_add_vprintf(c->stdout_data, fmt, ap);
56 	va_end(ap);
57 
58 	evbuffer_add(c->stdout_data, "\n", 1);
59 	server_push_stdout(c);
60 }
61 
62 /* Command info callback. */
63 void printflike2
64 control_msg_info(unused struct cmd_ctx *ctx, unused const char *fmt, ...)
65 {
66 }
67 
68 /* Write a line. */
69 void printflike2
70 control_write(struct client *c, const char *fmt, ...)
71 {
72 	va_list		 ap;
73 
74 	va_start(ap, fmt);
75 	evbuffer_add_vprintf(c->stdout_data, fmt, ap);
76 	va_end(ap);
77 
78 	evbuffer_add(c->stdout_data, "\n", 1);
79 	server_push_stdout(c);
80 }
81 
82 /* Control input callback. Read lines and fire commands. */
83 void
84 control_callback(struct client *c, int closed, unused void *data)
85 {
86 	char		*line, *cause;
87 	struct cmd_ctx	 ctx;
88 	struct cmd_list	*cmdlist;
89 
90 	if (closed)
91 		c->flags |= CLIENT_EXIT;
92 
93 	for (;;) {
94 		line = evbuffer_readln(c->stdin_data, NULL, EVBUFFER_EOL_LF);
95 		if (line == NULL)
96 			break;
97 		if (*line == '\0') { /* empty line exit */
98 			c->flags |= CLIENT_EXIT;
99 			break;
100 		}
101 
102 		ctx.msgdata = NULL;
103 		ctx.cmdclient = NULL;
104 		ctx.curclient = c;
105 
106 		ctx.error = control_msg_error;
107 		ctx.print = control_msg_print;
108 		ctx.info = control_msg_info;
109 
110 		if (cmd_string_parse(line, &cmdlist, &cause) != 0) {
111 			control_write(c, "%%error in line \"%s\": %s", line,
112 			    cause);
113 			free(cause);
114 		} else {
115 			cmd_list_exec(cmdlist, &ctx);
116 			cmd_list_free(cmdlist);
117 		}
118 
119 		free(line);
120 	}
121 }
122