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