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