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