commands.c revision 1.12 1 1.12 rillig /* $NetBSD: commands.c,v 1.12 2021/02/13 08:14:46 rillig Exp $ */
2 1.1 blymn
3 1.1 blymn /*-
4 1.1 blymn * Copyright 2009 Brett Lymn <blymn (at) NetBSD.org>
5 1.12 rillig * Copyright 2021 Roland Illig <rillig (at) NetBSD.org>
6 1.1 blymn *
7 1.1 blymn * All rights reserved.
8 1.1 blymn *
9 1.1 blymn * This code has been donated to The NetBSD Foundation by the Author.
10 1.1 blymn *
11 1.1 blymn * Redistribution and use in source and binary forms, with or without
12 1.1 blymn * modification, are permitted provided that the following conditions
13 1.1 blymn * are met:
14 1.1 blymn * 1. Redistributions of source code must retain the above copyright
15 1.1 blymn * notice, this list of conditions and the following disclaimer.
16 1.1 blymn * 2. The name of the author may not be used to endorse or promote products
17 1.7 rillig * derived from this software without specific prior written permission
18 1.1 blymn *
19 1.1 blymn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 1.1 blymn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 1.1 blymn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 1.1 blymn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 1.1 blymn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 1.1 blymn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 1.1 blymn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 1.1 blymn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 1.1 blymn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 1.1 blymn * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 1.1 blymn */
30 1.1 blymn
31 1.1 blymn #include <curses.h>
32 1.1 blymn #include <string.h>
33 1.1 blymn #include <stdlib.h>
34 1.1 blymn #include <stdio.h>
35 1.2 christos #include <unistd.h>
36 1.3 christos #include <err.h>
37 1.1 blymn #include <sys/types.h>
38 1.12 rillig
39 1.1 blymn #include "returns.h"
40 1.1 blymn #include "slave.h"
41 1.1 blymn #include "command_table.h"
42 1.1 blymn
43 1.6 blymn extern int initdone;
44 1.1 blymn
45 1.5 blymn static void report_type(data_enum_t);
46 1.3 christos static void report_message(int, const char *);
47 1.1 blymn
48 1.1 blymn /*
49 1.1 blymn * Match the passed command string and execute the associated test
50 1.1 blymn * function.
51 1.1 blymn */
52 1.1 blymn void
53 1.1 blymn command_execute(char *func, int nargs, char **args)
54 1.1 blymn {
55 1.6 blymn size_t i, j;
56 1.1 blymn
57 1.1 blymn i = 0;
58 1.1 blymn while (i < ncmds) {
59 1.8 rillig if (strcmp(func, commands[i].name) == 0) {
60 1.6 blymn /* Check only restricted set of functions is called before
61 1.6 blymn * initscr/newterm */
62 1.10 rillig if (!initdone) {
63 1.6 blymn j = 0;
64 1.9 rillig while (j < nrcmds) {
65 1.9 rillig if (strcmp(func, restricted_commands[j]) == 0) {
66 1.9 rillig if (strcmp(func, "initscr") == 0 ||
67 1.9 rillig strcmp(func, "newterm") == 0)
68 1.6 blymn initdone = 1;
69 1.6 blymn /* matched function */
70 1.6 blymn commands[i].func(nargs, args);
71 1.6 blymn return;
72 1.6 blymn }
73 1.6 blymn j++;
74 1.6 blymn }
75 1.6 blymn report_status("YOU NEED TO CALL INITSCR/NEWTERM FIRST");
76 1.6 blymn return;
77 1.6 blymn }
78 1.1 blymn /* matched function */
79 1.1 blymn commands[i].func(nargs, args);
80 1.1 blymn return;
81 1.1 blymn }
82 1.1 blymn i++;
83 1.1 blymn }
84 1.1 blymn
85 1.1 blymn report_status("UNKNOWN_FUNCTION");
86 1.1 blymn }
87 1.1 blymn
88 1.1 blymn /*
89 1.1 blymn * Report an pointer value back to the director
90 1.1 blymn */
91 1.1 blymn void
92 1.1 blymn report_ptr(void *ptr)
93 1.1 blymn {
94 1.1 blymn char *string;
95 1.1 blymn
96 1.4 blymn if (ptr == NULL)
97 1.4 blymn asprintf(&string, "NULL");
98 1.4 blymn else
99 1.4 blymn asprintf(&string, "%p", ptr);
100 1.1 blymn report_status(string);
101 1.1 blymn free(string);
102 1.1 blymn }
103 1.1 blymn
104 1.1 blymn /*
105 1.1 blymn * Report an integer value back to the director
106 1.1 blymn */
107 1.1 blymn void
108 1.1 blymn report_int(int value)
109 1.1 blymn {
110 1.1 blymn char *string;
111 1.1 blymn
112 1.1 blymn asprintf(&string, "%d", value);
113 1.1 blymn report_status(string);
114 1.1 blymn free(string);
115 1.1 blymn }
116 1.1 blymn
117 1.1 blymn /*
118 1.1 blymn * Report either an ERR or OK back to the director
119 1.1 blymn */
120 1.1 blymn void
121 1.1 blymn report_return(int status)
122 1.1 blymn {
123 1.1 blymn if (status == ERR)
124 1.5 blymn report_type(data_err);
125 1.1 blymn else if (status == OK)
126 1.5 blymn report_type(data_ok);
127 1.6 blymn else if (status == KEY_CODE_YES)
128 1.6 blymn report_int(status);
129 1.1 blymn else
130 1.1 blymn report_status("INVALID_RETURN");
131 1.1 blymn }
132 1.1 blymn
133 1.1 blymn /*
134 1.1 blymn * Report the type back to the director via the command pipe
135 1.1 blymn */
136 1.1 blymn static void
137 1.5 blymn report_type(data_enum_t return_type)
138 1.1 blymn {
139 1.1 blymn int type;
140 1.1 blymn
141 1.1 blymn type = return_type;
142 1.11 rillig if (write(to_director, &type, sizeof(int)) < 0)
143 1.3 christos err(1, "command pipe write for status type failed");
144 1.1 blymn
145 1.1 blymn }
146 1.1 blymn
147 1.1 blymn /*
148 1.1 blymn * Report the number of returns back to the director via the command pipe
149 1.1 blymn */
150 1.1 blymn void
151 1.1 blymn report_count(int count)
152 1.1 blymn {
153 1.1 blymn int type;
154 1.1 blymn
155 1.5 blymn type = data_count;
156 1.11 rillig if (write(to_director, &type, sizeof(int)) < 0)
157 1.3 christos err(1, "command pipe write for count type failed");
158 1.1 blymn
159 1.11 rillig if (write(to_director, &count, sizeof(int)) < 0)
160 1.3 christos err(1, "command pipe write for count");
161 1.1 blymn }
162 1.1 blymn
163 1.1 blymn /*
164 1.1 blymn * Report the status back to the director via the command pipe
165 1.1 blymn */
166 1.1 blymn void
167 1.3 christos report_status(const char *status)
168 1.1 blymn {
169 1.5 blymn report_message(data_string, status);
170 1.1 blymn }
171 1.1 blymn
172 1.1 blymn /*
173 1.1 blymn * Report an error message back to the director via the command pipe.
174 1.1 blymn */
175 1.1 blymn void
176 1.3 christos report_error(const char *status)
177 1.1 blymn {
178 1.5 blymn report_message(data_slave_error, status);
179 1.1 blymn }
180 1.1 blymn
181 1.1 blymn /*
182 1.1 blymn * Report the message with the given type back to the director via the
183 1.1 blymn * command pipe.
184 1.1 blymn */
185 1.1 blymn static void
186 1.3 christos report_message(int type, const char *status)
187 1.1 blymn {
188 1.1 blymn int len;
189 1.1 blymn
190 1.1 blymn len = strlen(status);
191 1.1 blymn
192 1.11 rillig if (write(to_director, &type, sizeof(int)) < 0)
193 1.3 christos err(1, "command pipe write for message type failed");
194 1.1 blymn
195 1.11 rillig if (write(to_director, &len, sizeof(int)) < 0)
196 1.3 christos err(1, "command pipe write for message length failed");
197 1.1 blymn
198 1.11 rillig if (write(to_director, status, len) < 0)
199 1.3 christos err(1, "command pipe write of message data failed");
200 1.1 blymn }
201 1.1 blymn
202 1.1 blymn /*
203 1.1 blymn * Report a string of chtype back to the director via the command pipe.
204 1.1 blymn */
205 1.1 blymn void
206 1.4 blymn report_byte(chtype c)
207 1.4 blymn {
208 1.4 blymn chtype string[2];
209 1.4 blymn
210 1.4 blymn string[0] = c;
211 1.4 blymn string[1] = A_NORMAL | '\0';
212 1.4 blymn report_nstr(string);
213 1.4 blymn }
214 1.4 blymn
215 1.4 blymn /*
216 1.4 blymn * Report a string of chtype back to the director via the command pipe.
217 1.4 blymn */
218 1.4 blymn void
219 1.1 blymn report_nstr(chtype *string)
220 1.1 blymn {
221 1.1 blymn int len, type;
222 1.1 blymn chtype *p;
223 1.1 blymn
224 1.1 blymn len = 0;
225 1.1 blymn p = string;
226 1.1 blymn
227 1.1 blymn while ((*p++ & __CHARTEXT) != 0) {
228 1.1 blymn len++;
229 1.1 blymn }
230 1.1 blymn
231 1.4 blymn len++; /* add in the termination chtype */
232 1.4 blymn len *= sizeof(chtype);
233 1.4 blymn
234 1.5 blymn type = data_byte;
235 1.11 rillig if (write(to_director, &type, sizeof(int)) < 0)
236 1.3 christos err(1, "%s: command pipe write for status type failed",
237 1.3 christos __func__);
238 1.3 christos
239 1.11 rillig if (write(to_director, &len, sizeof(int)) < 0)
240 1.3 christos err(1, "%s: command pipe write for status length failed",
241 1.3 christos __func__);
242 1.3 christos
243 1.11 rillig if (write(to_director, string, len) < 0)
244 1.3 christos err(1, "%s: command pipe write of status data failed",
245 1.3 christos __func__);
246 1.1 blymn }
247 1.1 blymn
248 1.1 blymn /*
249 1.6 blymn * Report a cchar_t back to the director via the command pipe.
250 1.6 blymn */
251 1.6 blymn void
252 1.6 blymn report_cchar(cchar_t c)
253 1.6 blymn {
254 1.6 blymn int len, type;
255 1.6 blymn len = sizeof(cchar_t);
256 1.6 blymn type = data_cchar;
257 1.6 blymn
258 1.11 rillig if (write(to_director, &type, sizeof(int)) < 0)
259 1.6 blymn err(1, "%s: command pipe write for status type failed",
260 1.6 blymn __func__);
261 1.6 blymn
262 1.11 rillig if (write(to_director, &len, sizeof(int)) < 0)
263 1.6 blymn err(1, "%s: command pipe write for status length failed",
264 1.6 blymn __func__);
265 1.6 blymn
266 1.11 rillig if (write(to_director, &c, len) < 0)
267 1.6 blymn err(1, "%s: command pipe write of status data failed",
268 1.6 blymn __func__);
269 1.6 blymn }
270 1.6 blymn
271 1.6 blymn /*
272 1.6 blymn * Report a wchar_t back to the director via the command pipe.
273 1.6 blymn */
274 1.6 blymn void
275 1.6 blymn report_wchar(wchar_t ch)
276 1.6 blymn {
277 1.6 blymn wchar_t wstr[2];
278 1.6 blymn
279 1.6 blymn wstr[0] = ch;
280 1.6 blymn wstr[1] = L'\0';
281 1.6 blymn report_wstr(wstr);
282 1.6 blymn }
283 1.6 blymn
284 1.6 blymn
285 1.6 blymn /*
286 1.6 blymn * Report a string of wchar_t back to the director via the command pipe.
287 1.6 blymn */
288 1.6 blymn void
289 1.6 blymn report_wstr(wchar_t *wstr)
290 1.6 blymn {
291 1.6 blymn int len, type;
292 1.6 blymn wchar_t *p;
293 1.6 blymn
294 1.6 blymn len = 0;
295 1.6 blymn p = wstr;
296 1.6 blymn
297 1.6 blymn while (*p++ != L'\0')
298 1.6 blymn len++;
299 1.6 blymn
300 1.6 blymn len++; /* add in the termination chtype */
301 1.6 blymn len *= sizeof(wchar_t);
302 1.6 blymn
303 1.6 blymn type = data_wchar;
304 1.11 rillig if (write(to_director, &type, sizeof(int)) < 0)
305 1.6 blymn err(1, "%s: command pipe write for status type failed",
306 1.6 blymn __func__);
307 1.6 blymn
308 1.11 rillig if (write(to_director, &len, sizeof(int)) < 0)
309 1.6 blymn err(1, "%s: command pipe write for status length failed",
310 1.6 blymn __func__);
311 1.6 blymn
312 1.11 rillig if (write(to_director, wstr, len) < 0)
313 1.6 blymn err(1, "%s: command pipe write of status data failed",
314 1.6 blymn __func__);
315 1.6 blymn }
316 1.6 blymn
317 1.6 blymn /*
318 1.1 blymn * Check the number of args we received are what we expect. Return an
319 1.1 blymn * error if they do not match.
320 1.1 blymn */
321 1.1 blymn int
322 1.1 blymn check_arg_count(int nargs, int expected)
323 1.1 blymn {
324 1.1 blymn if (nargs != expected) {
325 1.1 blymn report_count(1);
326 1.1 blymn report_error("INCORRECT_ARGUMENT_NUMBER");
327 1.1 blymn return(1);
328 1.1 blymn }
329 1.1 blymn
330 1.1 blymn return(0);
331 1.1 blymn }
332