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