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