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