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