xref: /netbsd-src/tests/lib/libcurses/slave/commands.c (revision 2209bb42847bd4a79c922117fa1ac24250df4e59)
1*2209bb42Srillig /*	$NetBSD: commands.c,v 1.18 2023/12/10 15:42:29 rillig Exp $	*/
2bdd37afaSblymn 
3bdd37afaSblymn /*-
4bdd37afaSblymn  * Copyright 2009 Brett Lymn <blymn@NetBSD.org>
5cf012ad4Srillig  * Copyright 2021 Roland Illig <rillig@NetBSD.org>
6bdd37afaSblymn  *
7bdd37afaSblymn  * All rights reserved.
8bdd37afaSblymn  *
9bdd37afaSblymn  * This code has been donated to The NetBSD Foundation by the Author.
10bdd37afaSblymn  *
11bdd37afaSblymn  * Redistribution and use in source and binary forms, with or without
12bdd37afaSblymn  * modification, are permitted provided that the following conditions
13bdd37afaSblymn  * are met:
14bdd37afaSblymn  * 1. Redistributions of source code must retain the above copyright
15bdd37afaSblymn  *    notice, this list of conditions and the following disclaimer.
16bdd37afaSblymn  * 2. The name of the author may not be used to endorse or promote products
1709f966d1Srillig  *    derived from this software without specific prior written permission
18bdd37afaSblymn  *
19bdd37afaSblymn  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20bdd37afaSblymn  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21bdd37afaSblymn  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22bdd37afaSblymn  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23bdd37afaSblymn  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24bdd37afaSblymn  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25bdd37afaSblymn  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26bdd37afaSblymn  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27bdd37afaSblymn  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28bdd37afaSblymn  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29bdd37afaSblymn  */
30bdd37afaSblymn 
31bdd37afaSblymn #include <curses.h>
32bdd37afaSblymn #include <string.h>
33bdd37afaSblymn #include <stdlib.h>
34bdd37afaSblymn #include <stdio.h>
3521bd6ba1Schristos #include <unistd.h>
362a18cea9Schristos #include <err.h>
37bdd37afaSblymn #include <sys/types.h>
38cf012ad4Srillig 
39bdd37afaSblymn #include "returns.h"
40bdd37afaSblymn #include "slave.h"
41bdd37afaSblymn #include "command_table.h"
42bdd37afaSblymn 
43ce321bb0Sblymn extern int initdone;
44bdd37afaSblymn 
4573417462Srillig static void report_message(data_enum_t, const char *);
46bdd37afaSblymn 
47bdd37afaSblymn /*
48bdd37afaSblymn  * Match the passed command string and execute the associated test
49bdd37afaSblymn  * function.
50bdd37afaSblymn  */
51bdd37afaSblymn void
command_execute(char * func,int nargs,char ** args)52bdd37afaSblymn command_execute(char *func, int nargs, char **args)
53bdd37afaSblymn {
54ce321bb0Sblymn 	size_t i, j;
55bdd37afaSblymn 
56bf61414fSrin 	for (i = 0; i < ncmds; i++) {
57bf61414fSrin 		if (strcmp(func, commands[i].name) != 0)
58bf61414fSrin 			continue;
59bf61414fSrin 
60ce321bb0Sblymn 		/* Check only restricted set of functions is called before
61ce321bb0Sblymn 		 * initscr/newterm */
62bf61414fSrin 		if (initdone) {
63bf61414fSrin 			/* matched function */
64bf61414fSrin 			commands[i].func(nargs, args);
65bf61414fSrin 			return;
66bf61414fSrin 		}
67bf61414fSrin 
68bf61414fSrin 		for (j = 0; j < nrcmds; j++) {
69bf61414fSrin 			if (strcmp(func, restricted_commands[j]) != 0)
70bf61414fSrin 				continue;
71bf61414fSrin 
7269385098Srillig 			if (strcmp(func, "initscr") == 0  ||
7369385098Srillig 			    strcmp(func, "newterm") == 0)
74ce321bb0Sblymn 				initdone = 1;
75bf61414fSrin 
76ce321bb0Sblymn 			/* matched function */
77ce321bb0Sblymn 			commands[i].func(nargs, args);
78ce321bb0Sblymn 			return;
79ce321bb0Sblymn 		}
80ce321bb0Sblymn 		report_status("YOU NEED TO CALL INITSCR/NEWTERM FIRST");
81ce321bb0Sblymn 		return;
82ce321bb0Sblymn 	}
83bdd37afaSblymn 
84bdd37afaSblymn 	report_status("UNKNOWN_FUNCTION");
85bdd37afaSblymn }
86bdd37afaSblymn 
8773417462Srillig static void
write_to_director(const void * mem,size_t size)8873417462Srillig write_to_director(const void *mem, size_t size)
8973417462Srillig {
9073417462Srillig 	ssize_t nwritten = write(to_director, mem, size);
9173417462Srillig 	if (nwritten == -1)
9273417462Srillig 		err(1, "writing to director failed");
9373417462Srillig 	if ((size_t)nwritten != size)
9465e35d76Srillig 		errx(1, "short write to director, expected %zu, got %zd",
9573417462Srillig 		    size, nwritten);
9673417462Srillig }
9773417462Srillig 
9873417462Srillig static void
write_to_director_int(int i)9973417462Srillig write_to_director_int(int i)
10073417462Srillig {
101b411b2c4Srillig 	write_to_director(&i, sizeof(i));
10273417462Srillig }
10373417462Srillig 
10473417462Srillig static void
write_to_director_type(data_enum_t return_type)10573417462Srillig write_to_director_type(data_enum_t return_type)
10673417462Srillig {
10773417462Srillig 	write_to_director_int(return_type);
10873417462Srillig }
10973417462Srillig 
110bdd37afaSblymn /*
1117fe998abSrillig  * Report a pointer value back to the director
112bdd37afaSblymn  */
113bdd37afaSblymn void
report_ptr(void * ptr)114bdd37afaSblymn report_ptr(void *ptr)
115bdd37afaSblymn {
116bdd37afaSblymn 	char *string;
117bdd37afaSblymn 
118f47c5ad5Sblymn 	if (ptr == NULL)
119f47c5ad5Sblymn 		asprintf(&string, "NULL");
120f47c5ad5Sblymn 	else
1212a18cea9Schristos 		asprintf(&string, "%p", ptr);
122bdd37afaSblymn 	report_status(string);
123bdd37afaSblymn 	free(string);
124bdd37afaSblymn }
125bdd37afaSblymn 
126bdd37afaSblymn /*
127bdd37afaSblymn  * Report an integer value back to the director
128bdd37afaSblymn  */
129bdd37afaSblymn void
report_int(int value)130bdd37afaSblymn report_int(int value)
131bdd37afaSblymn {
132bdd37afaSblymn 	char *string;
133bdd37afaSblymn 
134bdd37afaSblymn 	asprintf(&string, "%d", value);
135bdd37afaSblymn 	report_status(string);
136bdd37afaSblymn 	free(string);
137bdd37afaSblymn }
138bdd37afaSblymn 
139bdd37afaSblymn /*
140bdd37afaSblymn  * Report either an ERR or OK back to the director
141bdd37afaSblymn  */
142bdd37afaSblymn void
report_return(int status)143bdd37afaSblymn report_return(int status)
144bdd37afaSblymn {
145bdd37afaSblymn 	if (status == ERR)
14673417462Srillig 		write_to_director_type(data_err);
147bdd37afaSblymn 	else if (status == OK)
14873417462Srillig 		write_to_director_type(data_ok);
149ce321bb0Sblymn 	else if (status == KEY_CODE_YES)
150ce321bb0Sblymn 		report_int(status);
151bdd37afaSblymn 	else
152bdd37afaSblymn 		report_status("INVALID_RETURN");
153bdd37afaSblymn }
154bdd37afaSblymn 
155bdd37afaSblymn /*
156bdd37afaSblymn  * Report the number of returns back to the director via the command pipe
157bdd37afaSblymn  */
158bdd37afaSblymn void
report_count(int count)159bdd37afaSblymn report_count(int count)
160bdd37afaSblymn {
16173417462Srillig 	write_to_director_type(data_count);
16273417462Srillig 	write_to_director_int(count);
163bdd37afaSblymn }
164bdd37afaSblymn 
165bdd37afaSblymn /*
166bdd37afaSblymn  * Report the status back to the director via the command pipe
167bdd37afaSblymn  */
168bdd37afaSblymn void
report_status(const char * status)1692a18cea9Schristos report_status(const char *status)
170bdd37afaSblymn {
171e275f7f7Sblymn 	report_message(data_string, status);
172bdd37afaSblymn }
173bdd37afaSblymn 
174bdd37afaSblymn /*
175bdd37afaSblymn  * Report an error message back to the director via the command pipe.
176bdd37afaSblymn  */
177bdd37afaSblymn void
report_error(const char * status)1782a18cea9Schristos report_error(const char *status)
179bdd37afaSblymn {
180e275f7f7Sblymn 	report_message(data_slave_error, status);
181bdd37afaSblymn }
182bdd37afaSblymn 
183bdd37afaSblymn /*
184bdd37afaSblymn  * Report the message with the given type back to the director via the
185bdd37afaSblymn  * command pipe.
186bdd37afaSblymn  */
187bdd37afaSblymn static void
report_message(data_enum_t type,const char * status)18873417462Srillig report_message(data_enum_t type, const char *status)
189bdd37afaSblymn {
19073417462Srillig 	size_t len = strlen(status);
19173417462Srillig 	write_to_director_type(type);
19273417462Srillig 	write_to_director_int(len);
19373417462Srillig 	write_to_director(status, len);
194bdd37afaSblymn }
195bdd37afaSblymn 
196bdd37afaSblymn /*
197*2209bb42Srillig  * Report a single chtype back to the director via the command pipe.
198bdd37afaSblymn  */
199bdd37afaSblymn void
report_byte(chtype c)200f47c5ad5Sblymn report_byte(chtype c)
201f47c5ad5Sblymn {
202f47c5ad5Sblymn 	chtype string[2];
203f47c5ad5Sblymn 
204f47c5ad5Sblymn 	string[0] = c;
205f47c5ad5Sblymn 	string[1] = A_NORMAL | '\0';
206f47c5ad5Sblymn 	report_nstr(string);
207f47c5ad5Sblymn }
208f47c5ad5Sblymn 
209f47c5ad5Sblymn /*
210f47c5ad5Sblymn  * Report a string of chtype back to the director via the command pipe.
211f47c5ad5Sblymn  */
212f47c5ad5Sblymn void
report_nstr(chtype * string)213bdd37afaSblymn report_nstr(chtype *string)
214bdd37afaSblymn {
21573417462Srillig 	size_t size;
216bdd37afaSblymn 	chtype *p;
217bdd37afaSblymn 
21873417462Srillig 	for (p = string; (*p & __CHARTEXT) != 0; p++)
21973417462Srillig 		continue;
220bdd37afaSblymn 
221b411b2c4Srillig 	size = (size_t)(p + 1 - string) * sizeof(*p);
222bdd37afaSblymn 
22373417462Srillig 	write_to_director_type(data_byte);
22473417462Srillig 	write_to_director_int(size);
22573417462Srillig 	write_to_director(string, size);
226bdd37afaSblymn }
227bdd37afaSblymn 
228bdd37afaSblymn /*
229ce321bb0Sblymn  * Report a cchar_t back to the director via the command pipe.
230ce321bb0Sblymn  */
231ce321bb0Sblymn void
report_cchar(cchar_t c)232ce321bb0Sblymn report_cchar(cchar_t c)
233ce321bb0Sblymn {
234ce321bb0Sblymn 
23573417462Srillig 	write_to_director_type(data_cchar);
236b411b2c4Srillig 	write_to_director_int(sizeof(c));
237b411b2c4Srillig 	write_to_director(&c, sizeof(c));
238ce321bb0Sblymn }
239ce321bb0Sblymn 
240ce321bb0Sblymn /*
241ce321bb0Sblymn  * Report a wchar_t back to the director via the command pipe.
242ce321bb0Sblymn  */
243ce321bb0Sblymn void
report_wchar(wchar_t ch)244ce321bb0Sblymn report_wchar(wchar_t ch)
245ce321bb0Sblymn {
246ce321bb0Sblymn 	wchar_t wstr[2];
247ce321bb0Sblymn 
248ce321bb0Sblymn 	wstr[0] = ch;
249ce321bb0Sblymn 	wstr[1] = L'\0';
250ce321bb0Sblymn 	report_wstr(wstr);
251ce321bb0Sblymn }
252ce321bb0Sblymn 
253ce321bb0Sblymn 
254ce321bb0Sblymn /*
255ce321bb0Sblymn  * Report a string of wchar_t back to the director via the command pipe.
256ce321bb0Sblymn  */
257ce321bb0Sblymn void
report_wstr(wchar_t * wstr)258ce321bb0Sblymn report_wstr(wchar_t *wstr)
259ce321bb0Sblymn {
26073417462Srillig 	size_t size;
261ce321bb0Sblymn 	wchar_t *p;
262ce321bb0Sblymn 
26373417462Srillig 	for (p = wstr; *p != L'\0'; p++)
26473417462Srillig 		continue;
265b411b2c4Srillig 	size = (size_t)(p + 1 - wstr) * sizeof(*p);
266ce321bb0Sblymn 
267ce321bb0Sblymn 
26873417462Srillig 	write_to_director_type(data_wchar);
26973417462Srillig 	write_to_director_int(size);
27073417462Srillig 	write_to_director(wstr, size);
271ce321bb0Sblymn }
272ce321bb0Sblymn 
273ce321bb0Sblymn /*
274bdd37afaSblymn  * Check the number of args we received are what we expect.  Return an
275bdd37afaSblymn  * error if they do not match.
276bdd37afaSblymn  */
277bdd37afaSblymn int
check_arg_count(int nargs,int expected)278bdd37afaSblymn check_arg_count(int nargs, int expected)
279bdd37afaSblymn {
280bdd37afaSblymn 	if (nargs != expected) {
281bdd37afaSblymn 		report_count(1);
282bdd37afaSblymn 		report_error("INCORRECT_ARGUMENT_NUMBER");
28373417462Srillig 		return 1;
284bdd37afaSblymn 	}
285bdd37afaSblymn 
28673417462Srillig 	return 0;
287bdd37afaSblymn }
288