1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Kenneth Almquist. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #ifndef lint 36 #if 0 37 static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95"; 38 #endif 39 #endif /* not lint */ 40 #include <sys/cdefs.h> 41 __FBSDID("$FreeBSD: head/bin/sh/parser.c 343399 2019-01-24 11:59:46Z trasz $"); 42 43 #include <sys/param.h> 44 #include <pwd.h> 45 #include <stdlib.h> 46 #include <unistd.h> 47 #include <stdio.h> 48 49 #include "shell.h" 50 #include "parser.h" 51 #include "nodes.h" 52 #include "expand.h" /* defines rmescapes() */ 53 #include "syntax.h" 54 #include "options.h" 55 #include "input.h" 56 #include "output.h" 57 #include "var.h" 58 #include "error.h" 59 #include "memalloc.h" 60 #include "mystring.h" 61 #include "alias.h" 62 #include "show.h" 63 #include "eval.h" 64 #include "exec.h" /* to check for special builtins */ 65 #ifndef NO_HISTORY 66 #include "myhistedit.h" 67 #endif 68 69 /* 70 * Shell command parser. 71 */ 72 73 #define PROMPTLEN 128 74 75 /* values of checkkwd variable */ 76 #define CHKALIAS 0x1 77 #define CHKKWD 0x2 78 #define CHKNL 0x4 79 80 /* values returned by readtoken */ 81 #include "token.h" 82 83 84 85 struct heredoc { 86 struct heredoc *next; /* next here document in list */ 87 union node *here; /* redirection node */ 88 char *eofmark; /* string indicating end of input */ 89 int striptabs; /* if set, strip leading tabs */ 90 }; 91 92 struct parser_temp { 93 struct parser_temp *next; 94 void *data; 95 }; 96 97 98 static struct heredoc *heredoclist; /* list of here documents to read */ 99 static int doprompt; /* if set, prompt the user */ 100 static int needprompt; /* true if interactive and at start of line */ 101 static int lasttoken; /* last token read */ 102 static int tokpushback; /* last token pushed back */ 103 static char *wordtext; /* text of last word returned by readtoken */ 104 static int checkkwd; 105 static struct nodelist *backquotelist; 106 static union node *redirnode; 107 static struct heredoc *heredoc; 108 static int quoteflag; /* set if (part of) last token was quoted */ 109 static int startlinno; /* line # where last token started */ 110 static int funclinno; /* line # where the current function started */ 111 static struct parser_temp *parser_temp; 112 113 #define NOEOFMARK ((const char *)&heredoclist) 114 115 116 static union node *list(int); 117 static union node *andor(void); 118 static union node *pipeline(void); 119 static union node *command(void); 120 static union node *simplecmd(union node **, union node *); 121 static union node *makename(void); 122 static union node *makebinary(int type, union node *n1, union node *n2); 123 static void parsefname(void); 124 static void parseheredoc(void); 125 static int peektoken(void); 126 static int readtoken(void); 127 static int xxreadtoken(void); 128 static int readtoken1(int, const char *, const char *, int); 129 static int noexpand(char *); 130 static void consumetoken(int); 131 static void synexpect(int) __dead2; 132 static void synerror(const char *) __dead2; 133 static void setprompt(int); 134 static int pgetc_linecont(void); 135 static void getusername(char *, size_t); 136 137 138 static void * 139 parser_temp_alloc(size_t len) 140 { 141 struct parser_temp *t; 142 143 INTOFF; 144 t = ckmalloc(sizeof(*t)); 145 t->data = NULL; 146 t->next = parser_temp; 147 parser_temp = t; 148 t->data = ckmalloc(len); 149 INTON; 150 return t->data; 151 } 152 153 154 static void * 155 parser_temp_realloc(void *ptr, size_t len) 156 { 157 struct parser_temp *t; 158 159 INTOFF; 160 t = parser_temp; 161 if (ptr != t->data) 162 error("bug: parser_temp_realloc misused"); 163 t->data = ckrealloc(t->data, len); 164 INTON; 165 return t->data; 166 } 167 168 169 static void 170 parser_temp_free_upto(void *ptr) 171 { 172 struct parser_temp *t; 173 int done = 0; 174 175 INTOFF; 176 while (parser_temp != NULL && !done) { 177 t = parser_temp; 178 parser_temp = t->next; 179 done = t->data == ptr; 180 ckfree(t->data); 181 ckfree(t); 182 } 183 INTON; 184 if (!done) 185 error("bug: parser_temp_free_upto misused"); 186 } 187 188 189 static void 190 parser_temp_free_all(void) 191 { 192 struct parser_temp *t; 193 194 INTOFF; 195 while (parser_temp != NULL) { 196 t = parser_temp; 197 parser_temp = t->next; 198 ckfree(t->data); 199 ckfree(t); 200 } 201 INTON; 202 } 203 204 205 /* 206 * Read and parse a command. Returns NEOF on end of file. (NULL is a 207 * valid parse tree indicating a blank line.) 208 */ 209 210 union node * 211 parsecmd(int interact) 212 { 213 int t; 214 215 /* This assumes the parser is not re-entered, 216 * which could happen if we add command substitution on PS1/PS2. 217 */ 218 parser_temp_free_all(); 219 heredoclist = NULL; 220 221 tokpushback = 0; 222 checkkwd = 0; 223 doprompt = interact; 224 if (doprompt) 225 setprompt(1); 226 else 227 setprompt(0); 228 needprompt = 0; 229 t = readtoken(); 230 if (t == TEOF) 231 return NEOF; 232 if (t == TNL) 233 return NULL; 234 tokpushback++; 235 return list(1); 236 } 237 238 239 #if 0 240 /* 241 * Read and parse words for wordexp. 242 * Returns a list of NARG nodes; NULL if there are no words. 243 */ 244 union node * 245 parsewordexp(void) 246 { 247 union node *n, *first = NULL, **pnext; 248 int t; 249 250 /* This assumes the parser is not re-entered, 251 * which could happen if we add command substitution on PS1/PS2. 252 */ 253 parser_temp_free_all(); 254 heredoclist = NULL; 255 256 tokpushback = 0; 257 checkkwd = 0; 258 doprompt = 0; 259 setprompt(0); 260 needprompt = 0; 261 pnext = &first; 262 while ((t = readtoken()) != TEOF) { 263 if (t != TWORD) 264 synexpect(TWORD); 265 n = makename(); 266 *pnext = n; 267 pnext = &n->narg.next; 268 } 269 return first; 270 } 271 #endif 272 273 274 static union node * 275 list(int nlflag) 276 { 277 union node *ntop, *n1, *n2, *n3; 278 int tok; 279 280 checkkwd = CHKNL | CHKKWD | CHKALIAS; 281 if (!nlflag && tokendlist[peektoken()]) 282 return NULL; 283 ntop = n1 = NULL; 284 for (;;) { 285 n2 = andor(); 286 tok = readtoken(); 287 if (tok == TBACKGND) { 288 if (n2 != NULL && n2->type == NPIPE) { 289 n2->npipe.backgnd = 1; 290 } else if (n2 != NULL && n2->type == NREDIR) { 291 n2->type = NBACKGND; 292 } else { 293 n3 = (union node *)stalloc(sizeof (struct nredir)); 294 n3->type = NBACKGND; 295 n3->nredir.n = n2; 296 n3->nredir.redirect = NULL; 297 n2 = n3; 298 } 299 } 300 if (ntop == NULL) 301 ntop = n2; 302 else if (n1 == NULL) { 303 n1 = makebinary(NSEMI, ntop, n2); 304 ntop = n1; 305 } 306 else { 307 n3 = makebinary(NSEMI, n1->nbinary.ch2, n2); 308 n1->nbinary.ch2 = n3; 309 n1 = n3; 310 } 311 switch (tok) { 312 case TBACKGND: 313 case TSEMI: 314 tok = readtoken(); 315 /* FALLTHROUGH */ 316 case TNL: 317 if (tok == TNL) { 318 parseheredoc(); 319 if (nlflag) 320 return ntop; 321 } else if (tok == TEOF && nlflag) { 322 parseheredoc(); 323 return ntop; 324 } else { 325 tokpushback++; 326 } 327 checkkwd = CHKNL | CHKKWD | CHKALIAS; 328 if (!nlflag && tokendlist[peektoken()]) 329 return ntop; 330 break; 331 case TEOF: 332 if (heredoclist) 333 parseheredoc(); 334 else 335 pungetc(); /* push back EOF on input */ 336 return ntop; 337 default: 338 if (nlflag) 339 synexpect(-1); 340 tokpushback++; 341 return ntop; 342 } 343 } 344 } 345 346 347 348 static union node * 349 andor(void) 350 { 351 union node *n; 352 int t; 353 354 n = pipeline(); 355 for (;;) { 356 if ((t = readtoken()) == TAND) { 357 t = NAND; 358 } else if (t == TOR) { 359 t = NOR; 360 } else { 361 tokpushback++; 362 return n; 363 } 364 n = makebinary(t, n, pipeline()); 365 } 366 } 367 368 369 370 static union node * 371 pipeline(void) 372 { 373 union node *n1, *n2, *pipenode; 374 struct nodelist *lp, *prev; 375 int negate, t; 376 377 negate = 0; 378 checkkwd = CHKNL | CHKKWD | CHKALIAS; 379 TRACE(("pipeline: entered\n")); 380 while (readtoken() == TNOT) 381 negate = !negate; 382 tokpushback++; 383 n1 = command(); 384 if (readtoken() == TPIPE) { 385 pipenode = (union node *)stalloc(sizeof (struct npipe)); 386 pipenode->type = NPIPE; 387 pipenode->npipe.backgnd = 0; 388 lp = (struct nodelist *)stalloc(sizeof (struct nodelist)); 389 pipenode->npipe.cmdlist = lp; 390 lp->n = n1; 391 do { 392 prev = lp; 393 lp = (struct nodelist *)stalloc(sizeof (struct nodelist)); 394 checkkwd = CHKNL | CHKKWD | CHKALIAS; 395 t = readtoken(); 396 tokpushback++; 397 if (t == TNOT) 398 lp->n = pipeline(); 399 else 400 lp->n = command(); 401 prev->next = lp; 402 } while (readtoken() == TPIPE); 403 lp->next = NULL; 404 n1 = pipenode; 405 } 406 tokpushback++; 407 if (negate) { 408 n2 = (union node *)stalloc(sizeof (struct nnot)); 409 n2->type = NNOT; 410 n2->nnot.com = n1; 411 return n2; 412 } else 413 return n1; 414 } 415 416 417 418 static union node * 419 command(void) 420 { 421 union node *n1, *n2; 422 union node *ap, **app; 423 union node *cp, **cpp; 424 union node *redir, **rpp; 425 int t; 426 int is_subshell; 427 428 checkkwd = CHKNL | CHKKWD | CHKALIAS; 429 is_subshell = 0; 430 redir = NULL; 431 n1 = NULL; 432 rpp = &redir; 433 434 /* Check for redirection which may precede command */ 435 while (readtoken() == TREDIR) { 436 *rpp = n2 = redirnode; 437 rpp = &n2->nfile.next; 438 parsefname(); 439 } 440 tokpushback++; 441 442 switch (readtoken()) { 443 case TIF: 444 n1 = (union node *)stalloc(sizeof (struct nif)); 445 n1->type = NIF; 446 if ((n1->nif.test = list(0)) == NULL) 447 synexpect(-1); 448 consumetoken(TTHEN); 449 n1->nif.ifpart = list(0); 450 n2 = n1; 451 while (readtoken() == TELIF) { 452 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif)); 453 n2 = n2->nif.elsepart; 454 n2->type = NIF; 455 if ((n2->nif.test = list(0)) == NULL) 456 synexpect(-1); 457 consumetoken(TTHEN); 458 n2->nif.ifpart = list(0); 459 } 460 if (lasttoken == TELSE) 461 n2->nif.elsepart = list(0); 462 else { 463 n2->nif.elsepart = NULL; 464 tokpushback++; 465 } 466 consumetoken(TFI); 467 checkkwd = CHKKWD | CHKALIAS; 468 break; 469 case TWHILE: 470 case TUNTIL: 471 t = lasttoken; 472 if ((n1 = list(0)) == NULL) 473 synexpect(-1); 474 consumetoken(TDO); 475 n1 = makebinary((t == TWHILE)? NWHILE : NUNTIL, n1, list(0)); 476 consumetoken(TDONE); 477 checkkwd = CHKKWD | CHKALIAS; 478 break; 479 case TFOR: 480 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext)) 481 synerror("Bad for loop variable"); 482 n1 = (union node *)stalloc(sizeof (struct nfor)); 483 n1->type = NFOR; 484 n1->nfor.var = wordtext; 485 while (readtoken() == TNL) 486 ; 487 if (lasttoken == TWORD && ! quoteflag && equal(wordtext, "in")) { 488 app = ≈ 489 while (readtoken() == TWORD) { 490 n2 = makename(); 491 *app = n2; 492 app = &n2->narg.next; 493 } 494 *app = NULL; 495 n1->nfor.args = ap; 496 if (lasttoken != TNL && lasttoken != TSEMI) 497 synexpect(-1); 498 } else { 499 static char argvars[5] = { 500 CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' 501 }; 502 n2 = (union node *)stalloc(sizeof (struct narg)); 503 n2->type = NARG; 504 n2->narg.text = argvars; 505 n2->narg.backquote = NULL; 506 n2->narg.next = NULL; 507 n1->nfor.args = n2; 508 /* 509 * Newline or semicolon here is optional (but note 510 * that the original Bourne shell only allowed NL). 511 */ 512 if (lasttoken != TNL && lasttoken != TSEMI) 513 tokpushback++; 514 } 515 checkkwd = CHKNL | CHKKWD | CHKALIAS; 516 if ((t = readtoken()) == TDO) 517 t = TDONE; 518 else if (t == TBEGIN) 519 t = TEND; 520 else 521 synexpect(-1); 522 n1->nfor.body = list(0); 523 consumetoken(t); 524 checkkwd = CHKKWD | CHKALIAS; 525 break; 526 case TCASE: 527 n1 = (union node *)stalloc(sizeof (struct ncase)); 528 n1->type = NCASE; 529 consumetoken(TWORD); 530 n1->ncase.expr = makename(); 531 while (readtoken() == TNL); 532 if (lasttoken != TWORD || ! equal(wordtext, "in")) 533 synerror("expecting \"in\""); 534 cpp = &n1->ncase.cases; 535 checkkwd = CHKNL | CHKKWD, readtoken(); 536 while (lasttoken != TESAC) { 537 *cpp = cp = (union node *)stalloc(sizeof (struct nclist)); 538 cp->type = NCLIST; 539 app = &cp->nclist.pattern; 540 if (lasttoken == TLP) 541 readtoken(); 542 for (;;) { 543 *app = ap = makename(); 544 checkkwd = CHKNL | CHKKWD; 545 if (readtoken() != TPIPE) 546 break; 547 app = &ap->narg.next; 548 readtoken(); 549 } 550 ap->narg.next = NULL; 551 if (lasttoken != TRP) 552 synexpect(TRP); 553 cp->nclist.body = list(0); 554 555 checkkwd = CHKNL | CHKKWD | CHKALIAS; 556 if ((t = readtoken()) != TESAC) { 557 if (t == TENDCASE) 558 ; 559 else if (t == TFALLTHRU) 560 cp->type = NCLISTFALLTHRU; 561 else 562 synexpect(TENDCASE); 563 checkkwd = CHKNL | CHKKWD, readtoken(); 564 } 565 cpp = &cp->nclist.next; 566 } 567 *cpp = NULL; 568 checkkwd = CHKKWD | CHKALIAS; 569 break; 570 case TLP: 571 n1 = (union node *)stalloc(sizeof (struct nredir)); 572 n1->type = NSUBSHELL; 573 n1->nredir.n = list(0); 574 n1->nredir.redirect = NULL; 575 consumetoken(TRP); 576 checkkwd = CHKKWD | CHKALIAS; 577 is_subshell = 1; 578 break; 579 case TBEGIN: 580 n1 = list(0); 581 consumetoken(TEND); 582 checkkwd = CHKKWD | CHKALIAS; 583 break; 584 /* A simple command must have at least one redirection or word. */ 585 case TBACKGND: 586 case TSEMI: 587 case TAND: 588 case TOR: 589 case TPIPE: 590 case TENDCASE: 591 case TFALLTHRU: 592 case TEOF: 593 case TNL: 594 case TRP: 595 if (!redir) 596 synexpect(-1); 597 /* FALLTHROUGH */ 598 case TWORD: 599 tokpushback++; 600 n1 = simplecmd(rpp, redir); 601 return n1; 602 default: 603 synexpect(-1); 604 } 605 606 /* Now check for redirection which may follow command */ 607 while (readtoken() == TREDIR) { 608 *rpp = n2 = redirnode; 609 rpp = &n2->nfile.next; 610 parsefname(); 611 } 612 tokpushback++; 613 *rpp = NULL; 614 if (redir) { 615 if (!is_subshell) { 616 n2 = (union node *)stalloc(sizeof (struct nredir)); 617 n2->type = NREDIR; 618 n2->nredir.n = n1; 619 n1 = n2; 620 } 621 n1->nredir.redirect = redir; 622 } 623 624 return n1; 625 } 626 627 628 static union node * 629 simplecmd(union node **rpp, union node *redir) 630 { 631 union node *args, **app; 632 union node **orig_rpp = rpp; 633 union node *n = NULL; 634 int special; 635 int savecheckkwd; 636 637 /* If we don't have any redirections already, then we must reset */ 638 /* rpp to be the address of the local redir variable. */ 639 if (redir == NULL) 640 rpp = &redir; 641 642 args = NULL; 643 app = &args; 644 /* 645 * We save the incoming value, because we need this for shell 646 * functions. There can not be a redirect or an argument between 647 * the function name and the open parenthesis. 648 */ 649 orig_rpp = rpp; 650 651 savecheckkwd = CHKALIAS; 652 653 for (;;) { 654 checkkwd = savecheckkwd; 655 if (readtoken() == TWORD) { 656 n = makename(); 657 *app = n; 658 app = &n->narg.next; 659 if (savecheckkwd != 0 && !isassignment(wordtext)) 660 savecheckkwd = 0; 661 } else if (lasttoken == TREDIR) { 662 *rpp = n = redirnode; 663 rpp = &n->nfile.next; 664 parsefname(); /* read name of redirection file */ 665 } else if (lasttoken == TLP && app == &args->narg.next 666 && rpp == orig_rpp) { 667 /* We have a function */ 668 consumetoken(TRP); 669 funclinno = plinno; 670 /* 671 * - Require plain text. 672 * - Functions with '/' cannot be called. 673 * - Reject name=(). 674 * - Reject ksh extended glob patterns. 675 */ 676 if (!noexpand(n->narg.text) || quoteflag || 677 strchr(n->narg.text, '/') || 678 strchr("!%*+-=?@}~", 679 n->narg.text[strlen(n->narg.text) - 1])) 680 synerror("Bad function name"); 681 rmescapes(n->narg.text); 682 if (find_builtin(n->narg.text, &special) >= 0 && 683 special) 684 synerror("Cannot override a special builtin with a function"); 685 n->type = NDEFUN; 686 n->narg.next = command(); 687 funclinno = 0; 688 return n; 689 } else { 690 tokpushback++; 691 break; 692 } 693 } 694 *app = NULL; 695 *rpp = NULL; 696 n = (union node *)stalloc(sizeof (struct ncmd)); 697 n->type = NCMD; 698 n->ncmd.args = args; 699 n->ncmd.redirect = redir; 700 return n; 701 } 702 703 static union node * 704 makename(void) 705 { 706 union node *n; 707 708 n = (union node *)stalloc(sizeof (struct narg)); 709 n->type = NARG; 710 n->narg.next = NULL; 711 n->narg.text = wordtext; 712 n->narg.backquote = backquotelist; 713 return n; 714 } 715 716 static union node * 717 makebinary(int type, union node *n1, union node *n2) 718 { 719 union node *n; 720 721 n = (union node *)stalloc(sizeof (struct nbinary)); 722 n->type = type; 723 n->nbinary.ch1 = n1; 724 n->nbinary.ch2 = n2; 725 return (n); 726 } 727 728 void 729 forcealias(void) 730 { 731 checkkwd |= CHKALIAS; 732 } 733 734 void 735 fixredir(union node *n, const char *text, int err) 736 { 737 TRACE(("Fix redir %s %d\n", text, err)); 738 if (!err) 739 n->ndup.vname = NULL; 740 741 if (is_digit(text[0]) && text[1] == '\0') 742 n->ndup.dupfd = digit_val(text[0]); 743 else if (text[0] == '-' && text[1] == '\0') 744 n->ndup.dupfd = -1; 745 else { 746 747 if (err) 748 synerror("Bad fd number"); 749 else 750 n->ndup.vname = makename(); 751 } 752 } 753 754 755 static void 756 parsefname(void) 757 { 758 union node *n = redirnode; 759 760 consumetoken(TWORD); 761 if (n->type == NHERE) { 762 struct heredoc *here = heredoc; 763 struct heredoc *p; 764 765 if (quoteflag == 0) 766 n->type = NXHERE; 767 TRACE(("Here document %d\n", n->type)); 768 if (here->striptabs) { 769 while (*wordtext == '\t') 770 wordtext++; 771 } 772 if (! noexpand(wordtext)) 773 synerror("Illegal eof marker for << redirection"); 774 rmescapes(wordtext); 775 here->eofmark = wordtext; 776 here->next = NULL; 777 if (heredoclist == NULL) 778 heredoclist = here; 779 else { 780 for (p = heredoclist ; p->next ; p = p->next); 781 p->next = here; 782 } 783 } else if (n->type == NTOFD || n->type == NFROMFD) { 784 fixredir(n, wordtext, 0); 785 } else { 786 n->nfile.fname = makename(); 787 } 788 } 789 790 791 /* 792 * Input any here documents. 793 */ 794 795 static void 796 parseheredoc(void) 797 { 798 struct heredoc *here; 799 union node *n; 800 801 while (heredoclist) { 802 here = heredoclist; 803 heredoclist = here->next; 804 if (needprompt) { 805 setprompt(2); 806 needprompt = 0; 807 } 808 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX, 809 here->eofmark, here->striptabs); 810 n = makename(); 811 here->here->nhere.doc = n; 812 } 813 } 814 815 static int 816 peektoken(void) 817 { 818 int t; 819 820 t = readtoken(); 821 tokpushback++; 822 return (t); 823 } 824 825 static int 826 readtoken(void) 827 { 828 int t; 829 struct alias *ap; 830 #ifdef DEBUG 831 int alreadyseen = tokpushback; 832 #endif 833 834 top: 835 t = xxreadtoken(); 836 837 /* 838 * eat newlines 839 */ 840 if (checkkwd & CHKNL) { 841 while (t == TNL) { 842 parseheredoc(); 843 t = xxreadtoken(); 844 } 845 } 846 847 /* 848 * check for keywords and aliases 849 */ 850 if (t == TWORD && !quoteflag) 851 { 852 const char * const *pp; 853 854 if (checkkwd & CHKKWD) 855 for (pp = parsekwd; *pp; pp++) { 856 if (**pp == *wordtext && equal(*pp, wordtext)) 857 { 858 lasttoken = t = pp - parsekwd + KWDOFFSET; 859 TRACE(("keyword %s recognized\n", tokname[t])); 860 goto out; 861 } 862 } 863 if (checkkwd & CHKALIAS && 864 (ap = lookupalias(wordtext, 1)) != NULL) { 865 pushstring(ap->val, strlen(ap->val), ap); 866 goto top; 867 } 868 } 869 out: 870 if (t != TNOT) 871 checkkwd = 0; 872 873 #ifdef DEBUG 874 if (!alreadyseen) 875 TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : "")); 876 else 877 TRACE(("reread token %s %s\n", tokname[t], t == TWORD ? wordtext : "")); 878 #endif 879 return (t); 880 } 881 882 883 /* 884 * Read the next input token. 885 * If the token is a word, we set backquotelist to the list of cmds in 886 * backquotes. We set quoteflag to true if any part of the word was 887 * quoted. 888 * If the token is TREDIR, then we set redirnode to a structure containing 889 * the redirection. 890 * In all cases, the variable startlinno is set to the number of the line 891 * on which the token starts. 892 * 893 * [Change comment: here documents and internal procedures] 894 * [Readtoken shouldn't have any arguments. Perhaps we should make the 895 * word parsing code into a separate routine. In this case, readtoken 896 * doesn't need to have any internal procedures, but parseword does. 897 * We could also make parseoperator in essence the main routine, and 898 * have parseword (readtoken1?) handle both words and redirection.] 899 */ 900 901 #define RETURN(token) return lasttoken = token 902 903 static int 904 xxreadtoken(void) 905 { 906 int c; 907 908 if (tokpushback) { 909 tokpushback = 0; 910 return lasttoken; 911 } 912 if (needprompt) { 913 setprompt(2); 914 needprompt = 0; 915 } 916 startlinno = plinno; 917 for (;;) { /* until token or start of word found */ 918 c = pgetc_macro(); 919 switch (c) { 920 case ' ': case '\t': 921 continue; 922 case '#': 923 while ((c = pgetc()) != '\n' && c != PEOF); 924 pungetc(); 925 continue; 926 case '\\': 927 if (pgetc() == '\n') { 928 startlinno = ++plinno; 929 if (doprompt) 930 setprompt(2); 931 else 932 setprompt(0); 933 continue; 934 } 935 pungetc(); 936 /* FALLTHROUGH */ 937 default: 938 return readtoken1(c, BASESYNTAX, (char *)NULL, 0); 939 case '\n': 940 plinno++; 941 needprompt = doprompt; 942 RETURN(TNL); 943 case PEOF: 944 RETURN(TEOF); 945 case '&': 946 if (pgetc_linecont() == '&') 947 RETURN(TAND); 948 pungetc(); 949 RETURN(TBACKGND); 950 case '|': 951 if (pgetc_linecont() == '|') 952 RETURN(TOR); 953 pungetc(); 954 RETURN(TPIPE); 955 case ';': 956 c = pgetc_linecont(); 957 if (c == ';') 958 RETURN(TENDCASE); 959 else if (c == '&') 960 RETURN(TFALLTHRU); 961 pungetc(); 962 RETURN(TSEMI); 963 case '(': 964 RETURN(TLP); 965 case ')': 966 RETURN(TRP); 967 } 968 } 969 #undef RETURN 970 } 971 972 973 #define MAXNEST_static 8 974 struct tokenstate 975 { 976 const char *syntax; /* *SYNTAX */ 977 int parenlevel; /* levels of parentheses in arithmetic */ 978 enum tokenstate_category 979 { 980 TSTATE_TOP, 981 TSTATE_VAR_OLD, /* ${var+-=?}, inherits dquotes */ 982 TSTATE_VAR_NEW, /* other ${var...}, own dquote state */ 983 TSTATE_ARITH 984 } category; 985 }; 986 987 988 /* 989 * Check to see whether we are at the end of the here document. When this 990 * is called, c is set to the first character of the next input line. If 991 * we are at the end of the here document, this routine sets the c to PEOF. 992 * The new value of c is returned. 993 */ 994 995 static int 996 checkend(int c, const char *eofmark, int striptabs) 997 { 998 if (striptabs) { 999 while (c == '\t') 1000 c = pgetc(); 1001 } 1002 if (c == *eofmark) { 1003 int c2; 1004 const char *q; 1005 1006 for (q = eofmark + 1; c2 = pgetc(), *q != '\0' && c2 == *q; q++) 1007 ; 1008 if ((c2 == PEOF || c2 == '\n') && *q == '\0') { 1009 c = PEOF; 1010 if (c2 == '\n') { 1011 plinno++; 1012 needprompt = doprompt; 1013 } 1014 } else { 1015 pungetc(); 1016 pushstring(eofmark + 1, q - (eofmark + 1), NULL); 1017 } 1018 } else if (c == '\n' && *eofmark == '\0') { 1019 c = PEOF; 1020 plinno++; 1021 needprompt = doprompt; 1022 } 1023 return (c); 1024 } 1025 1026 1027 /* 1028 * Parse a redirection operator. The variable "out" points to a string 1029 * specifying the fd to be redirected. The variable "c" contains the 1030 * first character of the redirection operator. 1031 */ 1032 1033 static void 1034 parseredir(char *out, int c) 1035 { 1036 char fd = *out; 1037 union node *np; 1038 1039 np = (union node *)stalloc(sizeof (struct nfile)); 1040 if (c == '>') { 1041 np->nfile.fd = 1; 1042 c = pgetc_linecont(); 1043 if (c == '>') 1044 np->type = NAPPEND; 1045 else if (c == '&') 1046 np->type = NTOFD; 1047 else if (c == '|') 1048 np->type = NCLOBBER; 1049 else { 1050 np->type = NTO; 1051 pungetc(); 1052 } 1053 } else { /* c == '<' */ 1054 np->nfile.fd = 0; 1055 c = pgetc_linecont(); 1056 if (c == '<') { 1057 if (sizeof (struct nfile) != sizeof (struct nhere)) { 1058 np = (union node *)stalloc(sizeof (struct nhere)); 1059 np->nfile.fd = 0; 1060 } 1061 np->type = NHERE; 1062 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc)); 1063 heredoc->here = np; 1064 if ((c = pgetc_linecont()) == '-') { 1065 heredoc->striptabs = 1; 1066 } else { 1067 heredoc->striptabs = 0; 1068 pungetc(); 1069 } 1070 } else if (c == '&') 1071 np->type = NFROMFD; 1072 else if (c == '>') 1073 np->type = NFROMTO; 1074 else { 1075 np->type = NFROM; 1076 pungetc(); 1077 } 1078 } 1079 if (fd != '\0') 1080 np->nfile.fd = digit_val(fd); 1081 redirnode = np; 1082 } 1083 1084 /* 1085 * Called to parse command substitutions. 1086 */ 1087 1088 static char * 1089 parsebackq(char *out, struct nodelist **pbqlist, 1090 int oldstyle, int dblquote, int quoted) 1091 { 1092 struct nodelist **nlpp; 1093 union node *n; 1094 char *volatile str; 1095 struct jmploc jmploc; 1096 struct jmploc *const savehandler = handler; 1097 size_t savelen; 1098 int saveprompt; 1099 const int bq_startlinno = plinno; 1100 char *volatile ostr = NULL; 1101 struct parsefile *const savetopfile = getcurrentfile(); 1102 struct heredoc *const saveheredoclist = heredoclist; 1103 struct heredoc *here; 1104 1105 str = NULL; 1106 if (setjmp(jmploc.loc)) { 1107 popfilesupto(savetopfile); 1108 if (str) 1109 ckfree(str); 1110 if (ostr) 1111 ckfree(ostr); 1112 heredoclist = saveheredoclist; 1113 handler = savehandler; 1114 if (exception == EXERROR) { 1115 startlinno = bq_startlinno; 1116 synerror("Error in command substitution"); 1117 } 1118 longjmp(handler->loc, 1); 1119 } 1120 INTOFF; 1121 savelen = out - stackblock(); 1122 if (savelen > 0) { 1123 str = ckmalloc(savelen); 1124 memcpy(str, stackblock(), savelen); 1125 } 1126 handler = &jmploc; 1127 heredoclist = NULL; 1128 INTON; 1129 if (oldstyle) { 1130 /* We must read until the closing backquote, giving special 1131 treatment to some slashes, and then push the string and 1132 reread it as input, interpreting it normally. */ 1133 char *oout; 1134 int c; 1135 int olen; 1136 1137 1138 STARTSTACKSTR(oout); 1139 for (;;) { 1140 if (needprompt) { 1141 setprompt(2); 1142 needprompt = 0; 1143 } 1144 CHECKSTRSPACE(2, oout); 1145 c = pgetc_linecont(); 1146 if (c == '`') 1147 break; 1148 switch (c) { 1149 case '\\': 1150 c = pgetc(); 1151 if (c != '\\' && c != '`' && c != '$' 1152 && (!dblquote || c != '"')) 1153 USTPUTC('\\', oout); 1154 break; 1155 1156 case '\n': 1157 plinno++; 1158 needprompt = doprompt; 1159 break; 1160 1161 case PEOF: 1162 startlinno = plinno; 1163 synerror("EOF in backquote substitution"); 1164 break; 1165 1166 default: 1167 break; 1168 } 1169 USTPUTC(c, oout); 1170 } 1171 USTPUTC('\0', oout); 1172 olen = oout - stackblock(); 1173 INTOFF; 1174 ostr = ckmalloc(olen); 1175 memcpy(ostr, stackblock(), olen); 1176 setinputstring(ostr, 1); 1177 INTON; 1178 } 1179 nlpp = pbqlist; 1180 while (*nlpp) 1181 nlpp = &(*nlpp)->next; 1182 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist)); 1183 (*nlpp)->next = NULL; 1184 1185 if (oldstyle) { 1186 saveprompt = doprompt; 1187 doprompt = 0; 1188 } 1189 1190 n = list(0); 1191 1192 if (oldstyle) { 1193 if (peektoken() != TEOF) 1194 synexpect(-1); 1195 doprompt = saveprompt; 1196 } else 1197 consumetoken(TRP); 1198 1199 (*nlpp)->n = n; 1200 if (oldstyle) { 1201 /* 1202 * Start reading from old file again, ignoring any pushed back 1203 * tokens left from the backquote parsing 1204 */ 1205 popfile(); 1206 tokpushback = 0; 1207 } 1208 STARTSTACKSTR(out); 1209 CHECKSTRSPACE(savelen + 1, out); 1210 INTOFF; 1211 if (str) { 1212 memcpy(out, str, savelen); 1213 STADJUST(savelen, out); 1214 ckfree(str); 1215 str = NULL; 1216 } 1217 if (ostr) { 1218 ckfree(ostr); 1219 ostr = NULL; 1220 } 1221 here = saveheredoclist; 1222 if (here != NULL) { 1223 while (here->next != NULL) 1224 here = here->next; 1225 here->next = heredoclist; 1226 heredoclist = saveheredoclist; 1227 } 1228 handler = savehandler; 1229 INTON; 1230 if (quoted) 1231 USTPUTC(CTLBACKQ | CTLQUOTE, out); 1232 else 1233 USTPUTC(CTLBACKQ, out); 1234 return out; 1235 } 1236 1237 1238 /* 1239 * Called to parse a backslash escape sequence inside $'...'. 1240 * The backslash has already been read. 1241 */ 1242 static char * 1243 readcstyleesc(char *out) 1244 { 1245 int c, vc, i, n; 1246 unsigned int v; 1247 1248 c = pgetc(); 1249 switch (c) { 1250 case '\0': 1251 synerror("Unterminated quoted string"); 1252 case '\n': 1253 plinno++; 1254 if (doprompt) 1255 setprompt(2); 1256 else 1257 setprompt(0); 1258 return out; 1259 case '\\': 1260 case '\'': 1261 case '"': 1262 v = c; 1263 break; 1264 case 'a': v = '\a'; break; 1265 case 'b': v = '\b'; break; 1266 case 'e': v = '\033'; break; 1267 case 'f': v = '\f'; break; 1268 case 'n': v = '\n'; break; 1269 case 'r': v = '\r'; break; 1270 case 't': v = '\t'; break; 1271 case 'v': v = '\v'; break; 1272 case 'x': 1273 v = 0; 1274 for (;;) { 1275 c = pgetc(); 1276 if (c >= '0' && c <= '9') 1277 v = (v << 4) + c - '0'; 1278 else if (c >= 'A' && c <= 'F') 1279 v = (v << 4) + c - 'A' + 10; 1280 else if (c >= 'a' && c <= 'f') 1281 v = (v << 4) + c - 'a' + 10; 1282 else 1283 break; 1284 } 1285 pungetc(); 1286 break; 1287 case '0': case '1': case '2': case '3': 1288 case '4': case '5': case '6': case '7': 1289 v = c - '0'; 1290 c = pgetc(); 1291 if (c >= '0' && c <= '7') { 1292 v <<= 3; 1293 v += c - '0'; 1294 c = pgetc(); 1295 if (c >= '0' && c <= '7') { 1296 v <<= 3; 1297 v += c - '0'; 1298 } else 1299 pungetc(); 1300 } else 1301 pungetc(); 1302 break; 1303 case 'c': 1304 c = pgetc(); 1305 if (c < 0x3f || c > 0x7a || c == 0x60) 1306 synerror("Bad escape sequence"); 1307 if (c == '\\' && pgetc() != '\\') 1308 synerror("Bad escape sequence"); 1309 if (c == '?') 1310 v = 127; 1311 else 1312 v = c & 0x1f; 1313 break; 1314 case 'u': 1315 case 'U': 1316 n = c == 'U' ? 8 : 4; 1317 v = 0; 1318 for (i = 0; i < n; i++) { 1319 c = pgetc(); 1320 if (c >= '0' && c <= '9') 1321 v = (v << 4) + c - '0'; 1322 else if (c >= 'A' && c <= 'F') 1323 v = (v << 4) + c - 'A' + 10; 1324 else if (c >= 'a' && c <= 'f') 1325 v = (v << 4) + c - 'a' + 10; 1326 else 1327 synerror("Bad escape sequence"); 1328 } 1329 if (v == 0 || (v >= 0xd800 && v <= 0xdfff)) 1330 synerror("Bad escape sequence"); 1331 /* We really need iconv here. */ 1332 if (initial_localeisutf8 && v > 127) { 1333 CHECKSTRSPACE(4, out); 1334 /* 1335 * We cannot use wctomb() as the locale may have 1336 * changed. 1337 */ 1338 if (v <= 0x7ff) { 1339 USTPUTC(0xc0 | v >> 6, out); 1340 USTPUTC(0x80 | (v & 0x3f), out); 1341 return out; 1342 } else if (v <= 0xffff) { 1343 USTPUTC(0xe0 | v >> 12, out); 1344 USTPUTC(0x80 | ((v >> 6) & 0x3f), out); 1345 USTPUTC(0x80 | (v & 0x3f), out); 1346 return out; 1347 } else if (v <= 0x10ffff) { 1348 USTPUTC(0xf0 | v >> 18, out); 1349 USTPUTC(0x80 | ((v >> 12) & 0x3f), out); 1350 USTPUTC(0x80 | ((v >> 6) & 0x3f), out); 1351 USTPUTC(0x80 | (v & 0x3f), out); 1352 return out; 1353 } 1354 } 1355 if (v > 127) 1356 v = '?'; 1357 break; 1358 default: 1359 synerror("Bad escape sequence"); 1360 } 1361 vc = (char)v; 1362 /* 1363 * We can't handle NUL bytes. 1364 * POSIX says we should skip till the closing quote. 1365 */ 1366 if (vc == '\0') { 1367 while ((c = pgetc()) != '\'') { 1368 if (c == '\\') 1369 c = pgetc(); 1370 if (c == PEOF) 1371 synerror("Unterminated quoted string"); 1372 if (c == '\n') { 1373 plinno++; 1374 if (doprompt) 1375 setprompt(2); 1376 else 1377 setprompt(0); 1378 } 1379 } 1380 pungetc(); 1381 return out; 1382 } 1383 if (SQSYNTAX[vc] == CCTL) 1384 USTPUTC(CTLESC, out); 1385 USTPUTC(vc, out); 1386 return out; 1387 } 1388 1389 1390 /* 1391 * If eofmark is NULL, read a word or a redirection symbol. If eofmark 1392 * is not NULL, read a here document. In the latter case, eofmark is the 1393 * word which marks the end of the document and striptabs is true if 1394 * leading tabs should be stripped from the document. The argument firstc 1395 * is the first character of the input token or document. 1396 * 1397 * Because C does not have internal subroutines, I have simulated them 1398 * using goto's to implement the subroutine linkage. The following macros 1399 * will run code that appears at the end of readtoken1. 1400 */ 1401 1402 #define PARSESUB() {goto parsesub; parsesub_return:;} 1403 #define PARSEARITH() {goto parsearith; parsearith_return:;} 1404 1405 static int 1406 readtoken1(int firstc, char const *initialsyntax, const char *eofmark, 1407 int striptabs) 1408 { 1409 int c = firstc; 1410 char *out; 1411 int len; 1412 struct nodelist *bqlist; 1413 int quotef; 1414 int newvarnest; 1415 int level; 1416 int synentry; 1417 struct tokenstate state_static[MAXNEST_static]; 1418 int maxnest = MAXNEST_static; 1419 struct tokenstate *state = state_static; 1420 int sqiscstyle = 0; 1421 1422 startlinno = plinno; 1423 quotef = 0; 1424 bqlist = NULL; 1425 newvarnest = 0; 1426 level = 0; 1427 state[level].syntax = initialsyntax; 1428 state[level].parenlevel = 0; 1429 state[level].category = TSTATE_TOP; 1430 1431 STARTSTACKSTR(out); 1432 loop: { /* for each line, until end of word */ 1433 if (eofmark && eofmark != NOEOFMARK) 1434 /* set c to PEOF if at end of here document */ 1435 c = checkend(c, eofmark, striptabs); 1436 for (;;) { /* until end of line or end of word */ 1437 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */ 1438 1439 synentry = state[level].syntax[c]; 1440 1441 switch(synentry) { 1442 case CNL: /* '\n' */ 1443 if (level == 0) 1444 goto endword; /* exit outer loop */ 1445 /* FALLTHROUGH */ 1446 case CQNL: 1447 USTPUTC(c, out); 1448 plinno++; 1449 if (doprompt) 1450 setprompt(2); 1451 else 1452 setprompt(0); 1453 c = pgetc(); 1454 goto loop; /* continue outer loop */ 1455 case CSBACK: 1456 if (sqiscstyle) { 1457 out = readcstyleesc(out); 1458 break; 1459 } 1460 /* FALLTHROUGH */ 1461 case CWORD: 1462 USTPUTC(c, out); 1463 break; 1464 case CCTL: 1465 if (eofmark == NULL || initialsyntax != SQSYNTAX) 1466 USTPUTC(CTLESC, out); 1467 USTPUTC(c, out); 1468 break; 1469 case CBACK: /* backslash */ 1470 c = pgetc(); 1471 if (c == PEOF) { 1472 USTPUTC('\\', out); 1473 pungetc(); 1474 } else if (c == '\n') { 1475 plinno++; 1476 if (doprompt) 1477 setprompt(2); 1478 else 1479 setprompt(0); 1480 } else { 1481 if (state[level].syntax == DQSYNTAX && 1482 c != '\\' && c != '`' && c != '$' && 1483 (c != '"' || (eofmark != NULL && 1484 newvarnest == 0)) && 1485 (c != '}' || state[level].category != TSTATE_VAR_OLD)) 1486 USTPUTC('\\', out); 1487 if ((eofmark == NULL || 1488 newvarnest > 0) && 1489 state[level].syntax == BASESYNTAX) 1490 USTPUTC(CTLQUOTEMARK, out); 1491 if (SQSYNTAX[c] == CCTL) 1492 USTPUTC(CTLESC, out); 1493 USTPUTC(c, out); 1494 if ((eofmark == NULL || 1495 newvarnest > 0) && 1496 state[level].syntax == BASESYNTAX && 1497 state[level].category == TSTATE_VAR_OLD) 1498 USTPUTC(CTLQUOTEEND, out); 1499 quotef++; 1500 } 1501 break; 1502 case CSQUOTE: 1503 USTPUTC(CTLQUOTEMARK, out); 1504 state[level].syntax = SQSYNTAX; 1505 sqiscstyle = 0; 1506 break; 1507 case CDQUOTE: 1508 USTPUTC(CTLQUOTEMARK, out); 1509 state[level].syntax = DQSYNTAX; 1510 break; 1511 case CENDQUOTE: 1512 if (eofmark != NULL && newvarnest == 0) 1513 USTPUTC(c, out); 1514 else { 1515 if (state[level].category == TSTATE_VAR_OLD) 1516 USTPUTC(CTLQUOTEEND, out); 1517 state[level].syntax = BASESYNTAX; 1518 quotef++; 1519 } 1520 break; 1521 case CVAR: /* '$' */ 1522 PARSESUB(); /* parse substitution */ 1523 break; 1524 case CENDVAR: /* '}' */ 1525 if (level > 0 && 1526 ((state[level].category == TSTATE_VAR_OLD && 1527 state[level].syntax == 1528 state[level - 1].syntax) || 1529 (state[level].category == TSTATE_VAR_NEW && 1530 state[level].syntax == BASESYNTAX))) { 1531 if (state[level].category == TSTATE_VAR_NEW) 1532 newvarnest--; 1533 level--; 1534 USTPUTC(CTLENDVAR, out); 1535 } else { 1536 USTPUTC(c, out); 1537 } 1538 break; 1539 case CLP: /* '(' in arithmetic */ 1540 state[level].parenlevel++; 1541 USTPUTC(c, out); 1542 break; 1543 case CRP: /* ')' in arithmetic */ 1544 if (state[level].parenlevel > 0) { 1545 USTPUTC(c, out); 1546 --state[level].parenlevel; 1547 } else { 1548 if (pgetc_linecont() == ')') { 1549 if (level > 0 && 1550 state[level].category == TSTATE_ARITH) { 1551 level--; 1552 USTPUTC(CTLENDARI, out); 1553 } else 1554 USTPUTC(')', out); 1555 } else { 1556 /* 1557 * unbalanced parens 1558 * (don't 2nd guess - no error) 1559 */ 1560 pungetc(); 1561 USTPUTC(')', out); 1562 } 1563 } 1564 break; 1565 case CBQUOTE: /* '`' */ 1566 out = parsebackq(out, &bqlist, 1, 1567 state[level].syntax == DQSYNTAX && 1568 (eofmark == NULL || newvarnest > 0), 1569 state[level].syntax == DQSYNTAX || state[level].syntax == ARISYNTAX); 1570 break; 1571 case CEOF: 1572 goto endword; /* exit outer loop */ 1573 case CIGN: 1574 break; 1575 default: 1576 if (level == 0) 1577 goto endword; /* exit outer loop */ 1578 USTPUTC(c, out); 1579 } 1580 c = pgetc_macro(); 1581 } 1582 } 1583 endword: 1584 if (state[level].syntax == ARISYNTAX) 1585 synerror("Missing '))'"); 1586 if (state[level].syntax != BASESYNTAX && eofmark == NULL) 1587 synerror("Unterminated quoted string"); 1588 if (state[level].category == TSTATE_VAR_OLD || 1589 state[level].category == TSTATE_VAR_NEW) { 1590 startlinno = plinno; 1591 synerror("Missing '}'"); 1592 } 1593 if (state != state_static) 1594 parser_temp_free_upto(state); 1595 USTPUTC('\0', out); 1596 len = out - stackblock(); 1597 out = stackblock(); 1598 if (eofmark == NULL) { 1599 if ((c == '>' || c == '<') 1600 && quotef == 0 1601 && len <= 2 1602 && (*out == '\0' || is_digit(*out))) { 1603 parseredir(out, c); 1604 return lasttoken = TREDIR; 1605 } else { 1606 pungetc(); 1607 } 1608 } 1609 quoteflag = quotef; 1610 backquotelist = bqlist; 1611 grabstackblock(len); 1612 wordtext = out; 1613 return lasttoken = TWORD; 1614 /* end of readtoken routine */ 1615 1616 1617 /* 1618 * Parse a substitution. At this point, we have read the dollar sign 1619 * and nothing else. 1620 */ 1621 1622 parsesub: { 1623 int subtype; 1624 int typeloc; 1625 int flags; 1626 char *p; 1627 static const char types[] = "}-+?="; 1628 int linno; 1629 int length; 1630 int c1; 1631 1632 c = pgetc_linecont(); 1633 if (c == '(') { /* $(command) or $((arith)) */ 1634 if (pgetc_linecont() == '(') { 1635 PARSEARITH(); 1636 } else { 1637 pungetc(); 1638 out = parsebackq(out, &bqlist, 0, 1639 state[level].syntax == DQSYNTAX && 1640 (eofmark == NULL || newvarnest > 0), 1641 state[level].syntax == DQSYNTAX || 1642 state[level].syntax == ARISYNTAX); 1643 } 1644 } else if (c == '{' || is_name(c) || is_special(c)) { 1645 USTPUTC(CTLVAR, out); 1646 typeloc = out - stackblock(); 1647 USTPUTC(VSNORMAL, out); 1648 subtype = VSNORMAL; 1649 flags = 0; 1650 if (c == '{') { 1651 c = pgetc_linecont(); 1652 subtype = 0; 1653 } 1654 varname: 1655 if (!is_eof(c) && is_name(c)) { 1656 length = 0; 1657 do { 1658 STPUTC(c, out); 1659 c = pgetc_linecont(); 1660 length++; 1661 } while (!is_eof(c) && is_in_name(c)); 1662 if (length == 6 && 1663 strncmp(out - length, "LINENO", length) == 0) { 1664 /* Replace the variable name with the 1665 * current line number. */ 1666 STADJUST(-6, out); 1667 CHECKSTRSPACE(11, out); 1668 linno = plinno; 1669 if (funclinno != 0) 1670 linno -= funclinno - 1; 1671 length = snprintf(out, 11, "%d", linno); 1672 if (length > 10) 1673 length = 10; 1674 out += length; 1675 flags |= VSLINENO; 1676 } 1677 } else if (is_digit(c)) { 1678 if (subtype != VSNORMAL) { 1679 do { 1680 STPUTC(c, out); 1681 c = pgetc_linecont(); 1682 } while (is_digit(c)); 1683 } else { 1684 USTPUTC(c, out); 1685 c = pgetc_linecont(); 1686 } 1687 } else if (is_special(c)) { 1688 c1 = c; 1689 c = pgetc_linecont(); 1690 if (subtype == 0 && c1 == '#') { 1691 subtype = VSLENGTH; 1692 if (strchr(types, c) == NULL && c != ':' && 1693 c != '#' && c != '%') 1694 goto varname; 1695 c1 = c; 1696 c = pgetc_linecont(); 1697 if (c1 != '}' && c == '}') { 1698 pungetc(); 1699 c = c1; 1700 goto varname; 1701 } 1702 pungetc(); 1703 c = c1; 1704 c1 = '#'; 1705 subtype = 0; 1706 } 1707 USTPUTC(c1, out); 1708 } else { 1709 subtype = VSERROR; 1710 if (c == '}') 1711 pungetc(); 1712 else if (c == '\n' || c == PEOF) 1713 synerror("Unexpected end of line in substitution"); 1714 else if (BASESYNTAX[c] != CCTL) 1715 USTPUTC(c, out); 1716 } 1717 if (subtype == 0) { 1718 switch (c) { 1719 case ':': 1720 flags |= VSNUL; 1721 c = pgetc_linecont(); 1722 /*FALLTHROUGH*/ 1723 default: 1724 p = strchr(types, c); 1725 if (p == NULL) { 1726 if (c == '\n' || c == PEOF) 1727 synerror("Unexpected end of line in substitution"); 1728 if (flags == VSNUL) 1729 STPUTC(':', out); 1730 if (BASESYNTAX[c] != CCTL) 1731 STPUTC(c, out); 1732 subtype = VSERROR; 1733 } else 1734 subtype = p - types + VSNORMAL; 1735 break; 1736 case '%': 1737 case '#': 1738 { 1739 int cc = c; 1740 subtype = c == '#' ? VSTRIMLEFT : 1741 VSTRIMRIGHT; 1742 c = pgetc_linecont(); 1743 if (c == cc) 1744 subtype++; 1745 else 1746 pungetc(); 1747 break; 1748 } 1749 } 1750 } else if (subtype != VSERROR) { 1751 if (subtype == VSLENGTH && c != '}') 1752 subtype = VSERROR; 1753 pungetc(); 1754 } 1755 STPUTC('=', out); 1756 if (state[level].syntax == DQSYNTAX || 1757 state[level].syntax == ARISYNTAX) 1758 flags |= VSQUOTE; 1759 *(stackblock() + typeloc) = subtype | flags; 1760 if (subtype != VSNORMAL) { 1761 if (level + 1 >= maxnest) { 1762 maxnest *= 2; 1763 if (state == state_static) { 1764 state = parser_temp_alloc( 1765 maxnest * sizeof(*state)); 1766 memcpy(state, state_static, 1767 MAXNEST_static * sizeof(*state)); 1768 } else 1769 state = parser_temp_realloc(state, 1770 maxnest * sizeof(*state)); 1771 } 1772 level++; 1773 state[level].parenlevel = 0; 1774 if (subtype == VSMINUS || subtype == VSPLUS || 1775 subtype == VSQUESTION || subtype == VSASSIGN) { 1776 /* 1777 * For operators that were in the Bourne shell, 1778 * inherit the double-quote state. 1779 */ 1780 state[level].syntax = state[level - 1].syntax; 1781 state[level].category = TSTATE_VAR_OLD; 1782 } else { 1783 /* 1784 * The other operators take a pattern, 1785 * so go to BASESYNTAX. 1786 * Also, ' and " are now special, even 1787 * in here documents. 1788 */ 1789 state[level].syntax = BASESYNTAX; 1790 state[level].category = TSTATE_VAR_NEW; 1791 newvarnest++; 1792 } 1793 } 1794 } else if (c == '\'' && state[level].syntax == BASESYNTAX) { 1795 /* $'cstylequotes' */ 1796 USTPUTC(CTLQUOTEMARK, out); 1797 state[level].syntax = SQSYNTAX; 1798 sqiscstyle = 1; 1799 } else { 1800 USTPUTC('$', out); 1801 pungetc(); 1802 } 1803 goto parsesub_return; 1804 } 1805 1806 1807 /* 1808 * Parse an arithmetic expansion (indicate start of one and set state) 1809 */ 1810 parsearith: { 1811 1812 if (level + 1 >= maxnest) { 1813 maxnest *= 2; 1814 if (state == state_static) { 1815 state = parser_temp_alloc( 1816 maxnest * sizeof(*state)); 1817 memcpy(state, state_static, 1818 MAXNEST_static * sizeof(*state)); 1819 } else 1820 state = parser_temp_realloc(state, 1821 maxnest * sizeof(*state)); 1822 } 1823 level++; 1824 state[level].syntax = ARISYNTAX; 1825 state[level].parenlevel = 0; 1826 state[level].category = TSTATE_ARITH; 1827 USTPUTC(CTLARI, out); 1828 if (state[level - 1].syntax == DQSYNTAX) 1829 USTPUTC('"',out); 1830 else 1831 USTPUTC(' ',out); 1832 goto parsearith_return; 1833 } 1834 1835 } /* end of readtoken */ 1836 1837 1838 /* 1839 * Returns true if the text contains nothing to expand (no dollar signs 1840 * or backquotes). 1841 */ 1842 1843 static int 1844 noexpand(char *text) 1845 { 1846 char *p; 1847 char c; 1848 1849 p = text; 1850 while ((c = *p++) != '\0') { 1851 if ( c == CTLQUOTEMARK) 1852 continue; 1853 if (c == CTLESC) 1854 p++; 1855 else if (BASESYNTAX[(int)c] == CCTL) 1856 return 0; 1857 } 1858 return 1; 1859 } 1860 1861 1862 /* 1863 * Return true if the argument is a legal variable name (a letter or 1864 * underscore followed by zero or more letters, underscores, and digits). 1865 */ 1866 1867 int 1868 goodname(const char *name) 1869 { 1870 const char *p; 1871 1872 p = name; 1873 if (! is_name(*p)) 1874 return 0; 1875 while (*++p) { 1876 if (! is_in_name(*p)) 1877 return 0; 1878 } 1879 return 1; 1880 } 1881 1882 1883 int 1884 isassignment(const char *p) 1885 { 1886 if (!is_name(*p)) 1887 return 0; 1888 p++; 1889 for (;;) { 1890 if (*p == '=') 1891 return 1; 1892 else if (!is_in_name(*p)) 1893 return 0; 1894 p++; 1895 } 1896 } 1897 1898 1899 static void 1900 consumetoken(int token) 1901 { 1902 if (readtoken() != token) 1903 synexpect(token); 1904 } 1905 1906 1907 /* 1908 * Called when an unexpected token is read during the parse. The argument 1909 * is the token that is expected, or -1 if more than one type of token can 1910 * occur at this point. 1911 */ 1912 1913 static void 1914 synexpect(int token) 1915 { 1916 char msg[64]; 1917 1918 if (token >= 0) { 1919 fmtstr(msg, 64, "%s unexpected (expecting %s)", 1920 tokname[lasttoken], tokname[token]); 1921 } else { 1922 fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]); 1923 } 1924 synerror(msg); 1925 } 1926 1927 1928 static void 1929 synerror(const char *msg) 1930 { 1931 if (commandname) 1932 outfmt(out2, "%s: %d: ", commandname, startlinno); 1933 else if (arg0) 1934 outfmt(out2, "%s: ", arg0); 1935 outfmt(out2, "Syntax error: %s\n", msg); 1936 error((char *)NULL); 1937 } 1938 1939 static void 1940 setprompt(int which) 1941 { 1942 whichprompt = which; 1943 if (which == 0) 1944 return; 1945 1946 #ifndef NO_HISTORY 1947 if (!el) 1948 #endif 1949 { 1950 out2str(getprompt(NULL)); 1951 flushout(out2); 1952 } 1953 } 1954 1955 static int 1956 pgetc_linecont(void) 1957 { 1958 int c; 1959 1960 while ((c = pgetc_macro()) == '\\') { 1961 c = pgetc(); 1962 if (c == '\n') { 1963 plinno++; 1964 if (doprompt) 1965 setprompt(2); 1966 else 1967 setprompt(0); 1968 } else { 1969 pungetc(); 1970 /* Allow the backslash to be pushed back. */ 1971 pushstring("\\", 1, NULL); 1972 return (pgetc()); 1973 } 1974 } 1975 return (c); 1976 } 1977 1978 1979 static struct passwd * 1980 getpwlogin(void) 1981 { 1982 const char *login; 1983 1984 login = getlogin(); 1985 if (login == NULL) 1986 return (NULL); 1987 1988 return (getpwnam(login)); 1989 } 1990 1991 1992 static void 1993 getusername(char *name, size_t namelen) 1994 { 1995 static char cached_name[MAXLOGNAME]; 1996 struct passwd *pw; 1997 uid_t euid; 1998 1999 if (cached_name[0] == '\0') { 2000 euid = geteuid(); 2001 2002 /* 2003 * Handle the case when there is more than one 2004 * login with the same UID, or when the login 2005 * returned by getlogin(2) does no longer match 2006 * the current UID. 2007 */ 2008 pw = getpwlogin(); 2009 if (pw == NULL || pw->pw_uid != euid) 2010 pw = getpwuid(euid); 2011 2012 if (pw != NULL) { 2013 strlcpy(cached_name, pw->pw_name, 2014 sizeof(cached_name)); 2015 } else { 2016 snprintf(cached_name, sizeof(cached_name), 2017 "%u", euid); 2018 } 2019 } 2020 2021 strlcpy(name, cached_name, namelen); 2022 } 2023 2024 2025 /* 2026 * called by editline -- any expansions to the prompt 2027 * should be added here. 2028 */ 2029 char * 2030 getprompt(void *unused __unused) 2031 { 2032 static char ps[PROMPTLEN]; 2033 const char *fmt; 2034 const char *home; 2035 const char *pwd; 2036 size_t homelen; 2037 int i, trim; 2038 static char internal_error[] = "??"; 2039 2040 /* 2041 * Select prompt format. 2042 */ 2043 switch (whichprompt) { 2044 case 0: 2045 fmt = ""; 2046 break; 2047 case 1: 2048 fmt = ps1val(); 2049 break; 2050 case 2: 2051 fmt = ps2val(); 2052 break; 2053 default: 2054 return internal_error; 2055 } 2056 2057 /* 2058 * Format prompt string. 2059 */ 2060 for (i = 0; (i < PROMPTLEN - 1) && (*fmt != '\0'); i++, fmt++) 2061 if (*fmt == '\\') 2062 switch (*++fmt) { 2063 2064 /* 2065 * Hostname. 2066 * 2067 * \h specifies just the local hostname, 2068 * \H specifies fully-qualified hostname. 2069 */ 2070 case 'h': 2071 case 'H': 2072 ps[i] = '\0'; 2073 gethostname(&ps[i], PROMPTLEN - i - 1); 2074 ps[PROMPTLEN - 1] = '\0'; 2075 /* Skip to end of hostname. */ 2076 trim = (*fmt == 'h') ? '.' : '\0'; 2077 while ((ps[i] != '\0') && (ps[i] != trim)) 2078 i++; 2079 --i; 2080 break; 2081 2082 /* 2083 * User name. 2084 */ 2085 case 'u': 2086 ps[i] = '\0'; 2087 getusername(&ps[i], PROMPTLEN - i); 2088 /* Skip to end of username. */ 2089 while (ps[i + 1] != '\0') 2090 i++; 2091 break; 2092 2093 /* 2094 * Working directory. 2095 * 2096 * \W specifies just the final component, 2097 * \w specifies the entire path. 2098 */ 2099 case 'W': 2100 case 'w': 2101 pwd = lookupvar("PWD"); 2102 if (pwd == NULL || *pwd == '\0') 2103 pwd = "?"; 2104 if (*fmt == 'W' && 2105 *pwd == '/' && pwd[1] != '\0') 2106 strlcpy(&ps[i], strrchr(pwd, '/') + 1, 2107 PROMPTLEN - i); 2108 else { 2109 home = lookupvar("HOME"); 2110 if (home != NULL) 2111 homelen = strlen(home); 2112 if (home != NULL && 2113 strcmp(home, "/") != 0 && 2114 strncmp(pwd, home, homelen) == 0 && 2115 (pwd[homelen] == '/' || 2116 pwd[homelen] == '\0')) { 2117 strlcpy(&ps[i], "~", 2118 PROMPTLEN - i); 2119 strlcpy(&ps[i + 1], 2120 pwd + homelen, 2121 PROMPTLEN - i - 1); 2122 } else { 2123 strlcpy(&ps[i], pwd, PROMPTLEN - i); 2124 } 2125 } 2126 /* Skip to end of path. */ 2127 while (ps[i + 1] != '\0') 2128 i++; 2129 break; 2130 2131 /* 2132 * Superuser status. 2133 * 2134 * '$' for normal users, '#' for root. 2135 */ 2136 case '$': 2137 ps[i] = (geteuid() != 0) ? '$' : '#'; 2138 break; 2139 2140 /* 2141 * A literal \. 2142 */ 2143 case '\\': 2144 ps[i] = '\\'; 2145 break; 2146 2147 /* 2148 * Emit unrecognized formats verbatim. 2149 */ 2150 default: 2151 ps[i] = '\\'; 2152 if (i < PROMPTLEN - 2) 2153 ps[++i] = *fmt; 2154 break; 2155 } 2156 else 2157 ps[i] = *fmt; 2158 ps[i] = '\0'; 2159 return (ps); 2160 } 2161 2162 2163 const char * 2164 expandstr(const char *ps) 2165 { 2166 union node n; 2167 struct jmploc jmploc; 2168 struct jmploc *const savehandler = handler; 2169 const int saveprompt = doprompt; 2170 struct parsefile *const savetopfile = getcurrentfile(); 2171 struct parser_temp *const saveparser_temp = parser_temp; 2172 const char *result = NULL; 2173 2174 if (!setjmp(jmploc.loc)) { 2175 handler = &jmploc; 2176 parser_temp = NULL; 2177 setinputstring(ps, 1); 2178 doprompt = 0; 2179 readtoken1(pgetc(), DQSYNTAX, NOEOFMARK, 0); 2180 if (backquotelist != NULL) 2181 error("Command substitution not allowed here"); 2182 2183 n.narg.type = NARG; 2184 n.narg.next = NULL; 2185 n.narg.text = wordtext; 2186 n.narg.backquote = backquotelist; 2187 2188 expandarg(&n, NULL, 0); 2189 result = stackblock(); 2190 INTOFF; 2191 } 2192 handler = savehandler; 2193 doprompt = saveprompt; 2194 popfilesupto(savetopfile); 2195 if (parser_temp != saveparser_temp) { 2196 parser_temp_free_all(); 2197 parser_temp = saveparser_temp; 2198 } 2199 if (result != NULL) { 2200 INTON; 2201 } else if (exception == EXINT) 2202 raise(SIGINT); 2203 return result; 2204 } 2205