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