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