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