xref: /freebsd/contrib/netbsd-tests/lib/libcurses/director/testlang_parse.y (revision 9268022b74279434ed6300244e3f977e56a8ceb5)
1 %{
2 /*	$NetBSD: testlang_parse.y,v 1.13 2012/09/19 11:51:56 blymn Exp $	*/
3 
4 /*-
5  * Copyright 2009 Brett Lymn <blymn@NetBSD.org>
6  *
7  * All rights reserved.
8  *
9  * This code has been donated to The NetBSD Foundation by the Author.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. The name of the author may not be used to endorse or promote products
17  *    derived from this software withough specific prior written permission
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  *
31  */
32 #include <assert.h>
33 #include <curses.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <err.h>
37 #include <unistd.h>
38 #include <poll.h>
39 #include <stdbool.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <sys/syslimits.h>
43 #include <time.h>
44 #include <vis.h>
45 #include <stdint.h>
46 #include "returns.h"
47 
48 #define YYDEBUG 1
49 
50 extern int verbose;
51 extern int cmdpipe[2];
52 extern int slvpipe[2];
53 extern int master;
54 extern struct pollfd readfd;
55 extern char *check_path;
56 extern char *cur_file;		/* from director.c */
57 
58 int yylex(void);
59 
60 size_t line;
61 
62 static int input_delay;
63 
64 /* time delay between inputs chars - default to 0.1ms minimum to prevent
65  * problems with input tests
66  */
67 #define DELAY_MIN 0.1
68 
69 /* time delay after a function call - allows the slave time to
70  * run the function and output data before we do other actions.
71  * Set this to 50ms.
72  */
73 #define POST_CALL_DELAY 50
74 
75 static struct timespec delay_spec = {0, 1000 * DELAY_MIN};
76 static struct timespec delay_post_call = {0, 1000 * POST_CALL_DELAY};
77 
78 static char *input_str;	/* string to feed in as input */
79 static bool no_input;	/* don't need more input */
80 
81 #define READ_PIPE  0
82 #define WRITE_PIPE 1
83 
84 const char *returns_enum_names[] = {
85 	"unused", "numeric", "string", "byte", "ERR", "OK", "NULL", "not NULL",
86 	"variable", "reference", "returns count", "slave error"
87 };
88 
89 typedef enum {
90 	arg_static,
91 	arg_byte,
92 	arg_var,
93 	arg_null
94 } args_state_t;
95 
96 static const char *args_enum_names[] = {
97 	"static", "byte", "var", "NULL"
98 };
99 
100 typedef struct {
101 	args_state_t	arg_type;
102 	size_t		arg_len;
103 	char		*arg_string;
104 	int		var_index;
105 } args_t;
106 
107 typedef struct {
108 	char		*function;
109 	int		nrets;		/* number of returns */
110 	returns_t	*returns;	/* array of expected returns */
111 	int		nargs;		/* number of arguments */
112 	args_t		*args;		/* arguments for the call */
113 } cmd_line_t;
114 
115 static cmd_line_t	command;
116 
117 typedef struct {
118 	char *name;
119 	size_t len;
120 	returns_enum_t type;
121 	void *value;
122 } var_t;
123 
124 static size_t nvars; 		/* Number of declared variables */
125 static var_t *vars; 		/* Variables defined during the test. */
126 
127 static int	check_function_table(char *, const char *[], int);
128 static int	find_var_index(const char *);
129 static void 	assign_arg(args_state_t, void *);
130 static int	assign_var(char *);
131 void		init_parse_variables(int);
132 static void	validate(int, void *);
133 static void	validate_return(const char *, const char *, int);
134 static void	validate_variable(int, returns_enum_t, const void *, int, int);
135 static void	validate_byte(returns_t *, returns_t *, int);
136 static void	write_cmd_pipe(char *);
137 static void	write_cmd_pipe_args(args_state_t, void *);
138 static void	read_cmd_pipe(returns_t *);
139 static void	write_func_and_args(void);
140 static void	compare_streams(char *, bool);
141 static void	do_function_call(size_t);
142 static void	save_slave_output(bool);
143 static void	validate_type(returns_enum_t, returns_t *, int);
144 static void	set_var(returns_enum_t, char *, void *);
145 static void	validate_reference(int, void *);
146 static char	*numeric_or(char *, char *);
147 static char	*get_numeric_var(const char *);
148 static void	perform_delay(struct timespec *);
149 
150 static const char *input_functions[] = {
151 	"getch", "getnstr", "getstr", "mvgetnstr", "mvgetstr", "mvgetnstr",
152 	"mvgetstr", "mvscanw", "mvwscanw", "scanw", "wgetch", "wgetnstr",
153 	"wgetstr"
154 };
155 
156 static const unsigned ninput_functions =
157 	sizeof(input_functions) / sizeof(char *);
158 
159 saved_data_t saved_output;
160 
161 %}
162 
163 %union {
164 	char *string;
165 	returns_t *retval;
166 }
167 
168 %token <string> PATH
169 %token <string> STRING
170 %token <retval> BYTE
171 %token <string> VARNAME
172 %token <string> FILENAME
173 %token <string> VARIABLE
174 %token <string> REFERENCE
175 %token <string> NULL_RET
176 %token <string> NON_NULL
177 %token <string> ERR_RET
178 %token <string> OK_RET
179 %token <string> numeric
180 %token <string> DELAY
181 %token <string> INPUT
182 %token <string> COMPARE
183 %token <string> COMPAREND
184 %token <string> ASSIGN
185 %token EOL CALL CHECK NOINPUT OR LHB RHB
186 %token CALL2 CALL3 CALL4 DRAIN
187 
188 %nonassoc OR
189 
190 %%
191 
192 statement	:	/* empty */
193 		| assign statement
194 		| call statement
195 		| call2 statement
196 		| call3 statement
197 		| call4 statement
198 		| check statement
199 		| delay statement
200 		| input statement
201 		| noinput statement
202 		| compare statement
203 		| comparend statement
204 		| eol statement
205 		;
206 
207 assign		: ASSIGN VARNAME numeric {set_var(ret_number, $2, $3);} eol
208 		| ASSIGN VARNAME LHB expr RHB {set_var(ret_number, $2, $<string>4);} eol
209 		| ASSIGN VARNAME STRING {set_var(ret_string, $2, $3);} eol
210 		| ASSIGN VARNAME BYTE {set_var(ret_byte, $2, $3);} eol
211 		;
212 
213 call		: CALL result fn_name args eol {
214 	do_function_call(1);
215 }
216 		;
217 
218 call2		: CALL2 result result fn_name args eol {
219 	do_function_call(2);
220 }
221 		;
222 
223 call3		: CALL3 result result result fn_name args eol {
224 	do_function_call(3);
225 }
226 		;
227 
228 call4		: CALL4 result result result result fn_name args eol {
229 	do_function_call(4);
230  }
231 		;
232 
233 check		: CHECK var returns eol {
234 	returns_t retvar;
235 	var_t *vptr;
236 	if (command.returns[0].return_index == -1)
237 		err(1, "Undefined variable in check statement, line %zu"
238 		    " of file %s", line, cur_file);
239 
240 	if (verbose) {
241 		fprintf(stderr, "Checking contents of variable %s for %s\n",
242 		    vars[command.returns[0].return_index].name,
243 		    returns_enum_names[command.returns[1].return_type]);
244 	}
245 
246 	if (((command.returns[1].return_type == ret_byte) &&
247 	     (vars[command.returns[0].return_index].type != ret_byte)) ||
248 	    vars[command.returns[0].return_index].type != ret_string)
249 		err(1, "Var type %s (%d) does not match return type %s (%d)",
250 		    returns_enum_names[
251 		    vars[command.returns[0].return_index].type],
252 		    vars[command.returns[0].return_index].type,
253 		    returns_enum_names[command.returns[1].return_type],
254 		    command.returns[1].return_type);
255 
256 	switch (command.returns[1].return_type) {
257 	case ret_err:
258 		validate_variable(0, ret_string, "ERR",
259 				  command.returns[0].return_index, 0);
260 		break;
261 
262 	case ret_ok:
263 		validate_variable(0, ret_string, "OK",
264 				  command.returns[0].return_index, 0);
265 		break;
266 
267 	case ret_null:
268 		validate_variable(0, ret_string, "NULL",
269 				  command.returns[0].return_index, 0);
270 		break;
271 
272 	case ret_nonnull:
273 		validate_variable(0, ret_string, "NULL",
274 				  command.returns[0].return_index, 1);
275 		break;
276 
277 	case ret_string:
278 	case ret_number:
279 		if (verbose) {
280 			fprintf(stderr, " %s == returned %s\n",
281 			    (const char *)command.returns[1].return_value,
282 			    (const char *)
283 			    vars[command.returns[0].return_index].value);
284 		}
285 		validate_variable(0, ret_string,
286 		    command.returns[1].return_value,
287 		    command.returns[0].return_index, 0);
288 		break;
289 
290 	case ret_byte:
291 		vptr = &vars[command.returns[0].return_index];
292 		retvar.return_len = vptr->len;
293 		retvar.return_type = vptr->type;
294 		retvar.return_value = vptr->value;
295 		validate_byte(&retvar, &command.returns[1], 0);
296 		break;
297 
298 	default:
299 		err(1, "Malformed check statement at line %zu "
300 		    "of file %s", line, cur_file);
301 		break;
302 	}
303 
304 	init_parse_variables(0);
305  }
306 		;
307 
308 delay		: DELAY numeric eol {
309 	/* set the inter-character delay */
310 	if (sscanf($2, "%d", &input_delay) == 0)
311 		err(1, "delay specification %s could not be converted to "
312 		    "numeric at line %zu of file %s", $2, line, cur_file);
313 	if (verbose) {
314 		fprintf(stderr, "Set input delay to %d ms\n", input_delay);
315 	}
316 
317 	if (input_delay < DELAY_MIN)
318 		input_delay = DELAY_MIN;
319 	/*
320 	 * Fill in the timespec structure now ready for use later.
321 	 * The delay is specified in milliseconds so convert to timespec
322 	 * values
323 	 */
324 	delay_spec.tv_sec = input_delay / 1000;
325 	delay_spec.tv_nsec = (input_delay - 1000 * delay_spec.tv_sec) * 1000;
326 	if (verbose) {
327 		fprintf(stderr, "set delay to %jd.%jd\n",
328 		    (intmax_t)delay_spec.tv_sec,
329 		    (intmax_t)delay_spec.tv_nsec);
330 	}
331 
332 	init_parse_variables(0);
333  }
334 	;
335 
336 input		: INPUT STRING eol {
337 	if (input_str != NULL) {
338 		warnx("%s, %zu: Discarding unused input string",
339 		    cur_file, line);
340 		free(input_str);
341 	}
342 
343 	if ((input_str = malloc(strlen($2) + 1)) == NULL)
344 		err(2, "Cannot allocate memory for input string");
345 
346 	strlcpy(input_str, $2, strlen($2) + 1);
347 }
348 	;
349 
350 
351 noinput		: NOINPUT eol {
352 	if (input_str != NULL) {
353 		warnx("%s, %zu: Discarding unused input string",
354 		    cur_file, line);
355 		free(input_str);
356 	}
357 
358 	no_input = true;
359  }
360 
361 compare		: COMPARE PATH eol
362 		| COMPARE FILENAME eol
363 {
364 	compare_streams($2, true);
365 }
366 	;
367 
368 
369 comparend	: COMPAREND PATH eol
370 		| COMPAREND FILENAME eol
371 {
372 	compare_streams($2, false);
373 }
374 	;
375 
376 
377 result		: returns
378 		| var
379 		| reference
380 		;
381 
382 returns		: numeric { assign_rets(ret_number, $1); }
383 		| LHB expr RHB { assign_rets(ret_number, $<string>2); }
384 		| STRING { assign_rets(ret_string, $1); }
385 		| BYTE { assign_rets(ret_byte, (void *) $1); }
386 		| ERR_RET { assign_rets(ret_err, NULL); }
387 		| OK_RET { assign_rets(ret_ok, NULL); }
388 		| NULL_RET { assign_rets(ret_null, NULL); }
389 		| NON_NULL { assign_rets(ret_nonnull, NULL); }
390 		;
391 
392 var		: VARNAME {
393 	assign_rets(ret_var, $1);
394  }
395 		;
396 
397 reference	: VARIABLE {
398 	assign_rets(ret_ref, $1);
399  }
400 
401 fn_name		: VARNAME {
402 	if (command.function != NULL)
403 		free(command.function);
404 
405 	command.function = malloc(strlen($1) + 1);
406 	if (command.function == NULL)
407 		err(1, "Could not allocate memory for function name");
408 	strcpy(command.function, $1);
409  }
410 		;
411 
412 expr		: numeric
413 		| VARIABLE
414 			{ $<string>$ = get_numeric_var($1); }
415 		| expr OR expr
416 			{ $<string>$ = numeric_or($<string>1, $<string>3); }
417 		;
418 
419 args		: /* empty */
420 		| LHB expr RHB { assign_arg(arg_static, $<string>2); } args
421 		| numeric { assign_arg(arg_static, $1); } args
422 		| STRING { assign_arg(arg_static, $1); } args
423 		| BYTE { assign_arg(arg_byte, $1); } args
424 		| PATH { assign_arg(arg_static, $1); } args
425 		| FILENAME { assign_arg(arg_static, $1); } args
426 		| VARNAME { assign_arg(arg_static, $1); } args
427 		| VARIABLE  { assign_arg(arg_var, $1); } args
428 		| NULL_RET { assign_arg(arg_null, $1); } args
429 		;
430 
431 eol		: EOL
432 		;
433 
434 %%
435 
436 static void
437 excess(const char *fname, size_t lineno, const char *func, const char *comment,
438     const void *data, size_t datalen)
439 {
440 	size_t dstlen = datalen * 4 + 1;
441 	char *dst = malloc(dstlen);
442 
443 	if (dst == NULL)
444 		err(1, "malloc");
445 
446 	if (strnvisx(dst, dstlen, data, datalen, VIS_WHITE | VIS_OCTAL) == -1)
447 		err(1, "strnvisx");
448 
449 	warnx("%s, %zu: [%s] Excess %zu bytes%s [%s]",
450 	    fname, lineno, func, datalen, comment, dst);
451 	free(dst);
452 }
453 
454 /*
455  * Get the value of a variable, error if the variable has not been set or
456  * is not a numeric type.
457  */
458 static char *
459 get_numeric_var(const char *var)
460 {
461 	int i;
462 
463 	if ((i = find_var_index(var)) < 0)
464 		err(1, "Variable %s is undefined", var);
465 
466 	if (vars[i].type != ret_number)
467 		err(1, "Variable %s is not a numeric type", var);
468 
469 	return vars[i].value;
470 }
471 
472 /*
473  * Perform a bitwise OR on two numbers and return the result.
474  */
475 static char *
476 numeric_or(char *n1, char *n2)
477 {
478 	unsigned long i1, i2, result;
479 	char *ret;
480 
481 	i1 = strtoul(n1, NULL, 10);
482 	i2 = strtoul(n2, NULL, 10);
483 
484 	result = i1 | i2;
485 	asprintf(&ret, "%lu", result);
486 
487 	if (verbose) {
488 		fprintf(stderr, "numeric or of 0x%lx (%s) and 0x%lx (%s)"
489 		    " results in 0x%lx (%s)\n",
490 		    i1, n1, i2, n2, result, ret);
491 	}
492 
493 	return ret;
494 }
495 
496 /*
497  * Sleep for the specified time, handle the sleep getting interrupted
498  * by a signal.
499  */
500 static void
501 perform_delay(struct timespec *ts)
502 {
503 	struct timespec delay_copy, delay_remainder;
504 
505 	delay_copy = *ts;
506 	while (nanosleep(&delay_copy, &delay_remainder) < 0) {
507 		if (errno != EINTR)
508 			err(2, "nanosleep returned error");
509 		delay_copy = delay_remainder;
510 	}
511 }
512 
513 /*
514  * Assign the value given to the named variable.
515  */
516 static void
517 set_var(returns_enum_t type, char *name, void *value)
518 {
519 	int i;
520 	char *number;
521 	returns_t *ret;
522 
523 	i = find_var_index(name);
524 	if (i < 0)
525 		i = assign_var(name);
526 
527 	vars[i].type = type;
528 	if ((type == ret_number) || (type == ret_string)) {
529 		number = value;
530 		vars[i].len = strlen(number) + 1;
531 		vars[i].value = malloc(vars[i].len + 1);
532 		if (vars[i].value == NULL)
533 			err(1, "Could not malloc memory for assign string");
534 		strcpy(vars[i].value, number);
535 	} else {
536 		/* can only be a byte value */
537 		ret = value;
538 		vars[i].len = ret->return_len;
539 		vars[i].value = malloc(vars[i].len);
540 		if (vars[i].value == NULL)
541 			err(1, "Could not malloc memory to assign byte string");
542 		memcpy(vars[i].value, ret->return_value, vars[i].len);
543 	}
544 }
545 
546 /*
547  * Add a new variable to the vars array, the value will be assigned later,
548  * when a test function call returns.
549  */
550 static int
551 assign_var(char *varname)
552 {
553 	var_t *temp;
554 	char *name;
555 
556 	if ((name = malloc(strlen(varname) + 1)) == NULL)
557 		err(1, "Alloc of varname failed");
558 
559 	if ((temp = realloc(vars, sizeof(*temp) * (nvars + 1))) == NULL) {
560 		free(name);
561 		err(1, "Realloc of vars array failed");
562 	}
563 
564 	strcpy(name, varname);
565 	vars = temp;
566 	vars[nvars].name = name;
567 	vars[nvars].len = 0;
568 	vars[nvars].value = NULL;
569 	nvars++;
570 
571 	return (nvars - 1);
572 }
573 
574 /*
575  * Allocate and assign a new argument of the given type.
576  */
577 static void
578 assign_arg(args_state_t arg_type, void *arg)
579 {
580 	args_t *temp, cur;
581 	char *str = arg;
582 	returns_t *ret;
583 
584 	if (verbose) {
585 		fprintf(stderr, "function is >%s<, adding arg >%s< type %s\n",
586 		       command.function, str, args_enum_names[arg_type]);
587 	}
588 
589 	cur.arg_type = arg_type;
590 	switch (arg_type) {
591 	case arg_var:
592 		cur.var_index = find_var_index(arg);
593 		if (cur.var_index < 0)
594 			err(1, "Invalid variable %s at line %zu of file %s",
595 			    str, line, cur_file);
596 		cur.arg_type = ret_string;
597 		break;
598 
599 	case arg_byte:
600 		ret = arg;
601 		cur.arg_len = ret->return_len;
602 		cur.arg_string = malloc(cur.arg_len);
603 		if (cur.arg_string == NULL)
604 			err(1, "Could not malloc memory for arg bytes");
605 		memcpy(cur.arg_string, ret->return_value, cur.arg_len);
606 		break;
607 
608 	case arg_null:
609 		cur.arg_len = 0;
610 		cur.arg_string = NULL;
611 		break;
612 
613 	default:
614 		cur.arg_len = strlen(str);
615 		cur.arg_string = malloc(cur.arg_len + 1);
616 		if (cur.arg_string == NULL)
617 			err(1, "Could not malloc memory for arg string");
618 		strcpy(cur.arg_string, arg);
619 	}
620 
621 	temp = realloc(command.args, sizeof(*temp) * (command.nargs + 1));
622 	if (temp == NULL)
623 		err(1, "Failed to reallocate args");
624 	command.args = temp;
625 	memcpy(&command.args[command.nargs], &cur, sizeof(args_t));
626 	command.nargs++;
627 }
628 
629 /*
630  * Allocate and assign a new return.
631  */
632 static void
633 assign_rets(returns_enum_t ret_type, void *ret)
634 {
635 	returns_t *temp, cur;
636 	char *ret_str;
637 	returns_t *ret_ret;
638 
639 	cur.return_type = ret_type;
640 	if (ret_type != ret_var) {
641 		if ((ret_type == ret_number) || (ret_type == ret_string)) {
642 			ret_str = ret;
643 			cur.return_len = strlen(ret_str) + 1;
644 			cur.return_value = malloc(cur.return_len + 1);
645 			if (cur.return_value == NULL)
646 				err(1,
647 				    "Could not malloc memory for arg string");
648 			strcpy(cur.return_value, ret_str);
649 		} else if (ret_type == ret_byte) {
650 			ret_ret = ret;
651 			cur.return_len = ret_ret->return_len;
652 			cur.return_value = malloc(cur.return_len);
653 			if (cur.return_value == NULL)
654 				err(1,
655 				    "Could not malloc memory for byte string");
656 			memcpy(cur.return_value, ret_ret->return_value,
657 			       cur.return_len);
658 		} else if (ret_type == ret_ref) {
659 			if ((cur.return_index = find_var_index(ret)) < 0)
660 				err(1, "Undefined variable reference");
661 		}
662 	} else {
663 		cur.return_index = find_var_index(ret);
664 		if (cur.return_index < 0)
665 			cur.return_index = assign_var(ret);
666 	}
667 
668 	temp = realloc(command.returns, sizeof(*temp) * (command.nrets + 1));
669 	if (temp == NULL)
670 		err(1, "Failed to reallocate returns");
671 	command.returns = temp;
672 	memcpy(&command.returns[command.nrets], &cur, sizeof(returns_t));
673 	command.nrets++;
674 }
675 
676 /*
677  * Find the given variable name in the var array and return the i
678  * return -1 if var is not found.
679  */
680 static int
681 find_var_index(const char *var_name)
682 {
683 	int result;
684 	size_t i;
685 
686 	result = -1;
687 
688 	for (i = 0; i < nvars; i++) {
689 		if (strcmp(var_name, vars[i].name) == 0) {
690 			result = i;
691 			break;
692 		}
693 	}
694 
695 	return result;
696 }
697 
698 /*
699  * Check the given function name in the given table of names, return 1 if
700  * there is a match.
701  */
702 static int check_function_table(char *function, const char *table[],
703 				int nfunctions)
704 {
705 	int i;
706 
707 	for (i = 0; i < nfunctions; i++) {
708 		if ((strlen(function) == strlen(table[i])) &&
709 		    (strcmp(function, table[i]) == 0))
710 			return 1;
711 	}
712 
713 	return 0;
714 }
715 
716 /*
717  * Compare the output from the slave against the given file and report
718  * any differences.
719  */
720 static void
721 compare_streams(char *filename, bool discard)
722 {
723 	char check_file[PATH_MAX], drain[100], ref, data;
724 	struct pollfd fds[2];
725 	int nfd, check_fd;
726 	ssize_t result;
727 	size_t offs;
728 
729 	/*
730 	 * Don't prepend check path iff check file has an absolute
731 	 * path.
732 	 */
733 	if (filename[0] != '/') {
734 		if (strlcpy(check_file, check_path, sizeof(check_file))
735 		    >= sizeof(check_file))
736 			err(2, "CHECK_PATH too long");
737 
738 		if (strlcat(check_file, "/", sizeof(check_file))
739 		    >= sizeof(check_file))
740 			err(2, "Could not append / to check file path");
741 	} else {
742 		check_file[0] = '\0';
743 	}
744 
745 	if (strlcat(check_file, filename, sizeof(check_file))
746 	    >= sizeof(check_file))
747 		err(2, "Path to check file path overflowed");
748 
749 	if ((check_fd = open(check_file, O_RDONLY, 0)) < 0)
750 		err(2, "failed to open file %s line %zu of file %s",
751 		    check_file, line, cur_file);
752 
753 	fds[0].fd = check_fd;
754 	fds[0].events = POLLIN;
755 	fds[1].fd = master;
756 	fds[1].events = POLLIN;
757 
758 	nfd = 2;
759 	/*
760 	 * if we have saved output then only check for data in the
761 	 * reference file since the slave data may already be drained.
762 	 */
763 	if (saved_output.count > 0)
764 		nfd = 1;
765 
766 	offs = 0;
767 	while (poll(fds, nfd, 500) == nfd) {
768 		if (fds[0].revents & POLLIN) {
769 			if ((result = read(check_fd, &ref, 1)) < 1) {
770 				if (result != 0) {
771 					err(2,
772 					    "Bad read on file %s", check_file);
773 				} else {
774 					break;
775 				}
776 			}
777 		}
778 
779 		if (saved_output.count > 0) {
780 			data = saved_output.data[saved_output.readp];
781 			saved_output.count--;
782 			saved_output.readp++;
783 			/* run out of saved data, switch to file */
784 			if (saved_output.count == 0)
785 				nfd = 2;
786 		} else {
787 			if (fds[0].revents & POLLIN) {
788 				if (read(master, &data, 1) < 1)
789 					err(2, "Bad read on slave pty");
790 			} else
791 				continue;
792 		}
793 
794 		if (verbose) {
795 			fprintf(stderr, "Comparing reference byte 0x%x (%c)"
796 				" against slave byte 0x%x (%c)\n",
797 				ref, (ref >= ' ') ? ref : '-',
798 				data, (data >= ' ' )? data : '-');
799 		}
800 
801 		if (ref != data) {
802 			errx(2, "%s, %zu: refresh data from slave does "
803 			    "not match expected from file %s offs %zu "
804 			    "[reference 0x%x (%c) != slave 0x%x (%c)]",
805 			    cur_file, line, check_file, offs,
806 			    ref, (ref >= ' ') ? ref : '-',
807 			    data, (data >= ' ') ? data : '-');
808 		}
809 
810 		offs++;
811 	}
812 
813 
814 	if (saved_output.count > 0)
815 		excess(cur_file, line, __func__, " from slave",
816 		    &saved_output.data[saved_output.readp], saved_output.count);
817 
818 	/* discard any excess saved output if required */
819 	if (discard) {
820 		saved_output.count = 0;
821 		saved_output.readp = 0;
822 	}
823 
824 	if ((result = poll(&fds[0], 2, 0)) != 0) {
825 		if (result == -1)
826 			err(2, "poll of file descriptors failed");
827 
828 		if ((fds[1].revents & POLLIN) == POLLIN) {
829 			save_slave_output(true);
830 		} else if ((fds[0].revents & POLLIN) == POLLIN) {
831 			/*
832 			 * handle excess in file if it exists.  Poll
833 			 * says there is data until EOF is read.
834 			 * Check next read is EOF, if it is not then
835 			 * the file really has more data than the
836 			 * slave produced so flag this as a warning.
837 			 */
838 			result = read(check_fd, drain, sizeof(drain));
839 			if (result == -1)
840 				err(1, "read of data file failed");
841 
842 			if (result > 0) {
843 				excess(check_file, 0, __func__, "", drain,
844 				    result);
845 			}
846 		}
847 	}
848 
849 	close(check_fd);
850 }
851 
852 /*
853  * Pass a function call and arguments to the slave and wait for the
854  * results.  The variable nresults determines how many returns we expect
855  * back from the slave.  These results will be validated against the
856  * expected returns or assigned to variables.
857  */
858 static void
859 do_function_call(size_t nresults)
860 {
861 #define MAX_RESULTS 4
862 	char *p;
863 	int do_input;
864 	size_t i;
865 	struct pollfd fds[3];
866 	returns_t response[MAX_RESULTS], returns_count;
867 	assert(nresults <= MAX_RESULTS);
868 
869 	do_input = check_function_table(command.function, input_functions,
870 	    ninput_functions);
871 
872 	write_func_and_args();
873 
874 	/*
875 	 * We should get the number of returns back here, grab it before
876 	 * doing input otherwise it will confuse the input poll
877 	 */
878 	read_cmd_pipe(&returns_count);
879 	if (returns_count.return_type != ret_count)
880 		err(2, "expected return type of ret_count but received %s",
881 		    returns_enum_names[returns_count.return_type]);
882 
883 	perform_delay(&delay_post_call); /* let slave catch up */
884 
885 	if (verbose) {
886 		fprintf(stderr, "Expect %zu results from slave, slave "
887 		    "reported %zu\n", nresults, returns_count.return_len);
888 	}
889 
890 	if ((no_input == false) && (do_input == 1)) {
891 		if (verbose) {
892 			fprintf(stderr, "doing input with inputstr >%s<\n",
893 			    input_str);
894 		}
895 
896 		if (input_str == NULL)
897 			errx(2, "%s, %zu: Call to input function "
898 			    "but no input defined", cur_file, line);
899 
900 		fds[0].fd = slvpipe[READ_PIPE];
901 		fds[0].events = POLLIN;
902 		fds[1].fd = master;
903 		fds[1].events = POLLOUT;
904  		p = input_str;
905 		save_slave_output(false);
906 		while(*p != '\0') {
907 			perform_delay(&delay_spec);
908 
909 			if (poll(fds, 2, 0) < 0)
910 				err(2, "poll failed");
911 			if (fds[0].revents & POLLIN) {
912 				warnx("%s, %zu: Slave function "
913 				    "returned before end of input string",
914 				    cur_file, line);
915 				break;
916 			}
917 			if ((fds[1].revents & POLLOUT) == 0)
918 				continue;
919 			if (verbose) {
920 				fprintf(stderr, "Writing char >%c< to slave\n",
921 				    *p);
922 			}
923 			if (write(master, p, 1) != 1) {
924 				warn("%s, %zu: Slave function write error",
925 				    cur_file, line);
926 				break;
927 			}
928 			p++;
929 
930 		}
931 		save_slave_output(false);
932 
933 		if (verbose) {
934 			fprintf(stderr, "Input done.\n");
935 		}
936 
937 		/* done with the input string, free the resources */
938 		free(input_str);
939 		input_str = NULL;
940 	}
941 
942 	if (verbose) {
943 		fds[0].fd = slvpipe[READ_PIPE];
944 		fds[0].events = POLLIN;
945 
946 		fds[1].fd = slvpipe[WRITE_PIPE];
947 		fds[1].events = POLLOUT;
948 
949 		fds[2].fd = master;
950 		fds[2].events = POLLIN | POLLOUT;
951 
952 		i = poll(&fds[0], 3, 1000);
953 		fprintf(stderr, "Poll returned %zu\n", i);
954 		for (i = 0; i < 3; i++) {
955 			fprintf(stderr, "revents for fd[%zu] = 0x%x\n",
956 				i, fds[i].revents);
957 		}
958 	}
959 
960 	/* drain any trailing output */
961 	save_slave_output(false);
962 
963 	for (i = 0; i < returns_count.return_len; i++) {
964 		read_cmd_pipe(&response[i]);
965 	}
966 
967 	/*
968 	 * Check for a slave error in the first return slot, if the
969 	 * slave errored then we may not have the number of returns we
970 	 * expect but in this case we should report the slave error
971 	 * instead of a return count mismatch.
972 	 */
973 	if ((returns_count.return_len > 0) &&
974 	    (response[0].return_type == ret_slave_error))
975 		err(2, "Slave returned error: %s",
976 		    (const char *)response[0].return_value);
977 
978 	if (returns_count.return_len != nresults)
979 		err(2, "Incorrect number of returns from slave, expected %zu "
980 		    "but received %zu", nresults, returns_count.return_len);
981 
982 	if (verbose) {
983 		for (i = 0; i < nresults; i++) {
984 			if ((response[i].return_type != ret_byte) &&
985 			    (response[i].return_type != ret_err) &&
986 			    (response[i].return_type != ret_ok))
987 				fprintf(stderr,
988 					"received response >%s< "
989 					"expected",
990 					(const char *)response[i].return_value);
991 			else
992 				fprintf(stderr, "received");
993 
994 			fprintf(stderr, " return_type %s\n",
995 			    returns_enum_names[command.returns[i].return_type]);
996 		}
997 	}
998 
999 	for (i = 0; i < nresults; i++) {
1000 		if (command.returns[i].return_type != ret_var) {
1001 			validate(i, &response[i]);
1002 		} else {
1003 			vars[command.returns[i].return_index].len =
1004 				response[i].return_len;
1005 			vars[command.returns[i].return_index].value =
1006 				response[i].return_value;
1007 			vars[command.returns[i].return_index].type =
1008 				response[i].return_type;
1009 		}
1010 	}
1011 
1012 	if (verbose && (saved_output.count > 0))
1013 		excess(cur_file, line, __func__, " from slave",
1014 		    &saved_output.data[saved_output.readp], saved_output.count);
1015 
1016 	init_parse_variables(0);
1017 }
1018 
1019 /*
1020  * Write the function and command arguments to the command pipe.
1021  */
1022 static void
1023 write_func_and_args(void)
1024 {
1025 	int i;
1026 
1027 	if (verbose) {
1028 		fprintf(stderr, "calling function >%s<\n", command.function);
1029 	}
1030 
1031 	write_cmd_pipe(command.function);
1032 	for (i = 0; i < command.nargs; i++) {
1033 		if (command.args[i].arg_type == arg_var)
1034 			write_cmd_pipe_args(command.args[i].arg_type,
1035 					    &vars[command.args[i].var_index]);
1036 		else
1037 			write_cmd_pipe_args(command.args[i].arg_type,
1038 					    &command.args[i]);
1039 	}
1040 
1041 	write_cmd_pipe(NULL); /* signal end of arguments */
1042 }
1043 
1044 /*
1045  * Initialise the command structure - if initial is non-zero then just set
1046  * everything to sane values otherwise free any memory that was allocated
1047  * when building the structure.
1048  */
1049 void
1050 init_parse_variables(int initial)
1051 {
1052 	int i, result;
1053 	struct pollfd slave_pty;
1054 
1055 	if (initial == 0) {
1056 		free(command.function);
1057 		for (i = 0; i < command.nrets; i++) {
1058 			if (command.returns[i].return_type == ret_number)
1059 				free(command.returns[i].return_value);
1060 		}
1061 		free(command.returns);
1062 
1063 		for (i = 0; i < command.nargs; i++) {
1064 			if (command.args[i].arg_type != arg_var)
1065 				free(command.args[i].arg_string);
1066 		}
1067 		free(command.args);
1068 	} else {
1069 		line = 0;
1070 		input_delay = 0;
1071 		vars = NULL;
1072 		nvars = 0;
1073 		input_str = NULL;
1074 		saved_output.allocated = 0;
1075 		saved_output.count = 0;
1076 		saved_output.readp = 0;
1077 		saved_output.data = NULL;
1078 	}
1079 
1080 	no_input = false;
1081 	command.function = NULL;
1082 	command.nargs = 0;
1083 	command.args = NULL;
1084 	command.nrets = 0;
1085 	command.returns = NULL;
1086 
1087 	/*
1088 	 * Check the slave pty for stray output from the slave, at this
1089 	 * point we should not see any data as it should have been
1090 	 * consumed by the test functions.  If we see data then we have
1091 	 * either a bug or are not handling an output generating function
1092 	 * correctly.
1093 	 */
1094 	slave_pty.fd = master;
1095 	slave_pty.events = POLLIN;
1096 	result = poll(&slave_pty, 1, 0);
1097 
1098 	if (result < 0)
1099 		err(2, "Poll of slave pty failed");
1100 	else if (result > 0)
1101 		warnx("%s, %zu: Unexpected data from slave", cur_file, line);
1102 }
1103 
1104 /*
1105  * Validate the response against the expected return.  The variable
1106  * i is the i into the rets array in command.
1107  */
1108 static void
1109 validate(int i, void *data)
1110 {
1111 	char *response;
1112 	returns_t *byte_response;
1113 
1114 	byte_response = data;
1115 	if ((command.returns[i].return_type != ret_byte) &&
1116 	    (command.returns[i].return_type != ret_err) &&
1117 	    (command.returns[i].return_type != ret_ok)) {
1118 		if ((byte_response->return_type == ret_byte) ||
1119 		    (byte_response->return_type == ret_err) ||
1120 		    (byte_response->return_type == ret_ok))
1121 			err(1, "%s: expecting type %s, received type %s"
1122 			    " at line %zu of file %s", __func__,
1123 			    returns_enum_names[command.returns[i].return_type],
1124 			    returns_enum_names[byte_response->return_type],
1125 			    line, cur_file);
1126 
1127 		response = byte_response->return_value;
1128 	}
1129 
1130 	switch (command.returns[i].return_type) {
1131 	case ret_err:
1132 		validate_type(ret_err, byte_response, 0);
1133 		break;
1134 
1135 	case ret_ok:
1136 		validate_type(ret_ok, byte_response, 0);
1137 		break;
1138 
1139 	case ret_null:
1140 		validate_return("NULL", response, 0);
1141 		break;
1142 
1143 	case ret_nonnull:
1144 		validate_return("NULL", response, 1);
1145 		break;
1146 
1147 	case ret_string:
1148 	case ret_number:
1149 		validate_return(command.returns[i].return_value,
1150 				response, 0);
1151 		break;
1152 
1153 	case ret_ref:
1154 		validate_reference(i, response);
1155 		break;
1156 
1157 	case ret_byte:
1158 		validate_byte(&command.returns[i], byte_response, 0);
1159 		break;
1160 
1161 	default:
1162 		err(1, "Malformed statement at line %zu of file %s",
1163 		    line, cur_file);
1164 		break;
1165 	}
1166 }
1167 
1168 /*
1169  * Validate the return against the contents of a variable.
1170  */
1171 static void
1172 validate_reference(int i, void *data)
1173 {
1174 	char *response;
1175 	returns_t *byte_response;
1176 	var_t *varp;
1177 
1178 	varp = &vars[command.returns[i].return_index];
1179 
1180 	byte_response = data;
1181 	if (command.returns[i].return_type != ret_byte)
1182 		response = data;
1183 
1184 	if (verbose) {
1185 		fprintf(stderr,
1186 		    "%s: return type of %s, value %s \n", __func__,
1187 		    returns_enum_names[varp->type],
1188 		    (const char *)varp->value);
1189 	}
1190 
1191 	switch (varp->type) {
1192 	case ret_string:
1193 	case ret_number:
1194 		validate_return(varp->value, response, 0);
1195 		break;
1196 
1197 	case ret_byte:
1198 		validate_byte(varp->value, byte_response, 0);
1199 		break;
1200 
1201 	default:
1202 		err(1,
1203 		    "Invalid return type for reference at line %zu of file %s",
1204 		    line, cur_file);
1205 		break;
1206 	}
1207 }
1208 
1209 /*
1210  * Validate the return type against the expected type, throw an error
1211  * if they don't match.
1212  */
1213 static void
1214 validate_type(returns_enum_t expected, returns_t *value, int check)
1215 {
1216 	if (((check == 0) && (expected != value->return_type)) ||
1217 	    ((check == 1) && (expected == value->return_type)))
1218 		err(1, "Validate expected type %s %s %s line %zu of file %s",
1219 		    returns_enum_names[expected],
1220 		    (check == 0)? "matching" : "not matching",
1221 		    returns_enum_names[value->return_type], line, cur_file);
1222 
1223 	if (verbose) {
1224 		fprintf(stderr, "Validate expected type %s %s %s line %zu"
1225 		    " of file %s\n",
1226 		    returns_enum_names[expected],
1227 		    (check == 0)? "matching" : "not matching",
1228 		    returns_enum_names[value->return_type], line, cur_file);
1229 	}
1230 }
1231 
1232 /*
1233  * Validate the return value against the expected value, throw an error
1234  * if they don't match.
1235  */
1236 static void
1237 validate_return(const char *expected, const char *value, int check)
1238 {
1239 	if (((check == 0) && strcmp(expected, value) != 0) ||
1240 	    ((check == 1) && strcmp(expected, value) == 0))
1241 		errx(1, "Validate expected %s %s %s line %zu of file %s",
1242 		    expected,
1243 		    (check == 0)? "matching" : "not matching", value,
1244 		    line, cur_file);
1245 	if (verbose) {
1246 		fprintf(stderr, "Validated expected value %s %s %s "
1247 		    "at line %zu of file %s\n", expected,
1248 		    (check == 0)? "matches" : "does not match",
1249 		    value, line, cur_file);
1250 	}
1251 }
1252 
1253 /*
1254  * Validate the return value against the expected value, throw an error
1255  * if they don't match expectations.
1256  */
1257 static void
1258 validate_byte(returns_t *expected, returns_t *value, int check)
1259 {
1260 	char *ch;
1261 	size_t i;
1262 
1263 	if (verbose) {
1264 		ch = value->return_value;
1265 		fprintf(stderr, "checking returned byte stream: ");
1266 		for (i = 0; i < value->return_len; i++)
1267 			fprintf(stderr, "%s0x%x", (i != 0)? ", " : "", ch[i]);
1268 		fprintf(stderr, "\n");
1269 
1270 		fprintf(stderr, "%s byte stream: ",
1271 			(check == 0)? "matches" : "does not match");
1272 		ch = (char *) expected->return_value;
1273 		for (i = 0; i < expected->return_len; i++)
1274 			fprintf(stderr, "%s0x%x", (i != 0)? ", " : "", ch[i]);
1275 		fprintf(stderr, "\n");
1276 	}
1277 
1278 	/*
1279 	 * No chance of a match if lengths differ...
1280 	 */
1281 	if ((check == 0) && (expected->return_len != value->return_len))
1282 	    errx(1, "Byte validation failed, length mismatch, expected %zu,"
1283 		"received %zu", expected->return_len, value->return_len);
1284 
1285 	/*
1286 	 * If check is 0 then we want to throw an error IFF the byte streams
1287 	 * do not match, if check is 1 then throw an error if the byte
1288 	 * streams match.
1289 	 */
1290 	if (((check == 0) && memcmp(expected->return_value, value->return_value,
1291 				    value->return_len) != 0) ||
1292 	    ((check == 1) && (expected->return_len == value->return_len) &&
1293 	     memcmp(expected->return_value, value->return_value,
1294 		    value->return_len) == 0))
1295 		errx(1, "Validate expected %s byte stream at line %zu"
1296 		    "of file %s",
1297 		    (check == 0)? "matching" : "not matching", line, cur_file);
1298 	if (verbose) {
1299 		fprintf(stderr, "Validated expected %s byte stream "
1300 		    "at line %zu of file %s\n",
1301 		    (check == 0)? "matching" : "not matching",
1302 		    line, cur_file);
1303 	}
1304 }
1305 
1306 /*
1307  * Validate the variable at i against the expected value, throw an
1308  * error if they don't match, if check is non-zero then the match is
1309  * negated.
1310  */
1311 static void
1312 validate_variable(int ret, returns_enum_t type, const void *value, int i,
1313     int check)
1314 {
1315 	returns_t *retval;
1316 	var_t *varptr;
1317 
1318 	retval = &command.returns[ret];
1319 	varptr = &vars[command.returns[ret].return_index];
1320 
1321 	if (varptr->value == NULL)
1322 		err(1, "Variable %s has no value assigned to it", varptr->name);
1323 
1324 
1325 	if (varptr->type != type)
1326 		err(1, "Variable %s is not the expected type", varptr->name);
1327 
1328 	if (type != ret_byte) {
1329 		if ((((check == 0) && strcmp(value, varptr->value) != 0))
1330 		    || ((check == 1) && strcmp(value, varptr->value) == 0))
1331 			err(1, "Variable %s contains %s instead of %s"
1332 			    " value %s at line %zu of file %s",
1333 			    varptr->name, (const char *)varptr->value,
1334 			    (check == 0)? "expected" : "not matching",
1335 			    (const char *)value,
1336 			    line, cur_file);
1337 		if (verbose) {
1338 			fprintf(stderr, "Variable %s contains %s value "
1339 			    "%s at line %zu of file %s\n",
1340 			    varptr->name,
1341 			    (check == 0)? "expected" : "not matching",
1342 			    (const char *)varptr->value, line, cur_file);
1343 		}
1344 	} else {
1345 		if ((check == 0) && (retval->return_len != varptr->len))
1346 			err(1, "Byte validation failed, length mismatch");
1347 
1348 		/*
1349 		 * If check is 0 then we want to throw an error IFF
1350 		 * the byte streams do not match, if check is 1 then
1351 		 * throw an error if the byte streams match.
1352 		 */
1353 		if (((check == 0) && memcmp(retval->return_value, varptr->value,
1354 					    varptr->len) != 0) ||
1355 		    ((check == 1) && (retval->return_len == varptr->len) &&
1356 		     memcmp(retval->return_value, varptr->value,
1357 			    varptr->len) == 0))
1358 			err(1, "Validate expected %s byte stream at line %zu"
1359 			    " of file %s",
1360 			    (check == 0)? "matching" : "not matching",
1361 			    line, cur_file);
1362 		if (verbose) {
1363 			fprintf(stderr, "Validated expected %s byte stream "
1364 			    "at line %zu of file %s\n",
1365 			    (check == 0)? "matching" : "not matching",
1366 			    line, cur_file);
1367 		}
1368 	}
1369 }
1370 
1371 /*
1372  * Write a string to the command pipe - we feed the number of bytes coming
1373  * down first to allow storage allocation and then follow up with the data.
1374  * If cmd is NULL then feed a -1 down the pipe to say the end of the args.
1375  */
1376 static void
1377 write_cmd_pipe(char *cmd)
1378 {
1379 	args_t arg;
1380 	size_t len;
1381 
1382 	if (cmd == NULL)
1383 		len = 0;
1384 	else
1385 		len = strlen(cmd);
1386 
1387 	arg.arg_type = arg_static;
1388 	arg.arg_len = len;
1389 	arg.arg_string = cmd;
1390 	write_cmd_pipe_args(arg.arg_type, &arg);
1391 
1392 }
1393 
1394 static void
1395 write_cmd_pipe_args(args_state_t type, void *data)
1396 {
1397 	var_t *var_data;
1398 	args_t *arg_data;
1399 	int len, send_type;
1400 	void *cmd;
1401 
1402 	arg_data = data;
1403 	switch (type) {
1404 	case arg_var:
1405 		var_data = data;
1406 		len = var_data->len;
1407 		cmd = var_data->value;
1408 		if (type == arg_byte)
1409 			send_type = ret_byte;
1410 		else
1411 			send_type = ret_string;
1412 		break;
1413 
1414 	case arg_null:
1415 		send_type = ret_null;
1416 		len = 0;
1417 		break;
1418 
1419 	default:
1420 		if ((arg_data->arg_len == 0) && (arg_data->arg_string == NULL))
1421 			len = -1;
1422 		else
1423 			len = arg_data->arg_len;
1424 		cmd = arg_data->arg_string;
1425 		if (type == arg_byte)
1426 			send_type = ret_byte;
1427 		else
1428 			send_type = ret_string;
1429 	}
1430 
1431 	if (verbose) {
1432 		fprintf(stderr, "Writing type %s to command pipe\n",
1433 		    returns_enum_names[send_type]);
1434 	}
1435 
1436 	if (write(cmdpipe[WRITE_PIPE], &send_type, sizeof(int)) < 0)
1437 		err(1, "command pipe write for type failed");
1438 
1439 	if (verbose) {
1440 		fprintf(stderr, "Writing length %d to command pipe\n", len);
1441 	}
1442 
1443 	if (write(cmdpipe[WRITE_PIPE], &len, sizeof(int)) < 0)
1444 		err(1, "command pipe write for length failed");
1445 
1446 	if (len > 0) {
1447 		if (verbose) {
1448 			fprintf(stderr, "Writing data >%s< to command pipe\n",
1449 			    (const char *)cmd);
1450 		}
1451 		if (write(cmdpipe[WRITE_PIPE], cmd, len) < 0)
1452 			err(1, "command pipe write of data failed");
1453 	}
1454 }
1455 
1456 /*
1457  * Read a response from the command pipe, first we will receive the
1458  * length of the response then the actual data.
1459  */
1460 static void
1461 read_cmd_pipe(returns_t *response)
1462 {
1463 	int len, type;
1464 	struct pollfd rfd[2];
1465 	char *str;
1466 
1467 	/*
1468 	 * Check if there is data to read - just in case slave has died, we
1469 	 * don't want to block on the read and just hang.  We also check
1470 	 * output from the slave because the slave may be blocked waiting
1471 	 * for a flush on its stdout.
1472 	 */
1473 	rfd[0].fd = slvpipe[READ_PIPE];
1474 	rfd[0].events = POLLIN;
1475 	rfd[1].fd = master;
1476 	rfd[1].events = POLLIN;
1477 
1478 	do {
1479 		if (poll(rfd, 2, 4000) == 0)
1480 			errx(2, "%s, %zu: Command pipe read timeout",
1481 			    cur_file, line);
1482 
1483 		if ((rfd[1].revents & POLLIN) == POLLIN) {
1484 			if (verbose) {
1485 				fprintf(stderr,
1486 				    "draining output from slave\n");
1487 			}
1488 			save_slave_output(false);
1489 		}
1490 	}
1491 	while((rfd[1].revents & POLLIN) == POLLIN);
1492 
1493 	if (read(slvpipe[READ_PIPE], &type, sizeof(int)) < 0)
1494 		err(1, "command pipe read for type failed");
1495 	response->return_type = type;
1496 
1497 	if ((type != ret_ok) && (type != ret_err) && (type != ret_count)) {
1498 		if (read(slvpipe[READ_PIPE], &len, sizeof(int)) < 0)
1499 			err(1, "command pipe read for length failed");
1500 		response->return_len = len;
1501 
1502 		if (verbose) {
1503 			fprintf(stderr,
1504 			    "Reading %d bytes from command pipe\n", len);
1505 		}
1506 
1507 		if ((response->return_value = malloc(len + 1)) == NULL)
1508 			err(1, "Failed to alloc memory for cmd pipe read");
1509 
1510 		if (read(slvpipe[READ_PIPE], response->return_value, len) < 0)
1511 			err(1, "command pipe read of data failed");
1512 
1513 		if (response->return_type != ret_byte) {
1514 			str = response->return_value;
1515 			str[len] = '\0';
1516 
1517 			if (verbose) {
1518 				fprintf(stderr, "Read data >%s< from pipe\n",
1519 				    (const char *)response->return_value);
1520 			}
1521 		}
1522 	} else {
1523 		response->return_value = NULL;
1524 		if (type == ret_count) {
1525 			if (read(slvpipe[READ_PIPE], &len, sizeof(int)) < 0)
1526 				err(1, "command pipe read for number of "
1527 				       "returns failed");
1528 			response->return_len = len;
1529 		}
1530 
1531 		if (verbose) {
1532 			fprintf(stderr, "Read type %s from pipe\n",
1533 			    returns_enum_names[type]);
1534 		}
1535 	}
1536 }
1537 
1538 /*
1539  * Check for writes from the slave on the pty, save the output into a
1540  * buffer for later checking if discard is false.
1541  */
1542 #define MAX_DRAIN 256
1543 
1544 static void
1545 save_slave_output(bool discard)
1546 {
1547 	char *new_data, drain[MAX_DRAIN];
1548 	size_t to_allocate;
1549 	ssize_t result;
1550 	size_t i;
1551 
1552 	result = 0;
1553 	for (;;) {
1554 		if (result == -1)
1555 			err(2, "poll of slave pty failed");
1556 		result = MAX_DRAIN;
1557 		if ((result = read(master, drain, result)) < 0) {
1558 			if (errno == EAGAIN)
1559 				break;
1560 			else
1561 				err(2, "draining slave pty failed");
1562 		}
1563 		if (result == 0)
1564 			abort();
1565 
1566 		if (!discard) {
1567 			if ((size_t)result >
1568 			    (saved_output.allocated - saved_output.count)) {
1569 				to_allocate = 1024 * ((result / 1024) + 1);
1570 
1571 				if ((new_data = realloc(saved_output.data,
1572 					saved_output.allocated + to_allocate))
1573 				    == NULL)
1574 					err(2, "Realloc of saved_output failed");
1575 				saved_output.data = new_data;
1576 				saved_output.allocated += to_allocate;
1577 			}
1578 
1579 			if (verbose) {
1580 				fprintf(stderr, "count = %zu, "
1581 				    "allocated = %zu\n", saved_output.count,
1582 				    saved_output.allocated);
1583 				for (i = 0; i < (size_t)result; i++) {
1584 					fprintf(stderr, "Saving slave output "
1585 					    "at %zu: 0x%x (%c)\n",
1586 					    saved_output.count + i, drain[i],
1587 					    (drain[i] >= ' ')? drain[i] : '-');
1588 				}
1589 			}
1590 
1591 			memcpy(&saved_output.data[saved_output.count], drain,
1592 			       result);
1593 			saved_output.count += result;
1594 
1595 			if (verbose) {
1596 				fprintf(stderr, "count = %zu, "
1597 				    "allocated = %zu\n", saved_output.count,
1598 				    saved_output.allocated);
1599 			}
1600 		} else {
1601 			if (verbose) {
1602 				for (i = 0; i < (size_t)result; i++) {
1603 					fprintf(stderr, "Discarding slave "
1604 					    "output 0x%x (%c)\n",
1605 					    drain[i],
1606 					    (drain[i] >= ' ')? drain[i] : '-');
1607 				}
1608 			}
1609 		}
1610 	}
1611 }
1612 
1613 static void
1614 yyerror(const char *msg)
1615 {
1616 	warnx("%s in line %zu of file %s", msg, line, cur_file);
1617 }
1618