1 /* $OpenBSD: parse.c,v 1.8 2003/06/11 21:09:50 deraadt Exp $ */ 2 /* $NetBSD: parse.c,v 1.6 1995/03/21 09:03:10 cgd Exp $ */ 3 4 /*- 5 * Copyright (c) 1980, 1991, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 5/31/93"; 36 #else 37 static char rcsid[] = "$OpenBSD: parse.c,v 1.8 2003/06/11 21:09:50 deraadt Exp $"; 38 #endif 39 #endif /* not lint */ 40 41 #include <sys/types.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <stdarg.h> 45 46 #include "csh.h" 47 #include "extern.h" 48 49 static void asyntax(struct wordent *, struct wordent *); 50 static void asyn0(struct wordent *, struct wordent *); 51 static void asyn3(struct wordent *, struct wordent *); 52 static struct wordent 53 *freenod(struct wordent *, struct wordent *); 54 static struct command 55 *syn0(struct wordent *, struct wordent *, int); 56 static struct command 57 *syn1(struct wordent *, struct wordent *, int); 58 static struct command 59 *syn1a(struct wordent *, struct wordent *, int); 60 static struct command 61 *syn1b(struct wordent *, struct wordent *, int); 62 static struct command 63 *syn2(struct wordent *, struct wordent *, int); 64 static struct command 65 *syn3(struct wordent *, struct wordent *, int); 66 67 #define ALEFT 21 /* max of 20 alias expansions */ 68 #define HLEFT 11 /* max of 10 history expansions */ 69 /* 70 * Perform aliasing on the word list lex 71 * Do a (very rudimentary) parse to separate into commands. 72 * If word 0 of a command has an alias, do it. 73 * Repeat a maximum of 20 times. 74 */ 75 static int aleft; 76 extern int hleft; 77 void 78 alias(struct wordent *lex) 79 { 80 jmp_buf osetexit; 81 82 aleft = ALEFT; 83 hleft = HLEFT; 84 getexit(osetexit); 85 (void) setexit(); 86 if (haderr) { 87 resexit(osetexit); 88 reset(); 89 } 90 if (--aleft == 0) 91 stderror(ERR_ALIASLOOP); 92 asyntax(lex->next, lex); 93 resexit(osetexit); 94 } 95 96 static void 97 asyntax(struct wordent *p1, struct wordent *p2) 98 { 99 while (p1 != p2) 100 if (any(";&\n", p1->word[0])) 101 p1 = p1->next; 102 else { 103 asyn0(p1, p2); 104 return; 105 } 106 } 107 108 static void 109 asyn0(struct wordent *p1, struct wordent *p2) 110 { 111 struct wordent *p; 112 int l = 0; 113 114 for (p = p1; p != p2; p = p->next) 115 switch (p->word[0]) { 116 117 case '(': 118 l++; 119 continue; 120 121 case ')': 122 l--; 123 if (l < 0) 124 stderror(ERR_TOOMANYRP); 125 continue; 126 127 case '>': 128 if (p->next != p2 && eq(p->next->word, STRand)) 129 p = p->next; 130 continue; 131 132 case '&': 133 case '|': 134 case ';': 135 case '\n': 136 if (l != 0) 137 continue; 138 asyn3(p1, p); 139 asyntax(p->next, p2); 140 return; 141 } 142 if (l == 0) 143 asyn3(p1, p2); 144 } 145 146 static void 147 asyn3(struct wordent *p1, struct wordent *p2) 148 { 149 struct varent *ap; 150 struct wordent alout; 151 bool redid; 152 153 if (p1 == p2) 154 return; 155 if (p1->word[0] == '(') { 156 for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev) 157 if (p2 == p1) 158 return; 159 if (p2 == p1->next) 160 return; 161 asyn0(p1->next, p2); 162 return; 163 } 164 ap = adrof1(p1->word, &aliases); 165 if (ap == 0) 166 return; 167 alhistp = p1->prev; 168 alhistt = p2; 169 alvec = ap->vec; 170 redid = lex(&alout); 171 alhistp = alhistt = 0; 172 alvec = 0; 173 if (seterr) { 174 freelex(&alout); 175 stderror(ERR_OLD); 176 } 177 if (p1->word[0] && eq(p1->word, alout.next->word)) { 178 Char *cp = alout.next->word; 179 180 alout.next->word = Strspl(STRQNULL, cp); 181 xfree((ptr_t) cp); 182 } 183 p1 = freenod(p1, redid ? p2 : p1->next); 184 if (alout.next != &alout) { 185 p1->next->prev = alout.prev->prev; 186 alout.prev->prev->next = p1->next; 187 alout.next->prev = p1; 188 p1->next = alout.next; 189 xfree((ptr_t) alout.prev->word); 190 xfree((ptr_t) (alout.prev)); 191 } 192 reset(); /* throw! */ 193 } 194 195 static struct wordent * 196 freenod(struct wordent *p1, struct wordent *p2) 197 { 198 struct wordent *retp = p1->prev; 199 200 while (p1 != p2) { 201 xfree((ptr_t) p1->word); 202 p1 = p1->next; 203 xfree((ptr_t) (p1->prev)); 204 } 205 retp->next = p2; 206 p2->prev = retp; 207 return (retp); 208 } 209 210 #define PHERE 1 211 #define PIN 2 212 #define POUT 4 213 #define PERR 8 214 215 /* 216 * syntax 217 * empty 218 * syn0 219 */ 220 struct command * 221 syntax(struct wordent *p1, struct wordent *p2, int flags) 222 { 223 224 while (p1 != p2) 225 if (any(";&\n", p1->word[0])) 226 p1 = p1->next; 227 else 228 return (syn0(p1, p2, flags)); 229 return (0); 230 } 231 232 /* 233 * syn0 234 * syn1 235 * syn1 & syntax 236 */ 237 static struct command * 238 syn0(struct wordent *p1, struct wordent *p2, int flags) 239 { 240 struct wordent *p; 241 struct command *t, *t1; 242 int l; 243 244 l = 0; 245 for (p = p1; p != p2; p = p->next) 246 switch (p->word[0]) { 247 248 case '(': 249 l++; 250 continue; 251 252 case ')': 253 l--; 254 if (l < 0) 255 seterror(ERR_TOOMANYRP); 256 continue; 257 258 case '|': 259 if (p->word[1] == '|') 260 continue; 261 /* fall into ... */ 262 263 case '>': 264 if (p->next != p2 && eq(p->next->word, STRand)) 265 p = p->next; 266 continue; 267 268 case '&': 269 if (l != 0) 270 break; 271 if (p->word[1] == '&') 272 continue; 273 t1 = syn1(p1, p, flags); 274 if (t1->t_dtyp == NODE_LIST || 275 t1->t_dtyp == NODE_AND || 276 t1->t_dtyp == NODE_OR) { 277 t = (struct command *) xcalloc(1, sizeof(*t)); 278 t->t_dtyp = NODE_PAREN; 279 t->t_dflg = F_AMPERSAND | F_NOINTERRUPT; 280 t->t_dspr = t1; 281 t1 = t; 282 } 283 else 284 t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT; 285 t = (struct command *) xcalloc(1, sizeof(*t)); 286 t->t_dtyp = NODE_LIST; 287 t->t_dflg = 0; 288 t->t_dcar = t1; 289 t->t_dcdr = syntax(p, p2, flags); 290 return (t); 291 } 292 if (l == 0) 293 return (syn1(p1, p2, flags)); 294 seterror(ERR_TOOMANYLP); 295 return (0); 296 } 297 298 /* 299 * syn1 300 * syn1a 301 * syn1a ; syntax 302 */ 303 static struct command * 304 syn1(struct wordent *p1, struct wordent *p2, int flags) 305 { 306 struct wordent *p; 307 struct command *t; 308 int l; 309 310 l = 0; 311 for (p = p1; p != p2; p = p->next) 312 switch (p->word[0]) { 313 314 case '(': 315 l++; 316 continue; 317 318 case ')': 319 l--; 320 continue; 321 322 case ';': 323 case '\n': 324 if (l != 0) 325 break; 326 t = (struct command *) xcalloc(1, sizeof(*t)); 327 t->t_dtyp = NODE_LIST; 328 t->t_dcar = syn1a(p1, p, flags); 329 t->t_dcdr = syntax(p->next, p2, flags); 330 if (t->t_dcdr == 0) 331 t->t_dcdr = t->t_dcar, t->t_dcar = 0; 332 return (t); 333 } 334 return (syn1a(p1, p2, flags)); 335 } 336 337 /* 338 * syn1a 339 * syn1b 340 * syn1b || syn1a 341 */ 342 static struct command * 343 syn1a(struct wordent *p1, struct wordent *p2, int flags) 344 { 345 struct wordent *p; 346 struct command *t; 347 int l = 0; 348 349 for (p = p1; p != p2; p = p->next) 350 switch (p->word[0]) { 351 352 case '(': 353 l++; 354 continue; 355 356 case ')': 357 l--; 358 continue; 359 360 case '|': 361 if (p->word[1] != '|') 362 continue; 363 if (l == 0) { 364 t = (struct command *) xcalloc(1, sizeof(*t)); 365 t->t_dtyp = NODE_OR; 366 t->t_dcar = syn1b(p1, p, flags); 367 t->t_dcdr = syn1a(p->next, p2, flags); 368 t->t_dflg = 0; 369 return (t); 370 } 371 continue; 372 } 373 return (syn1b(p1, p2, flags)); 374 } 375 376 /* 377 * syn1b 378 * syn2 379 * syn2 && syn1b 380 */ 381 static struct command * 382 syn1b(struct wordent *p1, struct wordent *p2, int flags) 383 { 384 struct wordent *p; 385 struct command *t; 386 int l = 0; 387 388 for (p = p1; p != p2; p = p->next) 389 switch (p->word[0]) { 390 391 case '(': 392 l++; 393 continue; 394 395 case ')': 396 l--; 397 continue; 398 399 case '&': 400 if (p->word[1] == '&' && l == 0) { 401 t = (struct command *) xcalloc(1, sizeof(*t)); 402 t->t_dtyp = NODE_AND; 403 t->t_dcar = syn2(p1, p, flags); 404 t->t_dcdr = syn1b(p->next, p2, flags); 405 t->t_dflg = 0; 406 return (t); 407 } 408 continue; 409 } 410 return (syn2(p1, p2, flags)); 411 } 412 413 /* 414 * syn2 415 * syn3 416 * syn3 | syn2 417 * syn3 |& syn2 418 */ 419 static struct command * 420 syn2(struct wordent *p1, struct wordent *p2, int flags) 421 { 422 struct wordent *p, *pn; 423 struct command *t; 424 int l = 0; 425 int f; 426 427 for (p = p1; p != p2; p = p->next) 428 switch (p->word[0]) { 429 430 case '(': 431 l++; 432 continue; 433 434 case ')': 435 l--; 436 continue; 437 438 case '|': 439 if (l != 0) 440 continue; 441 t = (struct command *) xcalloc(1, sizeof(*t)); 442 f = flags | POUT; 443 pn = p->next; 444 if (pn != p2 && pn->word[0] == '&') { 445 f |= PERR; 446 t->t_dflg |= F_STDERR; 447 } 448 t->t_dtyp = NODE_PIPE; 449 t->t_dcar = syn3(p1, p, f); 450 if (pn != p2 && pn->word[0] == '&') 451 p = pn; 452 t->t_dcdr = syn2(p->next, p2, flags | PIN); 453 return (t); 454 } 455 return (syn3(p1, p2, flags)); 456 } 457 458 static char RELPAR[] = {'<', '>', '(', ')', '\0'}; 459 460 /* 461 * syn3 462 * ( syn0 ) [ < in ] [ > out ] 463 * word word* [ < in ] [ > out ] 464 * KEYWORD ( word* ) word* [ < in ] [ > out ] 465 * 466 * KEYWORD = (@ exit foreach if set switch test while) 467 */ 468 static struct command * 469 syn3(struct wordent *p1, struct wordent *p2, int flags) 470 { 471 struct wordent *p; 472 struct wordent *lp, *rp; 473 struct command *t; 474 int l; 475 Char **av; 476 int n, c; 477 bool specp = 0; 478 479 if (p1 != p2) { 480 p = p1; 481 again: 482 switch (srchx(p->word)) { 483 484 case T_ELSE: 485 p = p->next; 486 if (p != p2) 487 goto again; 488 break; 489 490 case T_EXIT: 491 case T_FOREACH: 492 case T_IF: 493 case T_LET: 494 case T_SET: 495 case T_SWITCH: 496 case T_WHILE: 497 specp = 1; 498 break; 499 } 500 } 501 n = 0; 502 l = 0; 503 for (p = p1; p != p2; p = p->next) 504 switch (p->word[0]) { 505 506 case '(': 507 if (specp) 508 n++; 509 l++; 510 continue; 511 512 case ')': 513 if (specp) 514 n++; 515 l--; 516 continue; 517 518 case '>': 519 case '<': 520 if (l != 0) { 521 if (specp) 522 n++; 523 continue; 524 } 525 if (p->next == p2) 526 continue; 527 if (any(RELPAR, p->next->word[0])) 528 continue; 529 n--; 530 continue; 531 532 default: 533 if (!specp && l != 0) 534 continue; 535 n++; 536 continue; 537 } 538 if (n < 0) 539 n = 0; 540 t = (struct command *) xcalloc(1, sizeof(*t)); 541 av = (Char **) xcalloc((size_t) (n + 1), sizeof(Char **)); 542 t->t_dcom = av; 543 n = 0; 544 if (p2->word[0] == ')') 545 t->t_dflg = F_NOFORK; 546 lp = 0; 547 rp = 0; 548 l = 0; 549 for (p = p1; p != p2; p = p->next) { 550 c = p->word[0]; 551 switch (c) { 552 553 case '(': 554 if (l == 0) { 555 if (lp != 0 && !specp) 556 seterror(ERR_BADPLP); 557 lp = p->next; 558 } 559 l++; 560 goto savep; 561 562 case ')': 563 l--; 564 if (l == 0) 565 rp = p; 566 goto savep; 567 568 case '>': 569 if (l != 0) 570 goto savep; 571 if (p->word[1] == '>') 572 t->t_dflg |= F_APPEND; 573 if (p->next != p2 && eq(p->next->word, STRand)) { 574 t->t_dflg |= F_STDERR, p = p->next; 575 if (flags & (POUT | PERR)) { 576 seterror(ERR_OUTRED); 577 continue; 578 } 579 } 580 if (p->next != p2 && eq(p->next->word, STRbang)) 581 t->t_dflg |= F_OVERWRITE, p = p->next; 582 if (p->next == p2) { 583 seterror(ERR_MISRED); 584 continue; 585 } 586 p = p->next; 587 if (any(RELPAR, p->word[0])) { 588 seterror(ERR_MISRED); 589 continue; 590 } 591 if ((flags & POUT) && ((flags & PERR) == 0 || t->t_drit)) 592 seterror(ERR_OUTRED); 593 else 594 t->t_drit = Strsave(p->word); 595 continue; 596 597 case '<': 598 if (l != 0) 599 goto savep; 600 if (p->word[1] == '<') 601 t->t_dflg |= F_READ; 602 if (p->next == p2) { 603 seterror(ERR_MISRED); 604 continue; 605 } 606 p = p->next; 607 if (any(RELPAR, p->word[0])) { 608 seterror(ERR_MISRED); 609 continue; 610 } 611 if ((flags & PHERE) && (t->t_dflg & F_READ)) 612 seterror(ERR_REDPAR); 613 else if ((flags & PIN) || t->t_dlef) 614 seterror(ERR_INRED); 615 else 616 t->t_dlef = Strsave(p->word); 617 continue; 618 619 savep: 620 if (!specp) 621 continue; 622 default: 623 if (l != 0 && !specp) 624 continue; 625 if (seterr == 0) 626 av[n] = Strsave(p->word); 627 n++; 628 continue; 629 } 630 } 631 if (lp != 0 && !specp) { 632 if (n != 0) 633 seterror(ERR_BADPLPS); 634 t->t_dtyp = NODE_PAREN; 635 t->t_dspr = syn0(lp, rp, PHERE); 636 } 637 else { 638 if (n == 0) 639 seterror(ERR_NULLCOM); 640 t->t_dtyp = NODE_COMMAND; 641 } 642 return (t); 643 } 644 645 void 646 freesyn(struct command *t) 647 { 648 Char **v; 649 650 if (t == 0) 651 return; 652 switch (t->t_dtyp) { 653 654 case NODE_COMMAND: 655 for (v = t->t_dcom; *v; v++) 656 xfree((ptr_t) * v); 657 xfree((ptr_t) (t->t_dcom)); 658 xfree((ptr_t) t->t_dlef); 659 xfree((ptr_t) t->t_drit); 660 break; 661 case NODE_PAREN: 662 freesyn(t->t_dspr); 663 xfree((ptr_t) t->t_dlef); 664 xfree((ptr_t) t->t_drit); 665 break; 666 667 case NODE_AND: 668 case NODE_OR: 669 case NODE_PIPE: 670 case NODE_LIST: 671 freesyn(t->t_dcar), freesyn(t->t_dcdr); 672 break; 673 } 674 xfree((ptr_t) t); 675 } 676