testlang_parse.y revision 1.37 1 %{
2 /* $NetBSD: testlang_parse.y,v 1.37 2021/02/08 19:28:08 rillig 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 without 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 <stdlib.h>
43 #include <limits.h>
44 #include <time.h>
45 #include <vis.h>
46 #include <stdint.h>
47 #include "returns.h"
48 #include "director.h"
49
50 #define YYDEBUG 1
51
52 extern int verbose;
53 extern int check_file_flag;
54 extern int cmdpipe[2];
55 extern int slvpipe[2];
56 extern int master;
57 extern struct pollfd readfd;
58 extern char *check_path;
59 extern char *cur_file; /* from director.c */
60
61 int yylex(void);
62
63 size_t line;
64
65 static int input_delay;
66
67 /* time delay between inputs chars - default to 0.1ms minimum to prevent
68 * problems with input tests
69 */
70 #define DELAY_MIN 0.1
71
72 /* time delay after a function call - allows the slave time to
73 * run the function and output data before we do other actions.
74 * Set this to 50ms.
75 */
76 #define POST_CALL_DELAY 50
77
78 static struct timespec delay_spec = {0, 1000 * DELAY_MIN};
79 static struct timespec delay_post_call = {0, 1000 * POST_CALL_DELAY};
80
81 static char *input_str; /* string to feed in as input */
82 static bool no_input; /* don't need more input */
83
84 static wchar_t *vals = NULL; /* wchars to attach to a cchar type */
85 static unsigned nvals; /* number of wchars */
86
87 #define READ_PIPE 0
88 #define WRITE_PIPE 1
89
90 const char *enum_names[] = {
91 "unused", "static", "numeric", "string", "byte", "cchar", "wchar", "ERR",
92 "OK", "NULL", "not NULL", "variable", "reference", "returns count",
93 "slave error"
94 };
95
96 typedef struct {
97 data_enum_t arg_type;
98 size_t arg_len;
99 char *arg_string;
100 int var_index;
101 } args_t;
102
103 typedef struct {
104 char *function;
105 int nrets; /* number of returns */
106 ct_data_t *returns; /* array of expected returns */
107 int nargs; /* number of arguments */
108 args_t *args; /* arguments for the call */
109 } cmd_line_t;
110
111 static cmd_line_t command;
112
113 typedef struct {
114 char *name;
115 size_t len;
116 data_enum_t type;
117 void *value;
118 cchar_t cchar;
119 } var_t;
120
121 static size_t nvars; /* Number of declared variables */
122 static var_t *vars; /* Variables defined during the test. */
123
124 static int check_function_table(char *, const char *[], int);
125 static int find_var_index(const char *);
126 static void assign_arg(data_enum_t, void *);
127 static int assign_var(const char *);
128 void init_parse_variables(int);
129 static void validate(int, void *);
130 static void validate_return(const char *, const char *, int);
131 static void validate_variable(int, data_enum_t, const void *, int, int);
132 static void validate_byte(ct_data_t *, ct_data_t *, int);
133 static void validate_cchar(cchar_t *, cchar_t *, int);
134 static void validate_wchar(wchar_t *, wchar_t *, int);
135 static void write_cmd_pipe(char *);
136 static void write_cmd_pipe_args(data_enum_t, void *);
137 static void read_cmd_pipe(ct_data_t *);
138 static void write_func_and_args(void);
139 static void compare_streams(const char *, bool);
140 static void do_function_call(size_t);
141 static void check(void);
142 static void save_slave_output(bool);
143 static void validate_type(data_enum_t, ct_data_t *, int);
144 static void set_var(data_enum_t, const 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 static void set_cchar(char *, void *);
150 static void set_wchar(char *);
151 static wchar_t *add_to_vals(data_enum_t, void *);
152
153 static const char *input_functions[] = {
154 "getch", "mvgetch", "mvwgetch", "wgetch", "getnstr", "getstr", "mvgetnstr",
155 "mvgetstr", "mvwgetnstr", "mvwgetstr", "wgetnstr", "wgetstr", "mvscanw",
156 "mvwscanw", "scanw", "wscanw", "get_wch", "mvget_wch", "mvwget_wch",
157 "wget_wch", "getn_wstr", "get_wstr", "mvgetn_wstr", "mvget_wstr",
158 "mvwgetn_wstr","mvwget_wstr", "wgetn_wstr", "wget_wstr"
159 };
160
161 static const unsigned ninput_functions =
162 sizeof(input_functions) / sizeof(char *);
163
164 extern saved_data_t saved_output;
165
166 %}
167
168 %union {
169 char *string;
170 ct_data_t *retval;
171 wchar_t *vals;
172 }
173
174 %token <string> PATH
175 %token <string> STRING
176 %token <retval> BYTE
177 %token <string> VARNAME
178 %token <string> FILENAME
179 %token <string> VARIABLE
180 %token <string> REFERENCE
181 %token <string> NULL_RET
182 %token <string> NON_NULL
183 %token <string> ERR_RET
184 %token <string> OK_RET
185 %token <string> numeric
186 %token <string> DELAY
187 %token <string> INPUT
188 %token <string> COMPARE
189 %token <string> COMPAREND
190 %token <string> ASSIGN
191 %token <string> CCHAR
192 %token <string> WCHAR
193 %token EOL CALL CHECK NOINPUT OR MULTIPLIER LPAREN RPAREN LBRACK RBRACK
194 %token COMMA
195 %token CALL2 CALL3 CALL4
196
197 %nonassoc OR
198
199 %%
200
201 statements : /* empty */
202 | statement EOL statements
203 ;
204
205 statement : assign
206 | call
207 | call2
208 | call3
209 | call4
210 | check
211 | delay
212 | input
213 | noinput
214 | compare
215 | comparend
216 | cchar
217 | wchar
218 | /* empty */
219 ;
220
221 assign : ASSIGN VARNAME numeric {
222 set_var(data_number, $2, $3);
223 }
224 | ASSIGN VARNAME LPAREN expr RPAREN {
225 set_var(data_number, $2, $<string>4);
226 }
227 | ASSIGN VARNAME STRING {
228 set_var(data_string, $2, $3);
229 }
230 | ASSIGN VARNAME BYTE {
231 set_var(data_byte, $2, $3);
232 }
233 ;
234
235 cchar : CCHAR VARNAME attributes char_vals {
236 set_cchar($2, $<string>3);
237 }
238 ;
239
240 wchar : WCHAR VARNAME char_vals {
241 set_wchar($2);
242 }
243 ;
244
245 attributes : numeric
246 | LPAREN expr RPAREN {
247 $<string>$ = $<string>2;
248 }
249 | VARIABLE {
250 $<string>$ = get_numeric_var($1);
251 }
252 ;
253
254 char_vals : numeric {
255 add_to_vals(data_number, $1);
256 }
257 | LBRACK array_elements RBRACK
258 | VARIABLE {
259 add_to_vals(data_var, $1);
260 }
261 | STRING {
262 add_to_vals(data_string, $1);
263 }
264 | BYTE {
265 add_to_vals(data_byte, $1);
266 }
267 ;
268
269 call : CALL result fn_name args {
270 do_function_call(1);
271 }
272 ;
273
274 call2 : CALL2 result result fn_name args {
275 do_function_call(2);
276 }
277 ;
278
279 call3 : CALL3 result result result fn_name args {
280 do_function_call(3);
281 }
282 ;
283
284 call4 : CALL4 result result result result fn_name args {
285 do_function_call(4);
286 }
287 ;
288
289 check : CHECK var returns {
290 check();
291 }
292 ;
293
294 delay : DELAY numeric {
295 /* set the inter-character delay */
296 if (sscanf($2, "%d", &input_delay) == 0)
297 err(1, "%s:%zu: Delay specification %s must be an int",
298 cur_file, line, $2);
299 if (verbose) {
300 fprintf(stderr, "Set input delay to %d ms\n", input_delay);
301 }
302
303 if (input_delay < DELAY_MIN)
304 input_delay = DELAY_MIN;
305 /*
306 * Fill in the timespec structure now ready for use later.
307 * The delay is specified in milliseconds so convert to timespec
308 * values
309 */
310 delay_spec.tv_sec = input_delay / 1000;
311 delay_spec.tv_nsec = (input_delay - 1000 * delay_spec.tv_sec) * 1000;
312 if (verbose) {
313 fprintf(stderr, "set delay to %jd.%jd\n",
314 (intmax_t)delay_spec.tv_sec,
315 (intmax_t)delay_spec.tv_nsec);
316 }
317
318 init_parse_variables(0);
319 }
320 ;
321
322 input : INPUT STRING {
323 if (input_str != NULL) {
324 warnx("%s:%zu: Discarding unused input string", cur_file, line);
325 free(input_str);
326 }
327
328 if ((input_str = malloc(strlen($2) + 1)) == NULL)
329 err(2, "Cannot allocate memory for input string");
330
331 strlcpy(input_str, $2, strlen($2) + 1);
332 }
333 ;
334
335
336 noinput : NOINPUT {
337 if (input_str != NULL) {
338 warnx("%s:%zu: Discarding unused input string", cur_file, line);
339 free(input_str);
340 }
341
342 no_input = true;
343 }
344
345 compare : COMPARE PATH {
346 compare_streams($2, true);
347 }
348 | COMPARE FILENAME {
349 compare_streams($2, true);
350 }
351 ;
352
353 comparend : COMPAREND PATH {
354 compare_streams($2, false);
355 }
356 | COMPAREND FILENAME {
357 compare_streams($2, false);
358 }
359 ;
360
361
362 result : returns
363 | reference
364 ;
365
366 returns : numeric { assign_rets(data_number, $1); }
367 | LPAREN expr RPAREN { assign_rets(data_number, $<string>2); }
368 | STRING { assign_rets(data_string, $1); }
369 | BYTE { assign_rets(data_byte, (void *) $1); }
370 | ERR_RET { assign_rets(data_err, NULL); }
371 | OK_RET { assign_rets(data_ok, NULL); }
372 | NULL_RET { assign_rets(data_null, NULL); }
373 | NON_NULL { assign_rets(data_nonnull, NULL); }
374 | var
375 ;
376
377 var : VARNAME {
378 assign_rets(data_var, $1);
379 }
380 ;
381
382 reference : VARIABLE {
383 assign_rets(data_ref, $1);
384 }
385 ;
386
387 fn_name : VARNAME {
388 if (command.function != NULL)
389 free(command.function);
390
391 command.function = malloc(strlen($1) + 1);
392 if (command.function == NULL)
393 err(1, "Could not allocate memory for function name");
394 strcpy(command.function, $1);
395 }
396 ;
397
398 array_elements : array_element
399 | array_element COMMA array_elements
400 ;
401
402 array_element : numeric {
403 $<vals>$ = add_to_vals(data_number, $1);
404 }
405 | VARIABLE {
406 $<vals>$ = add_to_vals(data_number,
407 get_numeric_var($1));
408 }
409 | BYTE {
410 $<vals>$ = add_to_vals(data_byte, (void *) $1);
411 }
412 | STRING {
413 $<vals>$ = add_to_vals(data_string, (void *) $1);
414 }
415 | numeric MULTIPLIER numeric {
416 unsigned long i;
417 unsigned long acount;
418
419 acount = strtoul($3, NULL, 10);
420 for (i = 0; i < acount; i++) {
421 $<vals>$ = add_to_vals(data_number, $1);
422 }
423 }
424 | VARIABLE MULTIPLIER numeric {
425 unsigned long i, acount;
426 char *val;
427
428 acount = strtoul($3, NULL, 10);
429 val = get_numeric_var($1);
430 for (i = 0; i < acount; i++) {
431 $<vals>$ = add_to_vals(data_number, val);
432 }
433 }
434 | BYTE MULTIPLIER numeric {
435 unsigned long i, acount;
436
437 acount = strtoul($3, NULL, 10);
438 for (i = 0; i < acount; i++) {
439 $<vals>$ = add_to_vals(data_byte, (void *) $1);
440 }
441 }
442 | STRING MULTIPLIER numeric {
443 unsigned long i, acount;
444
445 acount = strtoul($3, NULL, 10);
446 for (i = 0; i < acount; i++) {
447 $<vals>$ = add_to_vals(data_string,
448 (void *) $1);
449 }
450 }
451 ;
452
453 expr : numeric
454 | VARIABLE {
455 $<string>$ = get_numeric_var($1);
456 }
457 | expr OR expr {
458 $<string>$ = numeric_or($<string>1, $<string>3);
459 }
460 ;
461
462 args : /* empty */
463 | arg args
464 ;
465
466 arg : LPAREN expr RPAREN {
467 assign_arg(data_static, $<string>2);
468 }
469 | numeric {
470 assign_arg(data_static, $1);
471 }
472 | STRING {
473 assign_arg(data_static, $1);
474 }
475 | BYTE {
476 assign_arg(data_byte, $1);
477 }
478 | PATH {
479 assign_arg(data_static, $1);
480 }
481 | FILENAME {
482 assign_arg(data_static, $1);
483 }
484 | VARNAME {
485 assign_arg(data_static, $1);
486 }
487 | VARIABLE {
488 assign_arg(data_var, $1);
489 }
490 | NULL_RET {
491 assign_arg(data_null, $1);
492 }
493 ;
494
495 %%
496
497 static void
498 excess(const char *fname, size_t lineno, const char *func, const char *comment,
499 const void *data, size_t datalen)
500 {
501 size_t dstlen = datalen * 4 + 1;
502 char *dst = malloc(dstlen);
503
504 if (dst == NULL)
505 err(1, "malloc");
506
507 if (strnvisx(dst, dstlen, data, datalen, VIS_WHITE | VIS_OCTAL) == -1)
508 err(1, "strnvisx");
509
510 warnx("%s:%zu: [%s] Excess %zu bytes%s [%s]",
511 fname, lineno, func, datalen, comment, dst);
512 free(dst);
513 }
514
515 /*
516 * Get the value of a variable, error if the variable has not been set or
517 * is not a numeric type.
518 */
519 static char *
520 get_numeric_var(const char *var)
521 {
522 int i;
523
524 if ((i = find_var_index(var)) < 0)
525 err(1, "Variable %s is undefined", var);
526
527 if (vars[i].type != data_number)
528 err(1, "Variable %s is not a numeric type", var);
529
530 return vars[i].value;
531 }
532
533 /*
534 * Perform a bitwise OR on two numbers and return the result.
535 */
536 static char *
537 numeric_or(char *n1, char *n2)
538 {
539 unsigned long i1, i2, result;
540 char *ret;
541
542 i1 = strtoul(n1, NULL, 10);
543 i2 = strtoul(n2, NULL, 10);
544
545 result = i1 | i2;
546 asprintf(&ret, "%lu", result);
547
548 if (verbose) {
549 fprintf(stderr, "numeric or of 0x%lx (%s) and 0x%lx (%s)"
550 " results in 0x%lx (%s)\n",
551 i1, n1, i2, n2, result, ret);
552 }
553
554 return ret;
555 }
556
557 /*
558 * Sleep for the specified time, handle the sleep getting interrupted
559 * by a signal.
560 */
561 static void
562 perform_delay(struct timespec *ts)
563 {
564 struct timespec delay_copy, delay_remainder;
565
566 delay_copy = *ts;
567 while (nanosleep(&delay_copy, &delay_remainder) < 0) {
568 if (errno != EINTR)
569 err(2, "nanosleep returned error");
570 delay_copy = delay_remainder;
571 }
572 }
573
574 /*
575 * Add to temporary vals array
576 */
577 static wchar_t *add_to_vals(data_enum_t argtype, void *arg)
578 {
579 wchar_t *retval = NULL;
580 int have_malloced;
581 int i;
582 ct_data_t *ret;
583
584 have_malloced = 0;
585
586 if (nvals == 0) {
587 have_malloced = 1;
588 retval = malloc(sizeof(wchar_t));
589 } else {
590 retval = realloc(vals, (nvals + 1) * sizeof(wchar_t));
591 }
592
593 if (retval == NULL)
594 return retval;
595
596 vals = retval;
597
598 switch (argtype) {
599 case data_number:
600 vals[nvals++] = (wchar_t) strtoul((char *) arg, NULL, 10);
601 break;
602
603 case data_string:
604 vals[nvals++] = (wchar_t) ((char *)arg)[0];
605 break;
606
607 case data_byte:
608 ret = (ct_data_t *) arg;
609 vals[nvals++] = *((wchar_t *) ret->data_value);
610 break;
611
612 case data_var:
613 if ((i = find_var_index((char *) arg)) < 0)
614 err(1, "%s:%zu: Variable %s is undefined",
615 cur_file, line, (const char *) arg);
616
617 switch (vars[i].type) {
618
619 case data_number:
620 case data_string:
621 case data_byte:
622 retval = add_to_vals(vars[i].type, vars[i].value);
623 break;
624
625 default:
626 err(1, "%s:%zu: Variable %s has invalid type for cchar",
627 cur_file, line, (const char *) arg);
628 break;
629
630 }
631 break;
632
633 default:
634 err(1, "%s:%zu: Internal error: Unhandled type for vals array",
635 cur_file, line);
636
637 /* if we get here without a value then tidy up */
638 if ((nvals == 0) && (have_malloced == 1)) {
639 free(retval);
640 retval = vals;
641 }
642 break;
643
644 }
645
646 return retval;
647 }
648
649 /*
650 * Assign the value given to the named variable.
651 */
652 static void
653 set_var(data_enum_t type, const char *name, void *value)
654 {
655 int i;
656 char *number;
657 ct_data_t *ret;
658
659 i = find_var_index(name);
660 if (i < 0)
661 i = assign_var(name);
662
663 vars[i].type = type;
664 if ((type == data_number) || (type == data_string)) {
665 number = value;
666 vars[i].len = strlen(number) + 1;
667 vars[i].value = malloc(vars[i].len + 1);
668 if (vars[i].value == NULL)
669 err(1, "Could not malloc memory for assign string");
670 strcpy(vars[i].value, number);
671 } else {
672 /* can only be a byte value */
673 ret = value;
674 vars[i].len = ret->data_len;
675 vars[i].value = malloc(vars[i].len);
676 if (vars[i].value == NULL)
677 err(1, "Could not malloc memory to assign byte string");
678 memcpy(vars[i].value, ret->data_value, vars[i].len);
679 }
680 }
681
682 /*
683 * Form up a complex character type from the given components.
684 */
685 static void
686 set_cchar(char *name, void *attributes)
687 {
688 int i;
689 unsigned j;
690 attr_t attribs;
691
692 if (nvals >= CURSES_CCHAR_MAX)
693 err(1, "%s:%zu: %s: too many characters in complex char type",
694 cur_file, line, __func__);
695
696 i = find_var_index(name);
697 if (i < 0)
698 i = assign_var(name);
699
700 if (sscanf((char *) attributes, "%d", &attribs) != 1)
701 err(1, "%s:%zu: %s: conversion of attributes to integer failed",
702 cur_file, line, __func__);
703
704 vars[i].type = data_cchar;
705 vars[i].cchar.attributes = attribs;
706 vars[i].cchar.elements = nvals;
707 for (j = 0; j < nvals; j++)
708 vars[i].cchar.vals[j] = vals[j];
709
710 nvals = 0;
711 vals = NULL;
712
713 }
714
715 /*
716 * Form up a wide character string type from the given components.
717 */
718 static void
719 set_wchar(char *name)
720 {
721 int i;
722 unsigned j;
723 wchar_t *wcval;
724
725 i = find_var_index(name);
726 if (i < 0)
727 i = assign_var(name);
728
729 vars[i].type = data_wchar;
730 vars[i].len = (nvals+1) * sizeof(wchar_t);
731 vars[i].value = malloc(vars[i].len);
732 if (vars[i].value == NULL)
733 err(1, "Could not malloc memory to assign wchar string");
734 wcval = vars[i].value;
735 for(j = 0; j < nvals; j++)
736 wcval[j] = vals[j];
737 wcval[nvals] = L'\0';
738 nvals = 0;
739 vals = NULL;
740
741 }
742
743 /*
744 * Add a new variable to the vars array, the value will be assigned later,
745 * when a test function call returns.
746 */
747 static int
748 assign_var(const char *varname)
749 {
750 var_t *temp;
751 char *name;
752
753 if ((name = malloc(strlen(varname) + 1)) == NULL)
754 err(1, "Alloc of varname failed");
755
756 if ((temp = realloc(vars, sizeof(*temp) * (nvars + 1))) == NULL) {
757 free(name);
758 err(1, "Realloc of vars array failed");
759 }
760
761 strcpy(name, varname);
762 vars = temp;
763 vars[nvars].name = name;
764 vars[nvars].len = 0;
765 vars[nvars].value = NULL;
766 nvars++;
767
768 return (nvars - 1);
769 }
770
771 /*
772 * Allocate and assign a new argument of the given type.
773 */
774 static void
775 assign_arg(data_enum_t arg_type, void *arg)
776 {
777 args_t *temp, cur;
778 char *str = arg;
779 ct_data_t *ret;
780
781 if (verbose) {
782 fprintf(stderr, "function is >%s<, adding arg >%s< type %s (%d)\n",
783 command.function, str, enum_names[arg_type], arg_type);
784 }
785
786 cur.arg_type = arg_type;
787 if (cur.arg_type == data_var) {
788 cur.var_index = find_var_index(arg);
789 if (cur.var_index < 0)
790 err(1, "%s:%zu: Invalid variable %s",
791 cur_file, line, str);
792 } else if (cur.arg_type == data_byte) {
793 ret = arg;
794 cur.arg_len = ret->data_len;
795 cur.arg_string = malloc(cur.arg_len);
796 if (cur.arg_string == NULL)
797 err(1, "Could not malloc memory for arg bytes");
798 memcpy(cur.arg_string, ret->data_value, cur.arg_len);
799 } else if (cur.arg_type == data_null) {
800 cur.arg_len = 0;
801 cur.arg_string = NULL;
802 } else {
803 cur.arg_len = strlen(str);
804 cur.arg_string = malloc(cur.arg_len + 1);
805 if (cur.arg_string == NULL)
806 err(1, "Could not malloc memory for arg string");
807 strcpy(cur.arg_string, arg);
808 }
809
810 temp = realloc(command.args, sizeof(*temp) * (command.nargs + 1));
811 if (temp == NULL)
812 err(1, "Failed to reallocate args");
813 command.args = temp;
814 memcpy(&command.args[command.nargs], &cur, sizeof(args_t));
815 command.nargs++;
816 }
817
818 /*
819 * Allocate and assign a new return.
820 */
821 static void
822 assign_rets(data_enum_t ret_type, void *ret)
823 {
824 ct_data_t *temp, cur;
825 char *ret_str;
826 ct_data_t *ret_ret;
827
828 cur.data_type = ret_type;
829 if (ret_type != data_var) {
830 if ((ret_type == data_number) || (ret_type == data_string)) {
831 ret_str = ret;
832 cur.data_len = strlen(ret_str) + 1;
833 cur.data_value = malloc(cur.data_len + 1);
834 if (cur.data_value == NULL)
835 err(1,
836 "Could not malloc memory for arg string");
837 strcpy(cur.data_value, ret_str);
838 } else if (ret_type == data_byte) {
839 ret_ret = ret;
840 cur.data_len = ret_ret->data_len;
841 cur.data_value = malloc(cur.data_len);
842 if (cur.data_value == NULL)
843 err(1,
844 "Could not malloc memory for byte string");
845 memcpy(cur.data_value, ret_ret->data_value,
846 cur.data_len);
847 } else if (ret_type == data_ref) {
848 if ((cur.data_index = find_var_index(ret)) < 0)
849 err(1, "Undefined variable reference");
850 }
851 } else {
852 cur.data_index = find_var_index(ret);
853 if (cur.data_index < 0)
854 cur.data_index = assign_var(ret);
855 }
856
857 temp = realloc(command.returns, sizeof(*temp) * (command.nrets + 1));
858 if (temp == NULL)
859 err(1, "Failed to reallocate returns");
860 command.returns = temp;
861 memcpy(&command.returns[command.nrets], &cur, sizeof(ct_data_t));
862 command.nrets++;
863 }
864
865 /*
866 * Find the given variable name in the var array and return the i
867 * return -1 if var is not found.
868 */
869 static int
870 find_var_index(const char *var_name)
871 {
872 int result;
873 size_t i;
874
875 result = -1;
876
877 for (i = 0; i < nvars; i++) {
878 if (strcmp(var_name, vars[i].name) == 0) {
879 result = i;
880 break;
881 }
882 }
883
884 return result;
885 }
886
887 /*
888 * Check the given function name in the given table of names, return 1 if
889 * there is a match.
890 */
891 static int check_function_table(char *function, const char *table[],
892 int nfunctions)
893 {
894 int i;
895
896 for (i = 0; i < nfunctions; i++) {
897 if ((strlen(function) == strlen(table[i])) &&
898 (strcmp(function, table[i]) == 0))
899 return 1;
900 }
901
902 return 0;
903 }
904
905 /*
906 * Compare the output from the slave against the given file and report
907 * any differences.
908 */
909 static void
910 compare_streams(const char *filename, bool discard)
911 {
912 char check_file[PATH_MAX], drain[100], ref, data;
913 struct pollfd fds[2];
914 int nfd, check_fd;
915 ssize_t result;
916 size_t offs;
917
918 /*
919 * Don't prepend check path iff check file has an absolute
920 * path.
921 */
922 if (filename[0] != '/') {
923 if (strlcpy(check_file, check_path, sizeof(check_file))
924 >= sizeof(check_file))
925 err(2, "CHECK_PATH too long");
926
927 if (strlcat(check_file, "/", sizeof(check_file))
928 >= sizeof(check_file))
929 err(2, "Could not append / to check file path");
930 } else {
931 check_file[0] = '\0';
932 }
933
934 if (strlcat(check_file, filename, sizeof(check_file))
935 >= sizeof(check_file))
936 err(2, "Path to check file path overflowed");
937
938 int create_check_file = 0;
939
940 if (check_file_flag == (GEN_CHECK_FILE | FORCE_GEN))
941 create_check_file = 1;
942 else if ((check_fd = open(check_file, O_RDONLY, 0)) < 0) {
943 if (check_file_flag & GEN_CHECK_FILE)
944 create_check_file = 1;
945 else
946 err(2, "%s:%zu: failed to open file %s",
947 cur_file, line, check_file);
948 }
949
950 if (create_check_file) {
951 check_fd = open(check_file, O_WRONLY | O_CREAT, 0644);
952 if (check_fd < 0) {
953 err(2, "%s:%zu: failed to create file %s",
954 cur_file, line, check_file);
955 }
956 }
957
958 fds[0].fd = check_fd;
959 fds[0].events = create_check_file ? POLLOUT:POLLIN;
960 fds[1].fd = master;
961 fds[1].events = POLLIN;
962
963 nfd = 2;
964 /*
965 * if we have saved output then only check for data in the
966 * reference file since the slave data may already be drained.
967 */
968 if (saved_output.count > 0)
969 nfd = 1;
970
971 offs = 0;
972 while (poll(fds, nfd, 500) == nfd) {
973 /* Read from check file if doing comparison */
974 if (!create_check_file) {
975 if (fds[0].revents & POLLIN) {
976 if ((result = read(check_fd, &ref, 1)) < 1) {
977 if (result != 0) {
978 err(2, "Bad read on file %s",
979 check_file);
980 } else {
981 break;
982 }
983 }
984 }
985 }
986
987 if (saved_output.count > 0) {
988 data = saved_output.data[saved_output.readp];
989 saved_output.count--;
990 saved_output.readp++;
991 /* run out of saved data, switch to file */
992 if (saved_output.count == 0)
993 nfd = 2;
994 } else {
995 int revent = (create_check_file == 1) ? POLLOUT:POLLIN;
996 if (fds[0].revents & revent) {
997 if (read(master, &data, 1) < 1)
998 err(2, "Bad read on slave pty");
999 } else
1000 continue;
1001 }
1002
1003 if (create_check_file) {
1004 if ((result = write(check_fd, &data, 1)) < 1)
1005 err(2, "Bad write on file %s", check_file);
1006 ref = data;
1007 }
1008
1009 if (verbose) {
1010 if (create_check_file)
1011 fprintf(stderr, "Saving reference byte 0x%x (%c)"
1012 " against slave byte 0x%x (%c)\n",
1013 ref, (ref >= ' ') ? ref : '-',
1014 data, (data >= ' ' )? data : '-');
1015 else
1016 fprintf(stderr, "Comparing reference byte 0x%x (%c)"
1017 " against slave byte 0x%x (%c)\n",
1018 ref, (ref >= ' ') ? ref : '-',
1019 data, (data >= ' ' )? data : '-');
1020 }
1021
1022 if (!create_check_file && ref != data) {
1023 errx(2, "%s:%zu: refresh data from slave does "
1024 "not match expected from file %s offset %zu "
1025 "[reference 0x%02x (%c) != slave 0x%02x (%c)]",
1026 cur_file, line, check_file, offs,
1027 ref, (ref >= ' ') ? ref : '-',
1028 data, (data >= ' ') ? data : '-');
1029 }
1030
1031 offs++;
1032 }
1033
1034 /*
1035 * if creating a check file, there shouldn't be
1036 * anymore saved output
1037 */
1038 if (saved_output.count > 0) {
1039 if (create_check_file)
1040 err(2, "Slave output not flushed correctly");
1041 else
1042 excess(cur_file, line, __func__, " from slave",
1043 &saved_output.data[saved_output.readp], saved_output.count);
1044 }
1045
1046 /* discard any excess saved output if required */
1047 if (discard) {
1048 saved_output.count = 0;
1049 saved_output.readp = 0;
1050 }
1051
1052 if (!create_check_file && (result = poll(fds, 2, 0)) != 0) {
1053 if (result == -1)
1054 err(2, "poll of file descriptors failed");
1055
1056 if ((fds[1].revents & POLLIN) == POLLIN) {
1057 save_slave_output(true);
1058 } else if ((fds[0].revents & POLLIN) == POLLIN) {
1059 /*
1060 * handle excess in file if it exists. Poll
1061 * says there is data until EOF is read.
1062 * Check next read is EOF, if it is not then
1063 * the file really has more data than the
1064 * slave produced so flag this as a warning.
1065 */
1066 result = read(check_fd, drain, sizeof(drain));
1067 if (result == -1)
1068 err(1, "read of data file failed");
1069
1070 if (result > 0) {
1071 excess(check_file, 0, __func__, "", drain,
1072 result);
1073 }
1074 }
1075 }
1076
1077 close(check_fd);
1078 }
1079
1080 /*
1081 * Pass a function call and arguments to the slave and wait for the
1082 * results. The variable nresults determines how many returns we expect
1083 * back from the slave. These results will be validated against the
1084 * expected returns or assigned to variables.
1085 */
1086 static void
1087 do_function_call(size_t nresults)
1088 {
1089 #define MAX_RESULTS 4
1090 char *p;
1091 int do_input;
1092 size_t i;
1093 struct pollfd fds[3];
1094 ct_data_t response[MAX_RESULTS], returns_count;
1095 assert(nresults <= MAX_RESULTS);
1096
1097 do_input = check_function_table(command.function, input_functions,
1098 ninput_functions);
1099
1100 write_func_and_args();
1101
1102 /*
1103 * We should get the number of returns back here, grab it before
1104 * doing input otherwise it will confuse the input poll
1105 */
1106 read_cmd_pipe(&returns_count);
1107 if (returns_count.data_type != data_count)
1108 err(2, "expected return type of data_count but received %s",
1109 enum_names[returns_count.data_type]);
1110
1111 perform_delay(&delay_post_call); /* let slave catch up */
1112
1113 if (verbose) {
1114 fprintf(stderr, "Expect %zu results from slave, slave "
1115 "reported %zu\n", nresults, returns_count.data_len);
1116 }
1117
1118 if ((no_input == false) && (do_input == 1)) {
1119 if (verbose) {
1120 fprintf(stderr, "doing input with inputstr >%s<\n",
1121 input_str);
1122 }
1123
1124 if (input_str == NULL)
1125 errx(2, "%s:%zu: Call to input function "
1126 "but no input defined", cur_file, line);
1127
1128 fds[0].fd = slvpipe[READ_PIPE];
1129 fds[0].events = POLLIN;
1130 fds[1].fd = master;
1131 fds[1].events = POLLOUT;
1132 p = input_str;
1133 save_slave_output(false);
1134 while(*p != '\0') {
1135 perform_delay(&delay_spec);
1136
1137 if (poll(fds, 2, 0) < 0)
1138 err(2, "poll failed");
1139 if (fds[0].revents & POLLIN) {
1140 warnx("%s:%zu: Slave function "
1141 "returned before end of input string",
1142 cur_file, line);
1143 break;
1144 }
1145 if ((fds[1].revents & POLLOUT) == 0)
1146 continue;
1147 if (verbose) {
1148 fprintf(stderr, "Writing char >%c< to slave\n",
1149 *p);
1150 }
1151 if (write(master, p, 1) != 1) {
1152 warn("%s:%zu: Slave function write error",
1153 cur_file, line);
1154 break;
1155 }
1156 p++;
1157
1158 }
1159 save_slave_output(false);
1160
1161 if (verbose) {
1162 fprintf(stderr, "Input done.\n");
1163 }
1164
1165 /* done with the input string, free the resources */
1166 free(input_str);
1167 input_str = NULL;
1168 }
1169
1170 if (verbose) {
1171 fds[0].fd = slvpipe[READ_PIPE];
1172 fds[0].events = POLLIN;
1173
1174 fds[1].fd = slvpipe[WRITE_PIPE];
1175 fds[1].events = POLLOUT;
1176
1177 fds[2].fd = master;
1178 fds[2].events = POLLIN | POLLOUT;
1179
1180 i = poll(&fds[0], 3, 1000);
1181 fprintf(stderr, "Poll returned %zu\n", i);
1182 for (i = 0; i < 3; i++) {
1183 fprintf(stderr, "revents for fd[%zu] = 0x%x\n",
1184 i, fds[i].revents);
1185 }
1186 }
1187
1188 /* drain any trailing output */
1189 save_slave_output(false);
1190
1191 for (i = 0; i < returns_count.data_len; i++) {
1192 read_cmd_pipe(&response[i]);
1193 }
1194
1195 /*
1196 * Check for a slave error in the first return slot, if the
1197 * slave errored then we may not have the number of returns we
1198 * expect but in this case we should report the slave error
1199 * instead of a return count mismatch.
1200 */
1201 if ((returns_count.data_len > 0) &&
1202 (response[0].data_type == data_slave_error))
1203 err(2, "Slave returned error: %s",
1204 (const char *)response[0].data_value);
1205
1206 if (returns_count.data_len != nresults)
1207 err(2, "Incorrect number of returns from slave, expected %zu "
1208 "but received %zu", nresults, returns_count.data_len);
1209
1210 if (verbose) {
1211 for (i = 0; i < nresults; i++) {
1212 if ((response[i].data_type != data_byte) &&
1213 (response[i].data_type != data_err) &&
1214 (response[i].data_type != data_ok))
1215 fprintf(stderr,
1216 "received response >%s< "
1217 "expected",
1218 (const char *)response[i].data_value);
1219 else
1220 fprintf(stderr, "received");
1221
1222 fprintf(stderr, " data_type %s\n",
1223 enum_names[command.returns[i].data_type]);
1224 }
1225 }
1226
1227 for (i = 0; i < nresults; i++) {
1228 if (command.returns[i].data_type != data_var) {
1229 validate(i, &response[i]);
1230 } else {
1231 vars[command.returns[i].data_index].len =
1232 response[i].data_len;
1233
1234 if (response[i].data_type == data_cchar) {
1235 vars[command.returns[i].data_index].cchar =
1236 *((cchar_t *)response[i].data_value);
1237 } else {
1238 vars[command.returns[i].data_index].value =
1239 response[i].data_value;
1240 }
1241
1242 vars[command.returns[i].data_index].type =
1243 response[i].data_type;
1244 }
1245 }
1246
1247 if (verbose && (saved_output.count > 0))
1248 excess(cur_file, line, __func__, " from slave",
1249 &saved_output.data[saved_output.readp], saved_output.count);
1250
1251 init_parse_variables(0);
1252 }
1253
1254 /*
1255 * Write the function and command arguments to the command pipe.
1256 */
1257 static void
1258 write_func_and_args(void)
1259 {
1260 int i;
1261
1262 if (verbose) {
1263 fprintf(stderr, "calling function >%s<\n", command.function);
1264 }
1265
1266 write_cmd_pipe(command.function);
1267 for (i = 0; i < command.nargs; i++) {
1268 if (command.args[i].arg_type == data_var)
1269 write_cmd_pipe_args(command.args[i].arg_type,
1270 &vars[command.args[i].var_index]);
1271 else
1272 write_cmd_pipe_args(command.args[i].arg_type,
1273 &command.args[i]);
1274 }
1275
1276 write_cmd_pipe(NULL); /* signal end of arguments */
1277 }
1278
1279 static void
1280 check(void)
1281 {
1282 ct_data_t retvar;
1283 var_t *vptr;
1284
1285 if (command.returns[0].data_index == -1)
1286 err(1, "%s:%zu: Undefined variable in check statement",
1287 cur_file, line);
1288
1289 if (command.returns[1].data_type == data_var) {
1290 vptr = &vars[command.returns[1].data_index];
1291 command.returns[1].data_type = vptr->type;
1292 command.returns[1].data_len = vptr->len;
1293 if (vptr->type != data_cchar)
1294 command.returns[1].data_value = vptr->value;
1295 else
1296 command.returns[1].data_value = &vptr->cchar;
1297 }
1298
1299 if (verbose) {
1300 fprintf(stderr, "Checking contents of variable %s for %s\n",
1301 vars[command.returns[0].data_index].name,
1302 enum_names[command.returns[1].data_type]);
1303 }
1304
1305 /*
1306 * Check if var and return have same data types
1307 */
1308 if (((command.returns[1].data_type == data_byte) &&
1309 (vars[command.returns[0].data_index].type != data_byte)))
1310 err(1, "Var type %s (%d) does not match return type %s (%d)",
1311 enum_names[vars[command.returns[0].data_index].type],
1312 vars[command.returns[0].data_index].type,
1313 enum_names[command.returns[1].data_type],
1314 command.returns[1].data_type);
1315
1316 switch (command.returns[1].data_type) {
1317 case data_err:
1318 case data_ok:
1319 validate_type(vars[command.returns[0].data_index].type,
1320 &command.returns[1], 0);
1321 break;
1322
1323 case data_null:
1324 validate_variable(0, data_string, "NULL",
1325 command.returns[0].data_index, 0);
1326 break;
1327
1328 case data_nonnull:
1329 validate_variable(0, data_string, "NULL",
1330 command.returns[0].data_index, 1);
1331 break;
1332
1333 case data_string:
1334 case data_number:
1335 if (verbose) {
1336 fprintf(stderr, " %s == returned %s\n",
1337 (const char *)command.returns[1].data_value,
1338 (const char *)
1339 vars[command.returns[0].data_index].value);
1340 }
1341 validate_variable(0, data_string,
1342 command.returns[1].data_value,
1343 command.returns[0].data_index, 0);
1344 break;
1345
1346 case data_byte:
1347 vptr = &vars[command.returns[0].data_index];
1348 retvar.data_len = vptr->len;
1349 retvar.data_type = vptr->type;
1350 retvar.data_value = vptr->value;
1351 validate_byte(&retvar, &command.returns[1], 0);
1352 break;
1353
1354 case data_cchar:
1355 validate_cchar(&vars[command.returns[0].data_index].cchar,
1356 (cchar_t *) command.returns[1].data_value, 0);
1357 break;
1358
1359 case data_wchar:
1360 validate_wchar((wchar_t *) vars[command.returns[0].data_index].value,
1361 (wchar_t *) command.returns[1].data_value, 0);
1362 break;
1363
1364 default:
1365 err(1, "%s:%zu: Malformed check statement", cur_file, line);
1366 break;
1367 }
1368
1369 init_parse_variables(0);
1370 }
1371
1372 /*
1373 * Initialise the command structure - if initial is non-zero then just set
1374 * everything to sane values otherwise free any memory that was allocated
1375 * when building the structure.
1376 */
1377 void
1378 init_parse_variables(int initial)
1379 {
1380 int i, result;
1381 struct pollfd slave_pty;
1382
1383 if (initial == 0) {
1384 free(command.function);
1385 for (i = 0; i < command.nrets; i++) {
1386 if (command.returns[i].data_type == data_number)
1387 free(command.returns[i].data_value);
1388 }
1389 free(command.returns);
1390
1391 for (i = 0; i < command.nargs; i++) {
1392 if (command.args[i].arg_type != data_var)
1393 free(command.args[i].arg_string);
1394 }
1395 free(command.args);
1396 } else {
1397 line = 0;
1398 input_delay = 0;
1399 vars = NULL;
1400 nvars = 0;
1401 input_str = NULL;
1402 saved_output.allocated = 0;
1403 saved_output.count = 0;
1404 saved_output.readp = 0;
1405 saved_output.data = NULL;
1406 }
1407
1408 no_input = false;
1409 command.function = NULL;
1410 command.nargs = 0;
1411 command.args = NULL;
1412 command.nrets = 0;
1413 command.returns = NULL;
1414
1415 /*
1416 * Check the slave pty for stray output from the slave, at this
1417 * point we should not see any data as it should have been
1418 * consumed by the test functions. If we see data then we have
1419 * either a bug or are not handling an output generating function
1420 * correctly.
1421 */
1422 slave_pty.fd = master;
1423 slave_pty.events = POLLIN;
1424 result = poll(&slave_pty, 1, 0);
1425
1426 if (result < 0)
1427 err(2, "Poll of slave pty failed");
1428 else if (result > 0)
1429 warnx("%s:%zu: Unexpected data from slave", cur_file, line);
1430 }
1431
1432 /*
1433 * Validate the response against the expected return. The variable
1434 * i is the i into the rets array in command.
1435 */
1436 static void
1437 validate(int i, void *data)
1438 {
1439 char *response;
1440 ct_data_t *byte_response;
1441
1442 byte_response = data;
1443 if ((command.returns[i].data_type != data_byte) &&
1444 (command.returns[i].data_type != data_err) &&
1445 (command.returns[i].data_type != data_ok)) {
1446 if ((byte_response->data_type == data_byte) ||
1447 (byte_response->data_type == data_err) ||
1448 (byte_response->data_type == data_ok))
1449 err(1,
1450 "%s:%zu: %s: expecting type %s, received type %s",
1451 cur_file, line, __func__,
1452 enum_names[command.returns[i].data_type],
1453 enum_names[byte_response->data_type]);
1454
1455 response = byte_response->data_value;
1456 }
1457
1458 switch (command.returns[i].data_type) {
1459 case data_err:
1460 validate_type(data_err, byte_response, 0);
1461 break;
1462
1463 case data_ok:
1464 validate_type(data_ok, byte_response, 0);
1465 break;
1466
1467 case data_null:
1468 validate_return("NULL", response, 0);
1469 break;
1470
1471 case data_nonnull:
1472 validate_return("NULL", response, 1);
1473 break;
1474
1475 case data_string:
1476 case data_number:
1477 validate_return(command.returns[i].data_value,
1478 response, 0);
1479 break;
1480
1481 case data_ref:
1482 validate_reference(i, response);
1483 break;
1484
1485 case data_byte:
1486 validate_byte(&command.returns[i], byte_response, 0);
1487 break;
1488
1489 default:
1490 err(1, "%s:%zu: Malformed statement", cur_file, line);
1491 break;
1492 }
1493 }
1494
1495 /*
1496 * Validate the return against the contents of a variable.
1497 */
1498 static void
1499 validate_reference(int i, void *data)
1500 {
1501 char *response;
1502 ct_data_t *byte_response;
1503 var_t *varp;
1504
1505 varp = &vars[command.returns[i].data_index];
1506
1507 byte_response = data;
1508 if (command.returns[i].data_type != data_byte)
1509 response = data;
1510
1511 if (verbose) {
1512 fprintf(stderr,
1513 "%s: return type of %s, value %s \n", __func__,
1514 enum_names[varp->type],
1515 (varp->type != data_cchar && varp->type != data_wchar)
1516 ? (const char *)varp->value : "-");
1517 }
1518
1519 switch (varp->type) {
1520 case data_string:
1521 case data_number:
1522 validate_return(varp->value, response, 0);
1523 break;
1524
1525 case data_byte:
1526 validate_byte(varp->value, byte_response, 0);
1527 break;
1528
1529 case data_cchar:
1530 validate_cchar(&(varp->cchar), (cchar_t *) response, 0);
1531 break;
1532
1533 case data_wchar:
1534 validate_wchar((wchar_t *) varp->value, (wchar_t *) response, 0);
1535 break;
1536
1537 default:
1538 err(1, "%s:%zu: Invalid return type for reference",
1539 cur_file, line);
1540 break;
1541 }
1542 }
1543
1544 /*
1545 * Validate the return type against the expected type, throw an error
1546 * if they don't match.
1547 */
1548 static void
1549 validate_type(data_enum_t expected, ct_data_t *value, int check)
1550 {
1551 if (((check == 0) && (expected != value->data_type)) ||
1552 ((check == 1) && (expected == value->data_type)))
1553 err(1, "%s:%zu: Validate expected type %s %s %s",
1554 cur_file, line,
1555 enum_names[expected],
1556 (check == 0)? "matching" : "not matching",
1557 enum_names[value->data_type]);
1558
1559 if (verbose) {
1560 fprintf(stderr, "%s:%zu: Validated expected type %s %s %s\n",
1561 cur_file, line,
1562 enum_names[expected],
1563 (check == 0)? "matching" : "not matching",
1564 enum_names[value->data_type]);
1565 }
1566 }
1567
1568 /*
1569 * Validate the return value against the expected value, throw an error
1570 * if they don't match.
1571 */
1572 static void
1573 validate_return(const char *expected, const char *value, int check)
1574 {
1575 if (((check == 0) && strcmp(expected, value) != 0) ||
1576 ((check == 1) && strcmp(expected, value) == 0))
1577 errx(1, "%s:%zu: Validate expected >%s< %s >%s<",
1578 cur_file, line,
1579 expected,
1580 (check == 0)? "matching" : "not matching",
1581 value);
1582 if (verbose) {
1583 fprintf(stderr,
1584 "%s:%zu: Validated expected value >%s< %s >%s<\n",
1585 cur_file, line,
1586 expected,
1587 (check == 0)? "matches" : "does not match",
1588 value);
1589 }
1590 }
1591
1592 /*
1593 * Validate the return value against the expected value, throw an error
1594 * if they don't match expectations.
1595 */
1596 static void
1597 validate_byte(ct_data_t *expected, ct_data_t *value, int check)
1598 {
1599 char *ch;
1600 size_t i;
1601
1602 if (verbose) {
1603 ch = value->data_value;
1604 fprintf(stderr, "checking returned byte stream: ");
1605 for (i = 0; i < value->data_len; i++)
1606 fprintf(stderr, "%s0x%x", (i != 0)? ", " : "", ch[i]);
1607 fprintf(stderr, "\n");
1608
1609 fprintf(stderr, "%s byte stream: ",
1610 (check == 0)? "matches" : "does not match");
1611 ch = (char *) expected->data_value;
1612 for (i = 0; i < expected->data_len; i++)
1613 fprintf(stderr, "%s0x%x", (i != 0)? ", " : "", ch[i]);
1614 fprintf(stderr, "\n");
1615 }
1616
1617 /*
1618 * No chance of a match if lengths differ...
1619 */
1620 if ((check == 0) && (expected->data_len != value->data_len))
1621 errx(1,
1622 "Byte validation failed, length mismatch, "
1623 "expected %zu, received %zu",
1624 expected->data_len, value->data_len);
1625
1626 /*
1627 * If check is 0 then we want to throw an error IFF the byte streams
1628 * do not match, if check is 1 then throw an error if the byte
1629 * streams match.
1630 */
1631 if (((check == 0) && memcmp(expected->data_value, value->data_value,
1632 value->data_len) != 0) ||
1633 ((check == 1) && (expected->data_len == value->data_len) &&
1634 memcmp(expected->data_value, value->data_value,
1635 value->data_len) == 0))
1636 errx(1, "%s:%zu: Validate expected %s byte stream",
1637 cur_file, line,
1638 (check == 0)? "matching" : "not matching");
1639 if (verbose) {
1640 fprintf(stderr, "%s:%zu: Validated expected %s byte stream\n",
1641 cur_file, line,
1642 (check == 0)? "matching" : "not matching");
1643 }
1644 }
1645
1646 /*
1647 * Validate the return cchar against the expected cchar, throw an error
1648 * if they don't match expectations.
1649 */
1650 static void
1651 validate_cchar(cchar_t *expected, cchar_t *value, int check)
1652 {
1653 unsigned j;
1654
1655 /*
1656 * No chance of a match if elements count differ...
1657 */
1658 if ((expected->elements != value->elements)) {
1659 if (check == 0)
1660 errx(1,
1661 "cchar validation failed, elements count mismatch, "
1662 "expected %d, received %d",
1663 expected->elements, value->elements);
1664 else {
1665 if (verbose)
1666 fprintf(stderr,
1667 "%s:%zu: Validated expected %s cchar",
1668 cur_file, line, "not matching");
1669 return;
1670 }
1671 }
1672
1673 /*
1674 * No chance of a match if attributes differ...
1675 */
1676
1677 if ((expected->attributes & WA_ATTRIBUTES) !=
1678 (value->attributes & WA_ATTRIBUTES )) {
1679 if (check == 0)
1680 errx(1,
1681 "cchar validation failed, attributes mismatch, "
1682 "expected 0x%x, received 0x%x",
1683 expected->attributes & WA_ATTRIBUTES,
1684 value->attributes & WA_ATTRIBUTES);
1685 else {
1686 if (verbose)
1687 fprintf(stderr,
1688 "%s:%zu: Validated expected %s cchar\n",
1689 cur_file, line, "not matching");
1690 return;
1691 }
1692 }
1693
1694 /*
1695 * If check is 0 then we want to throw an error IFF the vals
1696 * do not match, if check is 1 then throw an error if the vals
1697 * streams match.
1698 */
1699 for(j = 0; j < expected->elements; j++) {
1700 if (expected->vals[j] != value->vals[j]) {
1701 if (check == 0)
1702 errx(1,
1703 "cchar validation failed, vals mismatch, "
1704 "expected 0x%x, received 0x%x",
1705 expected->vals[j], value->vals[j]);
1706 else {
1707 if (verbose)
1708 fprintf(stderr,
1709 "%s:%zu: Validated expected %s "
1710 "cchar\n",
1711 cur_file, line, "not matching");
1712 return;
1713 }
1714 }
1715 }
1716
1717 if (verbose) {
1718 fprintf(stderr,
1719 "%s:%zu: Validated expected %s cchar\n",
1720 cur_file, line, (check == 0)? "matching" : "not matching");
1721 }
1722 }
1723
1724 /*
1725 * Validate the return wchar string against the expected wchar, throw an
1726 * error if they don't match expectations.
1727 */
1728 static void
1729 validate_wchar(wchar_t *expected, wchar_t *value, int check)
1730 {
1731 unsigned j;
1732
1733 unsigned len1 = 0;
1734 unsigned len2 = 0;
1735 wchar_t *p;
1736
1737 p = expected;
1738 while(*p++ != L'\0')
1739 len1++;
1740
1741 p = value;
1742 while(*p++ != L'\0')
1743 len2++;
1744
1745 /*
1746 * No chance of a match if length differ...
1747 */
1748 if (len1 != len2) {
1749 if (check == 0)
1750 errx(1,
1751 "wchar string validation failed, length mismatch, "
1752 "expected %d, received %d",
1753 len1, len2);
1754 else {
1755 if (verbose)
1756 fprintf(stderr,
1757 "%s:%zu: Validated expected %s wchar\n",
1758 cur_file, line, "not matching");
1759 return;
1760 }
1761 }
1762
1763 /*
1764 * If check is 0 then we want to throw an error IFF the vals
1765 * do not match, if check is 1 then throw an error if the vals
1766 * streams match.
1767 */
1768 for(j = 0; j < len1; j++) {
1769 if (expected[j] != value[j]) {
1770 if (check == 0)
1771 errx(1, "wchar validation failed at index %d, expected %d,"
1772 "received %d", j, expected[j], value[j]);
1773 else {
1774 if (verbose)
1775 fprintf(stderr,
1776 "%s:%zu: Validated expected %s wchar\n",
1777 cur_file, line, "not matching");
1778 return;
1779 }
1780 }
1781 }
1782
1783 if (verbose) {
1784 fprintf(stderr,
1785 "%s:%zu: Validated expected %s wchar\n",
1786 cur_file, line,
1787 (check == 0)? "matching" : "not matching");
1788 }
1789 }
1790
1791 /*
1792 * Validate the variable at i against the expected value, throw an
1793 * error if they don't match, if check is non-zero then the match is
1794 * negated.
1795 */
1796 static void
1797 validate_variable(int ret, data_enum_t type, const void *value, int i,
1798 int check)
1799 {
1800 ct_data_t *retval;
1801 var_t *varptr;
1802
1803 retval = &command.returns[ret];
1804 varptr = &vars[command.returns[ret].data_index];
1805
1806 if (varptr->value == NULL)
1807 err(1, "Variable %s has no value assigned to it", varptr->name);
1808
1809
1810 if (varptr->type != type)
1811 err(1, "Variable %s is not the expected type", varptr->name);
1812
1813 if (type != data_byte) {
1814 if ((((check == 0) && strcmp(value, varptr->value) != 0))
1815 || ((check == 1) && strcmp(value, varptr->value) == 0))
1816 err(1, "%s:%zu: Variable %s contains %s instead of %s"
1817 " value %s",
1818 cur_file, line,
1819 varptr->name, (const char *)varptr->value,
1820 (check == 0)? "expected" : "not matching",
1821 (const char *)value);
1822 if (verbose) {
1823 fprintf(stderr,
1824 "%s:%zu: Variable %s contains %s value %s\n",
1825 cur_file, line,
1826 varptr->name,
1827 (check == 0)? "expected" : "not matching",
1828 (const char *)varptr->value);
1829 }
1830 } else {
1831 if ((check == 0) && (retval->data_len != varptr->len))
1832 err(1, "Byte validation failed, length mismatch");
1833
1834 /*
1835 * If check is 0 then we want to throw an error IFF
1836 * the byte streams do not match, if check is 1 then
1837 * throw an error if the byte streams match.
1838 */
1839 if (((check == 0) && memcmp(retval->data_value, varptr->value,
1840 varptr->len) != 0) ||
1841 ((check == 1) && (retval->data_len == varptr->len) &&
1842 memcmp(retval->data_value, varptr->value,
1843 varptr->len) == 0))
1844 err(1, "%s:%zu: Validate expected %s byte stream",
1845 cur_file, line,
1846 (check == 0)? "matching" : "not matching");
1847 if (verbose) {
1848 fprintf(stderr,
1849 "%s:%zu: Validated expected %s byte stream\n",
1850 cur_file, line,
1851 (check == 0)? "matching" : "not matching");
1852 }
1853 }
1854 }
1855
1856 /*
1857 * Write a string to the command pipe - we feed the number of bytes coming
1858 * down first to allow storage allocation and then follow up with the data.
1859 * If cmd is NULL then feed a -1 down the pipe to say the end of the args.
1860 */
1861 static void
1862 write_cmd_pipe(char *cmd)
1863 {
1864 args_t arg;
1865 size_t len;
1866
1867 if (cmd == NULL)
1868 len = 0;
1869 else
1870 len = strlen(cmd);
1871
1872 arg.arg_type = data_static;
1873 arg.arg_len = len;
1874 arg.arg_string = cmd;
1875 write_cmd_pipe_args(arg.arg_type, &arg);
1876
1877 }
1878
1879 static void
1880 write_cmd_pipe_args(data_enum_t type, void *data)
1881 {
1882 var_t *var_data;
1883 args_t *arg_data;
1884 int len, send_type;
1885 void *cmd;
1886
1887 arg_data = data;
1888 switch (type) {
1889 case data_var:
1890 var_data = data;
1891 len = var_data->len;
1892 cmd = var_data->value;
1893
1894 switch (var_data->type) {
1895 case data_byte:
1896 send_type = data_byte;
1897 break;
1898
1899 case data_cchar:
1900 send_type = data_cchar;
1901 cmd = (void *) &var_data->cchar;
1902 len = sizeof(cchar_t);
1903 break;
1904
1905 case data_wchar:
1906 send_type = data_wchar;
1907 break;
1908
1909 default:
1910 send_type = data_string;
1911 break;
1912 }
1913 break;
1914
1915 case data_null:
1916 send_type = data_null;
1917 len = 0;
1918 break;
1919
1920 default:
1921 if ((arg_data->arg_len == 0) && (arg_data->arg_string == NULL))
1922 len = -1;
1923 else
1924 len = arg_data->arg_len;
1925 cmd = arg_data->arg_string;
1926 if (type == data_byte)
1927 send_type = data_byte;
1928 else
1929 send_type = data_string;
1930 }
1931
1932 if (verbose) {
1933 fprintf(stderr, "Writing type %s to command pipe\n",
1934 enum_names[send_type]);
1935 }
1936
1937 if (write(cmdpipe[WRITE_PIPE], &send_type, sizeof(int)) < 0)
1938 err(1, "command pipe write for type failed");
1939
1940 if (verbose) {
1941 if (send_type == data_cchar)
1942 fprintf(stderr,
1943 "Writing cchar to command pipe\n");
1944 else if (send_type == data_wchar)
1945 fprintf(stderr,
1946 "Writing wchar(%d sized) to command pipe\n", len);
1947 else
1948 fprintf(stderr,
1949 "Writing length %d to command pipe\n", len);
1950 }
1951
1952 if (write(cmdpipe[WRITE_PIPE], &len, sizeof(int)) < 0)
1953 err(1, "command pipe write for length failed");
1954
1955 if (len > 0) {
1956 if (verbose) {
1957 fprintf(stderr, "Writing data >%s< to command pipe\n",
1958 (const char *)cmd);
1959 }
1960 if (write(cmdpipe[WRITE_PIPE], cmd, len) < 0)
1961 err(1, "command pipe write of data failed");
1962 }
1963 }
1964
1965 /*
1966 * Read a response from the command pipe, first we will receive the
1967 * length of the response then the actual data.
1968 */
1969 static void
1970 read_cmd_pipe(ct_data_t *response)
1971 {
1972 int len, type;
1973 struct pollfd rfd[2];
1974 char *str;
1975
1976 /*
1977 * Check if there is data to read - just in case slave has died, we
1978 * don't want to block on the read and just hang. We also check
1979 * output from the slave because the slave may be blocked waiting
1980 * for a flush on its stdout.
1981 */
1982 rfd[0].fd = slvpipe[READ_PIPE];
1983 rfd[0].events = POLLIN;
1984 rfd[1].fd = master;
1985 rfd[1].events = POLLIN;
1986
1987 do {
1988 if (poll(rfd, 2, 4000) == 0)
1989 errx(2, "%s:%zu: Command pipe read timeout",
1990 cur_file, line);
1991
1992 if ((rfd[1].revents & POLLIN) == POLLIN) {
1993 if (verbose) {
1994 fprintf(stderr,
1995 "draining output from slave\n");
1996 }
1997 save_slave_output(false);
1998 }
1999 }
2000 while((rfd[1].revents & POLLIN) == POLLIN);
2001
2002 if (read(slvpipe[READ_PIPE], &type, sizeof(int)) < 0)
2003 err(1, "command pipe read for type failed");
2004 response->data_type = type;
2005
2006 if ((type != data_ok) && (type != data_err) && (type != data_count)) {
2007 if (read(slvpipe[READ_PIPE], &len, sizeof(int)) < 0)
2008 err(1, "command pipe read for length failed");
2009 response->data_len = len;
2010
2011 if (verbose) {
2012 fprintf(stderr,
2013 "Reading %d bytes from command pipe\n", len);
2014 }
2015
2016 if ((response->data_value = malloc(len + 1)) == NULL)
2017 err(1, "Failed to alloc memory for cmd pipe read");
2018
2019 if (read(slvpipe[READ_PIPE], response->data_value, len) < 0)
2020 err(1, "command pipe read of data failed");
2021
2022 if (response->data_type != data_byte) {
2023 str = response->data_value;
2024 str[len] = '\0';
2025
2026 if (verbose) {
2027 fprintf(stderr, "Read data >%s< from pipe\n",
2028 (const char *)response->data_value);
2029 }
2030 }
2031 } else {
2032 response->data_value = NULL;
2033 if (type == data_count) {
2034 if (read(slvpipe[READ_PIPE], &len, sizeof(int)) < 0)
2035 err(1, "command pipe read for number of "
2036 "returns failed");
2037 response->data_len = len;
2038 }
2039
2040 if (verbose) {
2041 fprintf(stderr, "Read type %s from pipe\n",
2042 enum_names[type]);
2043 }
2044 }
2045 }
2046
2047 /*
2048 * Check for writes from the slave on the pty, save the output into a
2049 * buffer for later checking if discard is false.
2050 */
2051 #define MAX_DRAIN 256
2052
2053 static void
2054 save_slave_output(bool discard)
2055 {
2056 char *new_data, drain[MAX_DRAIN];
2057 size_t to_allocate;
2058 ssize_t result;
2059 size_t i;
2060
2061 result = 0;
2062 for (;;) {
2063 if (result == -1)
2064 err(2, "poll of slave pty failed");
2065 result = MAX_DRAIN;
2066 if ((result = read(master, drain, result)) < 0) {
2067 if (errno == EAGAIN)
2068 break;
2069 else
2070 err(2, "draining slave pty failed");
2071 }
2072 if (result == 0)
2073 abort();
2074
2075 if (!discard) {
2076 if ((size_t)result >
2077 (saved_output.allocated - saved_output.count)) {
2078 to_allocate = 1024 * ((result / 1024) + 1);
2079
2080 if ((new_data = realloc(saved_output.data,
2081 saved_output.allocated + to_allocate))
2082 == NULL)
2083 err(2, "Realloc of saved_output failed");
2084 saved_output.data = new_data;
2085 saved_output.allocated += to_allocate;
2086 }
2087
2088 if (verbose) {
2089 fprintf(stderr,
2090 "count = %zu, allocated = %zu\n",
2091 saved_output.count, saved_output.allocated);
2092 for (i = 0; i < (size_t)result; i++) {
2093 fprintf(stderr, "Saving slave output "
2094 "at %zu: 0x%x (%c)\n",
2095 saved_output.count + i, drain[i],
2096 (drain[i] >= ' ')? drain[i] : '-');
2097 }
2098 }
2099
2100 memcpy(&saved_output.data[saved_output.count], drain,
2101 result);
2102 saved_output.count += result;
2103
2104 if (verbose) {
2105 fprintf(stderr,
2106 "count = %zu, allocated = %zu\n",
2107 saved_output.count, saved_output.allocated);
2108 }
2109 } else {
2110 if (verbose) {
2111 for (i = 0; i < (size_t)result; i++) {
2112 fprintf(stderr, "Discarding slave "
2113 "output 0x%x (%c)\n",
2114 drain[i],
2115 (drain[i] >= ' ')? drain[i] : '-');
2116 }
2117 }
2118 }
2119 }
2120 }
2121
2122 static void
2123 yyerror(const char *msg)
2124 {
2125 errx(1, "%s:%zu: %s", cur_file, line, msg);
2126 }
2127