1/*	$NetBSD: commands.c,v 1.4 2011/09/15 11:46:19 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
43extern int cmdpipe[2];
44extern int slvpipe[2];
45
46static void report_type(returns_enum_t);
47static void report_message(int, const char *);
48
49/*
50 * Match the passed command string and execute the associated test
51 * function.
52 */
53void
54command_execute(char *func, int nargs, char **args)
55{
56	size_t i;
57
58	i = 0;
59	while (i < ncmds) {
60		if (strcasecmp(func, commands[i].name) == 0) {
61			/* matched function */
62			commands[i].func(nargs, args);
63			return;
64		}
65		i++;
66	}
67
68	report_status("UNKNOWN_FUNCTION");
69}
70
71/*
72 * Report an pointer value back to the director
73 */
74void
75report_ptr(void *ptr)
76{
77	char *string;
78
79	if (ptr == NULL)
80		asprintf(&string, "NULL");
81	else
82		asprintf(&string, "%p", ptr);
83	report_status(string);
84	free(string);
85}
86
87/*
88 * Report an integer value back to the director
89 */
90void
91report_int(int value)
92{
93	char *string;
94
95	asprintf(&string, "%d", value);
96	report_status(string);
97	free(string);
98}
99
100/*
101 * Report either an ERR or OK back to the director
102 */
103void
104report_return(int status)
105{
106	if (status == ERR)
107		report_type(ret_err);
108	else if (status == OK)
109		report_type(ret_ok);
110	else
111		report_status("INVALID_RETURN");
112}
113
114/*
115 * Report the type back to the director via the command pipe
116 */
117static void
118report_type(returns_enum_t return_type)
119{
120	int type;
121
122	type = return_type;
123	if (write(slvpipe[WRITE_PIPE], &type, sizeof(int)) < 0)
124		err(1, "command pipe write for status type failed");
125
126}
127
128/*
129 * Report the number of returns back to the director via the command pipe
130 */
131void
132report_count(int count)
133{
134	int type;
135
136	type = ret_count;
137	if (write(slvpipe[WRITE_PIPE], &type, sizeof(int)) < 0)
138		err(1, "command pipe write for count type failed");
139
140	if (write(slvpipe[WRITE_PIPE], &count, sizeof(int)) < 0)
141		err(1, "command pipe write for count");
142}
143
144/*
145 * Report the status back to the director via the command pipe
146 */
147void
148report_status(const char *status)
149{
150	report_message(ret_string, status);
151}
152
153/*
154 * Report an error message back to the director via the command pipe.
155 */
156void
157report_error(const char *status)
158{
159	report_message(ret_slave_error, status);
160}
161
162/*
163 * Report the message with the given type back to the director via the
164 * command pipe.
165 */
166static void
167report_message(int type, const char *status)
168{
169	int len;
170
171	len = strlen(status);
172
173	if (write(slvpipe[WRITE_PIPE], &type, sizeof(int)) < 0)
174		err(1, "command pipe write for message type failed");
175
176	if (write(slvpipe[WRITE_PIPE], &len, sizeof(int)) < 0)
177		err(1, "command pipe write for message length failed");
178
179	if (write(slvpipe[WRITE_PIPE], status, len) < 0)
180		err(1, "command pipe write of message data failed");
181}
182
183/*
184 * Report a string of chtype back to the director via the command pipe.
185 */
186void
187report_byte(chtype c)
188{
189	chtype string[2];
190
191	string[0] = c;
192	string[1] = A_NORMAL | '\0';
193	report_nstr(string);
194}
195
196/*
197 * Report a string of chtype back to the director via the command pipe.
198 */
199void
200report_nstr(chtype *string)
201{
202	int len, type;
203	chtype *p;
204
205	len = 0;
206	p = string;
207
208	while ((*p++ & __CHARTEXT) != 0) {
209		len++;
210	}
211
212	len++; /* add in the termination chtype */
213	len *= sizeof(chtype);
214
215	type = ret_byte;
216	if (write(slvpipe[WRITE_PIPE], &type, sizeof(int)) < 0)
217		err(1, "%s: command pipe write for status type failed",
218		    __func__);
219
220	if (write(slvpipe[WRITE_PIPE], &len, sizeof(int)) < 0)
221		err(1, "%s: command pipe write for status length failed",
222		    __func__);
223
224	if (write(slvpipe[WRITE_PIPE], string, len) < 0)
225		err(1, "%s: command pipe write of status data failed",
226		    __func__);
227}
228
229/*
230 * Check the number of args we received are what we expect.  Return an
231 * error if they do not match.
232 */
233int
234check_arg_count(int nargs, int expected)
235{
236	if (nargs != expected) {
237		report_count(1);
238		report_error("INCORRECT_ARGUMENT_NUMBER");
239		return(1);
240	}
241
242	return(0);
243}
244