1/* exp_clib.c - top-level functions in the expect C library, libexpect.a 2 3Written by: Don Libes, libes@cme.nist.gov, NIST, 12/3/90 4 5Design and implementation of this program was paid for by U.S. tax 6dollars. Therefore it is public domain. However, the author and NIST 7would appreciate credit if this program or parts of it are used. 8*/ 9 10#include "expect_cf.h" 11#include <stdio.h> 12#include <setjmp.h> 13#ifdef HAVE_INTTYPES_H 14# include <inttypes.h> 15#endif 16#include <sys/types.h> 17#include <sys/ioctl.h> 18 19#ifdef TIME_WITH_SYS_TIME 20# include <sys/time.h> 21# include <time.h> 22#else 23# if HAVE_SYS_TIME_H 24# include <sys/time.h> 25# else 26# include <time.h> 27# endif 28#endif 29 30#ifdef CRAY 31# ifndef TCSETCTTY 32# if defined(HAVE_TERMIOS) 33# include <termios.h> 34# else 35# include <termio.h> 36# endif 37# endif 38#endif 39 40#ifdef HAVE_SYS_FCNTL_H 41# include <sys/fcntl.h> 42#else 43# include <fcntl.h> 44#endif 45 46#ifdef HAVE_STRREDIR_H 47#include <sys/strredir.h> 48# ifdef SRIOCSREDIR 49# undef TIOCCONS 50# endif 51#endif 52 53#include <signal.h> 54/*#include <memory.h> - deprecated - ANSI C moves them into string.h */ 55#include "string.h" 56 57#include <errno.h> 58 59#ifdef NO_STDLIB_H 60 61/* 62 * Tcl's compat/stdlib.h 63 */ 64 65/* 66 * stdlib.h -- 67 * 68 * Declares facilities exported by the "stdlib" portion of 69 * the C library. This file isn't complete in the ANSI-C 70 * sense; it only declares things that are needed by Tcl. 71 * This file is needed even on many systems with their own 72 * stdlib.h (e.g. SunOS) because not all stdlib.h files 73 * declare all the procedures needed here (such as strtod). 74 * 75 * Copyright (c) 1991 The Regents of the University of California. 76 * Copyright (c) 1994 Sun Microsystems, Inc. 77 * 78 * See the file "license.terms" for information on usage and redistribution 79 * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 80 * 81 * RCS: @(#) $Id: exp_clib.c,v 5.39 2010/08/31 22:20:27 andreas_kupries Exp $ 82 */ 83 84#ifndef _STDLIB 85#define _STDLIB 86 87extern void abort _ANSI_ARGS_((void)); 88extern double atof _ANSI_ARGS_((CONST char *string)); 89extern int atoi _ANSI_ARGS_((CONST char *string)); 90extern long atol _ANSI_ARGS_((CONST char *string)); 91extern char * calloc _ANSI_ARGS_((unsigned int numElements, 92 unsigned int size)); 93extern void exit _ANSI_ARGS_((int status)); 94extern int free _ANSI_ARGS_((char *blockPtr)); 95extern char * getenv _ANSI_ARGS_((CONST char *name)); 96extern char * malloc _ANSI_ARGS_((unsigned int numBytes)); 97extern void qsort _ANSI_ARGS_((VOID *base, int n, int size, 98 int (*compar)(CONST VOID *element1, CONST VOID 99 *element2))); 100extern char * realloc _ANSI_ARGS_((char *ptr, unsigned int numBytes)); 101extern double strtod _ANSI_ARGS_((CONST char *string, char **endPtr)); 102extern long strtol _ANSI_ARGS_((CONST char *string, char **endPtr, 103 int base)); 104extern unsigned long strtoul _ANSI_ARGS_((CONST char *string, 105 char **endPtr, int base)); 106 107#endif /* _STDLIB */ 108 109/* 110 * end of Tcl's compat/stdlib.h 111 */ 112 113#else 114#include <stdlib.h> /* for malloc */ 115#endif 116 117#include <tcl.h> 118#include "expect.h" 119#define TclRegError exp_TclRegError 120 121/* 122 * regexp code - from tcl8.0.4/generic/regexp.c 123 */ 124 125/* 126 * TclRegComp and TclRegExec -- TclRegSub is elsewhere 127 * 128 * Copyright (c) 1986 by University of Toronto. 129 * Written by Henry Spencer. Not derived from licensed software. 130 * 131 * Permission is granted to anyone to use this software for any 132 * purpose on any computer system, and to redistribute it freely, 133 * subject to the following restrictions: 134 * 135 * 1. The author is not responsible for the consequences of use of 136 * this software, no matter how awful, even if they arise 137 * from defects in it. 138 * 139 * 2. The origin of this software must not be misrepresented, either 140 * by explicit claim or by omission. 141 * 142 * 3. Altered versions must be plainly marked as such, and must not 143 * be misrepresented as being the original software. 144 * 145 * Beware that some of this code is subtly aware of the way operator 146 * precedence is structured in regular expressions. Serious changes in 147 * regular-expression syntax might require a total rethink. 148 * 149 * *** NOTE: this code has been altered slightly for use in Tcl: *** 150 * *** 1. Use ckalloc and ckfree instead of malloc and free. *** 151 * *** 2. Add extra argument to regexp to specify the real *** 152 * *** start of the string separately from the start of the *** 153 * *** current search. This is needed to search for multiple *** 154 * *** matches within a string. *** 155 * *** 3. Names have been changed, e.g. from regcomp to *** 156 * *** TclRegComp, to avoid clashes with other *** 157 * *** regexp implementations used by applications. *** 158 * *** 4. Added errMsg declaration and TclRegError procedure *** 159 * *** 5. Various lint-like things, such as casting arguments *** 160 * *** in procedure calls. *** 161 * 162 * *** NOTE: This code has been altered for use in MT-Sturdy Tcl *** 163 * *** 1. All use of static variables has been changed to access *** 164 * *** fields of a structure. *** 165 * *** 2. This in addition to changes to TclRegError makes the *** 166 * *** code multi-thread safe. *** 167 * 168 * RCS: @(#) $Id: exp_clib.c,v 5.39 2010/08/31 22:20:27 andreas_kupries Exp $ 169 */ 170 171#if 0 172#include "tclInt.h" 173#include "tclPort.h" 174#endif 175 176/* 177 * The variable below is set to NULL before invoking regexp functions 178 * and checked after those functions. If an error occurred then TclRegError 179 * will set the variable to point to a (static) error message. This 180 * mechanism unfortunately does not support multi-threading, but the 181 * procedures TclRegError and TclGetRegError can be modified to use 182 * thread-specific storage for the variable and thereby make the code 183 * thread-safe. 184 */ 185 186static char *errMsg = NULL; 187 188/* 189 * The "internal use only" fields in regexp.h are present to pass info from 190 * compile to execute that permits the execute phase to run lots faster on 191 * simple cases. They are: 192 * 193 * regstart char that must begin a match; '\0' if none obvious 194 * reganch is the match anchored (at beginning-of-line only)? 195 * regmust string (pointer into program) that match must include, or NULL 196 * regmlen length of regmust string 197 * 198 * Regstart and reganch permit very fast decisions on suitable starting points 199 * for a match, cutting down the work a lot. Regmust permits fast rejection 200 * of lines that cannot possibly match. The regmust tests are costly enough 201 * that TclRegComp() supplies a regmust only if the r.e. contains something 202 * potentially expensive (at present, the only such thing detected is * or + 203 * at the start of the r.e., which can involve a lot of backup). Regmlen is 204 * supplied because the test in TclRegExec() needs it and TclRegComp() is 205 * computing it anyway. 206 */ 207 208/* 209 * Structure for regexp "program". This is essentially a linear encoding 210 * of a nondeterministic finite-state machine (aka syntax charts or 211 * "railroad normal form" in parsing technology). Each node is an opcode 212 * plus a "next" pointer, possibly plus an operand. "Next" pointers of 213 * all nodes except BRANCH implement concatenation; a "next" pointer with 214 * a BRANCH on both ends of it is connecting two alternatives. (Here we 215 * have one of the subtle syntax dependencies: an individual BRANCH (as 216 * opposed to a collection of them) is never concatenated with anything 217 * because of operator precedence.) The operand of some types of node is 218 * a literal string; for others, it is a node leading into a sub-FSM. In 219 * particular, the operand of a BRANCH node is the first node of the branch. 220 * (NB this is *not* a tree structure: the tail of the branch connects 221 * to the thing following the set of BRANCHes.) The opcodes are: 222 */ 223 224/* definition number opnd? meaning */ 225#define END 0 /* no End of program. */ 226#define BOL 1 /* no Match "" at beginning of line. */ 227#define EOL 2 /* no Match "" at end of line. */ 228#define ANY 3 /* no Match any one character. */ 229#define ANYOF 4 /* str Match any character in this string. */ 230#define ANYBUT 5 /* str Match any character not in this string. */ 231#define BRANCH 6 /* node Match this alternative, or the next... */ 232#define BACK 7 /* no Match "", "next" ptr points backward. */ 233#define EXACTLY 8 /* str Match this string. */ 234#define NOTHING 9 /* no Match empty string. */ 235#define STAR 10 /* node Match this (simple) thing 0 or more times. */ 236#define PLUS 11 /* node Match this (simple) thing 1 or more times. */ 237#define OPEN 20 /* no Mark this point in input as start of #n. */ 238 /* OPEN+1 is number 1, etc. */ 239#define CLOSE (OPEN+NSUBEXP) /* no Analogous to OPEN. */ 240 241/* 242 * Opcode notes: 243 * 244 * BRANCH The set of branches constituting a single choice are hooked 245 * together with their "next" pointers, since precedence prevents 246 * anything being concatenated to any individual branch. The 247 * "next" pointer of the last BRANCH in a choice points to the 248 * thing following the whole choice. This is also where the 249 * final "next" pointer of each individual branch points; each 250 * branch starts with the operand node of a BRANCH node. 251 * 252 * BACK Normal "next" pointers all implicitly point forward; BACK 253 * exists to make loop structures possible. 254 * 255 * STAR,PLUS '?', and complex '*' and '+', are implemented as circular 256 * BRANCH structures using BACK. Simple cases (one character 257 * per match) are implemented with STAR and PLUS for speed 258 * and to minimize recursive plunges. 259 * 260 * OPEN,CLOSE ...are numbered at compile time. 261 */ 262 263/* 264 * A node is one char of opcode followed by two chars of "next" pointer. 265 * "Next" pointers are stored as two 8-bit pieces, high order first. The 266 * value is a positive offset from the opcode of the node containing it. 267 * An operand, if any, simply follows the node. (Note that much of the 268 * code generation knows about this implicit relationship.) 269 * 270 * Using two bytes for the "next" pointer is vast overkill for most things, 271 * but allows patterns to get big without disasters. 272 */ 273#define OP(p) (*(p)) 274#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377)) 275#define OPERAND(p) ((p) + 3) 276 277/* 278 * See regmagic.h for one further detail of program structure. 279 */ 280 281 282/* 283 * Utility definitions. 284 */ 285#ifndef CHARBITS 286#define UCHARAT(p) ((int)*(unsigned char *)(p)) 287#else 288#define UCHARAT(p) ((int)*(p)&CHARBITS) 289#endif 290 291#define FAIL(m) { TclRegError(m); return(NULL); } 292#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?') 293#define META "^$.[()|?+*\\" 294 295/* 296 * Flags to be passed up and down. 297 */ 298#define HASWIDTH 01 /* Known never to match null string. */ 299#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */ 300#define SPSTART 04 /* Starts with * or +. */ 301#define WORST 0 /* Worst case. */ 302 303/* 304 * Global work variables for TclRegComp(). 305 */ 306struct regcomp_state { 307 char *regparse; /* Input-scan pointer. */ 308 int regnpar; /* () count. */ 309 char *regcode; /* Code-emit pointer; ®dummy = don't. */ 310 long regsize; /* Code size. */ 311}; 312 313static char regdummy; 314 315/* 316 * The first byte of the regexp internal "program" is actually this magic 317 * number; the start node begins in the second byte. 318 */ 319#define MAGIC 0234 320 321 322/* 323 * Forward declarations for TclRegComp()'s friends. 324 */ 325 326static char * reg _ANSI_ARGS_((int paren, int *flagp, 327 struct regcomp_state *rcstate)); 328static char * regatom _ANSI_ARGS_((int *flagp, 329 struct regcomp_state *rcstate)); 330static char * regbranch _ANSI_ARGS_((int *flagp, 331 struct regcomp_state *rcstate)); 332static void regc _ANSI_ARGS_((int b, 333 struct regcomp_state *rcstate)); 334static void reginsert _ANSI_ARGS_((int op, char *opnd, 335 struct regcomp_state *rcstate)); 336static char * regnext _ANSI_ARGS_((char *p)); 337static char * regnode _ANSI_ARGS_((int op, 338 struct regcomp_state *rcstate)); 339static void regoptail _ANSI_ARGS_((char *p, char *val)); 340static char * regpiece _ANSI_ARGS_((int *flagp, 341 struct regcomp_state *rcstate)); 342static void regtail _ANSI_ARGS_((char *p, char *val)); 343 344#ifdef STRCSPN 345static int strcspn _ANSI_ARGS_((char *s1, char *s2)); 346#endif 347 348/* 349 - TclRegComp - compile a regular expression into internal code 350 * 351 * We can't allocate space until we know how big the compiled form will be, 352 * but we can't compile it (and thus know how big it is) until we've got a 353 * place to put the code. So we cheat: we compile it twice, once with code 354 * generation turned off and size counting turned on, and once "for real". 355 * This also means that we don't allocate space until we are sure that the 356 * thing really will compile successfully, and we never have to move the 357 * code and thus invalidate pointers into it. (Note that it has to be in 358 * one piece because free() must be able to free it all.) 359 * 360 * Beware that the optimization-preparation code in here knows about some 361 * of the structure of the compiled regexp. 362 */ 363regexp * 364TclRegComp(exp) 365char *exp; 366{ 367 register regexp *r; 368 register char *scan; 369 register char *longest; 370 register int len; 371 int flags; 372 struct regcomp_state state; 373 struct regcomp_state *rcstate= &state; 374 375 if (exp == NULL) 376 FAIL("NULL argument"); 377 378 /* First pass: determine size, legality. */ 379 rcstate->regparse = exp; 380 rcstate->regnpar = 1; 381 rcstate->regsize = 0L; 382 rcstate->regcode = ®dummy; 383 regc(MAGIC, rcstate); 384 if (reg(0, &flags, rcstate) == NULL) 385 return(NULL); 386 387 /* Small enough for pointer-storage convention? */ 388 if (rcstate->regsize >= 32767L) /* Probably could be 65535L. */ 389 FAIL("regexp too big"); 390 391 /* Allocate space. */ 392 r = (regexp *)ckalloc(sizeof(regexp) + (unsigned)rcstate->regsize); 393 if (r == NULL) 394 FAIL("out of space"); 395 396 /* Second pass: emit code. */ 397 rcstate->regparse = exp; 398 rcstate->regnpar = 1; 399 rcstate->regcode = r->program; 400 regc(MAGIC, rcstate); 401 if (reg(0, &flags, rcstate) == NULL) { 402 ckfree ((char*) r); 403 return(NULL); 404 } 405 406 /* Dig out information for optimizations. */ 407 r->regstart = '\0'; /* Worst-case defaults. */ 408 r->reganch = 0; 409 r->regmust = NULL; 410 r->regmlen = 0; 411 scan = r->program+1; /* First BRANCH. */ 412 if (OP(regnext(scan)) == END) { /* Only one top-level choice. */ 413 scan = OPERAND(scan); 414 415 /* Starting-point info. */ 416 if (OP(scan) == EXACTLY) 417 r->regstart = *OPERAND(scan); 418 else if (OP(scan) == BOL) 419 r->reganch++; 420 421 /* 422 * If there's something expensive in the r.e., find the 423 * longest literal string that must appear and make it the 424 * regmust. Resolve ties in favor of later strings, since 425 * the regstart check works with the beginning of the r.e. 426 * and avoiding duplication strengthens checking. Not a 427 * strong reason, but sufficient in the absence of others. 428 */ 429 if (flags&SPSTART) { 430 longest = NULL; 431 len = 0; 432 for (; scan != NULL; scan = regnext(scan)) 433 if (OP(scan) == EXACTLY && ((int) strlen(OPERAND(scan))) >= len) { 434 longest = OPERAND(scan); 435 len = strlen(OPERAND(scan)); 436 } 437 r->regmust = longest; 438 r->regmlen = len; 439 } 440 } 441 442 return(r); 443} 444 445/* 446 - reg - regular expression, i.e. main body or parenthesized thing 447 * 448 * Caller must absorb opening parenthesis. 449 * 450 * Combining parenthesis handling with the base level of regular expression 451 * is a trifle forced, but the need to tie the tails of the branches to what 452 * follows makes it hard to avoid. 453 */ 454static char * 455reg(paren, flagp, rcstate) 456int paren; /* Parenthesized? */ 457int *flagp; 458struct regcomp_state *rcstate; 459{ 460 register char *ret; 461 register char *br; 462 register char *ender; 463 register int parno = 0; 464 int flags; 465 466 *flagp = HASWIDTH; /* Tentatively. */ 467 468 /* Make an OPEN node, if parenthesized. */ 469 if (paren) { 470 if (rcstate->regnpar >= NSUBEXP) 471 FAIL("too many ()"); 472 parno = rcstate->regnpar; 473 rcstate->regnpar++; 474 ret = regnode(OPEN+parno,rcstate); 475 } else 476 ret = NULL; 477 478 /* Pick up the branches, linking them together. */ 479 br = regbranch(&flags,rcstate); 480 if (br == NULL) 481 return(NULL); 482 if (ret != NULL) 483 regtail(ret, br); /* OPEN -> first. */ 484 else 485 ret = br; 486 if (!(flags&HASWIDTH)) 487 *flagp &= ~HASWIDTH; 488 *flagp |= flags&SPSTART; 489 while (*rcstate->regparse == '|') { 490 rcstate->regparse++; 491 br = regbranch(&flags,rcstate); 492 if (br == NULL) 493 return(NULL); 494 regtail(ret, br); /* BRANCH -> BRANCH. */ 495 if (!(flags&HASWIDTH)) 496 *flagp &= ~HASWIDTH; 497 *flagp |= flags&SPSTART; 498 } 499 500 /* Make a closing node, and hook it on the end. */ 501 ender = regnode((paren) ? CLOSE+parno : END,rcstate); 502 regtail(ret, ender); 503 504 /* Hook the tails of the branches to the closing node. */ 505 for (br = ret; br != NULL; br = regnext(br)) 506 regoptail(br, ender); 507 508 /* Check for proper termination. */ 509 if (paren && *rcstate->regparse++ != ')') { 510 FAIL("unmatched ()"); 511 } else if (!paren && *rcstate->regparse != '\0') { 512 if (*rcstate->regparse == ')') { 513 FAIL("unmatched ()"); 514 } else 515 FAIL("junk on end"); /* "Can't happen". */ 516 /* NOTREACHED */ 517 } 518 519 return(ret); 520} 521 522/* 523 - regbranch - one alternative of an | operator 524 * 525 * Implements the concatenation operator. 526 */ 527static char * 528regbranch(flagp, rcstate) 529int *flagp; 530struct regcomp_state *rcstate; 531{ 532 register char *ret; 533 register char *chain; 534 register char *latest; 535 int flags; 536 537 *flagp = WORST; /* Tentatively. */ 538 539 ret = regnode(BRANCH,rcstate); 540 chain = NULL; 541 while (*rcstate->regparse != '\0' && *rcstate->regparse != '|' && 542 *rcstate->regparse != ')') { 543 latest = regpiece(&flags, rcstate); 544 if (latest == NULL) 545 return(NULL); 546 *flagp |= flags&HASWIDTH; 547 if (chain == NULL) /* First piece. */ 548 *flagp |= flags&SPSTART; 549 else 550 regtail(chain, latest); 551 chain = latest; 552 } 553 if (chain == NULL) /* Loop ran zero times. */ 554 (void) regnode(NOTHING,rcstate); 555 556 return(ret); 557} 558 559/* 560 - regpiece - something followed by possible [*+?] 561 * 562 * Note that the branching code sequences used for ? and the general cases 563 * of * and + are somewhat optimized: they use the same NOTHING node as 564 * both the endmarker for their branch list and the body of the last branch. 565 * It might seem that this node could be dispensed with entirely, but the 566 * endmarker role is not redundant. 567 */ 568static char * 569regpiece(flagp, rcstate) 570int *flagp; 571struct regcomp_state *rcstate; 572{ 573 register char *ret; 574 register char op; 575 register char *next; 576 int flags; 577 578 ret = regatom(&flags,rcstate); 579 if (ret == NULL) 580 return(NULL); 581 582 op = *rcstate->regparse; 583 if (!ISMULT(op)) { 584 *flagp = flags; 585 return(ret); 586 } 587 588 if (!(flags&HASWIDTH) && op != '?') 589 FAIL("*+ operand could be empty"); 590 *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH); 591 592 if (op == '*' && (flags&SIMPLE)) 593 reginsert(STAR, ret, rcstate); 594 else if (op == '*') { 595 /* Emit x* as (x&|), where & means "self". */ 596 reginsert(BRANCH, ret, rcstate); /* Either x */ 597 regoptail(ret, regnode(BACK,rcstate)); /* and loop */ 598 regoptail(ret, ret); /* back */ 599 regtail(ret, regnode(BRANCH,rcstate)); /* or */ 600 regtail(ret, regnode(NOTHING,rcstate)); /* null. */ 601 } else if (op == '+' && (flags&SIMPLE)) 602 reginsert(PLUS, ret, rcstate); 603 else if (op == '+') { 604 /* Emit x+ as x(&|), where & means "self". */ 605 next = regnode(BRANCH,rcstate); /* Either */ 606 regtail(ret, next); 607 regtail(regnode(BACK,rcstate), ret); /* loop back */ 608 regtail(next, regnode(BRANCH,rcstate)); /* or */ 609 regtail(ret, regnode(NOTHING,rcstate)); /* null. */ 610 } else if (op == '?') { 611 /* Emit x? as (x|) */ 612 reginsert(BRANCH, ret, rcstate); /* Either x */ 613 regtail(ret, regnode(BRANCH,rcstate)); /* or */ 614 next = regnode(NOTHING,rcstate); /* null. */ 615 regtail(ret, next); 616 regoptail(ret, next); 617 } 618 rcstate->regparse++; 619 if (ISMULT(*rcstate->regparse)) 620 FAIL("nested *?+"); 621 622 return(ret); 623} 624 625/* 626 - regatom - the lowest level 627 * 628 * Optimization: gobbles an entire sequence of ordinary characters so that 629 * it can turn them into a single node, which is smaller to store and 630 * faster to run. Backslashed characters are exceptions, each becoming a 631 * separate node; the code is simpler that way and it's not worth fixing. 632 */ 633static char * 634regatom(flagp, rcstate) 635int *flagp; 636struct regcomp_state *rcstate; 637{ 638 register char *ret; 639 int flags; 640 641 *flagp = WORST; /* Tentatively. */ 642 643 switch (*rcstate->regparse++) { 644 case '^': 645 ret = regnode(BOL,rcstate); 646 break; 647 case '$': 648 ret = regnode(EOL,rcstate); 649 break; 650 case '.': 651 ret = regnode(ANY,rcstate); 652 *flagp |= HASWIDTH|SIMPLE; 653 break; 654 case '[': { 655 register int clss; 656 register int classend; 657 658 if (*rcstate->regparse == '^') { /* Complement of range. */ 659 ret = regnode(ANYBUT,rcstate); 660 rcstate->regparse++; 661 } else 662 ret = regnode(ANYOF,rcstate); 663 if (*rcstate->regparse == ']' || *rcstate->regparse == '-') 664 regc(*rcstate->regparse++,rcstate); 665 while (*rcstate->regparse != '\0' && *rcstate->regparse != ']') { 666 if (*rcstate->regparse == '-') { 667 rcstate->regparse++; 668 if (*rcstate->regparse == ']' || *rcstate->regparse == '\0') 669 regc('-',rcstate); 670 else { 671 clss = UCHARAT(rcstate->regparse-2)+1; 672 classend = UCHARAT(rcstate->regparse); 673 if (clss > classend+1) 674 FAIL("invalid [] range"); 675 for (; clss <= classend; clss++) 676 regc((char)clss,rcstate); 677 rcstate->regparse++; 678 } 679 } else 680 regc(*rcstate->regparse++,rcstate); 681 } 682 regc('\0',rcstate); 683 if (*rcstate->regparse != ']') 684 FAIL("unmatched []"); 685 rcstate->regparse++; 686 *flagp |= HASWIDTH|SIMPLE; 687 } 688 break; 689 case '(': 690 ret = reg(1, &flags, rcstate); 691 if (ret == NULL) 692 return(NULL); 693 *flagp |= flags&(HASWIDTH|SPSTART); 694 break; 695 case '\0': 696 case '|': 697 case ')': 698 FAIL("internal urp"); /* Supposed to be caught earlier. */ 699 /* NOTREACHED */ 700 case '?': 701 case '+': 702 case '*': 703 FAIL("?+* follows nothing"); 704 /* NOTREACHED */ 705 case '\\': 706 if (*rcstate->regparse == '\0') 707 FAIL("trailing \\"); 708 ret = regnode(EXACTLY,rcstate); 709 regc(*rcstate->regparse++,rcstate); 710 regc('\0',rcstate); 711 *flagp |= HASWIDTH|SIMPLE; 712 break; 713 default: { 714 register int len; 715 register char ender; 716 717 rcstate->regparse--; 718 len = strcspn(rcstate->regparse, META); 719 if (len <= 0) 720 FAIL("internal disaster"); 721 ender = *(rcstate->regparse+len); 722 if (len > 1 && ISMULT(ender)) 723 len--; /* Back off clear of ?+* operand. */ 724 *flagp |= HASWIDTH; 725 if (len == 1) 726 *flagp |= SIMPLE; 727 ret = regnode(EXACTLY,rcstate); 728 while (len > 0) { 729 regc(*rcstate->regparse++,rcstate); 730 len--; 731 } 732 regc('\0',rcstate); 733 } 734 break; 735 } 736 737 return(ret); 738} 739 740/* 741 - regnode - emit a node 742 */ 743static char * /* Location. */ 744regnode(op, rcstate) 745int op; 746struct regcomp_state *rcstate; 747{ 748 register char *ret; 749 register char *ptr; 750 751 ret = rcstate->regcode; 752 if (ret == ®dummy) { 753 rcstate->regsize += 3; 754 return(ret); 755 } 756 757 ptr = ret; 758 *ptr++ = (char)op; 759 *ptr++ = '\0'; /* Null "next" pointer. */ 760 *ptr++ = '\0'; 761 rcstate->regcode = ptr; 762 763 return(ret); 764} 765 766/* 767 - regc - emit (if appropriate) a byte of code 768 */ 769static void 770regc(b, rcstate) 771int b; 772struct regcomp_state *rcstate; 773{ 774 if (rcstate->regcode != ®dummy) 775 *rcstate->regcode++ = (char)b; 776 else 777 rcstate->regsize++; 778} 779 780/* 781 - reginsert - insert an operator in front of already-emitted operand 782 * 783 * Means relocating the operand. 784 */ 785static void 786reginsert(op, opnd, rcstate) 787int op; 788char *opnd; 789struct regcomp_state *rcstate; 790{ 791 register char *src; 792 register char *dst; 793 register char *place; 794 795 if (rcstate->regcode == ®dummy) { 796 rcstate->regsize += 3; 797 return; 798 } 799 800 src = rcstate->regcode; 801 rcstate->regcode += 3; 802 dst = rcstate->regcode; 803 while (src > opnd) 804 *--dst = *--src; 805 806 place = opnd; /* Op node, where operand used to be. */ 807 *place++ = (char)op; 808 *place++ = '\0'; 809 *place = '\0'; 810} 811 812/* 813 - regtail - set the next-pointer at the end of a node chain 814 */ 815static void 816regtail(p, val) 817char *p; 818char *val; 819{ 820 register char *scan; 821 register char *temp; 822 register int offset; 823 824 if (p == ®dummy) 825 return; 826 827 /* Find last node. */ 828 scan = p; 829 for (;;) { 830 temp = regnext(scan); 831 if (temp == NULL) 832 break; 833 scan = temp; 834 } 835 836 if (OP(scan) == BACK) 837 offset = scan - val; 838 else 839 offset = val - scan; 840 *(scan+1) = (char)((offset>>8)&0377); 841 *(scan+2) = (char)(offset&0377); 842} 843 844/* 845 - regoptail - regtail on operand of first argument; nop if operandless 846 */ 847static void 848regoptail(p, val) 849char *p; 850char *val; 851{ 852 /* "Operandless" and "op != BRANCH" are synonymous in practice. */ 853 if (p == NULL || p == ®dummy || OP(p) != BRANCH) 854 return; 855 regtail(OPERAND(p), val); 856} 857 858/* 859 * TclRegExec and friends 860 */ 861 862/* 863 * Global work variables for TclRegExec(). 864 */ 865struct regexec_state { 866 char *reginput; /* String-input pointer. */ 867 char *regbol; /* Beginning of input, for ^ check. */ 868 char **regstartp; /* Pointer to startp array. */ 869 char **regendp; /* Ditto for endp. */ 870}; 871 872/* 873 * Forwards. 874 */ 875static int regtry _ANSI_ARGS_((regexp *prog, char *string, 876 struct regexec_state *restate)); 877static int regmatch _ANSI_ARGS_((char *prog, 878 struct regexec_state *restate)); 879static int regrepeat _ANSI_ARGS_((char *p, 880 struct regexec_state *restate)); 881 882#ifdef DEBUG 883int regnarrate = 0; 884void regdump _ANSI_ARGS_((regexp *r)); 885static char *regprop _ANSI_ARGS_((char *op)); 886#endif 887 888/* 889 - TclRegExec - match a regexp against a string 890 */ 891int 892TclRegExec(prog, string, start) 893register regexp *prog; 894register char *string; 895char *start; 896{ 897 register char *s; 898 struct regexec_state state; 899 struct regexec_state *restate= &state; 900 901 /* Be paranoid... */ 902 if (prog == NULL || string == NULL) { 903 TclRegError("NULL parameter"); 904 return(0); 905 } 906 907 /* Check validity of program. */ 908 if (UCHARAT(prog->program) != MAGIC) { 909 TclRegError("corrupted program"); 910 return(0); 911 } 912 913 /* If there is a "must appear" string, look for it. */ 914 if (prog->regmust != NULL) { 915 s = string; 916 while ((s = strchr(s, prog->regmust[0])) != NULL) { 917 if (strncmp(s, prog->regmust, (size_t) prog->regmlen) 918 == 0) 919 break; /* Found it. */ 920 s++; 921 } 922 if (s == NULL) /* Not present. */ 923 return(0); 924 } 925 926 /* Mark beginning of line for ^ . */ 927 restate->regbol = start; 928 929 /* Simplest case: anchored match need be tried only once. */ 930 if (prog->reganch) 931 return(regtry(prog, string, restate)); 932 933 /* Messy cases: unanchored match. */ 934 s = string; 935 if (prog->regstart != '\0') 936 /* We know what char it must start with. */ 937 while ((s = strchr(s, prog->regstart)) != NULL) { 938 if (regtry(prog, s, restate)) 939 return(1); 940 s++; 941 } 942 else 943 /* We don't -- general case. */ 944 do { 945 if (regtry(prog, s, restate)) 946 return(1); 947 } while (*s++ != '\0'); 948 949 /* Failure. */ 950 return(0); 951} 952 953/* 954 - regtry - try match at specific point 955 */ 956static int /* 0 failure, 1 success */ 957regtry(prog, string, restate) 958regexp *prog; 959char *string; 960struct regexec_state *restate; 961{ 962 register int i; 963 register char **sp; 964 register char **ep; 965 966 restate->reginput = string; 967 restate->regstartp = prog->startp; 968 restate->regendp = prog->endp; 969 970 sp = prog->startp; 971 ep = prog->endp; 972 for (i = NSUBEXP; i > 0; i--) { 973 *sp++ = NULL; 974 *ep++ = NULL; 975 } 976 if (regmatch(prog->program + 1,restate)) { 977 prog->startp[0] = string; 978 prog->endp[0] = restate->reginput; 979 return(1); 980 } else 981 return(0); 982} 983 984/* 985 - regmatch - main matching routine 986 * 987 * Conceptually the strategy is simple: check to see whether the current 988 * node matches, call self recursively to see whether the rest matches, 989 * and then act accordingly. In practice we make some effort to avoid 990 * recursion, in particular by going through "ordinary" nodes (that don't 991 * need to know whether the rest of the match failed) by a loop instead of 992 * by recursion. 993 */ 994static int /* 0 failure, 1 success */ 995regmatch(prog, restate) 996char *prog; 997struct regexec_state *restate; 998{ 999 register char *scan; /* Current node. */ 1000 char *next; /* Next node. */ 1001 1002 scan = prog; 1003#ifdef DEBUG 1004 if (scan != NULL && regnarrate) 1005 fprintf(stderr, "%s(\n", regprop(scan)); 1006#endif 1007 while (scan != NULL) { 1008#ifdef DEBUG 1009 if (regnarrate) 1010 fprintf(stderr, "%s...\n", regprop(scan)); 1011#endif 1012 next = regnext(scan); 1013 1014 switch (OP(scan)) { 1015 case BOL: 1016 if (restate->reginput != restate->regbol) { 1017 return 0; 1018 } 1019 break; 1020 case EOL: 1021 if (*restate->reginput != '\0') { 1022 return 0; 1023 } 1024 break; 1025 case ANY: 1026 if (*restate->reginput == '\0') { 1027 return 0; 1028 } 1029 restate->reginput++; 1030 break; 1031 case EXACTLY: { 1032 register int len; 1033 register char *opnd; 1034 1035 opnd = OPERAND(scan); 1036 /* Inline the first character, for speed. */ 1037 if (*opnd != *restate->reginput) { 1038 return 0 ; 1039 } 1040 len = strlen(opnd); 1041 if (len > 1 && strncmp(opnd, restate->reginput, (size_t) len) 1042 != 0) { 1043 return 0; 1044 } 1045 restate->reginput += len; 1046 break; 1047 } 1048 case ANYOF: 1049 if (*restate->reginput == '\0' 1050 || strchr(OPERAND(scan), *restate->reginput) == NULL) { 1051 return 0; 1052 } 1053 restate->reginput++; 1054 break; 1055 case ANYBUT: 1056 if (*restate->reginput == '\0' 1057 || strchr(OPERAND(scan), *restate->reginput) != NULL) { 1058 return 0; 1059 } 1060 restate->reginput++; 1061 break; 1062 case NOTHING: 1063 break; 1064 case BACK: 1065 break; 1066 case OPEN+1: 1067 case OPEN+2: 1068 case OPEN+3: 1069 case OPEN+4: 1070 case OPEN+5: 1071 case OPEN+6: 1072 case OPEN+7: 1073 case OPEN+8: 1074 case OPEN+9: { 1075 register int no; 1076 register char *save; 1077 1078 doOpen: 1079 no = OP(scan) - OPEN; 1080 save = restate->reginput; 1081 1082 if (regmatch(next,restate)) { 1083 /* 1084 * Don't set startp if some later invocation of the 1085 * same parentheses already has. 1086 */ 1087 if (restate->regstartp[no] == NULL) { 1088 restate->regstartp[no] = save; 1089 } 1090 return 1; 1091 } else { 1092 return 0; 1093 } 1094 } 1095 case CLOSE+1: 1096 case CLOSE+2: 1097 case CLOSE+3: 1098 case CLOSE+4: 1099 case CLOSE+5: 1100 case CLOSE+6: 1101 case CLOSE+7: 1102 case CLOSE+8: 1103 case CLOSE+9: { 1104 register int no; 1105 register char *save; 1106 1107 doClose: 1108 no = OP(scan) - CLOSE; 1109 save = restate->reginput; 1110 1111 if (regmatch(next,restate)) { 1112 /* 1113 * Don't set endp if some later 1114 * invocation of the same parentheses 1115 * already has. 1116 */ 1117 if (restate->regendp[no] == NULL) 1118 restate->regendp[no] = save; 1119 return 1; 1120 } else { 1121 return 0; 1122 } 1123 } 1124 case BRANCH: { 1125 register char *save; 1126 1127 if (OP(next) != BRANCH) { /* No choice. */ 1128 next = OPERAND(scan); /* Avoid recursion. */ 1129 } else { 1130 do { 1131 save = restate->reginput; 1132 if (regmatch(OPERAND(scan),restate)) 1133 return(1); 1134 restate->reginput = save; 1135 scan = regnext(scan); 1136 } while (scan != NULL && OP(scan) == BRANCH); 1137 return 0; 1138 } 1139 break; 1140 } 1141 case STAR: 1142 case PLUS: { 1143 register char nextch; 1144 register int no; 1145 register char *save; 1146 register int min; 1147 1148 /* 1149 * Lookahead to avoid useless match attempts 1150 * when we know what character comes next. 1151 */ 1152 nextch = '\0'; 1153 if (OP(next) == EXACTLY) 1154 nextch = *OPERAND(next); 1155 min = (OP(scan) == STAR) ? 0 : 1; 1156 save = restate->reginput; 1157 no = regrepeat(OPERAND(scan),restate); 1158 while (no >= min) { 1159 /* If it could work, try it. */ 1160 if (nextch == '\0' || *restate->reginput == nextch) 1161 if (regmatch(next,restate)) 1162 return(1); 1163 /* Couldn't or didn't -- back up. */ 1164 no--; 1165 restate->reginput = save + no; 1166 } 1167 return(0); 1168 } 1169 case END: 1170 return(1); /* Success! */ 1171 default: 1172 if (OP(scan) > OPEN && OP(scan) < OPEN+NSUBEXP) { 1173 goto doOpen; 1174 } else if (OP(scan) > CLOSE && OP(scan) < CLOSE+NSUBEXP) { 1175 goto doClose; 1176 } 1177 TclRegError("memory corruption"); 1178 return 0; 1179 } 1180 1181 scan = next; 1182 } 1183 1184 /* 1185 * We get here only if there's trouble -- normally "case END" is 1186 * the terminating point. 1187 */ 1188 TclRegError("corrupted pointers"); 1189 return(0); 1190} 1191 1192/* 1193 - regrepeat - repeatedly match something simple, report how many 1194 */ 1195static int 1196regrepeat(p, restate) 1197char *p; 1198struct regexec_state *restate; 1199{ 1200 register int count = 0; 1201 register char *scan; 1202 register char *opnd; 1203 1204 scan = restate->reginput; 1205 opnd = OPERAND(p); 1206 switch (OP(p)) { 1207 case ANY: 1208 count = strlen(scan); 1209 scan += count; 1210 break; 1211 case EXACTLY: 1212 while (*opnd == *scan) { 1213 count++; 1214 scan++; 1215 } 1216 break; 1217 case ANYOF: 1218 while (*scan != '\0' && strchr(opnd, *scan) != NULL) { 1219 count++; 1220 scan++; 1221 } 1222 break; 1223 case ANYBUT: 1224 while (*scan != '\0' && strchr(opnd, *scan) == NULL) { 1225 count++; 1226 scan++; 1227 } 1228 break; 1229 default: /* Oh dear. Called inappropriately. */ 1230 TclRegError("internal foulup"); 1231 count = 0; /* Best compromise. */ 1232 break; 1233 } 1234 restate->reginput = scan; 1235 1236 return(count); 1237} 1238 1239/* 1240 - regnext - dig the "next" pointer out of a node 1241 */ 1242static char * 1243regnext(p) 1244register char *p; 1245{ 1246 register int offset; 1247 1248 if (p == ®dummy) 1249 return(NULL); 1250 1251 offset = NEXT(p); 1252 if (offset == 0) 1253 return(NULL); 1254 1255 if (OP(p) == BACK) 1256 return(p-offset); 1257 else 1258 return(p+offset); 1259} 1260 1261#ifdef DEBUG 1262 1263static char *regprop(); 1264 1265/* 1266 - regdump - dump a regexp onto stdout in vaguely comprehensible form 1267 */ 1268void 1269regdump(r) 1270regexp *r; 1271{ 1272 register char *s; 1273 register char op = EXACTLY; /* Arbitrary non-END op. */ 1274 register char *next; 1275 1276 1277 s = r->program + 1; 1278 while (op != END) { /* While that wasn't END last time... */ 1279 op = OP(s); 1280 printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */ 1281 next = regnext(s); 1282 if (next == NULL) /* Next ptr. */ 1283 printf("(0)"); 1284 else 1285 printf("(%d)", (s-r->program)+(next-s)); 1286 s += 3; 1287 if (op == ANYOF || op == ANYBUT || op == EXACTLY) { 1288 /* Literal string, where present. */ 1289 while (*s != '\0') { 1290 putchar(*s); 1291 s++; 1292 } 1293 s++; 1294 } 1295 putchar('\n'); 1296 } 1297 1298 /* Header fields of interest. */ 1299 if (r->regstart != '\0') 1300 printf("start `%c' ", r->regstart); 1301 if (r->reganch) 1302 printf("anchored "); 1303 if (r->regmust != NULL) 1304 printf("must have \"%s\"", r->regmust); 1305 printf("\n"); 1306} 1307 1308/* 1309 - regprop - printable representation of opcode 1310 */ 1311static char * 1312regprop(op) 1313char *op; 1314{ 1315 register char *p; 1316 static char buf[50]; 1317 1318 (void) strcpy(buf, ":"); 1319 1320 switch (OP(op)) { 1321 case BOL: 1322 p = "BOL"; 1323 break; 1324 case EOL: 1325 p = "EOL"; 1326 break; 1327 case ANY: 1328 p = "ANY"; 1329 break; 1330 case ANYOF: 1331 p = "ANYOF"; 1332 break; 1333 case ANYBUT: 1334 p = "ANYBUT"; 1335 break; 1336 case BRANCH: 1337 p = "BRANCH"; 1338 break; 1339 case EXACTLY: 1340 p = "EXACTLY"; 1341 break; 1342 case NOTHING: 1343 p = "NOTHING"; 1344 break; 1345 case BACK: 1346 p = "BACK"; 1347 break; 1348 case END: 1349 p = "END"; 1350 break; 1351 case OPEN+1: 1352 case OPEN+2: 1353 case OPEN+3: 1354 case OPEN+4: 1355 case OPEN+5: 1356 case OPEN+6: 1357 case OPEN+7: 1358 case OPEN+8: 1359 case OPEN+9: 1360 sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN); 1361 p = NULL; 1362 break; 1363 case CLOSE+1: 1364 case CLOSE+2: 1365 case CLOSE+3: 1366 case CLOSE+4: 1367 case CLOSE+5: 1368 case CLOSE+6: 1369 case CLOSE+7: 1370 case CLOSE+8: 1371 case CLOSE+9: 1372 sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE); 1373 p = NULL; 1374 break; 1375 case STAR: 1376 p = "STAR"; 1377 break; 1378 case PLUS: 1379 p = "PLUS"; 1380 break; 1381 default: 1382 if (OP(op) > OPEN && OP(op) < OPEN+NSUBEXP) { 1383 sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN); 1384 p = NULL; 1385 break; 1386 } else if (OP(op) > CLOSE && OP(op) < CLOSE+NSUBEXP) { 1387 sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE); 1388 p = NULL; 1389 } else { 1390 TclRegError("corrupted opcode"); 1391 } 1392 break; 1393 } 1394 if (p != NULL) 1395 (void) strcat(buf, p); 1396 return(buf); 1397} 1398#endif 1399 1400/* 1401 * The following is provided for those people who do not have strcspn() in 1402 * their C libraries. They should get off their butts and do something 1403 * about it; at least one public-domain implementation of those (highly 1404 * useful) string routines has been published on Usenet. 1405 */ 1406#ifdef STRCSPN 1407/* 1408 * strcspn - find length of initial segment of s1 consisting entirely 1409 * of characters not from s2 1410 */ 1411 1412static int 1413strcspn(s1, s2) 1414char *s1; 1415char *s2; 1416{ 1417 register char *scan1; 1418 register char *scan2; 1419 register int count; 1420 1421 count = 0; 1422 for (scan1 = s1; *scan1 != '\0'; scan1++) { 1423 for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */ 1424 if (*scan1 == *scan2++) 1425 return(count); 1426 count++; 1427 } 1428 return(count); 1429} 1430#endif 1431 1432/* 1433 *---------------------------------------------------------------------- 1434 * 1435 * TclRegError -- 1436 * 1437 * This procedure is invoked by the regexp code when an error 1438 * occurs. It saves the error message so it can be seen by the 1439 * code that called Spencer's code. 1440 * 1441 * Results: 1442 * None. 1443 * 1444 * Side effects: 1445 * The value of "string" is saved in "errMsg". 1446 * 1447 *---------------------------------------------------------------------- 1448 */ 1449 1450void 1451exp_TclRegError(string) 1452 char *string; /* Error message. */ 1453{ 1454 errMsg = string; 1455} 1456 1457char * 1458TclGetRegError() 1459{ 1460 return errMsg; 1461} 1462 1463/* 1464 * end of regexp definitions and code 1465 */ 1466 1467/* 1468 * stolen from exp_log.c - this function is called from the Expect library 1469 * but the one that the library supplies calls Tcl functions. So we supply 1470 * our own. 1471 */ 1472 1473static 1474void 1475expDiagLogU(str) 1476 char *str; 1477{ 1478 if (exp_is_debugging) { 1479 fprintf(stderr,str); 1480 if (exp_logfile) fprintf(exp_logfile,str); 1481 } 1482} 1483 1484/* 1485 * expect-specific definitions and code 1486 */ 1487 1488#include "expect.h" 1489#include "exp_int.h" 1490 1491/* exp_glob.c - expect functions for doing glob 1492 * 1493 * Based on Tcl's glob functions but modified to support anchors and to 1494 * return information about the possibility of future matches 1495 * 1496 * Modifications by: Don Libes, NIST, 2/6/90 1497 */ 1498 1499/* The following functions implement expect's glob-style string 1500 * matching Exp_StringMatch allow's implements the unanchored front 1501 * (or conversely the '^') feature. Exp_StringMatch2 does the rest of 1502 * the work. 1503 */ 1504 1505/* Exp_StringMatch2 -- 1506 * 1507 * Like Tcl_StringMatch except that 1508 * 1) returns number of characters matched, -1 if failed. 1509 * (Can return 0 on patterns like "" or "$") 1510 * 2) does not require pattern to match to end of string 1511 * 3) much of code is stolen from Tcl_StringMatch 1512 * 4) front-anchor is assumed (Tcl_StringMatch retries for non-front-anchor) 1513 */ 1514static 1515int 1516Exp_StringMatch2(string,pattern) 1517 register char *string; /* String. */ 1518 register char *pattern; /* Pattern, which may contain 1519 * special characters. */ 1520{ 1521 char c2; 1522 int match = 0; /* # of chars matched */ 1523 1524 while (1) { 1525 /* If at end of pattern, success! */ 1526 if (*pattern == 0) { 1527 return match; 1528 } 1529 1530 /* If last pattern character is '$', verify that entire 1531 * string has been matched. 1532 */ 1533 if ((*pattern == '$') && (pattern[1] == 0)) { 1534 if (*string == 0) return(match); 1535 else return(-1); 1536 } 1537 1538 /* Check for a "*" as the next pattern character. It matches 1539 * any substring. We handle this by calling ourselves 1540 * recursively for each postfix of string, until either we 1541 * match or we reach the end of the string. 1542 */ 1543 1544 if (*pattern == '*') { 1545 int head_len; 1546 char *tail; 1547 pattern += 1; 1548 if (*pattern == 0) { 1549 return(strlen(string)+match); /* DEL */ 1550 } 1551 /* find longest match - switched to this on 12/31/93 */ 1552 head_len = strlen(string); /* length before tail */ 1553 tail = string + head_len; 1554 while (head_len >= 0) { 1555 int rc; 1556 1557 if (-1 != (rc = Exp_StringMatch2(tail, pattern))) { 1558 return rc + match + head_len; /* DEL */ 1559 } 1560 tail--; 1561 head_len--; 1562 } 1563 return -1; /* DEL */ 1564 } 1565 1566 /* 1567 * after this point, all patterns must match at least one 1568 * character, so check this 1569 */ 1570 1571 if (*string == 0) return -1; 1572 1573 /* Check for a "?" as the next pattern character. It matches 1574 * any single character. 1575 */ 1576 1577 if (*pattern == '?') { 1578 goto thisCharOK; 1579 } 1580 1581 /* Check for a "[" as the next pattern character. It is followed 1582 * by a list of characters that are acceptable, or by a range 1583 * (two characters separated by "-"). 1584 */ 1585 1586 if (*pattern == '[') { 1587 pattern += 1; 1588 while (1) { 1589 if ((*pattern == ']') || (*pattern == 0)) { 1590 return -1; /* was 0; DEL */ 1591 } 1592 if (*pattern == *string) { 1593 break; 1594 } 1595 if (pattern[1] == '-') { 1596 c2 = pattern[2]; 1597 if (c2 == 0) { 1598 return -1; /* DEL */ 1599 } 1600 if ((*pattern <= *string) && (c2 >= *string)) { 1601 break; 1602 } 1603 if ((*pattern >= *string) && (c2 <= *string)) { 1604 break; 1605 } 1606 pattern += 2; 1607 } 1608 pattern += 1; 1609 } 1610 1611 while (*pattern != ']') { 1612 if (*pattern == 0) { 1613 pattern--; 1614 break; 1615 } 1616 pattern += 1; 1617 } 1618 goto thisCharOK; 1619 } 1620 1621 /* If the next pattern character is backslash, strip it off 1622 * so we do exact matching on the character that follows. 1623 */ 1624 1625 if (*pattern == '\\') { 1626 pattern += 1; 1627 if (*pattern == 0) { 1628 return -1; 1629 } 1630 } 1631 1632 /* There's no special character. Just make sure that the next 1633 * characters of each string match. 1634 */ 1635 1636 if (*pattern != *string) { 1637 return -1; 1638 } 1639 1640 thisCharOK: pattern += 1; 1641 string += 1; 1642 match++; 1643 } 1644} 1645 1646 1647static 1648int /* returns # of chars that matched */ 1649Exp_StringMatch(string, pattern,offset) 1650char *string; 1651char *pattern; 1652int *offset; /* offset from beginning of string where pattern matches */ 1653{ 1654 char *s; 1655 int sm; /* count of chars matched or -1 */ 1656 int caret = FALSE; 1657 int star = FALSE; 1658 1659 *offset = 0; 1660 1661 if (pattern[0] == '^') { 1662 caret = TRUE; 1663 pattern++; 1664 } else if (pattern[0] == '*') { 1665 star = TRUE; 1666 } 1667 1668 /* 1669 * test if pattern matches in initial position. 1670 * This handles front-anchor and 1st iteration of non-front-anchor. 1671 * Note that 1st iteration must be tried even if string is empty. 1672 */ 1673 1674 sm = Exp_StringMatch2(string,pattern); 1675 if (sm >= 0) return(sm); 1676 1677 if (caret) return -1; 1678 if (star) return -1; 1679 1680 if (*string == '\0') return -1; 1681 1682 for (s = string+1;*s;s++) { 1683 sm = Exp_StringMatch2(s,pattern); 1684 if (sm != -1) { 1685 *offset = s-string; 1686 return(sm); 1687 } 1688 } 1689 return -1; 1690} 1691 1692 1693#define EXP_MATCH_MAX 2000 1694/* public */ 1695char *exp_buffer = 0; 1696char *exp_buffer_end = 0; 1697char *exp_match = 0; 1698char *exp_match_end = 0; 1699int exp_match_max = EXP_MATCH_MAX; /* bytes */ 1700int exp_full_buffer = FALSE; /* don't return on full buffer */ 1701int exp_remove_nulls = TRUE; 1702int exp_timeout = 10; /* seconds */ 1703int exp_pty_timeout = 5; /* seconds - see CRAY below */ 1704int exp_autoallocpty = TRUE; /* if TRUE, we do allocation */ 1705int exp_pty[2]; /* master is [0], slave is [1] */ 1706int exp_pid; 1707char *exp_stty_init = 0; /* initial stty args */ 1708int exp_ttycopy = TRUE; /* copy tty parms from /dev/tty */ 1709int exp_ttyinit = TRUE; /* set tty parms to sane state */ 1710int exp_console = FALSE; /* redirect console */ 1711void (*exp_child_exec_prelude)() = 0; 1712void (*exp_close_in_child)() = 0; 1713 1714#ifdef HAVE_SIGLONGJMP 1715sigjmp_buf exp_readenv; /* for interruptable read() */ 1716#else 1717jmp_buf exp_readenv; /* for interruptable read() */ 1718#endif /* HAVE_SIGLONGJMP */ 1719 1720int exp_reading = FALSE; /* whether we can longjmp or not */ 1721 1722int exp_is_debugging = FALSE; 1723FILE *exp_debugfile = 0; 1724 1725FILE *exp_logfile = 0; 1726int exp_logfile_all = FALSE; /* if TRUE, write log of all interactions */ 1727int exp_loguser = TRUE; /* if TRUE, user sees interactions on stdout */ 1728 1729 1730char *exp_printify(); 1731int exp_getptymaster(); 1732int exp_getptyslave(); 1733 1734#define sysreturn(x) return(errno = x, -1) 1735 1736void exp_init_pty(); 1737 1738/* 1739 The following functions are linked from the Tcl library. They 1740 don't cause anything else in the library to be dragged in, so it 1741 shouldn't cause any problems (e.g., bloat). 1742 1743 The functions are relatively small but painful enough that I don't care 1744 to recode them. You may, if you absolutely want to get rid of any 1745 vestiges of Tcl. 1746*/ 1747 1748static unsigned int bufsiz = 2*EXP_MATCH_MAX; 1749 1750static struct f { 1751 int valid; 1752 1753 char *buffer; /* buffer of matchable chars */ 1754 char *buffer_end; /* one beyond end of matchable chars */ 1755 char *match_end; /* one beyond end of matched string */ 1756 int msize; /* size of allocate space */ 1757 /* actual size is one larger for null */ 1758} *fs = 0; 1759 1760static int fd_alloc_max = -1; /* max fd allocated */ 1761 1762/* translate fd or fp to fd */ 1763static struct f * 1764fdfp2f(fd,fp) 1765int fd; 1766FILE *fp; 1767{ 1768 if (fd == -1) return(fs + fileno(fp)); 1769 else return(fs + fd); 1770} 1771 1772static struct f * 1773fd_new(fd) 1774int fd; 1775{ 1776 int i, low; 1777 struct f *fp; 1778 struct f *newfs; /* temporary, so we don't lose old fs */ 1779 1780 if (fd > fd_alloc_max) { 1781 if (!fs) { /* no fd's yet allocated */ 1782 newfs = (struct f *)malloc(sizeof(struct f)*(fd+1)); 1783 low = 0; 1784 } else { /* enlarge fd table */ 1785 newfs = (struct f *)realloc((char *)fs,sizeof(struct f)*(fd+1)); 1786 low = fd_alloc_max+1; 1787 } 1788 fs = newfs; 1789 fd_alloc_max = fd; 1790 for (i = low; i <= fd_alloc_max; i++) { /* init new entries */ 1791 fs[i].valid = FALSE; 1792 } 1793 } 1794 1795 fp = fs+fd; 1796 1797 if (!fp->valid) { 1798 /* initialize */ 1799 fp->buffer = malloc((unsigned)(bufsiz+1)); 1800 if (!fp->buffer) return 0; 1801 fp->msize = bufsiz; 1802 fp->valid = TRUE; 1803 } 1804 fp->buffer_end = fp->buffer; 1805 fp->match_end = fp->buffer; 1806 return fp; 1807 1808} 1809 1810static 1811void 1812exp_setpgrp() 1813{ 1814#ifdef MIPS_BSD 1815 /* required on BSD side of MIPS OS <jmsellen@watdragon.waterloo.edu> */ 1816# include <sysv/sys.s> 1817 syscall(SYS_setpgrp); 1818#endif 1819 1820#ifdef SETPGRP_VOID 1821 (void) setpgrp(); 1822#else 1823 (void) setpgrp(0,0); 1824#endif 1825} 1826 1827/* returns fd of master side of pty */ 1828int 1829exp_spawnv(file,argv) 1830char *file; 1831char *argv[]; /* some compiler complains about **argv? */ 1832{ 1833 int cc; 1834 int errorfd; /* place to stash fileno(stderr) in child */ 1835 /* while we're setting up new stderr */ 1836 int ttyfd; 1837 int sync_fds[2]; 1838 int sync2_fds[2]; 1839 int status_pipe[2]; 1840 int child_errno; 1841 char sync_byte; 1842#ifdef PTYTRAP_DIES 1843 int slave_write_ioctls = 1; 1844 /* by default, slave will be write-ioctled this many times */ 1845#endif 1846 1847 static int first_time = TRUE; 1848 1849 if (first_time) { 1850 first_time = FALSE; 1851 exp_init_pty(); 1852 exp_init_tty(); 1853 expDiagLogPtrSet(expDiagLogU); 1854 1855 /* 1856 * TIP 27; It is unclear why this code produces a 1857 * warning. The equivalent code in exp_main_sub.c 1858 * (line 512) does not generate a warning ! 1859 */ 1860 1861 expErrnoMsgSet(Tcl_ErrnoMsg); 1862 } 1863 1864 if (!file || !argv) sysreturn(EINVAL); 1865 if (!argv[0] || strcmp(file,argv[0])) { 1866 exp_debuglog("expect: warning: file (%s) != argv[0] (%s)\n", 1867 file, 1868 argv[0]?argv[0]:""); 1869 } 1870 1871#ifdef PTYTRAP_DIES 1872/* any extraneous ioctl's that occur in slave must be accounted for 1873when trapping, see below in child half of fork */ 1874#if defined(TIOCSCTTY) && !defined(CIBAUD) && !defined(sun) && !defined(hp9000s300) 1875 slave_write_ioctls++; 1876#endif 1877#endif /*PTYTRAP_DIES*/ 1878 1879 if (exp_autoallocpty) { 1880 if (0 > (exp_pty[0] = exp_getptymaster())) sysreturn(ENODEV); 1881 } 1882 fcntl(exp_pty[0],F_SETFD,1); /* close on exec */ 1883#ifdef PTYTRAP_DIES 1884 exp_slave_control(exp_pty[0],1);*/ 1885#endif 1886 1887 if (!fd_new(exp_pty[0])) { 1888 errno = ENOMEM; 1889 return -1; 1890 } 1891 1892 if (-1 == (pipe(sync_fds))) { 1893 return -1; 1894 } 1895 if (-1 == (pipe(sync2_fds))) { 1896 close(sync_fds[0]); 1897 close(sync_fds[1]); 1898 return -1; 1899 } 1900 1901 if (-1 == pipe(status_pipe)) { 1902 close(sync_fds[0]); 1903 close(sync_fds[1]); 1904 close(sync2_fds[0]); 1905 close(sync2_fds[1]); 1906 return -1; 1907 } 1908 1909 if ((exp_pid = fork()) == -1) return(-1); 1910 if (exp_pid) { 1911 /* parent */ 1912 close(sync_fds[1]); 1913 close(sync2_fds[0]); 1914 close(status_pipe[1]); 1915 1916 if (!exp_autoallocpty) close(exp_pty[1]); 1917 1918#ifdef PTYTRAP_DIES 1919#ifdef HAVE_PTYTRAP 1920 if (exp_autoallocpty) { 1921 /* trap initial ioctls in a feeble attempt to not */ 1922 /* block the initially. If the process itself */ 1923 /* ioctls /dev/tty, such blocks will be trapped */ 1924 /* later during normal event processing */ 1925 1926 while (slave_write_ioctls) { 1927 int cc; 1928 1929 cc = exp_wait_for_slave_open(exp_pty[0]); 1930#if defined(TIOCSCTTY) && !defined(CIBAUD) && !defined(sun) && !defined(hp9000s300) 1931 if (cc == TIOCSCTTY) slave_write_ioctls = 0; 1932#endif 1933 if (cc & IOC_IN) slave_write_ioctls--; 1934 else if (cc == -1) { 1935 printf("failed to trap slave pty"); 1936 return -1; 1937 } 1938 } 1939 } 1940#endif 1941#endif /*PTYTRAP_DIES*/ 1942 1943 /* 1944 * wait for slave to initialize pty before allowing 1945 * user to send to it 1946 */ 1947 1948 exp_debuglog("parent: waiting for sync byte\r\n"); 1949 cc = read(sync_fds[0],&sync_byte,1); 1950 if (cc == -1) { 1951 exp_errorlog("parent sync byte read: %s\r\n",Tcl_ErrnoMsg(errno)); 1952 return -1; 1953 } 1954 1955 /* turn on detection of eof */ 1956 exp_slave_control(exp_pty[0],1); 1957 1958 /* 1959 * tell slave to go on now now that we have initialized pty 1960 */ 1961 1962 exp_debuglog("parent: telling child to go ahead\r\n"); 1963 cc = write(sync2_fds[1]," ",1); 1964 if (cc == -1) { 1965 exp_errorlog("parent sync byte write: %s\r\n",Tcl_ErrnoMsg(errno)); 1966 return -1; 1967 } 1968 1969 exp_debuglog("parent: now unsynchronized from child\r\n"); 1970 1971 close(sync_fds[0]); 1972 close(sync2_fds[1]); 1973 1974 /* see if child's exec worked */ 1975 1976 retry: 1977 switch (read(status_pipe[0],&child_errno,sizeof child_errno)) { 1978 case -1: 1979 if (errno == EINTR) goto retry; 1980 /* well it's not really the child's errno */ 1981 /* but it can be treated that way */ 1982 child_errno = errno; 1983 break; 1984 case 0: 1985 /* child's exec succeeded */ 1986 child_errno = 0; 1987 break; 1988 default: 1989 /* child's exec failed; err contains exec's errno */ 1990 waitpid(exp_pid, NULL, 0); 1991 errno = child_errno; 1992 exp_pty[0] = -1; 1993 } 1994 close(status_pipe[0]); 1995 return(exp_pty[0]); 1996 } 1997 1998 /* 1999 * child process - do not return from here! all errors must exit() 2000 */ 2001 2002 close(sync_fds[0]); 2003 close(sync2_fds[1]); 2004 close(status_pipe[0]); 2005 fcntl(status_pipe[1],F_SETFD,1); /* close on exec */ 2006 2007#ifdef CRAY 2008 (void) close(exp_pty[0]); 2009#endif 2010 2011/* ultrix (at least 4.1-2) fails to obtain controlling tty if setsid */ 2012/* is called. setpgrp works though. */ 2013#if defined(POSIX) && !defined(ultrix) 2014#define DO_SETSID 2015#endif 2016#ifdef __convex__ 2017#define DO_SETSID 2018#endif 2019 2020#ifdef DO_SETSID 2021 setsid(); 2022#else 2023#ifdef SYSV3 2024#ifndef CRAY 2025 exp_setpgrp(); 2026#endif /* CRAY */ 2027#else /* !SYSV3 */ 2028 exp_setpgrp(); 2029 2030#ifdef TIOCNOTTY 2031 ttyfd = open("/dev/tty", O_RDWR); 2032 if (ttyfd >= 0) { 2033 (void) ioctl(ttyfd, TIOCNOTTY, (char *)0); 2034 (void) close(ttyfd); 2035 } 2036#endif /* TIOCNOTTY */ 2037 2038#endif /* SYSV3 */ 2039#endif /* DO_SETSID */ 2040 2041 /* save error fd while we're setting up new one */ 2042 errorfd = fcntl(2,F_DUPFD,3); 2043 /* and here is the macro to restore it */ 2044#define restore_error_fd {close(2);fcntl(errorfd,F_DUPFD,2);} 2045 2046 if (exp_autoallocpty) { 2047 2048 close(0); 2049 close(1); 2050 close(2); 2051 2052 /* since we closed fd 0, open of pty slave must return fd 0 */ 2053 2054 if (0 > (exp_pty[1] = exp_getptyslave(exp_ttycopy,exp_ttyinit, 2055 exp_stty_init))) { 2056 restore_error_fd 2057 fprintf(stderr,"open(slave pty): %s\n",Tcl_ErrnoMsg(errno)); 2058 exit(-1); 2059 } 2060 /* sanity check */ 2061 if (exp_pty[1] != 0) { 2062 restore_error_fd 2063 fprintf(stderr,"exp_getptyslave: slave = %d but expected 0\n", 2064 exp_pty[1]); 2065 exit(-1); 2066 } 2067 } else { 2068 if (exp_pty[1] != 0) { 2069 close(0); fcntl(exp_pty[1],F_DUPFD,0); 2070 } 2071 close(1); fcntl(0,F_DUPFD,1); 2072 close(2); fcntl(0,F_DUPFD,1); 2073 close(exp_pty[1]); 2074 } 2075 2076 2077 2078/* The test for hpux may have to be more specific. In particular, the */ 2079/* code should be skipped on the hp9000s300 and hp9000s720 (but there */ 2080/* is no documented define for the 720!) */ 2081 2082#if defined(TIOCSCTTY) && !defined(sun) && !defined(hpux) 2083 /* 4.3+BSD way to acquire controlling terminal */ 2084 /* according to Stevens - Adv. Prog..., p 642 */ 2085#ifdef __QNX__ /* posix in general */ 2086 if (tcsetct(0, getpid()) == -1) { 2087 restore_error_fd 2088 expErrorLog("failed to get controlling terminal using TIOCSCTTY"); 2089 exit(-1); 2090 } 2091#else 2092 (void) ioctl(0,TIOCSCTTY,(char *)0); 2093 /* ignore return value - on some systems, it is defined but it 2094 * fails and it doesn't seem to cause any problems. Or maybe 2095 * it works but returns a bogus code. Noone seems to be able 2096 * to explain this to me. The systems are an assortment of 2097 * different linux systems (and FreeBSD 2.5), RedHat 5.2 and 2098 * Debian 2.0 2099 */ 2100#endif 2101#endif 2102 2103#ifdef CRAY 2104 (void) setsid(); 2105 (void) ioctl(0,TCSETCTTY,0); 2106 (void) close(0); 2107 if (open("/dev/tty", O_RDWR) < 0) { 2108 restore_error_fd 2109 fprintf(stderr,"open(/dev/tty): %s\r\n",Tcl_ErrnoMsg(errno)); 2110 exit(-1); 2111 } 2112 (void) close(1); 2113 (void) close(2); 2114 (void) dup(0); 2115 (void) dup(0); 2116 setptyutmp(); /* create a utmp entry */ 2117 2118 /* _CRAY2 code from Hal Peterson <hrp@cray.com>, Cray Research, Inc. */ 2119#ifdef _CRAY2 2120 /* 2121 * Interpose a process between expect and the spawned child to 2122 * keep the slave side of the pty open to allow time for expect 2123 * to read the last output. This is a workaround for an apparent 2124 * bug in the Unicos pty driver on Cray-2's under Unicos 6.0 (at 2125 * least). 2126 */ 2127 if ((pid = fork()) == -1) { 2128 restore_error_fd 2129 fprintf(stderr,"second fork: %s\r\n",Tcl_ErrnoMsg(errno)); 2130 exit(-1); 2131 } 2132 2133 if (pid) { 2134 /* Intermediate process. */ 2135 int status; 2136 int timeout; 2137 char *t; 2138 2139 /* How long should we wait? */ 2140 timeout = exp_pty_timeout; 2141 2142 /* Let the spawned process run to completion. */ 2143 while (wait(&status) < 0 && errno == EINTR) 2144 /* empty body */; 2145 2146 /* Wait for the pty to clear. */ 2147 sleep(timeout); 2148 2149 /* Duplicate the spawned process's status. */ 2150 if (WIFSIGNALED(status)) 2151 kill(getpid(), WTERMSIG(status)); 2152 2153 /* The kill may not have worked, but this will. */ 2154 exit(WEXITSTATUS(status)); 2155 } 2156#endif /* _CRAY2 */ 2157#endif /* CRAY */ 2158 2159 if (exp_console) { 2160#ifdef SRIOCSREDIR 2161 int fd; 2162 2163 if ((fd = open("/dev/console", O_RDONLY)) == -1) { 2164 restore_error_fd 2165 fprintf(stderr, "spawn %s: cannot open console, check permissions of /dev/console\n",argv[0]); 2166 exit(-1); 2167 } 2168 if (ioctl(fd, SRIOCSREDIR, 0) == -1) { 2169 restore_error_fd 2170 fprintf(stderr, "spawn %s: cannot redirect console, check permissions of /dev/console\n",argv[0]); 2171 } 2172 close(fd); 2173#endif 2174 2175#ifdef TIOCCONS 2176 int on = 1; 2177 if (ioctl(0,TIOCCONS,(char *)&on) == -1) { 2178 restore_error_fd 2179 fprintf(stderr, "spawn %s: cannot open console, check permissions of /dev/console\n",argv[0]); 2180 exit(-1); 2181 } 2182#endif /* TIOCCONS */ 2183 } 2184 2185 /* tell parent that we are done setting up pty */ 2186 /* The actual char sent back is irrelevant. */ 2187 2188 /* exp_debuglog("child: telling parent that pty is initialized\r\n");*/ 2189 cc = write(sync_fds[1]," ",1); 2190 if (cc == -1) { 2191 restore_error_fd 2192 fprintf(stderr,"child: sync byte write: %s\r\n",Tcl_ErrnoMsg(errno)); 2193 exit(-1); 2194 } 2195 close(sync_fds[1]); 2196 2197 /* wait for master to let us go on */ 2198 cc = read(sync2_fds[0],&sync_byte,1); 2199 if (cc == -1) { 2200 restore_error_fd 2201 exp_errorlog("child: sync byte read: %s\r\n",Tcl_ErrnoMsg(errno)); 2202 exit(-1); 2203 } 2204 close(sync2_fds[0]); 2205 2206 /* exp_debuglog("child: now unsynchronized from parent\r\n"); */ 2207 2208 /* (possibly multiple) masters are closed automatically due to */ 2209 /* earlier fcntl(,,CLOSE_ON_EXEC); */ 2210 2211 /* just in case, allow user to explicitly close other files */ 2212 if (exp_close_in_child) (*exp_close_in_child)(); 2213 2214 /* allow user to do anything else to child */ 2215 if (exp_child_exec_prelude) (*exp_child_exec_prelude)(); 2216 2217 (void) execvp(file,argv); 2218 2219 /* Unfortunately, by now we've closed fd's to stderr, logfile 2220 * and debugfile. The only reasonable thing to do is to send 2221 * *back the error as part of the program output. This will 2222 * be *picked up in an expect or interact command. 2223 */ 2224 2225 write(status_pipe[1], &errno, sizeof errno); 2226 exit(-1); 2227 /*NOTREACHED*/ 2228} 2229 2230/* returns fd of master side of pty */ 2231/*VARARGS*/ 2232int 2233exp_spawnl TCL_VARARGS_DEF(char *,arg1) 2234/*exp_spawnl(va_alist)*/ 2235/*va_dcl*/ 2236{ 2237 va_list args; /* problematic line here */ 2238 int i; 2239 char *arg, **argv; 2240 2241 arg = TCL_VARARGS_START(char *,arg1,args); 2242 /*va_start(args);*/ 2243 for (i=1;;i++) { 2244 arg = va_arg(args,char *); 2245 if (!arg) break; 2246 } 2247 va_end(args); 2248 if (i == 0) sysreturn(EINVAL); 2249 if (!(argv = (char **)malloc((i+1)*sizeof(char *)))) sysreturn(ENOMEM); 2250 argv[0] = TCL_VARARGS_START(char *,arg1,args); 2251 /*va_start(args);*/ 2252 for (i=1;;i++) { 2253 argv[i] = va_arg(args,char *); 2254 if (!argv[i]) break; 2255 } 2256 i = exp_spawnv(argv[0],argv+1); 2257 free((char *)argv); 2258 return(i); 2259} 2260 2261/* allow user-provided fd to be passed to expect funcs */ 2262int 2263exp_spawnfd(fd) 2264int fd; 2265{ 2266 if (!fd_new(fd)) { 2267 errno = ENOMEM; 2268 return -1; 2269 } 2270 return fd; 2271} 2272 2273/* remove nulls from s. Initially, the number of chars in s is c, */ 2274/* not strlen(s). This count does not include the trailing null. */ 2275/* returns number of nulls removed. */ 2276static int 2277rm_nulls(s,c) 2278char *s; 2279int c; 2280{ 2281 char *s2 = s; /* points to place in original string to put */ 2282 /* next non-null character */ 2283 int count = 0; 2284 int i; 2285 2286 for (i=0;i<c;i++,s++) { 2287 if (0 == *s) { 2288 count++; 2289 continue; 2290 } 2291 if (count) *s2 = *s; 2292 s2++; 2293 } 2294 return(count); 2295} 2296 2297static int i_read_errno;/* place to save errno, if i_read() == -1, so it 2298 doesn't get overwritten before we get to read it */ 2299 2300/*ARGSUSED*/ 2301static void 2302sigalarm_handler(n) 2303int n; /* signal number, unused by us */ 2304{ 2305#ifdef REARM_SIG 2306 signal(SIGALRM,sigalarm_handler); 2307#endif 2308 2309#ifdef HAVE_SIGLONGJMP 2310 siglongjmp(exp_readenv,1); 2311#else 2312 longjmp(exp_readenv,1); 2313#endif /* HAVE_SIGLONGJMP */ 2314} 2315 2316/* interruptable read */ 2317static int 2318i_read(fd,fp,buffer,length,timeout) 2319int fd; 2320FILE *fp; 2321char *buffer; 2322int length; 2323int timeout; 2324{ 2325 int cc = -2; 2326 2327 /* since setjmp insists on returning 1 upon longjmp(,0), */ 2328 /* longjmp(,2 (EXP_RESTART)) instead. */ 2329 2330 /* no need to set alarm if -1 (infinite) or 0 (poll with */ 2331 /* guaranteed data) */ 2332 2333 if (timeout > 0) alarm(timeout); 2334 2335 /* restart read if setjmp returns 0 (first time) or 2 (EXP_RESTART). */ 2336 /* abort if setjmp returns 1 (EXP_ABORT). */ 2337#ifdef HAVE_SIGLONGJMP 2338 if (EXP_ABORT != sigsetjmp(exp_readenv,1)) { 2339#else 2340 if (EXP_ABORT != setjmp(exp_readenv)) { 2341#endif /* HAVE_SIGLONGJMP */ 2342 exp_reading = TRUE; 2343 if (fd == -1) { 2344 int c; 2345 c = getc(fp); 2346 if (c == EOF) { 2347/*fprintf(stderr,"<<EOF>>",c);fflush(stderr);*/ 2348 if (feof(fp)) cc = 0; 2349 else cc = -1; 2350 } else { 2351/*fprintf(stderr,"<<%c>>",c);fflush(stderr);*/ 2352 buffer[0] = c; 2353 cc = 1; 2354 } 2355 } else { 2356#ifndef HAVE_PTYTRAP 2357 cc = read(fd,buffer,length); 2358#else 2359# include <sys/ptyio.h> 2360 2361 fd_set rdrs; 2362 fd_set excep; 2363 2364 restart: 2365 FD_ZERO(&rdrs); 2366 FD_ZERO(&excep); 2367 FD_SET(fd,&rdrs); 2368 FD_SET(fd,&excep); 2369 if (-1 == (cc = select(fd+1, 2370 (SELECT_MASK_TYPE *)&rdrs, 2371 (SELECT_MASK_TYPE *)0, 2372 (SELECT_MASK_TYPE *)&excep, 2373 (struct timeval *)0))) { 2374 /* window refreshes trigger EINTR, ignore */ 2375 if (errno == EINTR) goto restart; 2376 } 2377 if (FD_ISSET(fd,&rdrs)) { 2378 cc = read(fd,buffer,length); 2379 } else if (FD_ISSET(fd,&excep)) { 2380 struct request_info ioctl_info; 2381 ioctl(fd,TIOCREQCHECK,&ioctl_info); 2382 if (ioctl_info.request == TIOCCLOSE) { 2383 cc = 0; /* indicate eof */ 2384 } else { 2385 ioctl(fd, TIOCREQSET, &ioctl_info); 2386 /* presumably, we trapped an open here */ 2387 goto restart; 2388 } 2389 } 2390#endif /* HAVE_PTYTRAP */ 2391 } 2392#if 0 2393 /* can't get fread to return early! */ 2394 else { 2395 if (!(cc = fread(buffer,1,length,fp))) { 2396 if (ferror(fp)) cc = -1; 2397 } 2398 } 2399#endif 2400 i_read_errno = errno; /* errno can be overwritten by the */ 2401 /* time we return */ 2402 } 2403 exp_reading = FALSE; 2404 2405 if (timeout > 0) alarm(0); 2406 return(cc); 2407} 2408 2409/* I tried really hard to make the following two functions share the code */ 2410/* that makes the ecase array, but I kept running into a brick wall when */ 2411/* passing var args into the funcs and then again into a make_cases func */ 2412/* I would very much appreciate it if someone showed me how to do it right */ 2413 2414/* takes triplets of args, with a final "exp_last" arg */ 2415/* triplets are type, pattern, and then int to return */ 2416/* returns negative value if error (or EOF/timeout) occurs */ 2417/* some negative values can also have an associated errno */ 2418 2419/* the key internal variables that this function depends on are: 2420 exp_buffer 2421 exp_buffer_end 2422 exp_match_end 2423*/ 2424static int 2425expectv(fd,fp,ecases) 2426int fd; 2427FILE *fp; 2428struct exp_case *ecases; 2429{ 2430 int cc = 0; /* number of chars returned in a single read */ 2431 int buf_length; /* numbers of chars in exp_buffer */ 2432 int old_length; /* old buf_length */ 2433 int first_time = TRUE; /* force old buffer to be tested before */ 2434 /* additional reads */ 2435 int polled = 0; /* true if poll has caused read() to occur */ 2436 2437 struct exp_case *ec; /* points to current ecase */ 2438 2439 time_t current_time; /* current time (when we last looked)*/ 2440 time_t end_time; /* future time at which to give up */ 2441 int remtime; /* remaining time in timeout */ 2442 2443 struct f *f; 2444 int return_val; 2445 int sys_error = 0; 2446#define return_normally(x) {return_val = x; goto cleanup;} 2447#define return_errno(x) {sys_error = x; goto cleanup;} 2448 2449 f = fdfp2f(fd,fp); 2450 if (!f) return_errno(ENOMEM); 2451 2452 exp_buffer = f->buffer; 2453 exp_buffer_end = f->buffer_end; 2454 exp_match_end = f->match_end; 2455 2456 buf_length = exp_buffer_end - exp_match_end; 2457 if (buf_length) { 2458 /* 2459 * take end of previous match to end of buffer 2460 * and copy to beginning of buffer 2461 */ 2462 memmove(exp_buffer,exp_match_end,buf_length); 2463 } 2464 exp_buffer_end = exp_buffer + buf_length; 2465 *exp_buffer_end = '\0'; 2466 2467 if (!ecases) return_errno(EINVAL); 2468 2469 /* compile if necessary */ 2470 for (ec=ecases;ec->type != exp_end;ec++) { 2471 if ((ec->type == exp_regexp) && !ec->re) { 2472 TclRegError((char *)0); 2473 if (!(ec->re = TclRegComp(ec->pattern))) { 2474 fprintf(stderr,"regular expression %s is bad: %s",ec->pattern,TclGetRegError()); 2475 return_errno(EINVAL); 2476 } 2477 } 2478 } 2479 2480 /* get the latest buffer size. Double the user input for two */ 2481 /* reasons. 1) Need twice the space in case the match */ 2482 /* straddles two bufferfuls, 2) easier to hack the division by */ 2483 /* two when shifting the buffers later on */ 2484 2485 bufsiz = 2*exp_match_max; 2486 if (f->msize != bufsiz) { 2487 /* if truncated, forget about some data */ 2488 if (buf_length > bufsiz) { 2489 /* copy end of buffer down */ 2490 2491 /* copy one less than what buffer can hold to avoid */ 2492 /* triggering buffer-full handling code below */ 2493 /* which will immediately dump the first half */ 2494 /* of the buffer */ 2495 memmove(exp_buffer,exp_buffer+(buf_length - bufsiz)+1, 2496 bufsiz-1); 2497 buf_length = bufsiz-1; 2498 } 2499 exp_buffer = realloc(exp_buffer,bufsiz+1); 2500 if (!exp_buffer) return_errno(ENOMEM); 2501 exp_buffer[buf_length] = '\0'; 2502 exp_buffer_end = exp_buffer + buf_length; 2503 f->msize = bufsiz; 2504 } 2505 2506 /* some systems (i.e., Solaris) require fp be flushed when switching */ 2507 /* directions - do this again afterwards */ 2508 if (fd == -1) fflush(fp); 2509 2510 if (exp_timeout != -1) signal(SIGALRM,sigalarm_handler); 2511 2512 /* remtime and current_time updated at bottom of loop */ 2513 remtime = exp_timeout; 2514 2515 time(¤t_time); 2516 end_time = current_time + remtime; 2517 2518 for (;;) { 2519 /* when buffer fills, copy second half over first and */ 2520 /* continue, so we can do matches over multiple buffers */ 2521 if (buf_length == bufsiz) { 2522 int first_half, second_half; 2523 2524 if (exp_full_buffer) { 2525 exp_debuglog("expect: full buffer\r\n"); 2526 exp_match = exp_buffer; 2527 exp_match_end = exp_buffer + buf_length; 2528 exp_buffer_end = exp_match_end; 2529 return_normally(EXP_FULLBUFFER); 2530 } 2531 first_half = bufsiz/2; 2532 second_half = bufsiz - first_half; 2533 2534 memcpy(exp_buffer,exp_buffer+first_half,second_half); 2535 buf_length = second_half; 2536 exp_buffer_end = exp_buffer + second_half; 2537 } 2538 2539 /* 2540 * always check first if pattern is already in buffer 2541 */ 2542 if (first_time) { 2543 first_time = FALSE; 2544 goto after_read; 2545 } 2546 2547 /* 2548 * check for timeout 2549 * we should timeout if either 2550 * 1) exp_timeout > remtime <= 0 (normal) 2551 * 2) exp_timeout == 0 and we have polled at least once 2552 * 2553 */ 2554 if (((exp_timeout > remtime) && (remtime <= 0)) || 2555 ((exp_timeout == 0) && polled)) { 2556 exp_debuglog("expect: timeout\r\n"); 2557 exp_match_end = exp_buffer; 2558 return_normally(EXP_TIMEOUT); 2559 } 2560 2561 /* remember that we have actually checked at least once */ 2562 polled = 1; 2563 2564 cc = i_read(fd,fp, 2565 exp_buffer_end, 2566 bufsiz - buf_length, 2567 remtime); 2568 2569 if (cc == 0) { 2570 exp_debuglog("expect: eof\r\n"); 2571 return_normally(EXP_EOF); /* normal EOF */ 2572 } else if (cc == -1) { /* abnormal EOF */ 2573 /* ptys produce EIO upon EOF - sigh */ 2574 if (i_read_errno == EIO) { 2575 /* convert to EOF indication */ 2576 exp_debuglog("expect: eof\r\n"); 2577 return_normally(EXP_EOF); 2578 } 2579 exp_debuglog("expect: error (errno = %d)\r\n",i_read_errno); 2580 return_errno(i_read_errno); 2581 } else if (cc == -2) { 2582 exp_debuglog("expect: timeout\r\n"); 2583 exp_match_end = exp_buffer; 2584 return_normally(EXP_TIMEOUT); 2585 } 2586 2587 old_length = buf_length; 2588 buf_length += cc; 2589 exp_buffer_end += buf_length; 2590 2591 if (exp_logfile_all || (exp_loguser && exp_logfile)) { 2592 fwrite(exp_buffer + old_length,1,cc,exp_logfile); 2593 } 2594 if (exp_loguser) fwrite(exp_buffer + old_length,1,cc,stdout); 2595 if (exp_debugfile) fwrite(exp_buffer + old_length,1,cc,exp_debugfile); 2596 2597 /* if we wrote to any logs, flush them */ 2598 if (exp_debugfile) fflush(exp_debugfile); 2599 if (exp_loguser) { 2600 fflush(stdout); 2601 if (exp_logfile) fflush(exp_logfile); 2602 } 2603 2604 /* remove nulls from input, so we can use C-style strings */ 2605 /* doing it here lets them be sent to the screen, just */ 2606 /* in case they are involved in formatting operations */ 2607 if (exp_remove_nulls) { 2608 buf_length -= rm_nulls(exp_buffer + old_length, cc); 2609 } 2610 /* cc should be decremented as well, but since it will not */ 2611 /* be used before being set again, there is no need */ 2612 exp_buffer_end = exp_buffer + buf_length; 2613 *exp_buffer_end = '\0'; 2614 exp_match_end = exp_buffer; 2615 2616 after_read: 2617 exp_debuglog("expect: does {%s} match ",exp_printify(exp_buffer)); 2618 /* pattern supplied */ 2619 for (ec=ecases;ec->type != exp_end;ec++) { 2620 int matched = -1; 2621 2622 exp_debuglog("{%s}? ",exp_printify(ec->pattern)); 2623 if (ec->type == exp_glob) { 2624 int offset; 2625 matched = Exp_StringMatch(exp_buffer,ec->pattern,&offset); 2626 if (matched >= 0) { 2627 exp_match = exp_buffer + offset; 2628 exp_match_end = exp_match + matched; 2629 } 2630 } else if (ec->type == exp_exact) { 2631 char *p = strstr(exp_buffer,ec->pattern); 2632 if (p) { 2633 matched = 1; 2634 exp_match = p; 2635 exp_match_end = p + strlen(ec->pattern); 2636 } 2637 } else if (ec->type == exp_null) { 2638 char *p; 2639 2640 for (p=exp_buffer;p<exp_buffer_end;p++) { 2641 if (*p == 0) { 2642 matched = 1; 2643 exp_match = p; 2644 exp_match_end = p+1; 2645 } 2646 } 2647 } else { 2648 TclRegError((char *)0); 2649 if (TclRegExec(ec->re,exp_buffer,exp_buffer)) { 2650 matched = 1; 2651 exp_match = ec->re->startp[0]; 2652 exp_match_end = ec->re->endp[0]; 2653 } else if (TclGetRegError()) { 2654 fprintf(stderr,"r.e. match (pattern %s) failed: %s",ec->pattern,TclGetRegError()); 2655 } 2656 } 2657 2658 if (matched != -1) { 2659 exp_debuglog("yes\nexp_buffer is {%s}\n", 2660 exp_printify(exp_buffer)); 2661 return_normally(ec->value); 2662 } else exp_debuglog("no\n"); 2663 } 2664 2665 /* 2666 * Update current time and remaining time. 2667 * Don't bother if we are waiting forever or polling. 2668 */ 2669 if (exp_timeout > 0) { 2670 time(¤t_time); 2671 remtime = end_time - current_time; 2672 } 2673 } 2674 cleanup: 2675 f->buffer = exp_buffer; 2676 f->buffer_end = exp_buffer_end; 2677 f->match_end = exp_match_end; 2678 2679 /* some systems (i.e., Solaris) require fp be flushed when switching */ 2680 /* directions - do this before as well */ 2681 if (fd == -1) fflush(fp); 2682 2683 if (sys_error) { 2684 errno = sys_error; 2685 return -1; 2686 } 2687 return return_val; 2688} 2689 2690int 2691exp_fexpectv(fp,ecases) 2692FILE *fp; 2693struct exp_case *ecases; 2694{ 2695 return(expectv(-1,fp,ecases)); 2696} 2697 2698int 2699exp_expectv(fd,ecases) 2700int fd; 2701struct exp_case *ecases; 2702{ 2703 return(expectv(fd,(FILE *)0,ecases)); 2704} 2705 2706/*VARARGS*/ 2707int 2708exp_expectl TCL_VARARGS_DEF(int,arg1) 2709/*exp_expectl(va_alist)*/ 2710/*va_dcl*/ 2711{ 2712 va_list args; 2713 int fd; 2714 struct exp_case *ec, *ecases; 2715 int i; 2716 enum exp_type type; 2717 2718 fd = TCL_VARARGS_START(int,arg1,args); 2719 /* va_start(args);*/ 2720 /* fd = va_arg(args,int);*/ 2721 /* first just count the arg sets */ 2722 for (i=0;;i++) { 2723 type = va_arg(args,enum exp_type); 2724 if (type == exp_end) break; 2725 2726 /* Ultrix 4.2 compiler refuses enumerations comparison!? */ 2727 if ((int)type < 0 || (int)type >= (int)exp_bogus) { 2728 fprintf(stderr,"bad type (set %d) in exp_expectl\n",i); 2729 sysreturn(EINVAL); 2730 } 2731 2732 va_arg(args,char *); /* COMPUTED BUT NOT USED */ 2733 if (type == exp_compiled) { 2734 va_arg(args,regexp *); /* COMPUTED BUT NOT USED */ 2735 } 2736 va_arg(args,int); /* COMPUTED BUT NOT USED*/ 2737 } 2738 va_end(args); 2739 2740 if (!(ecases = (struct exp_case *) 2741 malloc((1+i)*sizeof(struct exp_case)))) 2742 sysreturn(ENOMEM); 2743 2744 /* now set up the actual cases */ 2745 fd = TCL_VARARGS_START(int,arg1,args); 2746 /*va_start(args);*/ 2747 /*va_arg(args,int);*/ /*COMPUTED BUT NOT USED*/ 2748 for (ec=ecases;;ec++) { 2749 ec->type = va_arg(args,enum exp_type); 2750 if (ec->type == exp_end) break; 2751 ec->pattern = va_arg(args,char *); 2752 if (ec->type == exp_compiled) { 2753 ec->re = va_arg(args,regexp *); 2754 } else { 2755 ec->re = 0; 2756 } 2757 ec->value = va_arg(args,int); 2758 } 2759 va_end(args); 2760 i = expectv(fd,(FILE *)0,ecases); 2761 2762 for (ec=ecases;ec->type != exp_end;ec++) { 2763 /* free only if regexp and we compiled it for user */ 2764 if (ec->type == exp_regexp) { 2765 free((char *)ec->re); 2766 } 2767 } 2768 free((char *)ecases); 2769 return(i); 2770} 2771 2772int 2773exp_fexpectl TCL_VARARGS_DEF(FILE *,arg1) 2774/*exp_fexpectl(va_alist)*/ 2775/*va_dcl*/ 2776{ 2777 va_list args; 2778 FILE *fp; 2779 struct exp_case *ec, *ecases; 2780 int i; 2781 enum exp_type type; 2782 2783 fp = TCL_VARARGS_START(FILE *,arg1,args); 2784 /*va_start(args);*/ 2785 /*fp = va_arg(args,FILE *);*/ 2786 /* first just count the arg-pairs */ 2787 for (i=0;;i++) { 2788 type = va_arg(args,enum exp_type); 2789 if (type == exp_end) break; 2790 2791 /* Ultrix 4.2 compiler refuses enumerations comparison!? */ 2792 if ((int)type < 0 || (int)type >= (int)exp_bogus) { 2793 fprintf(stderr,"bad type (set %d) in exp_expectl\n",i); 2794 sysreturn(EINVAL); 2795 } 2796 2797 va_arg(args,char *); /* COMPUTED BUT NOT USED */ 2798 if (type == exp_compiled) { 2799 va_arg(args,regexp *); /* COMPUTED BUT NOT USED */ 2800 } 2801 va_arg(args,int); /* COMPUTED BUT NOT USED*/ 2802 } 2803 va_end(args); 2804 2805 if (!(ecases = (struct exp_case *) 2806 malloc((1+i)*sizeof(struct exp_case)))) 2807 sysreturn(ENOMEM); 2808 2809#if 0 2810 va_start(args); 2811 va_arg(args,FILE *); /*COMPUTED, BUT NOT USED*/ 2812#endif 2813 (void) TCL_VARARGS_START(FILE *,arg1,args); 2814 2815 for (ec=ecases;;ec++) { 2816 ec->type = va_arg(args,enum exp_type); 2817 if (ec->type == exp_end) break; 2818 ec->pattern = va_arg(args,char *); 2819 if (ec->type == exp_compiled) { 2820 ec->re = va_arg(args,regexp *); 2821 } else { 2822 ec->re = 0; 2823 } 2824 ec->value = va_arg(args,int); 2825 } 2826 va_end(args); 2827 i = expectv(-1,fp,ecases); 2828 2829 for (ec=ecases;ec->type != exp_end;ec++) { 2830 /* free only if regexp and we compiled it for user */ 2831 if (ec->type == exp_regexp) { 2832 free((char *)ec->re); 2833 } 2834 } 2835 free((char *)ecases); 2836 return(i); 2837} 2838 2839/* like popen(3) but works in both directions */ 2840FILE * 2841exp_popen(program) 2842char *program; 2843{ 2844 FILE *fp; 2845 int ec; 2846 2847 if (0 > (ec = exp_spawnl("sh","sh","-c",program,(char *)0))) return(0); 2848 if (!(fp = fdopen(ec,"r+"))) return(0); 2849 setbuf(fp,(char *)0); 2850 return(fp); 2851} 2852 2853int 2854exp_disconnect() 2855{ 2856 int ttyfd; 2857 2858#ifndef EALREADY 2859#define EALREADY 37 2860#endif 2861 2862 /* presumably, no stderr, so don't bother with error message */ 2863 if (exp_disconnected) sysreturn(EALREADY); 2864 exp_disconnected = TRUE; 2865 2866 freopen("/dev/null","r",stdin); 2867 freopen("/dev/null","w",stdout); 2868 freopen("/dev/null","w",stderr); 2869 2870#ifdef POSIX 2871 setsid(); 2872#else 2873#ifdef SYSV3 2874 /* put process in our own pgrp, and lose controlling terminal */ 2875 exp_setpgrp(); 2876 signal(SIGHUP,SIG_IGN); 2877 if (fork()) exit(0); /* first child exits (as per Stevens, */ 2878 /* UNIX Network Programming, p. 79-80) */ 2879 /* second child process continues as daemon */ 2880#else /* !SYSV3 */ 2881 exp_setpgrp(); 2882/* Pyramid lacks this defn */ 2883#ifdef TIOCNOTTY 2884 ttyfd = open("/dev/tty", O_RDWR); 2885 if (ttyfd >= 0) { 2886 /* zap controlling terminal if we had one */ 2887 (void) ioctl(ttyfd, TIOCNOTTY, (char *)0); 2888 (void) close(ttyfd); 2889 } 2890#endif /* TIOCNOTTY */ 2891#endif /* SYSV3 */ 2892#endif /* POSIX */ 2893 return(0); 2894} 2895 2896/* send to log if open and debugging enabled */ 2897/* send to stderr if debugging enabled */ 2898/* use this function for recording unusual things in the log */ 2899/*VARARGS*/ 2900void 2901exp_debuglog TCL_VARARGS_DEF(char *,arg1) 2902{ 2903 char *fmt; 2904 va_list args; 2905 2906 fmt = TCL_VARARGS_START(char *,arg1,args); 2907 if (exp_debugfile) vfprintf(exp_debugfile,fmt,args); 2908 if (exp_is_debugging) { 2909 vfprintf(stderr,fmt,args); 2910 if (exp_logfile) vfprintf(exp_logfile,fmt,args); 2911 } 2912 2913 va_end(args); 2914} 2915 2916 2917/* send to log if open */ 2918/* send to stderr */ 2919/* use this function for error conditions */ 2920/*VARARGS*/ 2921void 2922exp_errorlog TCL_VARARGS_DEF(char *,arg1) 2923{ 2924 char *fmt; 2925 va_list args; 2926 2927 fmt = TCL_VARARGS_START(char *,arg1,args); 2928 vfprintf(stderr,fmt,args); 2929 if (exp_debugfile) vfprintf(exp_debugfile,fmt,args); 2930 if (exp_logfile) vfprintf(exp_logfile,fmt,args); 2931 va_end(args); 2932} 2933 2934#include <ctype.h> 2935 2936char * 2937exp_printify(s) 2938char *s; 2939{ 2940 static int destlen = 0; 2941 static char *dest = 0; 2942 char *d; /* ptr into dest */ 2943 unsigned int need; 2944 2945 if (s == 0) return("<null>"); 2946 2947 /* worst case is every character takes 4 to printify */ 2948 need = strlen(s)*4 + 1; 2949 if (need > destlen) { 2950 if (dest) ckfree(dest); 2951 dest = ckalloc(need); 2952 destlen = need; 2953 } 2954 2955 for (d = dest;*s;s++) { 2956 if (*s == '\r') { 2957 strcpy(d,"\\r"); d += 2; 2958 } else if (*s == '\n') { 2959 strcpy(d,"\\n"); d += 2; 2960 } else if (*s == '\t') { 2961 strcpy(d,"\\t"); d += 2; 2962 } else if (isascii(*s) && isprint(*s)) { 2963 *d = *s; d += 1; 2964 } else { 2965 sprintf(d,"\\x%02x",*s & 0xff); d += 4; 2966 } 2967 } 2968 *d = '\0'; 2969 return(dest); 2970} 2971