1 /* $NetBSD: slave.c,v 1.16 2021/02/13 10:03:49 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 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 static bool 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 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 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