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