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