1 /* $NetBSD: slave.c,v 1.17 2021/06/13 12:46:01 rillig Exp $ */
2
3 /*-
4 * Copyright 2009 Brett Lymn <blymn@NetBSD.org>
5 * Copyright 2021 Roland Illig <rillig@NetBSD.org>
6 *
7 * All rights reserved.
8 *
9 * This code has been donated to The NetBSD Foundation by the Author.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <fcntl.h>
32 #include <sys/ioctl.h>
33 #include <unistd.h>
34 #include <err.h>
35 #include <stdbool.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <curses.h>
40 #include "returns.h"
41 #include "slave.h"
42
43 int from_director;
44 int to_director;
45 int initdone = 0;
46
47 #if 0
48 static const char *returns_enum_names[] = {
49 "unused", "numeric", "string", "byte", "ERR", "OK", "NULL", "not NULL",
50 "variable"
51 };
52 #endif
53
54 static bool
try_read_from_director(void * data,size_t n)55 try_read_from_director(void *data, size_t n)
56 {
57 ssize_t nread = read(from_director, data, n);
58 if (nread < 0)
59 err(2, "error reading from command pipe");
60 if (nread == 0)
61 return false;
62 if ((size_t)nread != n)
63 errx(2, "short read from command pipe: expected %zu, got %zu",
64 n, (size_t)nread);
65 return true;
66 }
67
68 static void
read_from_director(void * data,size_t n)69 read_from_director(void *data, size_t n)
70 {
71 ssize_t nread = read(from_director, data, n);
72 if (nread < 0)
73 err(2, "error reading from command pipe");
74 if ((size_t)nread != n)
75 errx(2, "short read from command pipe: expected %zu, got %zu",
76 n, (size_t)nread);
77 }
78
79 static bool
read_command_argument(char *** pargs,int argslen)80 read_command_argument(char ***pargs, int argslen)
81 {
82 int type, len;
83 char **args = *pargs;
84
85 read_from_director(&type, sizeof(type));
86 read_from_director(&len, sizeof(len));
87 if (len < 0)
88 return false;
89
90 args = realloc(args, (argslen + 1) * sizeof(args[0]));
91 if (args == NULL)
92 err(1, "slave realloc of args array failed");
93 *pargs = args;
94
95 if (type != data_null) {
96 args[argslen] = malloc(len + 1);
97
98 if (args[argslen] == NULL)
99 err(1, "slave alloc of %d bytes for args failed", len);
100 }
101
102 if (len == 0) {
103 if (type == data_null)
104 args[argslen] = NULL;
105 else
106 args[argslen][0] = '\0';
107 } else {
108 read_from_director(args[argslen], len);
109 if (type != data_byte)
110 args[argslen][len] = '\0';
111
112 if (len == 6 && strcmp(args[argslen], "STDSCR") == 0) {
113 char *stdscr_buf;
114 if (asprintf(&stdscr_buf, "%p", stdscr) < 0)
115 err(2, "asprintf of stdscr failed");
116 free(args[argslen]);
117 args[argslen] = stdscr_buf;
118 }
119 }
120 return true;
121 }
122
123 /*
124 * Read the command pipe for the function to execute, gather the args
125 * and then process the command.
126 */
127 static void
process_commands(void)128 process_commands(void)
129 {
130 int len, maxlen, argslen, i, type;
131 char *cmdbuf, *tmpbuf, **args;
132
133 len = maxlen = 30;
134 if ((cmdbuf = malloc(maxlen)) == NULL)
135 err(1, "slave cmdbuf malloc failed");
136
137 while (try_read_from_director(&type, sizeof(type))) {
138 if (type != data_string)
139 errx(1, "Unexpected type for command, got %d", type);
140
141 read_from_director(&len, sizeof(len));
142
143 if ((len + 1) > maxlen) {
144 maxlen = len + 1;
145 if ((tmpbuf = realloc(cmdbuf, maxlen)) == NULL)
146 err(1, "slave cmdbuf realloc to %d "
147 "bytes failed", maxlen);
148 cmdbuf = tmpbuf;
149 }
150
151 read_from_director(cmdbuf, len);
152 cmdbuf[len] = '\0';
153 argslen = 0;
154 args = NULL;
155
156 while (read_command_argument(&args, argslen))
157 argslen++;
158
159 command_execute(cmdbuf, argslen, args);
160
161 if (args != NULL) {
162 for (i = 0; i < argslen; i++)
163 free(args[i]);
164
165 free(args);
166 }
167 }
168 }
169
170 int
main(int argc,char * argv[])171 main(int argc, char *argv[])
172 {
173 if (argc != 3) {
174 fprintf(stderr, "usage: %s <in_fd> <out_fd>\n", getprogname());
175 return 0;
176 }
177 sscanf(argv[1], "%d", &from_director);
178 sscanf(argv[2], "%d", &to_director);
179
180 process_commands();
181
182 return 0;
183 }
184