1 /* $NetBSD: commands.c,v 1.6 2020/10/24 04:46:17 blymn Exp $ */ 2 3 /*- 4 * Copyright 2009 Brett Lymn <blymn@NetBSD.org> 5 * 6 * All rights reserved. 7 * 8 * This code has been donated to The NetBSD Foundation by the Author. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. The name of the author may not be used to endorse or promote products 16 * derived from this software withough specific prior written permission 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * 30 */ 31 32 #include <curses.h> 33 #include <string.h> 34 #include <stdlib.h> 35 #include <stdio.h> 36 #include <unistd.h> 37 #include <err.h> 38 #include <sys/types.h> 39 #include "returns.h" 40 #include "slave.h" 41 #include "command_table.h" 42 43 extern int cmdpipe[2]; 44 extern int slvpipe[2]; 45 extern int initdone; 46 47 static void report_type(data_enum_t); 48 static void report_message(int, const char *); 49 50 /* 51 * Match the passed command string and execute the associated test 52 * function. 53 */ 54 void 55 command_execute(char *func, int nargs, char **args) 56 { 57 size_t i, j; 58 59 i = 0; 60 while (i < ncmds) { 61 if (strcasecmp(func, commands[i].name) == 0) { 62 /* Check only restricted set of functions is called before 63 * initscr/newterm */ 64 if(!initdone){ 65 j = 0; 66 while(j < nrcmds) { 67 if(strcasecmp(func, restricted_commands[j]) == 0){ 68 if(strcasecmp(func, "initscr") == 0 || 69 strcasecmp(func, "newterm") == 0) 70 initdone = 1; 71 /* matched function */ 72 commands[i].func(nargs, args); 73 return; 74 } 75 j++; 76 } 77 report_status("YOU NEED TO CALL INITSCR/NEWTERM FIRST"); 78 return; 79 } 80 /* matched function */ 81 commands[i].func(nargs, args); 82 return; 83 } 84 i++; 85 } 86 87 report_status("UNKNOWN_FUNCTION"); 88 } 89 90 /* 91 * Report an pointer value back to the director 92 */ 93 void 94 report_ptr(void *ptr) 95 { 96 char *string; 97 98 if (ptr == NULL) 99 asprintf(&string, "NULL"); 100 else 101 asprintf(&string, "%p", ptr); 102 report_status(string); 103 free(string); 104 } 105 106 /* 107 * Report an integer value back to the director 108 */ 109 void 110 report_int(int value) 111 { 112 char *string; 113 114 asprintf(&string, "%d", value); 115 report_status(string); 116 free(string); 117 } 118 119 /* 120 * Report either an ERR or OK back to the director 121 */ 122 void 123 report_return(int status) 124 { 125 if (status == ERR) 126 report_type(data_err); 127 else if (status == OK) 128 report_type(data_ok); 129 else if (status == KEY_CODE_YES) 130 report_int(status); 131 else 132 report_status("INVALID_RETURN"); 133 } 134 135 /* 136 * Report the type back to the director via the command pipe 137 */ 138 static void 139 report_type(data_enum_t return_type) 140 { 141 int type; 142 143 type = return_type; 144 if (write(slvpipe[WRITE_PIPE], &type, sizeof(int)) < 0) 145 err(1, "command pipe write for status type failed"); 146 147 } 148 149 /* 150 * Report the number of returns back to the director via the command pipe 151 */ 152 void 153 report_count(int count) 154 { 155 int type; 156 157 type = data_count; 158 if (write(slvpipe[WRITE_PIPE], &type, sizeof(int)) < 0) 159 err(1, "command pipe write for count type failed"); 160 161 if (write(slvpipe[WRITE_PIPE], &count, sizeof(int)) < 0) 162 err(1, "command pipe write for count"); 163 } 164 165 /* 166 * Report the status back to the director via the command pipe 167 */ 168 void 169 report_status(const char *status) 170 { 171 report_message(data_string, status); 172 } 173 174 /* 175 * Report an error message back to the director via the command pipe. 176 */ 177 void 178 report_error(const char *status) 179 { 180 report_message(data_slave_error, status); 181 } 182 183 /* 184 * Report the message with the given type back to the director via the 185 * command pipe. 186 */ 187 static void 188 report_message(int type, const char *status) 189 { 190 int len; 191 192 len = strlen(status); 193 194 if (write(slvpipe[WRITE_PIPE], &type, sizeof(int)) < 0) 195 err(1, "command pipe write for message type failed"); 196 197 if (write(slvpipe[WRITE_PIPE], &len, sizeof(int)) < 0) 198 err(1, "command pipe write for message length failed"); 199 200 if (write(slvpipe[WRITE_PIPE], status, len) < 0) 201 err(1, "command pipe write of message data failed"); 202 } 203 204 /* 205 * Report a string of chtype back to the director via the command pipe. 206 */ 207 void 208 report_byte(chtype c) 209 { 210 chtype string[2]; 211 212 string[0] = c; 213 string[1] = A_NORMAL | '\0'; 214 report_nstr(string); 215 } 216 217 /* 218 * Report a string of chtype back to the director via the command pipe. 219 */ 220 void 221 report_nstr(chtype *string) 222 { 223 int len, type; 224 chtype *p; 225 226 len = 0; 227 p = string; 228 229 while ((*p++ & __CHARTEXT) != 0) { 230 len++; 231 } 232 233 len++; /* add in the termination chtype */ 234 len *= sizeof(chtype); 235 236 type = data_byte; 237 if (write(slvpipe[WRITE_PIPE], &type, sizeof(int)) < 0) 238 err(1, "%s: command pipe write for status type failed", 239 __func__); 240 241 if (write(slvpipe[WRITE_PIPE], &len, sizeof(int)) < 0) 242 err(1, "%s: command pipe write for status length failed", 243 __func__); 244 245 if (write(slvpipe[WRITE_PIPE], string, len) < 0) 246 err(1, "%s: command pipe write of status data failed", 247 __func__); 248 } 249 250 /* 251 * Report a cchar_t back to the director via the command pipe. 252 */ 253 void 254 report_cchar(cchar_t c) 255 { 256 int len, type; 257 len = sizeof(cchar_t); 258 type = data_cchar; 259 260 if (write(slvpipe[WRITE_PIPE], &type, sizeof(int)) < 0) 261 err(1, "%s: command pipe write for status type failed", 262 __func__); 263 264 if (write(slvpipe[WRITE_PIPE], &len, sizeof(int)) < 0) 265 err(1, "%s: command pipe write for status length failed", 266 __func__); 267 268 if (write(slvpipe[WRITE_PIPE], &c, len) < 0) 269 err(1, "%s: command pipe write of status data failed", 270 __func__); 271 } 272 273 /* 274 * Report a wchar_t back to the director via the command pipe. 275 */ 276 void 277 report_wchar(wchar_t ch) 278 { 279 wchar_t wstr[2]; 280 281 wstr[0] = ch; 282 wstr[1] = L'\0'; 283 report_wstr(wstr); 284 } 285 286 287 /* 288 * Report a string of wchar_t back to the director via the command pipe. 289 */ 290 void 291 report_wstr(wchar_t *wstr) 292 { 293 int len, type; 294 wchar_t *p; 295 296 len = 0; 297 p = wstr; 298 299 while (*p++ != L'\0') 300 len++; 301 302 len++; /* add in the termination chtype */ 303 len *= sizeof(wchar_t); 304 305 type = data_wchar; 306 if (write(slvpipe[WRITE_PIPE], &type, sizeof(int)) < 0) 307 err(1, "%s: command pipe write for status type failed", 308 __func__); 309 310 if (write(slvpipe[WRITE_PIPE], &len, sizeof(int)) < 0) 311 err(1, "%s: command pipe write for status length failed", 312 __func__); 313 314 if (write(slvpipe[WRITE_PIPE], wstr, len) < 0) 315 err(1, "%s: command pipe write of status data failed", 316 __func__); 317 } 318 319 /* 320 * Check the number of args we received are what we expect. Return an 321 * error if they do not match. 322 */ 323 int 324 check_arg_count(int nargs, int expected) 325 { 326 if (nargs != expected) { 327 report_count(1); 328 report_error("INCORRECT_ARGUMENT_NUMBER"); 329 return(1); 330 } 331 332 return(0); 333 } 334