xref: /netbsd-src/tests/lib/libcurses/slave/slave.c (revision b411b2c44889a3e7a7fad2a472d87b4d7390124a)
1*b411b2c4Srillig /*	$NetBSD: slave.c,v 1.17 2021/06/13 12:46:01 rillig Exp $	*/
2bdd37afaSblymn 
3bdd37afaSblymn /*-
4bdd37afaSblymn  * Copyright 2009 Brett Lymn <blymn@NetBSD.org>
5177fdb97Srillig  * 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  */
30177fdb97Srillig 
31bdd37afaSblymn #include <fcntl.h>
32bdd37afaSblymn #include <sys/ioctl.h>
3321bd6ba1Schristos #include <unistd.h>
3421bd6ba1Schristos #include <err.h>
3578dd027bSrillig #include <stdbool.h>
36bdd37afaSblymn #include <stdio.h>
37bdd37afaSblymn #include <stdlib.h>
38bdd37afaSblymn #include <string.h>
39bdd37afaSblymn #include <curses.h>
40bdd37afaSblymn #include "returns.h"
41bdd37afaSblymn #include "slave.h"
42bdd37afaSblymn 
4326ce28a5Srillig int from_director;
4426ce28a5Srillig int to_director;
45ce321bb0Sblymn int initdone = 0;
46bdd37afaSblymn 
472a18cea9Schristos #if 0
482a18cea9Schristos static const char *returns_enum_names[] = {
49bdd37afaSblymn 	"unused", "numeric", "string", "byte", "ERR", "OK", "NULL", "not NULL",
50bdd37afaSblymn 	"variable"
51bdd37afaSblymn };
522a18cea9Schristos #endif
53bdd37afaSblymn 
5478dd027bSrillig static bool
try_read_from_director(void * data,size_t n)5578dd027bSrillig try_read_from_director(void *data, size_t n)
5678dd027bSrillig {
5778dd027bSrillig 	ssize_t nread = read(from_director, data, n);
5878dd027bSrillig 	if (nread < 0)
5978dd027bSrillig 		err(2, "error reading from command pipe");
6078dd027bSrillig 	if (nread == 0)
6178dd027bSrillig 		return false;
6278dd027bSrillig 	if ((size_t)nread != n)
6378dd027bSrillig 		errx(2, "short read from command pipe: expected %zu, got %zu",
6478dd027bSrillig 		    n, (size_t)nread);
6578dd027bSrillig 	return true;
6678dd027bSrillig }
6778dd027bSrillig 
6878dd027bSrillig static void
read_from_director(void * data,size_t n)6978dd027bSrillig read_from_director(void *data, size_t n)
7078dd027bSrillig {
7178dd027bSrillig 	ssize_t nread = read(from_director, data, n);
7278dd027bSrillig 	if (nread < 0)
7378dd027bSrillig 		err(2, "error reading from command pipe");
7478dd027bSrillig 	if ((size_t)nread != n)
7578dd027bSrillig 		errx(2, "short read from command pipe: expected %zu, got %zu",
7678dd027bSrillig 		    n, (size_t)nread);
7778dd027bSrillig }
7878dd027bSrillig 
7986536876Srillig static bool
read_command_argument(char *** pargs,int argslen)8086536876Srillig read_command_argument(char ***pargs, int argslen)
8186536876Srillig {
8286536876Srillig 	int type, len;
8386536876Srillig 	char **args = *pargs;
8486536876Srillig 
85*b411b2c4Srillig 	read_from_director(&type, sizeof(type));
86*b411b2c4Srillig 	read_from_director(&len, sizeof(len));
8786536876Srillig 	if (len < 0)
8886536876Srillig 		return false;
8986536876Srillig 
90*b411b2c4Srillig 	args = realloc(args, (argslen + 1) * sizeof(args[0]));
9186536876Srillig 	if (args == NULL)
9286536876Srillig 		err(1, "slave realloc of args array failed");
9386536876Srillig 	*pargs = args;
9486536876Srillig 
9586536876Srillig 	if (type != data_null) {
9686536876Srillig 		args[argslen] = malloc(len + 1);
9786536876Srillig 
9886536876Srillig 		if (args[argslen] == NULL)
9986536876Srillig 			err(1, "slave alloc of %d bytes for args failed", len);
10086536876Srillig 	}
10186536876Srillig 
10286536876Srillig 	if (len == 0) {
10386536876Srillig 		if (type == data_null)
10486536876Srillig 			args[argslen] = NULL;
10586536876Srillig 		else
10686536876Srillig 			args[argslen][0] = '\0';
10786536876Srillig 	} else {
10886536876Srillig 		read_from_director(args[argslen], len);
10986536876Srillig 		if (type != data_byte)
11086536876Srillig 			args[argslen][len] = '\0';
11186536876Srillig 
11286536876Srillig 		if (len == 6 && strcmp(args[argslen], "STDSCR") == 0) {
11386536876Srillig 			char *stdscr_buf;
11486536876Srillig 			if (asprintf(&stdscr_buf, "%p", stdscr) < 0)
11586536876Srillig 				err(2, "asprintf of stdscr failed");
11686536876Srillig 			free(args[argslen]);
11786536876Srillig 			args[argslen] = stdscr_buf;
11886536876Srillig 		}
11986536876Srillig 	}
12086536876Srillig 	return true;
12186536876Srillig }
12286536876Srillig 
123bdd37afaSblymn /*
124bdd37afaSblymn  * Read the command pipe for the function to execute, gather the args
125bdd37afaSblymn  * and then process the command.
126bdd37afaSblymn  */
1272a18cea9Schristos static void
process_commands(void)128ce321bb0Sblymn process_commands(void)
129bdd37afaSblymn {
13086536876Srillig 	int len, maxlen, argslen, i, type;
13186536876Srillig 	char *cmdbuf, *tmpbuf, **args;
132bdd37afaSblymn 
133bdd37afaSblymn 	len = maxlen = 30;
134bdd37afaSblymn 	if ((cmdbuf = malloc(maxlen)) == NULL)
135bdd37afaSblymn 		err(1, "slave cmdbuf malloc failed");
136bdd37afaSblymn 
137*b411b2c4Srillig 	while (try_read_from_director(&type, sizeof(type))) {
138e275f7f7Sblymn 		if (type != data_string)
13923bea509Schristos 			errx(1, "Unexpected type for command, got %d", type);
140bdd37afaSblymn 
141*b411b2c4Srillig 		read_from_director(&len, sizeof(len));
142bdd37afaSblymn 
143bdd37afaSblymn 		if ((len + 1) > maxlen) {
144bdd37afaSblymn 			maxlen = len + 1;
145bdd37afaSblymn 			if ((tmpbuf = realloc(cmdbuf, maxlen)) == NULL)
146bdd37afaSblymn 				err(1, "slave cmdbuf realloc to %d "
147bdd37afaSblymn 				    "bytes failed", maxlen);
148bdd37afaSblymn 			cmdbuf = tmpbuf;
149bdd37afaSblymn 		}
150bdd37afaSblymn 
15178dd027bSrillig 		read_from_director(cmdbuf, len);
152bdd37afaSblymn 		cmdbuf[len] = '\0';
153bdd37afaSblymn 		argslen = 0;
154bdd37afaSblymn 		args = NULL;
155bdd37afaSblymn 
15686536876Srillig 		while (read_command_argument(&args, argslen))
157bdd37afaSblymn 			argslen++;
158bdd37afaSblymn 
159bdd37afaSblymn 		command_execute(cmdbuf, argslen, args);
160bdd37afaSblymn 
161bdd37afaSblymn 		if (args != NULL) {
162bdd37afaSblymn 			for (i = 0; i < argslen; i++)
163bdd37afaSblymn 				free(args[i]);
164bdd37afaSblymn 
165bdd37afaSblymn 			free(args);
166bdd37afaSblymn 		}
167bdd37afaSblymn 	}
168bdd37afaSblymn }
169bdd37afaSblymn 
170bdd37afaSblymn int
main(int argc,char * argv[])171bdd37afaSblymn main(int argc, char *argv[])
172bdd37afaSblymn {
17326ce28a5Srillig 	if (argc != 3) {
17426ce28a5Srillig 		fprintf(stderr, "usage: %s <in_fd> <out_fd>\n", getprogname());
17523bea509Schristos 		return 0;
17623bea509Schristos 	}
17726ce28a5Srillig 	sscanf(argv[1], "%d", &from_director);
17826ce28a5Srillig 	sscanf(argv[2], "%d", &to_director);
179bdd37afaSblymn 
180ce321bb0Sblymn 	process_commands();
181bdd37afaSblymn 
18223bea509Schristos 	return 0;
183bdd37afaSblymn }
184