Thu Mar 31 23:11:05 2016 UTC ()
After discussions with Jilles Tjoelker (FreeBSD shell) and
following a suggestion from him, the way the fix to PR bin/50993
was implemented has changed a little.   There are three steps involved
in processing a here document, reading it, parsing it, and then
evaluating it before applying it to the correct file descriptor for
the command to use.  The third of those is not related to this
problem, and has not changed.  The bug was caused by combining the
first two steps into one (and not doing it correctly - which would be
hard that way.)  The fix is to split the first two stages into
separate events.   The original fix moved the 2nd stage (parsing)
to just immediately before the 3rd stage (evaluation.)  Jilles
pointed out some unwanted side effects from doing it that way, and
suggested moving the 2nd stage to immediately after the first.
This commit makes that change.  The effect is to revert the changes
to expand.c and parser.h (which are no longer needed) and simplify
slightly the change to parser.c. (from kre@)


(christos)
diff -r1.114 -r1.115 src/bin/sh/parser.c
diff -r1.20 -r1.21 src/bin/sh/parser.h

cvs diff -r1.114 -r1.115 src/bin/sh/parser.c (expand / switch to unified diff)

--- src/bin/sh/parser.c 2016/03/31 16:12:52 1.114
+++ src/bin/sh/parser.c 2016/03/31 23:11:05 1.115
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: parser.c,v 1.114 2016/03/31 16:12:52 christos Exp $ */ 1/* $NetBSD: parser.c,v 1.115 2016/03/31 23:11:05 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1991, 1993 4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist. 8 * Kenneth Almquist.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36#ifndef lint 36#ifndef lint
37#if 0 37#if 0
38static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95"; 38static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95";
39#else 39#else
40__RCSID("$NetBSD: parser.c,v 1.114 2016/03/31 16:12:52 christos Exp $"); 40__RCSID("$NetBSD: parser.c,v 1.115 2016/03/31 23:11:05 christos Exp $");
41#endif 41#endif
42#endif /* not lint */ 42#endif /* not lint */
43 43
44#include <stdio.h> 44#include <stdio.h>
45#include <stdlib.h> 45#include <stdlib.h>
46#include <limits.h> 46#include <limits.h>
47 47
48#include "shell.h" 48#include "shell.h"
49#include "parser.h" 49#include "parser.h"
50#include "nodes.h" 50#include "nodes.h"
51#include "expand.h" /* defines rmescapes() */ 51#include "expand.h" /* defines rmescapes() */
52#include "eval.h" /* defines commandname */ 52#include "eval.h" /* defines commandname */
53#include "redir.h" /* defines copyfd() */ 53#include "redir.h" /* defines copyfd() */
@@ -99,27 +99,27 @@ union node *redirnode; @@ -99,27 +99,27 @@ union node *redirnode;
99struct heredoc *heredoc; 99struct heredoc *heredoc;
100int quoteflag; /* set if (part of) last token was quoted */ 100int quoteflag; /* set if (part of) last token was quoted */
101int startlinno; /* line # where last token started */ 101int startlinno; /* line # where last token started */
102int funclinno; /* line # where the current function started */ 102int funclinno; /* line # where the current function started */
103 103
104 104
105STATIC union node *list(int, int); 105STATIC union node *list(int, int);
106STATIC union node *andor(void); 106STATIC union node *andor(void);
107STATIC union node *pipeline(void); 107STATIC union node *pipeline(void);
108STATIC union node *command(void); 108STATIC union node *command(void);
109STATIC union node *simplecmd(union node **, union node *); 109STATIC union node *simplecmd(union node **, union node *);
110STATIC union node *makename(void); 110STATIC union node *makename(void);
111STATIC void parsefname(void); 111STATIC void parsefname(void);
112STATIC void slurp_heredoc(char *const, int, int); 112STATIC void slurp_heredoc(char *const, const int, const int);
113STATIC void readheredocs(void); 113STATIC void readheredocs(void);
114STATIC int peektoken(void); 114STATIC int peektoken(void);
115STATIC int readtoken(void); 115STATIC int readtoken(void);
116STATIC int xxreadtoken(void); 116STATIC int xxreadtoken(void);
117STATIC int readtoken1(int, char const *, int); 117STATIC int readtoken1(int, char const *, int);
118STATIC int noexpand(char *); 118STATIC int noexpand(char *);
119STATIC void synexpect(int, const char *) __dead; 119STATIC void synexpect(int, const char *) __dead;
120STATIC void synerror(const char *) __dead; 120STATIC void synerror(const char *) __dead;
121STATIC void setprompt(int); 121STATIC void setprompt(int);
122 122
123 123
124static const char EOFhere[] = "EOF reading here (<<) document"; 124static const char EOFhere[] = "EOF reading here (<<) document";
125 125
@@ -749,27 +749,27 @@ checkend(int c, char * const eofmark, co @@ -749,27 +749,27 @@ checkend(int c, char * const eofmark, co
749 c = PEOF; 749 c = PEOF;
750 plinno++; 750 plinno++;
751 needprompt = doprompt; 751 needprompt = doprompt;
752 } 752 }
753 return (c); 753 return (c);
754} 754}
755 755
756 756
757/* 757/*
758 * Input any here documents. 758 * Input any here documents.
759 */ 759 */
760 760
761STATIC void 761STATIC void
762slurp_heredoc(char *const eofmark, int striptabs, int sq) 762slurp_heredoc(char *const eofmark, const int striptabs, const int sq)
763{ 763{
764 int c; 764 int c;
765 char *out; 765 char *out;
766 766
767 c = pgetc(); 767 c = pgetc();
768 768
769 /* 769 /*
770 * If we hit EOF on the input, and the eofmark is a null string ('') 770 * If we hit EOF on the input, and the eofmark is a null string ('')
771 * we consider this empty line to be the eofmark, and exit without err. 771 * we consider this empty line to be the eofmark, and exit without err.
772 */ 772 */
773 if (c == PEOF && *eofmark != '\0') 773 if (c == PEOF && *eofmark != '\0')
774 synerror(EOFhere); 774 synerror(EOFhere);
775 775
@@ -842,46 +842,39 @@ readheredocs(void) @@ -842,46 +842,39 @@ readheredocs(void)
842 setprompt(2); 842 setprompt(2);
843 needprompt = 0; 843 needprompt = 0;
844 } 844 }
845 845
846 slurp_heredoc(here->eofmark, here->striptabs, 846 slurp_heredoc(here->eofmark, here->striptabs,
847 here->here->nhere.type == NHERE); 847 here->here->nhere.type == NHERE);
848 848
849 n = stalloc(sizeof(struct narg)); 849 n = stalloc(sizeof(struct narg));
850 n->narg.type = NARG; 850 n->narg.type = NARG;
851 n->narg.next = NULL; 851 n->narg.next = NULL;
852 n->narg.text = wordtext; 852 n->narg.text = wordtext;
853 n->narg.backquote = backquotelist; 853 n->narg.backquote = backquotelist;
854 here->here->nhere.doc = n; 854 here->here->nhere.doc = n;
855 } 
856} 
857 
858void 
859parse_heredoc(union node *n) 
860{ 
861 if (n->narg.type != NARG) 
862 abort(); 
863 
864 if (n->narg.text[0] == '\0') /* nothing to do */ 
865 return; 
866 
867 setinputstring(n->narg.text, 1); 
868 
869 readtoken1(pgetc(), DQSYNTAX, 1); 
870 855
871 n->narg.text = wordtext; 856 if (here->here->nhere.type == NHERE)
872 n->narg.backquote = backquotelist; 857 continue;
873 858
874 popfile(); 859 /*
 860 * Now "parse" here docs that have unquoted eofmarkers.
 861 */
 862 setinputstring(wordtext, 1);
 863 readtoken1(pgetc(), DQSYNTAX, 1);
 864 n->narg.text = wordtext;
 865 n->narg.backquote = backquotelist;
 866 popfile();
 867 }
