Home | History | Annotate | Line # | Download | only in slave
commands.c revision 1.11
      1 /*	$NetBSD: commands.c,v 1.11 2021/02/13 06:45:42 rillig Exp $	*/
      2 
      3 /*-
      4  * Copyright 2009 Brett Lymn <blymn (at) 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 without 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 initdone;
     44 
     45 static void report_type(data_enum_t);
     46 static void report_message(int, const char *);
     47 
     48 /*
     49  * Match the passed command string and execute the associated test
     50  * function.
     51  */
     52 void
     53 command_execute(char *func, int nargs, char **args)
     54 {
     55 	size_t i, j;
     56 
     57 	i = 0;
     58 	while (i < ncmds) {
     59 		if (strcmp(func, commands[i].name) == 0) {
     60 			/* Check only restricted set of functions is called before
     61 			 * initscr/newterm */
     62 			if (!initdone) {
     63 				j = 0;
     64 				while (j < nrcmds) {
     65 					if (strcmp(func, restricted_commands[j]) == 0) {
     66 						if (strcmp(func, "initscr") == 0  ||
     67 							strcmp(func, "newterm") == 0)
     68 							initdone = 1;
     69 						/* matched function */
     70 						commands[i].func(nargs, args);
     71 						return;
     72 					}
     73 					j++;
     74 				}
     75 				report_status("YOU NEED TO CALL INITSCR/NEWTERM FIRST");
     76 				return;
     77 			}
     78 			/* matched function */
     79 			commands[i].func(nargs, args);
     80 			return;
     81 		}
     82 		i++;
     83 	}
     84 
     85 	report_status("UNKNOWN_FUNCTION");
     86 }
     87 
     88 /*
     89  * Report an pointer value back to the director
     90  */
     91 void
     92 report_ptr(void *ptr)
     93 {
     94 	char *string;
     95 
     96 	if (ptr == NULL)
     97 		asprintf(&string, "NULL");
     98 	else
     99 		asprintf(&string, "%p", ptr);
    100 	report_status(string);
    101 	free(string);
    102 }
    103 
    104 /*
    105  * Report an integer value back to the director
    106  */
    107 void
    108 report_int(int value)
    109 {
    110 	char *string;
    111 
    112 	asprintf(&string, "%d", value);
    113 	report_status(string);
    114 	free(string);
    115 }
    116 
    117 /*
    118  * Report either an ERR or OK back to the director
    119  */
    120 void
    121 report_return(int status)
    122 {
    123 	if (status == ERR)
    124 		report_type(data_err);
    125 	else if (status == OK)
    126 		report_type(data_ok);
    127 	else if (status == KEY_CODE_YES)
    128 		report_int(status);
    129 	else
    130 		report_status("INVALID_RETURN");
    131 }
    132 
    133 /*
    134  * Report the type back to the director via the command pipe
    135  */
    136 static void
    137 report_type(data_enum_t return_type)
    138 {
    139 	int type;
    140 
    141 	type = return_type;
    142 	if (write(to_director, &type, sizeof(int)) < 0)
    143 		err(1, "command pipe write for status type failed");
    144 
    145 }
    146 
    147 /*
    148  * Report the number of returns back to the director via the command pipe
    149  */
    150 void
    151 report_count(int count)
    152 {
    153 	int type;
    154 
    155 	type = data_count;
    156 	if (write(to_director, &type, sizeof(int)) < 0)
    157 		err(1, "command pipe write for count type failed");
    158 
    159 	if (write(to_director, &count, sizeof(int)) < 0)
    160 		err(1, "command pipe write for count");
    161 }
    162 
    163 /*
    164  * Report the status back to the director via the command pipe
    165  */
    166 void
    167 report_status(const char *status)
    168 {
    169 	report_message(data_string, status);
    170 }
    171 
    172 /*
    173  * Report an error message back to the director via the command pipe.
    174  */
    175 void
    176 report_error(const char *status)
    177 {
    178 	report_message(data_slave_error, status);
    179 }
    180 
    181 /*
    182  * Report the message with the given type back to the director via the
    183  * command pipe.
    184  */
    185 static void
    186 report_message(int type, const char *status)
    187 {
    188 	int len;
    189 
    190 	len = strlen(status);
    191 
    192 	if (write(to_director, &type, sizeof(int)) < 0)
    193 		err(1, "command pipe write for message type failed");
    194 
    195 	if (write(to_director, &len, sizeof(int)) < 0)
    196 		err(1, "command pipe write for message length failed");
    197 
    198 	if (write(to_director, status, len) < 0)
    199 		err(1, "command pipe write of message data failed");
    200 }
    201 
    202 /*
    203  * Report a string of chtype back to the director via the command pipe.
    204  */
    205 void
    206 report_byte(chtype c)
    207 {
    208 	chtype string[2];
    209 
    210 	string[0] = c;
    211 	string[1] = A_NORMAL | '\0';
    212 	report_nstr(string);
    213 }
    214 
    215 /*
    216  * Report a string of chtype back to the director via the command pipe.
    217  */
    218 void
    219 report_nstr(chtype *string)
    220 {
    221 	int len, type;
    222 	chtype *p;
    223 
    224 	len = 0;
    225 	p = string;
    226 
    227 	while ((*p++ & __CHARTEXT) != 0) {
    228 		len++;
    229 	}
    230 
    231 	len++; /* add in the termination chtype */
    232 	len *= sizeof(chtype);
    233 
    234 	type = data_byte;
    235 	if (write(to_director, &type, sizeof(int)) < 0)
    236 		err(1, "%s: command pipe write for status type failed",
    237 		    __func__);
    238 
    239 	if (write(to_director, &len, sizeof(int)) < 0)
    240 		err(1, "%s: command pipe write for status length failed",
    241 		    __func__);
    242 
    243 	if (write(to_director, string, len) < 0)
    244 		err(1, "%s: command pipe write of status data failed",
    245 		    __func__);
    246 }
    247 
    248 /*
    249  * Report a cchar_t back to the director via the command pipe.
    250  */
    251 void
    252 report_cchar(cchar_t c)
    253 {
    254 	int len, type;
    255 	len = sizeof(cchar_t);
    256 	type = data_cchar;
    257 
    258 	if (write(to_director, &type, sizeof(int)) < 0)
    259 		err(1, "%s: command pipe write for status type failed",
    260 		    __func__);
    261 
    262 	if (write(to_director, &len, sizeof(int)) < 0)
    263 		err(1, "%s: command pipe write for status length failed",
    264 		    __func__);
    265 
    266 	if (write(to_director, &c, len) < 0)
    267 		err(1, "%s: command pipe write of status data failed",
    268 		    __func__);
    269 }
    270 
    271 /*
    272  * Report a wchar_t back to the director via the command pipe.
    273  */
    274 void
    275 report_wchar(wchar_t ch)
    276 {
    277 	wchar_t wstr[2];
    278 
    279 	wstr[0] = ch;
    280 	wstr[1] = L'\0';
    281 	report_wstr(wstr);
    282 }
    283 
    284 
    285 /*
    286  * Report a string of wchar_t back to the director via the command pipe.
    287  */
    288 void
    289 report_wstr(wchar_t *wstr)
    290 {
    291 	int len, type;
    292 	wchar_t *p;
    293 
    294 	len = 0;
    295 	p = wstr;
    296 
    297 	while (*p++ != L'\0')
    298 		len++;
    299 
    300 	len++; /* add in the termination chtype */
    301 	len *= sizeof(wchar_t);
    302 
    303 	type = data_wchar;
    304 	if (write(to_director, &type, sizeof(int)) < 0)
    305 		err(1, "%s: command pipe write for status type failed",
    306 		    __func__);
    307 
    308 	if (write(to_director, &len, sizeof(int)) < 0)
    309 		err(1, "%s: command pipe write for status length failed",
    310 		    __func__);
    311 
    312 	if (write(to_director, wstr, len) < 0)
    313 		err(1, "%s: command pipe write of status data failed",
    314 		    __func__);
    315 }
    316 
    317 /*
    318  * Check the number of args we received are what we expect.  Return an
    319  * error if they do not match.
    320  */
    321 int
    322 check_arg_count(int nargs, int expected)
    323 {
    324 	if (nargs != expected) {
    325 		report_count(1);
    326 		report_error("INCORRECT_ARGUMENT_NUMBER");
    327 		return(1);
    328 	}
    329 
    330 	return(0);
    331 }
    332