1 | /* $OpenBSD$ */ |
2 | |
3 | /* |
4 | * Copyright (c) 2012 Nicholas Marriott <[email protected]> |
5 | * Copyright (c) 2012 George Nachman <[email protected]> |
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 | #include <time.h> |
26 | |
27 | #include "tmux.h" |
28 | |
29 | /* Write a line. */ |
30 | void |
31 | control_write(struct client *c, const char *fmt, ...) |
32 | { |
33 | va_list ap; |
34 | |
35 | va_start(ap, fmt); |
36 | file_vprint(c, fmt, ap); |
37 | file_print(c, "\n" ); |
38 | va_end(ap); |
39 | } |
40 | |
41 | /* Control error callback. */ |
42 | static enum cmd_retval |
43 | control_error(struct cmdq_item *item, void *data) |
44 | { |
45 | struct client *c = item->client; |
46 | char *error = data; |
47 | |
48 | cmdq_guard(item, "begin" , 1); |
49 | control_write(c, "parse error: %s" , error); |
50 | cmdq_guard(item, "error" , 1); |
51 | |
52 | free(error); |
53 | return (CMD_RETURN_NORMAL); |
54 | } |
55 | |
56 | /* Control input callback. Read lines and fire commands. */ |
57 | static void |
58 | control_callback(__unused struct client *c, __unused const char *path, |
59 | int error, int closed, struct evbuffer *buffer, __unused void *data) |
60 | { |
61 | char *line; |
62 | struct cmdq_item *item; |
63 | struct cmd_parse_result *pr; |
64 | |
65 | if (closed || error != 0) |
66 | c->flags |= CLIENT_EXIT; |
67 | |
68 | for (;;) { |
69 | line = evbuffer_readln(buffer, NULL, EVBUFFER_EOL_LF); |
70 | if (line == NULL) |
71 | break; |
72 | log_debug("%s: %s" , __func__, line); |
73 | if (*line == '\0') { /* empty line exit */ |
74 | free(line); |
75 | c->flags |= CLIENT_EXIT; |
76 | break; |
77 | } |
78 | |
79 | pr = cmd_parse_from_string(line, NULL); |
80 | switch (pr->status) { |
81 | case CMD_PARSE_EMPTY: |
82 | break; |
83 | case CMD_PARSE_ERROR: |
84 | item = cmdq_get_callback(control_error, pr->error); |
85 | cmdq_append(c, item); |
86 | break; |
87 | case CMD_PARSE_SUCCESS: |
88 | item = cmdq_get_command(pr->cmdlist, NULL, NULL, 0); |
89 | item->shared->flags |= CMDQ_SHARED_CONTROL; |
90 | cmdq_append(c, item); |
91 | cmd_list_free(pr->cmdlist); |
92 | break; |
93 | } |
94 | |
95 | free(line); |
96 | } |
97 | } |
98 | |
99 | void |
100 | control_start(struct client *c) |
101 | { |
102 | file_read(c, "-" , control_callback, c); |
103 | |
104 | if (c->flags & CLIENT_CONTROLCONTROL) |
105 | file_print(c, "\033P1000p" ); |
106 | } |
107 | |