875} 868}
876 869
877STATIC int 870STATIC int
878peektoken(void) 871peektoken(void)
879{ 872{
880 int t; 873 int t;
881 874
882 t = readtoken(); 875 t = readtoken();
883 tokpushback++; 876 tokpushback++;
884 return (t); 877 return (t);
885} 878}
886 879
887STATIC int 880STATIC int

cvs diff -r1.20 -r1.21 src/bin/sh/parser.h (expand / switch to unified diff)

--- src/bin/sh/parser.h 2016/03/27 14:39:33 1.20
+++ src/bin/sh/parser.h 2016/03/31 23:11:05 1.21
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: parser.h,v 1.20 2016/03/27 14:39:33 christos Exp $ */ 1/* $NetBSD: parser.h,v 1.21 2016/03/31 23:11:05 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1991, 1993 4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist. 8 * Kenneth Almquist.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -71,16 +71,15 @@ @@ -71,16 +71,15 @@
71 71
72/* 72/*
73 * NEOF is returned by parsecmd when it encounters an end of file. It 73 * NEOF is returned by parsecmd when it encounters an end of file. It
74 * must be distinct from NULL, so we use the address of a variable that 74 * must be distinct from NULL, so we use the address of a variable that
75 * happens to be handy. 75 * happens to be handy.
76 */ 76 */
77extern int tokpushback; 77extern int tokpushback;
78#define NEOF ((union node *)&tokpushback) 78#define NEOF ((union node *)&tokpushback)
79extern int whichprompt; /* 1 == PS1, 2 == PS2 */ 79extern int whichprompt; /* 1 == PS1, 2 == PS2 */
80 80
81 81
82union node *parsecmd(int); 82union node *parsecmd(int);
83void fixredir(union node *, const char *, int); 83void fixredir(union node *, const char *, int);
84void parse_heredoc(union node *); 
85int goodname(char *); 84int goodname(char *);
86const char *getprompt(void *); 85const char *getprompt(void *);