xref: /netbsd-src/tests/lib/libcurses/slave/commands.c (revision e5d758f832e07a177fa24707c434b7ce26d0f762)
1 /*	$NetBSD: commands.c,v 1.6 2020/10/24 04:46:17 blymn Exp $	*/
2 
3 /*-
4  * Copyright 2009 Brett Lymn <blymn@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 withough 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 cmdpipe[2];
44 extern int slvpipe[2];
45 extern int initdone;
46 
47 static void report_type(data_enum_t);
48 static void report_message(int, const char *);
49 
50 /*
51  * Match the passed command string and execute the associated test
52  * function.
53  */
54 void
55 command_execute(char *func, int nargs, char **args)
56 {
57 	size_t i, j;
58 
59 	i = 0;
60 	while (i < ncmds) {
61 		if (strcasecmp(func, commands[i].name) == 0) {
62 			/* Check only restricted set of functions is called before
63 			 * initscr/newterm */
64 			if(!initdone){
65 				j = 0;
66 				while(j < nrcmds) {
67 					if(strcasecmp(func, restricted_commands[j]) == 0){
68 						if(strcasecmp(func, "initscr") == 0  ||
69 							strcasecmp(func, "newterm") == 0)
70 							initdone = 1;
71 						/* matched function */
72 						commands[i].func(nargs, args);
73 						return;
74 					}
75 					j++;
76 				}
77 				report_status("YOU NEED TO CALL INITSCR/NEWTERM FIRST");
78 				return;
79 			}
80 			/* matched function */
81 			commands[i].func(nargs, args);
82 			return;
83 		}
84 		i++;
85 	}
86 
87 	report_status("UNKNOWN_FUNCTION");
88 }
89 
90 /*
91  * Report an pointer value back to the director
92  */
93 void
94 report_ptr(void *ptr)
95 {
96 	char *string;
97 
98 	if (ptr == NULL)
99 		asprintf(&string, "NULL");
100 	else
101 		asprintf(&string, "%p", ptr);
102 	report_status(string);
103 	free(string);
104 }
105 
106 /*
107  * Report an integer value back to the director
108  */
109 void
110 report_int(int value)
111 {
112 	char *string;
113 
114 	asprintf(&string, "%d", value);
115 	report_status(string);
116 	free(string);
117 }
118 
119 /*
120  * Report either an ERR or OK back to the director
121  */
122 void
123 report_return(int status)
124 {
125 	if (status == ERR)
126 		report_type(data_err);
127 	else if (status == OK)
128 		report_type(data_ok);
129 	else if (status == KEY_CODE_YES)
130 		report_int(status);
131 	else
132 		report_status("INVALID_RETURN");
133 }
134 
135 /*
136  * Report the type back to the director via the command pipe
137  */
138 static void
139 report_type(data_enum_t return_type)
140 {
141 	int type;
142 
143 	type = return_type;
144 	if (write(slvpipe[WRITE_PIPE], &type, sizeof(int)) < 0)
145 		err(1, "command pipe write for status type failed");
146 
147 }
148 
149 /*
150  * Report the number of returns back to the director via the command pipe
151  */
152 void
153 report_count(int count)
154 {
155 	int type;
156 
157 	type = data_count;
158 	if (write(slvpipe[WRITE_PIPE], &type, sizeof(int)) < 0)
159 		err(1, "command pipe write for count type failed");
160 
161 	if (write(slvpipe[WRITE_PIPE], &count, sizeof(int)) < 0)
162 		err(1, "command pipe write for count");
163 }
164 
165 /*
166  * Report the status back to the director via the command pipe
167  */
168 void
169 report_status(const char *status)
170 {
171 	report_message(data_string, status);
172 }
173 
174 /*
175  * Report an error message back to the director via the command pipe.
176  */
177 void
178 report_error(const char *status)
179 {
180 	report_message(data_slave_error, status);
181 }
182 
183 /*
184  * Report the message with the given type back to the director via the
185  * command pipe.
186  */
187 static void
188 report_message(int type, const char *status)
189 {
190 	int len;
191 
192 	len = strlen(status);
193 
194 	if (write(slvpipe[WRITE_PIPE], &type, sizeof(int)) < 0)
195 		err(1, "command pipe write for message type failed");
196 
197 	if (write(slvpipe[WRITE_PIPE], &len, sizeof(int)) < 0)
198 		err(1, "command pipe write for message length failed");
199 
200 	if (write(slvpipe[WRITE_PIPE], status, len) < 0)
201 		err(1, "command pipe write of message data failed");
202 }
203 
204 /*
205  * Report a string of chtype back to the director via the command pipe.
206  */
207 void
208 report_byte(chtype c)
209 {
210 	chtype string[2];
211 
212 	string[0] = c;
213 	string[1] = A_NORMAL | '\0';
214 	report_nstr(string);
215 }
216 
217 /*
218  * Report a string of chtype back to the director via the command pipe.
219  */
220 void
221 report_nstr(chtype *string)
222 {
223 	int len, type;
224 	chtype *p;
225 
226 	len = 0;
227 	p = string;
228 
229 	while ((*p++ & __CHARTEXT) != 0) {
230 		len++;
231 	}
232 
233 	len++; /* add in the termination chtype */
234 	len *= sizeof(chtype);
235 
236 	type = data_byte;
237 	if (write(slvpipe[WRITE_PIPE], &type, sizeof(int)) < 0)
238 		err(1, "%s: command pipe write for status type failed",
239 		    __func__);
240 
241 	if (write(slvpipe[WRITE_PIPE], &len, sizeof(int)) < 0)
242 		err(1, "%s: command pipe write for status length failed",
243 		    __func__);
244 
245 	if (write(slvpipe[WRITE_PIPE], string, len) < 0)
246 		err(1, "%s: command pipe write of status data failed",
247 		    __func__);
248 }
249 
250 /*
251  * Report a cchar_t back to the director via the command pipe.
252  */
253 void
254 report_cchar(cchar_t c)
255 {
256 	int len, type;
257 	len = sizeof(cchar_t);
258 	type = data_cchar;
259 
260 	if (write(slvpipe[WRITE_PIPE], &type, sizeof(int)) < 0)
261 		err(1, "%s: command pipe write for status type failed",
262 		    __func__);
263 
264 	if (write(slvpipe[WRITE_PIPE], &len, sizeof(int)) < 0)
265 		err(1, "%s: command pipe write for status length failed",
266 		    __func__);
267 
268 	if (write(slvpipe[WRITE_PIPE], &c, len) < 0)
269 		err(1, "%s: command pipe write of status data failed",
270 		    __func__);
271 }
272 
273 /*
274  * Report a wchar_t back to the director via the command pipe.
275  */
276 void
277 report_wchar(wchar_t ch)
278 {
279 	wchar_t wstr[2];
280 
281 	wstr[0] = ch;
282 	wstr[1] = L'\0';
283 	report_wstr(wstr);
284 }
285 
286 
287 /*
288  * Report a string of wchar_t back to the director via the command pipe.
289  */
290 void
291 report_wstr(wchar_t *wstr)
292 {
293 	int len, type;
294 	wchar_t *p;
295 
296 	len = 0;
297 	p = wstr;
298 
299 	while (*p++ != L'\0')
300 		len++;
301 
302 	len++; /* add in the termination chtype */
303 	len *= sizeof(wchar_t);
304 
305 	type = data_wchar;
306 	if (write(slvpipe[WRITE_PIPE], &type, sizeof(int)) < 0)
307 		err(1, "%s: command pipe write for status type failed",
308 		    __func__);
309 
310 	if (write(slvpipe[WRITE_PIPE], &len, sizeof(int)) < 0)
311 		err(1, "%s: command pipe write for status length failed",
312 		    __func__);
313 
314 	if (write(slvpipe[WRITE_PIPE], wstr, len) < 0)
315 		err(1, "%s: command pipe write of status data failed",
316 		    __func__);
317 }
318 
319 /*
320  * Check the number of args we received are what we expect.  Return an
321  * error if they do not match.
322  */
323 int
324 check_arg_count(int nargs, int expected)
325 {
326 	if (nargs != expected) {
327 		report_count(1);
328 		report_error("INCORRECT_ARGUMENT_NUMBER");
329 		return(1);
330 	}
331 
332 	return(0);
333 }
334