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