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