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