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