aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-07-29 21:12:29 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-07-29 21:12:29 +0200
commit469998015f57a552718420a4050d90e5dae6a6fd (patch)
tree7abea9787997b088dbbf5857b8bbe9446a383274 /shell
parent0f018b30700989462de0a15b8285206d16170c1f (diff)
downloadbusybox-w32-469998015f57a552718420a4050d90e5dae6a6fd.tar.gz
busybox-w32-469998015f57a552718420a4050d90e5dae6a6fd.tar.bz2
busybox-w32-469998015f57a552718420a4050d90e5dae6a6fd.zip
ash: [PARSER] Add FAKEEOFMARK for expandstr
Upstream commit: Date: Thu, 27 Dec 2007 13:54:16 +1100 [PARSER] Add FAKEEOFMARK for expandstr Previously expandstr used the string "" to indicate that it needs to be treated just like a here-doc except that there is no terminator. However, the string "" is in fact a valid here-doc terminator so now that we deal with it correctly expandstr no longer works in the presence of new-lines in the prompt. This patch introduces the FAKEEOFMARK macro which does not equal any real EOF marker but is distinct from the NULL pointer which is used to indicate non-here-doc contexts. Thanks to Markus Triska for reporting this regression. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Unfortunately, I did not find the failing example for this old fix. I also tweaked the code which was added by this commit: " Date: Mon Sep 24 18:30:02 2007 +0000 ash: fix prompt expansion (Natanael Copa <natanael.copa@gmail.com>) " since other parts of code do expect expandstr() to use DQSYNTAX, not PSSYNTAX. function old new delta parse_stream 2609 2634 +25 setprompt_if 128 133 +5 read_profile 32 37 +5 evalcommand 1334 1339 +5 expandstr 122 120 -2 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/1 up/down: 40/-2) Total: 38 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c46
1 files changed, 27 insertions, 19 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 2bfec83e6..3184249f5 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -2488,8 +2488,18 @@ putprompt(const char *s)
2488#endif 2488#endif
2489 2489
2490/* expandstr() needs parsing machinery, so it is far away ahead... */ 2490/* expandstr() needs parsing machinery, so it is far away ahead... */
2491static const char *expandstr(const char *ps); 2491static const char *expandstr(const char *ps, int syntax_type);
2492/* Values for syntax param */
2493#define BASESYNTAX 0 /* not in quotes */
2494#define DQSYNTAX 1 /* in double quotes */
2495#define SQSYNTAX 2 /* in single quotes */
2496#define ARISYNTAX 3 /* in arithmetic */
2497#define PSSYNTAX 4 /* prompt. never passed to SIT() */
2498/* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2492 2499
2500/*
2501 * called by editline -- any expansions to the prompt should be added here.
2502 */
2493static void 2503static void
2494setprompt_if(smallint do_set, int whichprompt) 2504setprompt_if(smallint do_set, int whichprompt)
2495{ 2505{
@@ -2513,7 +2523,7 @@ setprompt_if(smallint do_set, int whichprompt)
2513 } 2523 }
2514#if ENABLE_ASH_EXPAND_PRMT 2524#if ENABLE_ASH_EXPAND_PRMT
2515 pushstackmark(&smark, stackblocksize()); 2525 pushstackmark(&smark, stackblocksize());
2516 putprompt(expandstr(prompt)); 2526 putprompt(expandstr(prompt, PSSYNTAX));
2517 popstackmark(&smark); 2527 popstackmark(&smark);
2518#else 2528#else
2519 putprompt(prompt); 2529 putprompt(prompt);
@@ -2838,13 +2848,6 @@ enum {
2838/* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF, 2848/* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2839 * caller must ensure proper cast on it if c is *char_ptr! 2849 * caller must ensure proper cast on it if c is *char_ptr!
2840 */ 2850 */
2841/* Values for syntax param */
2842#define BASESYNTAX 0 /* not in quotes */
2843#define DQSYNTAX 1 /* in double quotes */
2844#define SQSYNTAX 2 /* in single quotes */
2845#define ARISYNTAX 3 /* in arithmetic */
2846#define PSSYNTAX 4 /* prompt. never passed to SIT() */
2847
2848#if USE_SIT_FUNCTION 2851#if USE_SIT_FUNCTION
2849 2852
2850static int 2853static int
@@ -9709,7 +9712,7 @@ evalcommand(union node *cmd, int flags)
9709 if (xflag) { 9712 if (xflag) {
9710 const char *pfx = ""; 9713 const char *pfx = "";
9711 9714
9712 fdprintf(preverrout_fd, "%s", expandstr(ps4val())); 9715 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
9713 9716
9714 sp = varlist.list; 9717 sp = varlist.list;
9715 while (sp) { 9718 while (sp) {
@@ -11522,6 +11525,15 @@ decode_dollar_squote(void)
11522} 11525}
11523#endif 11526#endif
11524 11527
11528/* Used by expandstr to get here-doc like behaviour. */
11529#define FAKEEOFMARK ((char*)(uintptr_t)1)
11530
11531static ALWAYS_INLINE int
11532realeofmark(const char *eofmark)
11533{
11534 return eofmark && eofmark != FAKEEOFMARK;
11535}
11536
11525/* 11537/*
11526 * If eofmark is NULL, read a word or a redirection symbol. If eofmark 11538 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
11527 * is not NULL, read a here document. In the latter case, eofmark is the 11539 * is not NULL, read a here document. In the latter case, eofmark is the
@@ -11767,7 +11779,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11767 * we are at the end of the here document, this routine sets the c to PEOF. 11779 * we are at the end of the here document, this routine sets the c to PEOF.
11768 */ 11780 */
11769checkend: { 11781checkend: {
11770 if (eofmark) { 11782 if (realeofmark(eofmark)) {
11771 int markloc; 11783 int markloc;
11772 char *p; 11784 char *p;
11773 11785
@@ -12472,22 +12484,18 @@ parseheredoc(void)
12472} 12484}
12473 12485
12474 12486
12475/*
12476 * called by editline -- any expansions to the prompt should be added here.
12477 */
12478static const char * 12487static const char *
12479expandstr(const char *ps) 12488expandstr(const char *ps, int syntax_type)
12480{ 12489{
12481 union node n; 12490 union node n;
12482 int saveprompt; 12491 int saveprompt;
12483 12492
12484 /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value, 12493 /* XXX Fix (char *) cast. */
12485 * and token processing _can_ alter it (delete NULs etc). */
12486 setinputstring((char *)ps); 12494 setinputstring((char *)ps);
12487 12495
12488 saveprompt = doprompt; 12496 saveprompt = doprompt;
12489 doprompt = 0; 12497 doprompt = 0;
12490 readtoken1(pgetc(), PSSYNTAX, nullstr, 0); 12498 readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12491 doprompt = saveprompt; 12499 doprompt = saveprompt;
12492 12500
12493 popfile(); 12501 popfile();
@@ -13548,7 +13556,7 @@ procargs(char **argv)
13548static void 13556static void
13549read_profile(const char *name) 13557read_profile(const char *name)
13550{ 13558{
13551 name = expandstr(name); 13559 name = expandstr(name, DQSYNTAX);
13552 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0) 13560 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13553 return; 13561 return;
13554 cmdloop(0); 13562 cmdloop(0);