slave.c revision 1.15 1 /* $NetBSD: slave.c,v 1.15 2021/02/13 09:28:27 rillig Exp $ */
2
3 /*-
4 * Copyright 2009 Brett Lymn <blymn (at) NetBSD.org>
5 * Copyright 2021 Roland Illig <rillig (at) 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
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
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 /*
80 * Read the command pipe for the function to execute, gather the args
81 * and then process the command.
82 */
83 static void
84 process_commands(void)
85 {
86 int len, maxlen, argslen, i, ret, type;
87 char *cmdbuf, *tmpbuf, **args, **tmpargs;
88
89 len = maxlen = 30;
90 if ((cmdbuf = malloc(maxlen)) == NULL)
91 err(1, "slave cmdbuf malloc failed");
92
93 while (try_read_from_director(&type, sizeof type)) {
94 if (type != data_string)
95 errx(1, "Unexpected type for command, got %d", type);
96
97 read_from_director(&len, sizeof len);
98
99 if ((len + 1) > maxlen) {
100 maxlen = len + 1;
101 if ((tmpbuf = realloc(cmdbuf, maxlen)) == NULL)
102 err(1, "slave cmdbuf realloc to %d "
103 "bytes failed", maxlen);
104 cmdbuf = tmpbuf;
105 }
106
107 read_from_director(cmdbuf, len);
108 cmdbuf[len] = '\0';
109 argslen = 0;
110 args = NULL;
111
112 do {
113 read_from_director(&type, sizeof type);
114 read_from_director(&len, sizeof len);
115
116 if (len >= 0) {
117 tmpargs = realloc(args,
118 (argslen + 1) * sizeof(char *));
119 if (tmpargs == NULL)
120 err(1, "slave realloc of args array "
121 "failed");
122
123 args = tmpargs;
124 if (type != data_null) {
125 args[argslen] = malloc(len + 1);
126
127 if (args[argslen] == NULL)
128 err(1, "slave alloc of %d bytes"
129 " for args failed", len);
130 }
131
132 if (len == 0) {
133 if (type == data_null)
134 args[argslen] = NULL;
135 else
136 args[argslen][0] = '\0';
137 } else {
138 read_from_director(args[argslen], len);
139 if (type != data_byte)
140 args[argslen][len] = '\0';
141
142 if (len == 6) {
143 if (strcmp(args[argslen],
144 "STDSCR") == 0) {
145 ret = asprintf(&tmpbuf,
146 "%p",
147 stdscr);
148 if (ret < 0)
149 err(2,
150 "asprintf of stdscr failed");
151 free(args[argslen]);
152 args[argslen] = tmpbuf;
153 }
154 }
155 }
156
157 argslen++;
158 }
159 } while (len >= 0);
160
161 command_execute(cmdbuf, argslen, args);
162
163 if (args != NULL) {
164 for (i = 0; i < argslen; i++)
165 free(args[i]);
166
167 free(args);
168 }
169 }
170 }
171
172 int
173 main(int argc, char *argv[])
174 {
175 if (argc != 3) {
176 fprintf(stderr, "usage: %s <in_fd> <out_fd>\n", getprogname());
177 return 0;
178 }
179 sscanf(argv[1], "%d", &from_director);
180 sscanf(argv[2], "%d", &to_director);
181
182 process_commands();
183
184 return 0;
185 }
186