1*d1e4d7ceSDavid van Moolenbroek /* $NetBSD: dol.c,v 1.29 2013/07/16 17:47:43 christos Exp $ */
2*d1e4d7ceSDavid van Moolenbroek
3*d1e4d7ceSDavid van Moolenbroek /*-
4*d1e4d7ceSDavid van Moolenbroek * Copyright (c) 1980, 1991, 1993
5*d1e4d7ceSDavid van Moolenbroek * The Regents of the University of California. All rights reserved.
6*d1e4d7ceSDavid van Moolenbroek *
7*d1e4d7ceSDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
8*d1e4d7ceSDavid van Moolenbroek * modification, are permitted provided that the following conditions
9*d1e4d7ceSDavid van Moolenbroek * are met:
10*d1e4d7ceSDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
11*d1e4d7ceSDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
12*d1e4d7ceSDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright
13*d1e4d7ceSDavid van Moolenbroek * notice, this list of conditions and the following disclaimer in the
14*d1e4d7ceSDavid van Moolenbroek * documentation and/or other materials provided with the distribution.
15*d1e4d7ceSDavid van Moolenbroek * 3. Neither the name of the University nor the names of its contributors
16*d1e4d7ceSDavid van Moolenbroek * may be used to endorse or promote products derived from this software
17*d1e4d7ceSDavid van Moolenbroek * without specific prior written permission.
18*d1e4d7ceSDavid van Moolenbroek *
19*d1e4d7ceSDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20*d1e4d7ceSDavid van Moolenbroek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*d1e4d7ceSDavid van Moolenbroek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*d1e4d7ceSDavid van Moolenbroek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23*d1e4d7ceSDavid van Moolenbroek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*d1e4d7ceSDavid van Moolenbroek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*d1e4d7ceSDavid van Moolenbroek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*d1e4d7ceSDavid van Moolenbroek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*d1e4d7ceSDavid van Moolenbroek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*d1e4d7ceSDavid van Moolenbroek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*d1e4d7ceSDavid van Moolenbroek * SUCH DAMAGE.
30*d1e4d7ceSDavid van Moolenbroek */
31*d1e4d7ceSDavid van Moolenbroek
32*d1e4d7ceSDavid van Moolenbroek #include <sys/cdefs.h>
33*d1e4d7ceSDavid van Moolenbroek #ifndef lint
34*d1e4d7ceSDavid van Moolenbroek #if 0
35*d1e4d7ceSDavid van Moolenbroek static char sccsid[] = "@(#)dol.c 8.1 (Berkeley) 5/31/93";
36*d1e4d7ceSDavid van Moolenbroek #else
37*d1e4d7ceSDavid van Moolenbroek __RCSID("$NetBSD: dol.c,v 1.29 2013/07/16 17:47:43 christos Exp $");
38*d1e4d7ceSDavid van Moolenbroek #endif
39*d1e4d7ceSDavid van Moolenbroek #endif /* not lint */
40*d1e4d7ceSDavid van Moolenbroek
41*d1e4d7ceSDavid van Moolenbroek #include <sys/types.h>
42*d1e4d7ceSDavid van Moolenbroek
43*d1e4d7ceSDavid van Moolenbroek #include <errno.h>
44*d1e4d7ceSDavid van Moolenbroek #include <fcntl.h>
45*d1e4d7ceSDavid van Moolenbroek #include <stdarg.h>
46*d1e4d7ceSDavid van Moolenbroek #include <stddef.h>
47*d1e4d7ceSDavid van Moolenbroek #include <stdlib.h>
48*d1e4d7ceSDavid van Moolenbroek #include <string.h>
49*d1e4d7ceSDavid van Moolenbroek #include <unistd.h>
50*d1e4d7ceSDavid van Moolenbroek
51*d1e4d7ceSDavid van Moolenbroek #include "csh.h"
52*d1e4d7ceSDavid van Moolenbroek #include "extern.h"
53*d1e4d7ceSDavid van Moolenbroek
54*d1e4d7ceSDavid van Moolenbroek /*
55*d1e4d7ceSDavid van Moolenbroek * These routines perform variable substitution and quoting via ' and ".
56*d1e4d7ceSDavid van Moolenbroek * To this point these constructs have been preserved in the divided
57*d1e4d7ceSDavid van Moolenbroek * input words. Here we expand variables and turn quoting via ' and " into
58*d1e4d7ceSDavid van Moolenbroek * QUOTE bits on characters (which prevent further interpretation).
59*d1e4d7ceSDavid van Moolenbroek * If the `:q' modifier was applied during history expansion, then
60*d1e4d7ceSDavid van Moolenbroek * some QUOTEing may have occurred already, so we dont "trim()" here.
61*d1e4d7ceSDavid van Moolenbroek */
62*d1e4d7ceSDavid van Moolenbroek
63*d1e4d7ceSDavid van Moolenbroek static int Dpeekc, Dpeekrd; /* Peeks for DgetC and Dreadc */
64*d1e4d7ceSDavid van Moolenbroek static Char *Dcp, **Dvp; /* Input vector for Dreadc */
65*d1e4d7ceSDavid van Moolenbroek
66*d1e4d7ceSDavid van Moolenbroek #define DEOF -1
67*d1e4d7ceSDavid van Moolenbroek #define unDgetC(c) Dpeekc = c
68*d1e4d7ceSDavid van Moolenbroek #define QUOTES (_QF|_QB|_ESC) /* \ ' " ` */
69*d1e4d7ceSDavid van Moolenbroek
70*d1e4d7ceSDavid van Moolenbroek /*
71*d1e4d7ceSDavid van Moolenbroek * The following variables give the information about the current
72*d1e4d7ceSDavid van Moolenbroek * $ expansion, recording the current word position, the remaining
73*d1e4d7ceSDavid van Moolenbroek * words within this expansion, the count of remaining words, and the
74*d1e4d7ceSDavid van Moolenbroek * information about any : modifier which is being applied.
75*d1e4d7ceSDavid van Moolenbroek */
76*d1e4d7ceSDavid van Moolenbroek #define MAXWLEN (BUFSIZE - 4)
77*d1e4d7ceSDavid van Moolenbroek #define MAXMOD MAXWLEN /* This cannot overflow */
78*d1e4d7ceSDavid van Moolenbroek static Char dolmod[MAXMOD]; /* : modifier character */
79*d1e4d7ceSDavid van Moolenbroek static Char *dolp; /* Remaining chars from this word */
80*d1e4d7ceSDavid van Moolenbroek static Char **dolnxt; /* Further words */
81*d1e4d7ceSDavid van Moolenbroek static int dolcnt; /* Count of further words */
82*d1e4d7ceSDavid van Moolenbroek static int dolnmod; /* Number of modifiers */
83*d1e4d7ceSDavid van Moolenbroek static int dolmcnt; /* :gx -> 10000, else 1 */
84*d1e4d7ceSDavid van Moolenbroek static int dolwcnt; /* :wx -> 10000, else 1 */
85*d1e4d7ceSDavid van Moolenbroek
86*d1e4d7ceSDavid van Moolenbroek static void Dfix2(Char **);
87*d1e4d7ceSDavid van Moolenbroek static Char *Dpack(Char *, Char *);
88*d1e4d7ceSDavid van Moolenbroek static int Dword(void);
89*d1e4d7ceSDavid van Moolenbroek __dead static void dolerror(Char *);
90*d1e4d7ceSDavid van Moolenbroek static int DgetC(int);
91*d1e4d7ceSDavid van Moolenbroek static void Dgetdol(void);
92*d1e4d7ceSDavid van Moolenbroek static void fixDolMod(void);
93*d1e4d7ceSDavid van Moolenbroek static void setDolp(Char *);
94*d1e4d7ceSDavid van Moolenbroek static void unDredc(int);
95*d1e4d7ceSDavid van Moolenbroek static int Dredc(void);
96*d1e4d7ceSDavid van Moolenbroek static void Dtestq(int);
97*d1e4d7ceSDavid van Moolenbroek
98*d1e4d7ceSDavid van Moolenbroek
99*d1e4d7ceSDavid van Moolenbroek /*
100*d1e4d7ceSDavid van Moolenbroek * Fix up the $ expansions and quotations in the
101*d1e4d7ceSDavid van Moolenbroek * argument list to command t.
102*d1e4d7ceSDavid van Moolenbroek */
103*d1e4d7ceSDavid van Moolenbroek void
Dfix(struct command * t)104*d1e4d7ceSDavid van Moolenbroek Dfix(struct command *t)
105*d1e4d7ceSDavid van Moolenbroek {
106*d1e4d7ceSDavid van Moolenbroek Char *p, **pp;
107*d1e4d7ceSDavid van Moolenbroek
108*d1e4d7ceSDavid van Moolenbroek if (noexec)
109*d1e4d7ceSDavid van Moolenbroek return;
110*d1e4d7ceSDavid van Moolenbroek /* Note that t_dcom isn't trimmed thus !...:q's aren't lost */
111*d1e4d7ceSDavid van Moolenbroek for (pp = t->t_dcom; (p = *pp++) != NULL;)
112*d1e4d7ceSDavid van Moolenbroek for (; *p; p++) {
113*d1e4d7ceSDavid van Moolenbroek if (cmap(*p, _DOL | QUOTES)) { /* $, \, ', ", ` */
114*d1e4d7ceSDavid van Moolenbroek Dfix2(t->t_dcom); /* found one */
115*d1e4d7ceSDavid van Moolenbroek blkfree(t->t_dcom);
116*d1e4d7ceSDavid van Moolenbroek t->t_dcom = gargv;
117*d1e4d7ceSDavid van Moolenbroek gargv = 0;
118*d1e4d7ceSDavid van Moolenbroek return;
119*d1e4d7ceSDavid van Moolenbroek }
120*d1e4d7ceSDavid van Moolenbroek }
121*d1e4d7ceSDavid van Moolenbroek }
122*d1e4d7ceSDavid van Moolenbroek
123*d1e4d7ceSDavid van Moolenbroek /*
124*d1e4d7ceSDavid van Moolenbroek * $ substitute one word, for i/o redirection
125*d1e4d7ceSDavid van Moolenbroek */
126*d1e4d7ceSDavid van Moolenbroek Char *
Dfix1(Char * cp)127*d1e4d7ceSDavid van Moolenbroek Dfix1(Char *cp)
128*d1e4d7ceSDavid van Moolenbroek {
129*d1e4d7ceSDavid van Moolenbroek Char *Dv[2];
130*d1e4d7ceSDavid van Moolenbroek
131*d1e4d7ceSDavid van Moolenbroek if (noexec)
132*d1e4d7ceSDavid van Moolenbroek return (0);
133*d1e4d7ceSDavid van Moolenbroek Dv[0] = cp;
134*d1e4d7ceSDavid van Moolenbroek Dv[1] = NULL;
135*d1e4d7ceSDavid van Moolenbroek Dfix2(Dv);
136*d1e4d7ceSDavid van Moolenbroek if (gargc != 1) {
137*d1e4d7ceSDavid van Moolenbroek setname(vis_str(cp));
138*d1e4d7ceSDavid van Moolenbroek stderror(ERR_NAME | ERR_AMBIG);
139*d1e4d7ceSDavid van Moolenbroek }
140*d1e4d7ceSDavid van Moolenbroek cp = Strsave(gargv[0]);
141*d1e4d7ceSDavid van Moolenbroek blkfree(gargv), gargv = 0;
142*d1e4d7ceSDavid van Moolenbroek return (cp);
143*d1e4d7ceSDavid van Moolenbroek }
144*d1e4d7ceSDavid van Moolenbroek
145*d1e4d7ceSDavid van Moolenbroek /*
146*d1e4d7ceSDavid van Moolenbroek * Subroutine to do actual fixing after state initialization.
147*d1e4d7ceSDavid van Moolenbroek */
148*d1e4d7ceSDavid van Moolenbroek static void
Dfix2(Char ** v)149*d1e4d7ceSDavid van Moolenbroek Dfix2(Char **v)
150*d1e4d7ceSDavid van Moolenbroek {
151*d1e4d7ceSDavid van Moolenbroek ginit(); /* Initialize glob's area pointers */
152*d1e4d7ceSDavid van Moolenbroek Dvp = v;
153*d1e4d7ceSDavid van Moolenbroek Dcp = STRNULL; /* Setup input vector for Dreadc */
154*d1e4d7ceSDavid van Moolenbroek unDgetC(0);
155*d1e4d7ceSDavid van Moolenbroek unDredc(0); /* Clear out any old peeks (at error) */
156*d1e4d7ceSDavid van Moolenbroek dolp = 0;
157*d1e4d7ceSDavid van Moolenbroek dolcnt = 0; /* Clear out residual $ expands (...) */
158*d1e4d7ceSDavid van Moolenbroek while (Dword())
159*d1e4d7ceSDavid van Moolenbroek continue;
160*d1e4d7ceSDavid van Moolenbroek }
161*d1e4d7ceSDavid van Moolenbroek
162*d1e4d7ceSDavid van Moolenbroek /*
163*d1e4d7ceSDavid van Moolenbroek * Pack up more characters in this word
164*d1e4d7ceSDavid van Moolenbroek */
165*d1e4d7ceSDavid van Moolenbroek static Char *
Dpack(Char * wbuf,Char * wp)166*d1e4d7ceSDavid van Moolenbroek Dpack(Char *wbuf, Char *wp)
167*d1e4d7ceSDavid van Moolenbroek {
168*d1e4d7ceSDavid van Moolenbroek int c;
169*d1e4d7ceSDavid van Moolenbroek ptrdiff_t i;
170*d1e4d7ceSDavid van Moolenbroek
171*d1e4d7ceSDavid van Moolenbroek i = MAXWLEN - (wp - wbuf);
172*d1e4d7ceSDavid van Moolenbroek for (;;) {
173*d1e4d7ceSDavid van Moolenbroek c = DgetC(DODOL);
174*d1e4d7ceSDavid van Moolenbroek if (c == '\\') {
175*d1e4d7ceSDavid van Moolenbroek c = DgetC(0);
176*d1e4d7ceSDavid van Moolenbroek if (c == DEOF) {
177*d1e4d7ceSDavid van Moolenbroek unDredc(c);
178*d1e4d7ceSDavid van Moolenbroek *wp = 0;
179*d1e4d7ceSDavid van Moolenbroek Gcat(STRNULL, wbuf);
180*d1e4d7ceSDavid van Moolenbroek return (NULL);
181*d1e4d7ceSDavid van Moolenbroek }
182*d1e4d7ceSDavid van Moolenbroek if (c == '\n')
183*d1e4d7ceSDavid van Moolenbroek c = ' ';
184*d1e4d7ceSDavid van Moolenbroek else
185*d1e4d7ceSDavid van Moolenbroek c |= QUOTE;
186*d1e4d7ceSDavid van Moolenbroek }
187*d1e4d7ceSDavid van Moolenbroek if (c == DEOF) {
188*d1e4d7ceSDavid van Moolenbroek unDredc(c);
189*d1e4d7ceSDavid van Moolenbroek *wp = 0;
190*d1e4d7ceSDavid van Moolenbroek Gcat(STRNULL, wbuf);
191*d1e4d7ceSDavid van Moolenbroek return (NULL);
192*d1e4d7ceSDavid van Moolenbroek }
193*d1e4d7ceSDavid van Moolenbroek if (cmap(c, _SP | _NL | _QF | _QB)) { /* sp \t\n'"` */
194*d1e4d7ceSDavid van Moolenbroek unDgetC(c);
195*d1e4d7ceSDavid van Moolenbroek if (cmap(c, QUOTES))
196*d1e4d7ceSDavid van Moolenbroek return (wp);
197*d1e4d7ceSDavid van Moolenbroek *wp++ = 0;
198*d1e4d7ceSDavid van Moolenbroek Gcat(STRNULL, wbuf);
199*d1e4d7ceSDavid van Moolenbroek return (NULL);
200*d1e4d7ceSDavid van Moolenbroek }
201*d1e4d7ceSDavid van Moolenbroek if (--i <= 0)
202*d1e4d7ceSDavid van Moolenbroek stderror(ERR_WTOOLONG);
203*d1e4d7ceSDavid van Moolenbroek *wp++ = (Char)c;
204*d1e4d7ceSDavid van Moolenbroek }
205*d1e4d7ceSDavid van Moolenbroek }
206*d1e4d7ceSDavid van Moolenbroek
207*d1e4d7ceSDavid van Moolenbroek /*
208*d1e4d7ceSDavid van Moolenbroek * Get a word. This routine is analogous to the routine
209*d1e4d7ceSDavid van Moolenbroek * word() in sh.lex.c for the main lexical input. One difference
210*d1e4d7ceSDavid van Moolenbroek * here is that we don't get a newline to terminate our expansion.
211*d1e4d7ceSDavid van Moolenbroek * Rather, DgetC will return a DEOF when we hit the end-of-input.
212*d1e4d7ceSDavid van Moolenbroek */
213*d1e4d7ceSDavid van Moolenbroek static int
Dword(void)214*d1e4d7ceSDavid van Moolenbroek Dword(void)
215*d1e4d7ceSDavid van Moolenbroek {
216*d1e4d7ceSDavid van Moolenbroek Char wbuf[BUFSIZE], *wp;
217*d1e4d7ceSDavid van Moolenbroek int c, c1;
218*d1e4d7ceSDavid van Moolenbroek ptrdiff_t i;
219*d1e4d7ceSDavid van Moolenbroek int dolflg, done, sofar;
220*d1e4d7ceSDavid van Moolenbroek
221*d1e4d7ceSDavid van Moolenbroek done = 0;
222*d1e4d7ceSDavid van Moolenbroek i = MAXWLEN;
223*d1e4d7ceSDavid van Moolenbroek sofar = 0;
224*d1e4d7ceSDavid van Moolenbroek wp = wbuf;
225*d1e4d7ceSDavid van Moolenbroek
226*d1e4d7ceSDavid van Moolenbroek while (!done) {
227*d1e4d7ceSDavid van Moolenbroek done = 1;
228*d1e4d7ceSDavid van Moolenbroek c = DgetC(DODOL);
229*d1e4d7ceSDavid van Moolenbroek switch (c) {
230*d1e4d7ceSDavid van Moolenbroek case DEOF:
231*d1e4d7ceSDavid van Moolenbroek if (sofar == 0)
232*d1e4d7ceSDavid van Moolenbroek return (0);
233*d1e4d7ceSDavid van Moolenbroek /* finish this word and catch the code above the next time */
234*d1e4d7ceSDavid van Moolenbroek unDredc(c);
235*d1e4d7ceSDavid van Moolenbroek /* FALLTHROUGH */
236*d1e4d7ceSDavid van Moolenbroek case '\n':
237*d1e4d7ceSDavid van Moolenbroek *wp = 0;
238*d1e4d7ceSDavid van Moolenbroek Gcat(STRNULL, wbuf);
239*d1e4d7ceSDavid van Moolenbroek return (1);
240*d1e4d7ceSDavid van Moolenbroek case ' ':
241*d1e4d7ceSDavid van Moolenbroek case '\t':
242*d1e4d7ceSDavid van Moolenbroek done = 0;
243*d1e4d7ceSDavid van Moolenbroek break;
244*d1e4d7ceSDavid van Moolenbroek case '`':
245*d1e4d7ceSDavid van Moolenbroek /* We preserve ` quotations which are done yet later */
246*d1e4d7ceSDavid van Moolenbroek *wp++ = (Char)c, --i;
247*d1e4d7ceSDavid van Moolenbroek /* FALLTHROUGH */
248*d1e4d7ceSDavid van Moolenbroek case '\'':
249*d1e4d7ceSDavid van Moolenbroek case '"':
250*d1e4d7ceSDavid van Moolenbroek /*
251*d1e4d7ceSDavid van Moolenbroek * Note that DgetC never returns a QUOTES character from an
252*d1e4d7ceSDavid van Moolenbroek * expansion, so only true input quotes will get us here or out.
253*d1e4d7ceSDavid van Moolenbroek */
254*d1e4d7ceSDavid van Moolenbroek c1 = c;
255*d1e4d7ceSDavid van Moolenbroek dolflg = c1 == '"' ? DODOL : 0;
256*d1e4d7ceSDavid van Moolenbroek for (;;) {
257*d1e4d7ceSDavid van Moolenbroek c = DgetC(dolflg);
258*d1e4d7ceSDavid van Moolenbroek if (c == c1)
259*d1e4d7ceSDavid van Moolenbroek break;
260*d1e4d7ceSDavid van Moolenbroek if (c == '\n' || c == DEOF)
261*d1e4d7ceSDavid van Moolenbroek stderror(ERR_UNMATCHED, c1);
262*d1e4d7ceSDavid van Moolenbroek if ((c & (QUOTE | TRIM)) == ('\n' | QUOTE))
263*d1e4d7ceSDavid van Moolenbroek --wp, ++i;
264*d1e4d7ceSDavid van Moolenbroek if (--i <= 0)
265*d1e4d7ceSDavid van Moolenbroek stderror(ERR_WTOOLONG);
266*d1e4d7ceSDavid van Moolenbroek switch (c1) {
267*d1e4d7ceSDavid van Moolenbroek case '"':
268*d1e4d7ceSDavid van Moolenbroek /*
269*d1e4d7ceSDavid van Moolenbroek * Leave any `s alone for later. Other chars are all
270*d1e4d7ceSDavid van Moolenbroek * quoted, thus `...` can tell it was within "...".
271*d1e4d7ceSDavid van Moolenbroek */
272*d1e4d7ceSDavid van Moolenbroek *wp++ = (Char)(c == '`' ? '`' : (c | QUOTE));
273*d1e4d7ceSDavid van Moolenbroek break;
274*d1e4d7ceSDavid van Moolenbroek case '\'':
275*d1e4d7ceSDavid van Moolenbroek /* Prevent all further interpretation */
276*d1e4d7ceSDavid van Moolenbroek *wp++ = (Char)(c | QUOTE);
277*d1e4d7ceSDavid van Moolenbroek break;
278*d1e4d7ceSDavid van Moolenbroek case '`':
279*d1e4d7ceSDavid van Moolenbroek /* Leave all text alone for later */
280*d1e4d7ceSDavid van Moolenbroek *wp++ = (Char)c;
281*d1e4d7ceSDavid van Moolenbroek break;
282*d1e4d7ceSDavid van Moolenbroek default:
283*d1e4d7ceSDavid van Moolenbroek break;
284*d1e4d7ceSDavid van Moolenbroek }
285*d1e4d7ceSDavid van Moolenbroek }
286*d1e4d7ceSDavid van Moolenbroek if (c1 == '`')
287*d1e4d7ceSDavid van Moolenbroek *wp++ = '`' /* i--; eliminated */;
288*d1e4d7ceSDavid van Moolenbroek sofar = 1;
289*d1e4d7ceSDavid van Moolenbroek if ((wp = Dpack(wbuf, wp)) == NULL)
290*d1e4d7ceSDavid van Moolenbroek return (1);
291*d1e4d7ceSDavid van Moolenbroek else {
292*d1e4d7ceSDavid van Moolenbroek i = MAXWLEN - (wp - wbuf);
293*d1e4d7ceSDavid van Moolenbroek done = 0;
294*d1e4d7ceSDavid van Moolenbroek }
295*d1e4d7ceSDavid van Moolenbroek break;
296*d1e4d7ceSDavid van Moolenbroek case '\\':
297*d1e4d7ceSDavid van Moolenbroek c = DgetC(0); /* No $ subst! */
298*d1e4d7ceSDavid van Moolenbroek if (c == '\n' || c == DEOF) {
299*d1e4d7ceSDavid van Moolenbroek done = 0;
300*d1e4d7ceSDavid van Moolenbroek break;
301*d1e4d7ceSDavid van Moolenbroek }
302*d1e4d7ceSDavid van Moolenbroek c |= QUOTE;
303*d1e4d7ceSDavid van Moolenbroek break;
304*d1e4d7ceSDavid van Moolenbroek default:
305*d1e4d7ceSDavid van Moolenbroek break;
306*d1e4d7ceSDavid van Moolenbroek }
307*d1e4d7ceSDavid van Moolenbroek if (done) {
308*d1e4d7ceSDavid van Moolenbroek unDgetC(c);
309*d1e4d7ceSDavid van Moolenbroek sofar = 1;
310*d1e4d7ceSDavid van Moolenbroek if ((wp = Dpack(wbuf, wp)) == NULL)
311*d1e4d7ceSDavid van Moolenbroek return (1);
312*d1e4d7ceSDavid van Moolenbroek else {
313*d1e4d7ceSDavid van Moolenbroek i = MAXWLEN - (wp - wbuf);
314*d1e4d7ceSDavid van Moolenbroek done = 0;
315*d1e4d7ceSDavid van Moolenbroek }
316*d1e4d7ceSDavid van Moolenbroek }
317*d1e4d7ceSDavid van Moolenbroek }
318*d1e4d7ceSDavid van Moolenbroek /* Really NOTREACHED */
319*d1e4d7ceSDavid van Moolenbroek return (0);
320*d1e4d7ceSDavid van Moolenbroek }
321*d1e4d7ceSDavid van Moolenbroek
322*d1e4d7ceSDavid van Moolenbroek
323*d1e4d7ceSDavid van Moolenbroek /*
324*d1e4d7ceSDavid van Moolenbroek * Get a character, performing $ substitution unless flag is 0.
325*d1e4d7ceSDavid van Moolenbroek * Any QUOTES character which is returned from a $ expansion is
326*d1e4d7ceSDavid van Moolenbroek * QUOTEd so that it will not be recognized above.
327*d1e4d7ceSDavid van Moolenbroek */
328*d1e4d7ceSDavid van Moolenbroek static int
DgetC(int flag)329*d1e4d7ceSDavid van Moolenbroek DgetC(int flag)
330*d1e4d7ceSDavid van Moolenbroek {
331*d1e4d7ceSDavid van Moolenbroek int c;
332*d1e4d7ceSDavid van Moolenbroek top:
333*d1e4d7ceSDavid van Moolenbroek if ((c = Dpeekc) != '\0') {
334*d1e4d7ceSDavid van Moolenbroek Dpeekc = 0;
335*d1e4d7ceSDavid van Moolenbroek return (c);
336*d1e4d7ceSDavid van Moolenbroek }
337*d1e4d7ceSDavid van Moolenbroek if (lap) {
338*d1e4d7ceSDavid van Moolenbroek c = *lap++ & (QUOTE | TRIM);
339*d1e4d7ceSDavid van Moolenbroek if (c == 0) {
340*d1e4d7ceSDavid van Moolenbroek lap = 0;
341*d1e4d7ceSDavid van Moolenbroek goto top;
342*d1e4d7ceSDavid van Moolenbroek }
343*d1e4d7ceSDavid van Moolenbroek quotspec:
344*d1e4d7ceSDavid van Moolenbroek if (cmap(c, QUOTES))
345*d1e4d7ceSDavid van Moolenbroek return (c | QUOTE);
346*d1e4d7ceSDavid van Moolenbroek return (c);
347*d1e4d7ceSDavid van Moolenbroek }
348*d1e4d7ceSDavid van Moolenbroek if (dolp) {
349*d1e4d7ceSDavid van Moolenbroek if ((c = *dolp++ & (QUOTE | TRIM)) != '\0')
350*d1e4d7ceSDavid van Moolenbroek goto quotspec;
351*d1e4d7ceSDavid van Moolenbroek if (dolcnt > 0) {
352*d1e4d7ceSDavid van Moolenbroek setDolp(*dolnxt++);
353*d1e4d7ceSDavid van Moolenbroek --dolcnt;
354*d1e4d7ceSDavid van Moolenbroek return (' ');
355*d1e4d7ceSDavid van Moolenbroek }
356*d1e4d7ceSDavid van Moolenbroek dolp = 0;
357*d1e4d7ceSDavid van Moolenbroek }
358*d1e4d7ceSDavid van Moolenbroek if (dolcnt > 0) {
359*d1e4d7ceSDavid van Moolenbroek setDolp(*dolnxt++);
360*d1e4d7ceSDavid van Moolenbroek --dolcnt;
361*d1e4d7ceSDavid van Moolenbroek goto top;
362*d1e4d7ceSDavid van Moolenbroek }
363*d1e4d7ceSDavid van Moolenbroek c = Dredc();
364*d1e4d7ceSDavid van Moolenbroek if (c == '$' && flag) {
365*d1e4d7ceSDavid van Moolenbroek Dgetdol();
366*d1e4d7ceSDavid van Moolenbroek goto top;
367*d1e4d7ceSDavid van Moolenbroek }
368*d1e4d7ceSDavid van Moolenbroek return (c);
369*d1e4d7ceSDavid van Moolenbroek }
370*d1e4d7ceSDavid van Moolenbroek
371*d1e4d7ceSDavid van Moolenbroek static Char *nulvec[] = {0};
372*d1e4d7ceSDavid van Moolenbroek static struct varent nulargv = {nulvec, STRargv, { NULL, NULL, NULL }, 0};
373*d1e4d7ceSDavid van Moolenbroek
374*d1e4d7ceSDavid van Moolenbroek static void
dolerror(Char * s)375*d1e4d7ceSDavid van Moolenbroek dolerror(Char *s)
376*d1e4d7ceSDavid van Moolenbroek {
377*d1e4d7ceSDavid van Moolenbroek setname(vis_str(s));
378*d1e4d7ceSDavid van Moolenbroek stderror(ERR_NAME | ERR_RANGE);
379*d1e4d7ceSDavid van Moolenbroek /* NOTREACHED */
380*d1e4d7ceSDavid van Moolenbroek }
381*d1e4d7ceSDavid van Moolenbroek
382*d1e4d7ceSDavid van Moolenbroek /*
383*d1e4d7ceSDavid van Moolenbroek * Handle the multitudinous $ expansion forms.
384*d1e4d7ceSDavid van Moolenbroek * Ugh.
385*d1e4d7ceSDavid van Moolenbroek */
386*d1e4d7ceSDavid van Moolenbroek static void
Dgetdol(void)387*d1e4d7ceSDavid van Moolenbroek Dgetdol(void)
388*d1e4d7ceSDavid van Moolenbroek {
389*d1e4d7ceSDavid van Moolenbroek static Char *dolbang = NULL;
390*d1e4d7ceSDavid van Moolenbroek Char name[4*MAXVARLEN+1];
391*d1e4d7ceSDavid van Moolenbroek Char wbuf[BUFSIZE];
392*d1e4d7ceSDavid van Moolenbroek struct varent *vp;
393*d1e4d7ceSDavid van Moolenbroek Char *np;
394*d1e4d7ceSDavid van Moolenbroek int c, lwb, sc, subscr, upb;
395*d1e4d7ceSDavid van Moolenbroek int dimen, bitset;
396*d1e4d7ceSDavid van Moolenbroek char tnp;
397*d1e4d7ceSDavid van Moolenbroek
398*d1e4d7ceSDavid van Moolenbroek bitset = 0;
399*d1e4d7ceSDavid van Moolenbroek dimen = 0;
400*d1e4d7ceSDavid van Moolenbroek lwb = 1;
401*d1e4d7ceSDavid van Moolenbroek upb = 0;
402*d1e4d7ceSDavid van Moolenbroek subscr = 0;
403*d1e4d7ceSDavid van Moolenbroek vp = NULL;
404*d1e4d7ceSDavid van Moolenbroek
405*d1e4d7ceSDavid van Moolenbroek dolnmod = dolmcnt = dolwcnt = 0;
406*d1e4d7ceSDavid van Moolenbroek c = sc = DgetC(0);
407*d1e4d7ceSDavid van Moolenbroek if (c == '{')
408*d1e4d7ceSDavid van Moolenbroek c = DgetC(0); /* sc is { to take } later */
409*d1e4d7ceSDavid van Moolenbroek if ((c & TRIM) == '#')
410*d1e4d7ceSDavid van Moolenbroek dimen++, c = DgetC(0); /* $# takes dimension */
411*d1e4d7ceSDavid van Moolenbroek else if (c == '?')
412*d1e4d7ceSDavid van Moolenbroek bitset++, c = DgetC(0); /* $? tests existence */
413*d1e4d7ceSDavid van Moolenbroek switch (c) {
414*d1e4d7ceSDavid van Moolenbroek case '!':
415*d1e4d7ceSDavid van Moolenbroek if (dimen || bitset)
416*d1e4d7ceSDavid van Moolenbroek stderror(ERR_SYNTAX);
417*d1e4d7ceSDavid van Moolenbroek if (backpid != 0) {
418*d1e4d7ceSDavid van Moolenbroek if (dolbang)
419*d1e4d7ceSDavid van Moolenbroek xfree((ptr_t)dolbang);
420*d1e4d7ceSDavid van Moolenbroek setDolp(dolbang = putn(backpid));
421*d1e4d7ceSDavid van Moolenbroek }
422*d1e4d7ceSDavid van Moolenbroek goto eatbrac;
423*d1e4d7ceSDavid van Moolenbroek case '$':
424*d1e4d7ceSDavid van Moolenbroek if (dimen || bitset)
425*d1e4d7ceSDavid van Moolenbroek stderror(ERR_SYNTAX);
426*d1e4d7ceSDavid van Moolenbroek setDolp(doldol);
427*d1e4d7ceSDavid van Moolenbroek goto eatbrac;
428*d1e4d7ceSDavid van Moolenbroek case '<' | QUOTE:
429*d1e4d7ceSDavid van Moolenbroek if (bitset)
430*d1e4d7ceSDavid van Moolenbroek stderror(ERR_NOTALLOWED, "$?<");
431*d1e4d7ceSDavid van Moolenbroek if (dimen)
432*d1e4d7ceSDavid van Moolenbroek stderror(ERR_NOTALLOWED, "$?#");
433*d1e4d7ceSDavid van Moolenbroek for (np = wbuf; read(OLDSTD, &tnp, 1) == 1; np++) {
434*d1e4d7ceSDavid van Moolenbroek *np = (unsigned char)tnp;
435*d1e4d7ceSDavid van Moolenbroek if (np >= &wbuf[BUFSIZE - 1])
436*d1e4d7ceSDavid van Moolenbroek stderror(ERR_LTOOLONG);
437*d1e4d7ceSDavid van Moolenbroek if (tnp == '\n')
438*d1e4d7ceSDavid van Moolenbroek break;
439*d1e4d7ceSDavid van Moolenbroek }
440*d1e4d7ceSDavid van Moolenbroek *np = 0;
441*d1e4d7ceSDavid van Moolenbroek /*
442*d1e4d7ceSDavid van Moolenbroek * KLUDGE: dolmod is set here because it will cause setDolp to call
443*d1e4d7ceSDavid van Moolenbroek * domod and thus to copy wbuf. Otherwise setDolp would use it
444*d1e4d7ceSDavid van Moolenbroek * directly. If we saved it ourselves, no one would know when to free
445*d1e4d7ceSDavid van Moolenbroek * it. The actual function of the 'q' causes filename expansion not to
446*d1e4d7ceSDavid van Moolenbroek * be done on the interpolated value.
447*d1e4d7ceSDavid van Moolenbroek */
448*d1e4d7ceSDavid van Moolenbroek dolmod[dolnmod++] = 'q';
449*d1e4d7ceSDavid van Moolenbroek dolmcnt = 10000;
450*d1e4d7ceSDavid van Moolenbroek setDolp(wbuf);
451*d1e4d7ceSDavid van Moolenbroek goto eatbrac;
452*d1e4d7ceSDavid van Moolenbroek case DEOF:
453*d1e4d7ceSDavid van Moolenbroek case '\n':
454*d1e4d7ceSDavid van Moolenbroek stderror(ERR_SYNTAX);
455*d1e4d7ceSDavid van Moolenbroek /* NOTREACHED */
456*d1e4d7ceSDavid van Moolenbroek case '*':
457*d1e4d7ceSDavid van Moolenbroek (void) Strcpy(name, STRargv);
458*d1e4d7ceSDavid van Moolenbroek vp = adrof(STRargv);
459*d1e4d7ceSDavid van Moolenbroek subscr = -1; /* Prevent eating [...] */
460*d1e4d7ceSDavid van Moolenbroek break;
461*d1e4d7ceSDavid van Moolenbroek default:
462*d1e4d7ceSDavid van Moolenbroek np = name;
463*d1e4d7ceSDavid van Moolenbroek if (Isdigit(c)) {
464*d1e4d7ceSDavid van Moolenbroek if (dimen)
465*d1e4d7ceSDavid van Moolenbroek stderror(ERR_NOTALLOWED, "$#<num>");
466*d1e4d7ceSDavid van Moolenbroek subscr = 0;
467*d1e4d7ceSDavid van Moolenbroek do {
468*d1e4d7ceSDavid van Moolenbroek subscr = subscr * 10 + c - '0';
469*d1e4d7ceSDavid van Moolenbroek c = DgetC(0);
470*d1e4d7ceSDavid van Moolenbroek } while (Isdigit(c));
471*d1e4d7ceSDavid van Moolenbroek unDredc(c);
472*d1e4d7ceSDavid van Moolenbroek if (subscr < 0)
473*d1e4d7ceSDavid van Moolenbroek stderror(ERR_RANGE);
474*d1e4d7ceSDavid van Moolenbroek if (subscr == 0) {
475*d1e4d7ceSDavid van Moolenbroek if (bitset) {
476*d1e4d7ceSDavid van Moolenbroek dolp = ffile ? STR1 : STR0;
477*d1e4d7ceSDavid van Moolenbroek goto eatbrac;
478*d1e4d7ceSDavid van Moolenbroek }
479*d1e4d7ceSDavid van Moolenbroek if (ffile == 0)
480*d1e4d7ceSDavid van Moolenbroek stderror(ERR_DOLZERO);
481*d1e4d7ceSDavid van Moolenbroek fixDolMod();
482*d1e4d7ceSDavid van Moolenbroek setDolp(ffile);
483*d1e4d7ceSDavid van Moolenbroek goto eatbrac;
484*d1e4d7ceSDavid van Moolenbroek }
485*d1e4d7ceSDavid van Moolenbroek if (bitset)
486*d1e4d7ceSDavid van Moolenbroek stderror(ERR_DOLQUEST);
487*d1e4d7ceSDavid van Moolenbroek vp = adrof(STRargv);
488*d1e4d7ceSDavid van Moolenbroek if (vp == 0) {
489*d1e4d7ceSDavid van Moolenbroek vp = &nulargv;
490*d1e4d7ceSDavid van Moolenbroek goto eatmod;
491*d1e4d7ceSDavid van Moolenbroek }
492*d1e4d7ceSDavid van Moolenbroek break;
493*d1e4d7ceSDavid van Moolenbroek }
494*d1e4d7ceSDavid van Moolenbroek if (!alnum(c))
495*d1e4d7ceSDavid van Moolenbroek stderror(ERR_VARALNUM);
496*d1e4d7ceSDavid van Moolenbroek for (;;) {
497*d1e4d7ceSDavid van Moolenbroek *np++ = (Char)c;
498*d1e4d7ceSDavid van Moolenbroek c = DgetC(0);
499*d1e4d7ceSDavid van Moolenbroek if (!alnum(c))
500*d1e4d7ceSDavid van Moolenbroek break;
501*d1e4d7ceSDavid van Moolenbroek if (np >= &name[MAXVARLEN])
502*d1e4d7ceSDavid van Moolenbroek stderror(ERR_VARTOOLONG);
503*d1e4d7ceSDavid van Moolenbroek }
504*d1e4d7ceSDavid van Moolenbroek *np++ = 0;
505*d1e4d7ceSDavid van Moolenbroek unDredc(c);
506*d1e4d7ceSDavid van Moolenbroek vp = adrof(name);
507*d1e4d7ceSDavid van Moolenbroek }
508*d1e4d7ceSDavid van Moolenbroek if (bitset) {
509*d1e4d7ceSDavid van Moolenbroek dolp = (vp || getenv(short2str(name))) ? STR1 : STR0;
510*d1e4d7ceSDavid van Moolenbroek goto eatbrac;
511*d1e4d7ceSDavid van Moolenbroek }
512*d1e4d7ceSDavid van Moolenbroek if (vp == 0) {
513*d1e4d7ceSDavid van Moolenbroek np = str2short(getenv(short2str(name)));
514*d1e4d7ceSDavid van Moolenbroek if (np) {
515*d1e4d7ceSDavid van Moolenbroek fixDolMod();
516*d1e4d7ceSDavid van Moolenbroek setDolp(np);
517*d1e4d7ceSDavid van Moolenbroek goto eatbrac;
518*d1e4d7ceSDavid van Moolenbroek }
519*d1e4d7ceSDavid van Moolenbroek udvar(name);
520*d1e4d7ceSDavid van Moolenbroek }
521*d1e4d7ceSDavid van Moolenbroek c = DgetC(0);
522*d1e4d7ceSDavid van Moolenbroek upb = blklen(vp->vec);
523*d1e4d7ceSDavid van Moolenbroek if (dimen == 0 && subscr == 0 && c == '[') {
524*d1e4d7ceSDavid van Moolenbroek np = name;
525*d1e4d7ceSDavid van Moolenbroek for (;;) {
526*d1e4d7ceSDavid van Moolenbroek c = DgetC(DODOL); /* Allow $ expand within [ ] */
527*d1e4d7ceSDavid van Moolenbroek if (c == ']')
528*d1e4d7ceSDavid van Moolenbroek break;
529*d1e4d7ceSDavid van Moolenbroek if (c == '\n' || c == DEOF)
530*d1e4d7ceSDavid van Moolenbroek stderror(ERR_INCBR);
531*d1e4d7ceSDavid van Moolenbroek if (np >= &name[sizeof(name) / sizeof(Char) - 2])
532*d1e4d7ceSDavid van Moolenbroek stderror(ERR_VARTOOLONG);
533*d1e4d7ceSDavid van Moolenbroek *np++ = (Char)c;
534*d1e4d7ceSDavid van Moolenbroek }
535*d1e4d7ceSDavid van Moolenbroek *np = 0, np = name;
536*d1e4d7ceSDavid van Moolenbroek if (dolp || dolcnt) /* $ exp must end before ] */
537*d1e4d7ceSDavid van Moolenbroek stderror(ERR_EXPORD);
538*d1e4d7ceSDavid van Moolenbroek if (!*np)
539*d1e4d7ceSDavid van Moolenbroek stderror(ERR_SYNTAX);
540*d1e4d7ceSDavid van Moolenbroek if (Isdigit(*np)) {
541*d1e4d7ceSDavid van Moolenbroek int i;
542*d1e4d7ceSDavid van Moolenbroek
543*d1e4d7ceSDavid van Moolenbroek for (i = 0; Isdigit(*np); i = i * 10 + *np++ - '0')
544*d1e4d7ceSDavid van Moolenbroek continue;
545*d1e4d7ceSDavid van Moolenbroek if ((i < 0 || i > upb) && !any("-*", *np)) {
546*d1e4d7ceSDavid van Moolenbroek dolerror(vp->v_name);
547*d1e4d7ceSDavid van Moolenbroek return;
548*d1e4d7ceSDavid van Moolenbroek }
549*d1e4d7ceSDavid van Moolenbroek lwb = i;
550*d1e4d7ceSDavid van Moolenbroek if (!*np)
551*d1e4d7ceSDavid van Moolenbroek upb = lwb, np = STRstar;
552*d1e4d7ceSDavid van Moolenbroek }
553*d1e4d7ceSDavid van Moolenbroek if (*np == '*')
554*d1e4d7ceSDavid van Moolenbroek np++;
555*d1e4d7ceSDavid van Moolenbroek else if (*np != '-')
556*d1e4d7ceSDavid van Moolenbroek stderror(ERR_MISSING, '-');
557*d1e4d7ceSDavid van Moolenbroek else {
558*d1e4d7ceSDavid van Moolenbroek int i = upb;
559*d1e4d7ceSDavid van Moolenbroek
560*d1e4d7ceSDavid van Moolenbroek np++;
561*d1e4d7ceSDavid van Moolenbroek if (Isdigit(*np)) {
562*d1e4d7ceSDavid van Moolenbroek i = 0;
563*d1e4d7ceSDavid van Moolenbroek while (Isdigit(*np))
564*d1e4d7ceSDavid van Moolenbroek i = i * 10 + *np++ - '0';
565*d1e4d7ceSDavid van Moolenbroek if (i < 0 || i > upb) {
566*d1e4d7ceSDavid van Moolenbroek dolerror(vp->v_name);
567*d1e4d7ceSDavid van Moolenbroek return;
568*d1e4d7ceSDavid van Moolenbroek }
569*d1e4d7ceSDavid van Moolenbroek }
570*d1e4d7ceSDavid van Moolenbroek if (i < lwb)
571*d1e4d7ceSDavid van Moolenbroek upb = lwb - 1;
572*d1e4d7ceSDavid van Moolenbroek else
573*d1e4d7ceSDavid van Moolenbroek upb = i;
574*d1e4d7ceSDavid van Moolenbroek }
575*d1e4d7ceSDavid van Moolenbroek if (lwb == 0) {
576*d1e4d7ceSDavid van Moolenbroek if (upb != 0) {
577*d1e4d7ceSDavid van Moolenbroek dolerror(vp->v_name);
578*d1e4d7ceSDavid van Moolenbroek return;
579*d1e4d7ceSDavid van Moolenbroek }
580*d1e4d7ceSDavid van Moolenbroek upb = -1;
581*d1e4d7ceSDavid van Moolenbroek }
582*d1e4d7ceSDavid van Moolenbroek if (*np)
583*d1e4d7ceSDavid van Moolenbroek stderror(ERR_SYNTAX);
584*d1e4d7ceSDavid van Moolenbroek }
585*d1e4d7ceSDavid van Moolenbroek else {
586*d1e4d7ceSDavid van Moolenbroek if (subscr > 0) {
587*d1e4d7ceSDavid van Moolenbroek if (subscr > upb)
588*d1e4d7ceSDavid van Moolenbroek lwb = 1, upb = 0;
589*d1e4d7ceSDavid van Moolenbroek else
590*d1e4d7ceSDavid van Moolenbroek lwb = upb = subscr;
591*d1e4d7ceSDavid van Moolenbroek }
592*d1e4d7ceSDavid van Moolenbroek unDredc(c);
593*d1e4d7ceSDavid van Moolenbroek }
594*d1e4d7ceSDavid van Moolenbroek if (dimen) {
595*d1e4d7ceSDavid van Moolenbroek Char *cp = putn(upb - lwb + 1);
596*d1e4d7ceSDavid van Moolenbroek
597*d1e4d7ceSDavid van Moolenbroek addla(cp);
598*d1e4d7ceSDavid van Moolenbroek xfree((ptr_t) cp);
599*d1e4d7ceSDavid van Moolenbroek }
600*d1e4d7ceSDavid van Moolenbroek else {
601*d1e4d7ceSDavid van Moolenbroek eatmod:
602*d1e4d7ceSDavid van Moolenbroek fixDolMod();
603*d1e4d7ceSDavid van Moolenbroek dolnxt = &vp->vec[lwb - 1];
604*d1e4d7ceSDavid van Moolenbroek dolcnt = upb - lwb + 1;
605*d1e4d7ceSDavid van Moolenbroek }
606*d1e4d7ceSDavid van Moolenbroek eatbrac:
607*d1e4d7ceSDavid van Moolenbroek if (sc == '{') {
608*d1e4d7ceSDavid van Moolenbroek c = Dredc();
609*d1e4d7ceSDavid van Moolenbroek if (c != '}')
610*d1e4d7ceSDavid van Moolenbroek stderror(ERR_MISSING, '}');
611*d1e4d7ceSDavid van Moolenbroek }
612*d1e4d7ceSDavid van Moolenbroek }
613*d1e4d7ceSDavid van Moolenbroek
614*d1e4d7ceSDavid van Moolenbroek static void
fixDolMod(void)615*d1e4d7ceSDavid van Moolenbroek fixDolMod(void)
616*d1e4d7ceSDavid van Moolenbroek {
617*d1e4d7ceSDavid van Moolenbroek int c;
618*d1e4d7ceSDavid van Moolenbroek
619*d1e4d7ceSDavid van Moolenbroek c = DgetC(0);
620*d1e4d7ceSDavid van Moolenbroek if (c == ':') {
621*d1e4d7ceSDavid van Moolenbroek do {
622*d1e4d7ceSDavid van Moolenbroek c = DgetC(0), dolmcnt = 1, dolwcnt = 1;
623*d1e4d7ceSDavid van Moolenbroek if (c == 'g' || c == 'a') {
624*d1e4d7ceSDavid van Moolenbroek if (c == 'g')
625*d1e4d7ceSDavid van Moolenbroek dolmcnt = 10000;
626*d1e4d7ceSDavid van Moolenbroek else
627*d1e4d7ceSDavid van Moolenbroek dolwcnt = 10000;
628*d1e4d7ceSDavid van Moolenbroek c = DgetC(0);
629*d1e4d7ceSDavid van Moolenbroek }
630*d1e4d7ceSDavid van Moolenbroek if ((c == 'g' && dolmcnt != 10000) ||
631*d1e4d7ceSDavid van Moolenbroek (c == 'a' && dolwcnt != 10000)) {
632*d1e4d7ceSDavid van Moolenbroek if (c == 'g')
633*d1e4d7ceSDavid van Moolenbroek dolmcnt = 10000;
634*d1e4d7ceSDavid van Moolenbroek else
635*d1e4d7ceSDavid van Moolenbroek dolwcnt = 10000;
636*d1e4d7ceSDavid van Moolenbroek c = DgetC(0);
637*d1e4d7ceSDavid van Moolenbroek }
638*d1e4d7ceSDavid van Moolenbroek
639*d1e4d7ceSDavid van Moolenbroek if (c == 's') { /* [eichin:19910926.0755EST] */
640*d1e4d7ceSDavid van Moolenbroek int delimcnt = 2;
641*d1e4d7ceSDavid van Moolenbroek int delim = DgetC(0);
642*d1e4d7ceSDavid van Moolenbroek dolmod[dolnmod++] = (Char)c;
643*d1e4d7ceSDavid van Moolenbroek dolmod[dolnmod++] = (Char)delim;
644*d1e4d7ceSDavid van Moolenbroek
645*d1e4d7ceSDavid van Moolenbroek if (!delim || letter(delim)
646*d1e4d7ceSDavid van Moolenbroek || Isdigit(delim) || any(" \t\n", delim)) {
647*d1e4d7ceSDavid van Moolenbroek seterror(ERR_BADSUBST);
648*d1e4d7ceSDavid van Moolenbroek break;
649*d1e4d7ceSDavid van Moolenbroek }
650*d1e4d7ceSDavid van Moolenbroek while ((c = DgetC(0)) != (-1)) {
651*d1e4d7ceSDavid van Moolenbroek dolmod[dolnmod++] = (Char)c;
652*d1e4d7ceSDavid van Moolenbroek if(c == delim) delimcnt--;
653*d1e4d7ceSDavid van Moolenbroek if(!delimcnt) break;
654*d1e4d7ceSDavid van Moolenbroek }
655*d1e4d7ceSDavid van Moolenbroek if(delimcnt) {
656*d1e4d7ceSDavid van Moolenbroek seterror(ERR_BADSUBST);
657*d1e4d7ceSDavid van Moolenbroek break;
658*d1e4d7ceSDavid van Moolenbroek }
659*d1e4d7ceSDavid van Moolenbroek continue;
660*d1e4d7ceSDavid van Moolenbroek }
661*d1e4d7ceSDavid van Moolenbroek if (!any("htrqxes", c))
662*d1e4d7ceSDavid van Moolenbroek stderror(ERR_BADMOD, c);
663*d1e4d7ceSDavid van Moolenbroek dolmod[dolnmod++] = (Char)c;
664*d1e4d7ceSDavid van Moolenbroek if (c == 'q')
665*d1e4d7ceSDavid van Moolenbroek dolmcnt = 10000;
666*d1e4d7ceSDavid van Moolenbroek }
667*d1e4d7ceSDavid van Moolenbroek while ((c = DgetC(0)) == ':');
668*d1e4d7ceSDavid van Moolenbroek unDredc(c);
669*d1e4d7ceSDavid van Moolenbroek }
670*d1e4d7ceSDavid van Moolenbroek else
671*d1e4d7ceSDavid van Moolenbroek unDredc(c);
672*d1e4d7ceSDavid van Moolenbroek }
673*d1e4d7ceSDavid van Moolenbroek
674*d1e4d7ceSDavid van Moolenbroek static void
setDolp(Char * cp)675*d1e4d7ceSDavid van Moolenbroek setDolp(Char *cp)
676*d1e4d7ceSDavid van Moolenbroek {
677*d1e4d7ceSDavid van Moolenbroek Char *dp;
678*d1e4d7ceSDavid van Moolenbroek int i;
679*d1e4d7ceSDavid van Moolenbroek
680*d1e4d7ceSDavid van Moolenbroek if (dolnmod == 0 || dolmcnt == 0) {
681*d1e4d7ceSDavid van Moolenbroek dolp = cp;
682*d1e4d7ceSDavid van Moolenbroek return;
683*d1e4d7ceSDavid van Moolenbroek }
684*d1e4d7ceSDavid van Moolenbroek dp = cp = Strsave(cp);
685*d1e4d7ceSDavid van Moolenbroek for (i = 0; i < dolnmod; i++) {
686*d1e4d7ceSDavid van Moolenbroek /* handle s// [eichin:19910926.0510EST] */
687*d1e4d7ceSDavid van Moolenbroek if(dolmod[i] == 's') {
688*d1e4d7ceSDavid van Moolenbroek int delim;
689*d1e4d7ceSDavid van Moolenbroek Char *lhsub, *rhsub, *np;
690*d1e4d7ceSDavid van Moolenbroek size_t lhlen = 0, rhlen = 0;
691*d1e4d7ceSDavid van Moolenbroek int didmod = 0;
692*d1e4d7ceSDavid van Moolenbroek
693*d1e4d7ceSDavid van Moolenbroek delim = dolmod[++i];
694*d1e4d7ceSDavid van Moolenbroek if (!delim || letter(delim)
695*d1e4d7ceSDavid van Moolenbroek || Isdigit(delim) || any(" \t\n", delim)) {
696*d1e4d7ceSDavid van Moolenbroek seterror(ERR_BADSUBST);
697*d1e4d7ceSDavid van Moolenbroek break;
698*d1e4d7ceSDavid van Moolenbroek }
699*d1e4d7ceSDavid van Moolenbroek lhsub = &dolmod[++i];
700*d1e4d7ceSDavid van Moolenbroek while(dolmod[i] != delim && dolmod[++i]) {
701*d1e4d7ceSDavid van Moolenbroek lhlen++;
702*d1e4d7ceSDavid van Moolenbroek }
703*d1e4d7ceSDavid van Moolenbroek dolmod[i] = 0;
704*d1e4d7ceSDavid van Moolenbroek rhsub = &dolmod[++i];
705*d1e4d7ceSDavid van Moolenbroek while(dolmod[i] != delim && dolmod[++i]) {
706*d1e4d7ceSDavid van Moolenbroek rhlen++;
707*d1e4d7ceSDavid van Moolenbroek }
708*d1e4d7ceSDavid van Moolenbroek dolmod[i] = 0;
709*d1e4d7ceSDavid van Moolenbroek
710*d1e4d7ceSDavid van Moolenbroek do {
711*d1e4d7ceSDavid van Moolenbroek dp = Strstr(cp, lhsub);
712*d1e4d7ceSDavid van Moolenbroek if (dp) {
713*d1e4d7ceSDavid van Moolenbroek np = xmalloc(
714*d1e4d7ceSDavid van Moolenbroek (size_t)((Strlen(cp) + 1 - lhlen + rhlen) *
715*d1e4d7ceSDavid van Moolenbroek sizeof(*np)));
716*d1e4d7ceSDavid van Moolenbroek (void)Strncpy(np, cp, (size_t)(dp - cp));
717*d1e4d7ceSDavid van Moolenbroek (void)Strcpy(np + (dp - cp), rhsub);
718*d1e4d7ceSDavid van Moolenbroek (void)Strcpy(np + (dp - cp) + rhlen, dp + lhlen);
719*d1e4d7ceSDavid van Moolenbroek
720*d1e4d7ceSDavid van Moolenbroek xfree((ptr_t) cp);
721*d1e4d7ceSDavid van Moolenbroek dp = cp = np;
722*d1e4d7ceSDavid van Moolenbroek didmod = 1;
723*d1e4d7ceSDavid van Moolenbroek } else {
724*d1e4d7ceSDavid van Moolenbroek /* should this do a seterror? */
725*d1e4d7ceSDavid van Moolenbroek break;
726*d1e4d7ceSDavid van Moolenbroek }
727*d1e4d7ceSDavid van Moolenbroek }
728*d1e4d7ceSDavid van Moolenbroek while (dolwcnt == 10000);
729*d1e4d7ceSDavid van Moolenbroek /*
730*d1e4d7ceSDavid van Moolenbroek * restore dolmod for additional words
731*d1e4d7ceSDavid van Moolenbroek */
732*d1e4d7ceSDavid van Moolenbroek dolmod[i] = rhsub[-1] = (Char)delim;
733*d1e4d7ceSDavid van Moolenbroek if (didmod)
734*d1e4d7ceSDavid van Moolenbroek dolmcnt--;
735*d1e4d7ceSDavid van Moolenbroek else
736*d1e4d7ceSDavid van Moolenbroek break;
737*d1e4d7ceSDavid van Moolenbroek } else {
738*d1e4d7ceSDavid van Moolenbroek int didmod = 0;
739*d1e4d7ceSDavid van Moolenbroek
740*d1e4d7ceSDavid van Moolenbroek do {
741*d1e4d7ceSDavid van Moolenbroek if ((dp = domod(cp, dolmod[i]))) {
742*d1e4d7ceSDavid van Moolenbroek didmod = 1;
743*d1e4d7ceSDavid van Moolenbroek if (Strcmp(cp, dp) == 0) {
744*d1e4d7ceSDavid van Moolenbroek xfree((ptr_t) cp);
745*d1e4d7ceSDavid van Moolenbroek cp = dp;
746*d1e4d7ceSDavid van Moolenbroek break;
747*d1e4d7ceSDavid van Moolenbroek }
748*d1e4d7ceSDavid van Moolenbroek else {
749*d1e4d7ceSDavid van Moolenbroek xfree((ptr_t) cp);
750*d1e4d7ceSDavid van Moolenbroek cp = dp;
751*d1e4d7ceSDavid van Moolenbroek }
752*d1e4d7ceSDavid van Moolenbroek }
753*d1e4d7ceSDavid van Moolenbroek else
754*d1e4d7ceSDavid van Moolenbroek break;
755*d1e4d7ceSDavid van Moolenbroek }
756*d1e4d7ceSDavid van Moolenbroek while (dolwcnt == 10000);
757*d1e4d7ceSDavid van Moolenbroek dp = cp;
758*d1e4d7ceSDavid van Moolenbroek if (didmod)
759*d1e4d7ceSDavid van Moolenbroek dolmcnt--;
760*d1e4d7ceSDavid van Moolenbroek else
761*d1e4d7ceSDavid van Moolenbroek break;
762*d1e4d7ceSDavid van Moolenbroek }
763*d1e4d7ceSDavid van Moolenbroek }
764*d1e4d7ceSDavid van Moolenbroek
765*d1e4d7ceSDavid van Moolenbroek if (dp) {
766*d1e4d7ceSDavid van Moolenbroek addla(dp);
767*d1e4d7ceSDavid van Moolenbroek xfree((ptr_t) dp);
768*d1e4d7ceSDavid van Moolenbroek }
769*d1e4d7ceSDavid van Moolenbroek else {
770*d1e4d7ceSDavid van Moolenbroek addla(cp);
771*d1e4d7ceSDavid van Moolenbroek xfree((ptr_t) cp);
772*d1e4d7ceSDavid van Moolenbroek }
773*d1e4d7ceSDavid van Moolenbroek
774*d1e4d7ceSDavid van Moolenbroek dolp = STRNULL;
775*d1e4d7ceSDavid van Moolenbroek if (seterr)
776*d1e4d7ceSDavid van Moolenbroek stderror(ERR_OLD);
777*d1e4d7ceSDavid van Moolenbroek }
778*d1e4d7ceSDavid van Moolenbroek
779*d1e4d7ceSDavid van Moolenbroek static void
unDredc(int c)780*d1e4d7ceSDavid van Moolenbroek unDredc(int c)
781*d1e4d7ceSDavid van Moolenbroek {
782*d1e4d7ceSDavid van Moolenbroek Dpeekrd = c;
783*d1e4d7ceSDavid van Moolenbroek }
784*d1e4d7ceSDavid van Moolenbroek
785*d1e4d7ceSDavid van Moolenbroek static int
Dredc(void)786*d1e4d7ceSDavid van Moolenbroek Dredc(void)
787*d1e4d7ceSDavid van Moolenbroek {
788*d1e4d7ceSDavid van Moolenbroek int c;
789*d1e4d7ceSDavid van Moolenbroek
790*d1e4d7ceSDavid van Moolenbroek if ((c = Dpeekrd) != '\0') {
791*d1e4d7ceSDavid van Moolenbroek Dpeekrd = 0;
792*d1e4d7ceSDavid van Moolenbroek return (c);
793*d1e4d7ceSDavid van Moolenbroek }
794*d1e4d7ceSDavid van Moolenbroek if (Dcp && (c = *Dcp++))
795*d1e4d7ceSDavid van Moolenbroek return (c & (QUOTE | TRIM));
796*d1e4d7ceSDavid van Moolenbroek if (*Dvp == 0) {
797*d1e4d7ceSDavid van Moolenbroek Dcp = 0;
798*d1e4d7ceSDavid van Moolenbroek return (DEOF);
799*d1e4d7ceSDavid van Moolenbroek }
800*d1e4d7ceSDavid van Moolenbroek Dcp = *Dvp++;
801*d1e4d7ceSDavid van Moolenbroek return (' ');
802*d1e4d7ceSDavid van Moolenbroek }
803*d1e4d7ceSDavid van Moolenbroek
804*d1e4d7ceSDavid van Moolenbroek static void
Dtestq(int c)805*d1e4d7ceSDavid van Moolenbroek Dtestq(int c)
806*d1e4d7ceSDavid van Moolenbroek {
807*d1e4d7ceSDavid van Moolenbroek if (cmap(c, QUOTES))
808*d1e4d7ceSDavid van Moolenbroek gflag = 1;
809*d1e4d7ceSDavid van Moolenbroek }
810*d1e4d7ceSDavid van Moolenbroek
811*d1e4d7ceSDavid van Moolenbroek /*
812*d1e4d7ceSDavid van Moolenbroek * Form a shell temporary file (in unit 0) from the words
813*d1e4d7ceSDavid van Moolenbroek * of the shell input up to EOF or a line the same as "term".
814*d1e4d7ceSDavid van Moolenbroek * Unit 0 should have been closed before this call.
815*d1e4d7ceSDavid van Moolenbroek */
816*d1e4d7ceSDavid van Moolenbroek void
817*d1e4d7ceSDavid van Moolenbroek /*ARGSUSED*/
heredoc(Char * term)818*d1e4d7ceSDavid van Moolenbroek heredoc(Char *term)
819*d1e4d7ceSDavid van Moolenbroek {
820*d1e4d7ceSDavid van Moolenbroek Char obuf[BUFSIZE], lbuf[BUFSIZE], mbuf[BUFSIZE];
821*d1e4d7ceSDavid van Moolenbroek struct timespec tv;
822*d1e4d7ceSDavid van Moolenbroek Char *Dv[2], *lbp, *obp, *mbp, **vp;
823*d1e4d7ceSDavid van Moolenbroek char *tmp;
824*d1e4d7ceSDavid van Moolenbroek int c, ocnt, lcnt, mcnt;
825*d1e4d7ceSDavid van Moolenbroek int quoted;
826*d1e4d7ceSDavid van Moolenbroek
827*d1e4d7ceSDavid van Moolenbroek again:
828*d1e4d7ceSDavid van Moolenbroek tmp = short2str(shtemp);
829*d1e4d7ceSDavid van Moolenbroek if (open(tmp, O_RDWR | O_CREAT | O_TRUNC | O_EXCL, 0600) < 0) {
830*d1e4d7ceSDavid van Moolenbroek if (errno == EEXIST) {
831*d1e4d7ceSDavid van Moolenbroek if (unlink(tmp) == -1) {
832*d1e4d7ceSDavid van Moolenbroek (void)clock_gettime(CLOCK_MONOTONIC, &tv);
833*d1e4d7ceSDavid van Moolenbroek mbp = putn((((int)tv.tv_sec) ^
834*d1e4d7ceSDavid van Moolenbroek ((int)tv.tv_nsec) ^ ((int)getpid())) & 0x00ffffff);
835*d1e4d7ceSDavid van Moolenbroek shtemp = Strspl(STRtmpsh, mbp);
836*d1e4d7ceSDavid van Moolenbroek xfree((ptr_t)mbp);
837*d1e4d7ceSDavid van Moolenbroek }
838*d1e4d7ceSDavid van Moolenbroek goto again;
839*d1e4d7ceSDavid van Moolenbroek }
840*d1e4d7ceSDavid van Moolenbroek stderror(ERR_SYSTEM, tmp, strerror(errno));
841*d1e4d7ceSDavid van Moolenbroek }
842*d1e4d7ceSDavid van Moolenbroek (void)unlink(tmp); /* 0 0 inode! */
843*d1e4d7ceSDavid van Moolenbroek Dv[0] = term;
844*d1e4d7ceSDavid van Moolenbroek Dv[1] = NULL;
845*d1e4d7ceSDavid van Moolenbroek gflag = 0;
846*d1e4d7ceSDavid van Moolenbroek trim(Dv);
847*d1e4d7ceSDavid van Moolenbroek rscan(Dv, Dtestq);
848*d1e4d7ceSDavid van Moolenbroek quoted = gflag;
849*d1e4d7ceSDavid van Moolenbroek ocnt = BUFSIZE;
850*d1e4d7ceSDavid van Moolenbroek obp = obuf;
851*d1e4d7ceSDavid van Moolenbroek for (;;) {
852*d1e4d7ceSDavid van Moolenbroek /*
853*d1e4d7ceSDavid van Moolenbroek * Read up a line
854*d1e4d7ceSDavid van Moolenbroek */
855*d1e4d7ceSDavid van Moolenbroek lbp = lbuf;
856*d1e4d7ceSDavid van Moolenbroek lcnt = BUFSIZE - 4;
857*d1e4d7ceSDavid van Moolenbroek for (;;) {
858*d1e4d7ceSDavid van Moolenbroek c = readc(1); /* 1 -> Want EOF returns */
859*d1e4d7ceSDavid van Moolenbroek if (c < 0 || c == '\n')
860*d1e4d7ceSDavid van Moolenbroek break;
861*d1e4d7ceSDavid van Moolenbroek if ((c &= TRIM) != '\0') {
862*d1e4d7ceSDavid van Moolenbroek *lbp++ = (Char)c;
863*d1e4d7ceSDavid van Moolenbroek if (--lcnt < 0) {
864*d1e4d7ceSDavid van Moolenbroek setname("<<");
865*d1e4d7ceSDavid van Moolenbroek stderror(ERR_NAME | ERR_OVERFLOW);
866*d1e4d7ceSDavid van Moolenbroek }
867*d1e4d7ceSDavid van Moolenbroek }
868*d1e4d7ceSDavid van Moolenbroek }
869*d1e4d7ceSDavid van Moolenbroek *lbp = 0;
870*d1e4d7ceSDavid van Moolenbroek
871*d1e4d7ceSDavid van Moolenbroek /*
872*d1e4d7ceSDavid van Moolenbroek * Check for EOF or compare to terminator -- before expansion
873*d1e4d7ceSDavid van Moolenbroek */
874*d1e4d7ceSDavid van Moolenbroek if (c < 0 || eq(lbuf, term)) {
875*d1e4d7ceSDavid van Moolenbroek (void)write(0, short2str(obuf), (size_t)(BUFSIZE - ocnt));
876*d1e4d7ceSDavid van Moolenbroek (void)lseek(0, (off_t)0, SEEK_SET);
877*d1e4d7ceSDavid van Moolenbroek return;
878*d1e4d7ceSDavid van Moolenbroek }
879*d1e4d7ceSDavid van Moolenbroek
880*d1e4d7ceSDavid van Moolenbroek /*
881*d1e4d7ceSDavid van Moolenbroek * If term was quoted or -n just pass it on
882*d1e4d7ceSDavid van Moolenbroek */
883*d1e4d7ceSDavid van Moolenbroek if (quoted || noexec) {
884*d1e4d7ceSDavid van Moolenbroek *lbp++ = '\n';
885*d1e4d7ceSDavid van Moolenbroek *lbp = 0;
886*d1e4d7ceSDavid van Moolenbroek for (lbp = lbuf; (c = *lbp++) != '\0';) {
887*d1e4d7ceSDavid van Moolenbroek *obp++ = (Char)c;
888*d1e4d7ceSDavid van Moolenbroek if (--ocnt == 0) {
889*d1e4d7ceSDavid van Moolenbroek (void) write(0, short2str(obuf), BUFSIZE);
890*d1e4d7ceSDavid van Moolenbroek obp = obuf;
891*d1e4d7ceSDavid van Moolenbroek ocnt = BUFSIZE;
892*d1e4d7ceSDavid van Moolenbroek }
893*d1e4d7ceSDavid van Moolenbroek }
894*d1e4d7ceSDavid van Moolenbroek continue;
895*d1e4d7ceSDavid van Moolenbroek }
896*d1e4d7ceSDavid van Moolenbroek
897*d1e4d7ceSDavid van Moolenbroek /*
898*d1e4d7ceSDavid van Moolenbroek * Term wasn't quoted so variable and then command expand the input
899*d1e4d7ceSDavid van Moolenbroek * line
900*d1e4d7ceSDavid van Moolenbroek */
901*d1e4d7ceSDavid van Moolenbroek Dcp = lbuf;
902*d1e4d7ceSDavid van Moolenbroek Dvp = Dv + 1;
903*d1e4d7ceSDavid van Moolenbroek mbp = mbuf;
904*d1e4d7ceSDavid van Moolenbroek mcnt = BUFSIZE - 4;
905*d1e4d7ceSDavid van Moolenbroek for (;;) {
906*d1e4d7ceSDavid van Moolenbroek c = DgetC(DODOL);
907*d1e4d7ceSDavid van Moolenbroek if (c == DEOF)
908*d1e4d7ceSDavid van Moolenbroek break;
909*d1e4d7ceSDavid van Moolenbroek if ((c &= TRIM) == 0)
910*d1e4d7ceSDavid van Moolenbroek continue;
911*d1e4d7ceSDavid van Moolenbroek /* \ quotes \ $ ` here */
912*d1e4d7ceSDavid van Moolenbroek if (c == '\\') {
913*d1e4d7ceSDavid van Moolenbroek c = DgetC(0);
914*d1e4d7ceSDavid van Moolenbroek if (!any("$\\`", c))
915*d1e4d7ceSDavid van Moolenbroek unDgetC(c | QUOTE), c = '\\';
916*d1e4d7ceSDavid van Moolenbroek else
917*d1e4d7ceSDavid van Moolenbroek c |= QUOTE;
918*d1e4d7ceSDavid van Moolenbroek }
919*d1e4d7ceSDavid van Moolenbroek *mbp++ = (Char)c;
920*d1e4d7ceSDavid van Moolenbroek if (--mcnt == 0) {
921*d1e4d7ceSDavid van Moolenbroek setname("<<");
922*d1e4d7ceSDavid van Moolenbroek stderror(ERR_NAME | ERR_OVERFLOW);
923*d1e4d7ceSDavid van Moolenbroek }
924*d1e4d7ceSDavid van Moolenbroek }
925*d1e4d7ceSDavid van Moolenbroek *mbp++ = 0;
926*d1e4d7ceSDavid van Moolenbroek
927*d1e4d7ceSDavid van Moolenbroek /*
928*d1e4d7ceSDavid van Moolenbroek * If any ` in line do command substitution
929*d1e4d7ceSDavid van Moolenbroek */
930*d1e4d7ceSDavid van Moolenbroek mbp = mbuf;
931*d1e4d7ceSDavid van Moolenbroek if (any(short2str(mbp), '`')) {
932*d1e4d7ceSDavid van Moolenbroek /*
933*d1e4d7ceSDavid van Moolenbroek * 1 arg to dobackp causes substitution to be literal. Words are
934*d1e4d7ceSDavid van Moolenbroek * broken only at newlines so that all blanks and tabs are
935*d1e4d7ceSDavid van Moolenbroek * preserved. Blank lines (null words) are not discarded.
936*d1e4d7ceSDavid van Moolenbroek */
937*d1e4d7ceSDavid van Moolenbroek vp = dobackp(mbuf, 1);
938*d1e4d7ceSDavid van Moolenbroek }
939*d1e4d7ceSDavid van Moolenbroek else
940*d1e4d7ceSDavid van Moolenbroek /* Setup trivial vector similar to return of dobackp */
941*d1e4d7ceSDavid van Moolenbroek Dv[0] = mbp, Dv[1] = NULL, vp = Dv;
942*d1e4d7ceSDavid van Moolenbroek
943*d1e4d7ceSDavid van Moolenbroek /*
944*d1e4d7ceSDavid van Moolenbroek * Resurrect the words from the command substitution each separated by
945*d1e4d7ceSDavid van Moolenbroek * a newline. Note that the last newline of a command substitution
946*d1e4d7ceSDavid van Moolenbroek * will have been discarded, but we put a newline after the last word
947*d1e4d7ceSDavid van Moolenbroek * because this represents the newline after the last input line!
948*d1e4d7ceSDavid van Moolenbroek */
949*d1e4d7ceSDavid van Moolenbroek for (; *vp; vp++) {
950*d1e4d7ceSDavid van Moolenbroek for (mbp = *vp; *mbp; mbp++) {
951*d1e4d7ceSDavid van Moolenbroek *obp++ = *mbp & TRIM;
952*d1e4d7ceSDavid van Moolenbroek if (--ocnt == 0) {
953*d1e4d7ceSDavid van Moolenbroek (void)write(0, short2str(obuf), BUFSIZE);
954*d1e4d7ceSDavid van Moolenbroek obp = obuf;
955*d1e4d7ceSDavid van Moolenbroek ocnt = BUFSIZE;
956*d1e4d7ceSDavid van Moolenbroek }
957*d1e4d7ceSDavid van Moolenbroek }
958*d1e4d7ceSDavid van Moolenbroek *obp++ = '\n';
959*d1e4d7ceSDavid van Moolenbroek if (--ocnt == 0) {
960*d1e4d7ceSDavid van Moolenbroek (void)write(0, short2str(obuf), BUFSIZE);
961*d1e4d7ceSDavid van Moolenbroek obp = obuf;
962*d1e4d7ceSDavid van Moolenbroek ocnt = BUFSIZE;
963*d1e4d7ceSDavid van Moolenbroek }
964*d1e4d7ceSDavid van Moolenbroek }
965*d1e4d7ceSDavid van Moolenbroek if (pargv)
966*d1e4d7ceSDavid van Moolenbroek blkfree(pargv), pargv = 0;
967*d1e4d7ceSDavid van Moolenbroek }
968*d1e4d7ceSDavid van Moolenbroek }
969