xref: /minix3/bin/sh/input.c (revision d90bee97498b3043241050f61aed100786c59df4)
1*d90bee97SLionel Sambuc /*	$NetBSD: input.c,v 1.46 2013/10/30 08:38:40 mrg Exp $	*/
2*d90bee97SLionel Sambuc 
3*d90bee97SLionel Sambuc /*-
4*d90bee97SLionel Sambuc  * Copyright (c) 1991, 1993
5*d90bee97SLionel Sambuc  *	The Regents of the University of California.  All rights reserved.
6*d90bee97SLionel Sambuc  *
7*d90bee97SLionel Sambuc  * This code is derived from software contributed to Berkeley by
8*d90bee97SLionel Sambuc  * Kenneth Almquist.
9*d90bee97SLionel Sambuc  *
10*d90bee97SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
11*d90bee97SLionel Sambuc  * modification, are permitted provided that the following conditions
12*d90bee97SLionel Sambuc  * are met:
13*d90bee97SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
14*d90bee97SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
15*d90bee97SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
16*d90bee97SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
17*d90bee97SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
18*d90bee97SLionel Sambuc  * 3. Neither the name of the University nor the names of its contributors
19*d90bee97SLionel Sambuc  *    may be used to endorse or promote products derived from this software
20*d90bee97SLionel Sambuc  *    without specific prior written permission.
21*d90bee97SLionel Sambuc  *
22*d90bee97SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23*d90bee97SLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24*d90bee97SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25*d90bee97SLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26*d90bee97SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27*d90bee97SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28*d90bee97SLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29*d90bee97SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30*d90bee97SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31*d90bee97SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*d90bee97SLionel Sambuc  * SUCH DAMAGE.
33*d90bee97SLionel Sambuc  */
34*d90bee97SLionel Sambuc 
35*d90bee97SLionel Sambuc #include <sys/cdefs.h>
36*d90bee97SLionel Sambuc #ifndef lint
37*d90bee97SLionel Sambuc #if 0
38*d90bee97SLionel Sambuc static char sccsid[] = "@(#)input.c	8.3 (Berkeley) 6/9/95";
39*d90bee97SLionel Sambuc #else
40*d90bee97SLionel Sambuc __RCSID("$NetBSD: input.c,v 1.46 2013/10/30 08:38:40 mrg Exp $");
41*d90bee97SLionel Sambuc #endif
42*d90bee97SLionel Sambuc #endif /* not lint */
43*d90bee97SLionel Sambuc 
44*d90bee97SLionel Sambuc #include <stdio.h>	/* defines BUFSIZ */
45*d90bee97SLionel Sambuc #include <fcntl.h>
46*d90bee97SLionel Sambuc #include <errno.h>
47*d90bee97SLionel Sambuc #include <unistd.h>
48*d90bee97SLionel Sambuc #include <limits.h>
49*d90bee97SLionel Sambuc #include <stdlib.h>
50*d90bee97SLionel Sambuc #include <string.h>
51*d90bee97SLionel Sambuc 
52*d90bee97SLionel Sambuc /*
53*d90bee97SLionel Sambuc  * This file implements the input routines used by the parser.
54*d90bee97SLionel Sambuc  */
55*d90bee97SLionel Sambuc 
56*d90bee97SLionel Sambuc #include "shell.h"
57*d90bee97SLionel Sambuc #include "redir.h"
58*d90bee97SLionel Sambuc #include "syntax.h"
59*d90bee97SLionel Sambuc #include "input.h"
60*d90bee97SLionel Sambuc #include "output.h"
61*d90bee97SLionel Sambuc #include "options.h"
62*d90bee97SLionel Sambuc #include "memalloc.h"
63*d90bee97SLionel Sambuc #include "error.h"
64*d90bee97SLionel Sambuc #include "alias.h"
65*d90bee97SLionel Sambuc #include "parser.h"
66*d90bee97SLionel Sambuc #include "myhistedit.h"
67*d90bee97SLionel Sambuc 
68*d90bee97SLionel Sambuc #define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
69*d90bee97SLionel Sambuc 
70*d90bee97SLionel Sambuc MKINIT
71*d90bee97SLionel Sambuc struct strpush {
72*d90bee97SLionel Sambuc 	struct strpush *prev;	/* preceding string on stack */
73*d90bee97SLionel Sambuc 	char *prevstring;
74*d90bee97SLionel Sambuc 	int prevnleft;
75*d90bee97SLionel Sambuc 	int prevlleft;
76*d90bee97SLionel Sambuc 	struct alias *ap;	/* if push was associated with an alias */
77*d90bee97SLionel Sambuc };
78*d90bee97SLionel Sambuc 
79*d90bee97SLionel Sambuc /*
80*d90bee97SLionel Sambuc  * The parsefile structure pointed to by the global variable parsefile
81*d90bee97SLionel Sambuc  * contains information about the current file being read.
82*d90bee97SLionel Sambuc  */
83*d90bee97SLionel Sambuc 
84*d90bee97SLionel Sambuc MKINIT
85*d90bee97SLionel Sambuc struct parsefile {
86*d90bee97SLionel Sambuc 	struct parsefile *prev;	/* preceding file on stack */
87*d90bee97SLionel Sambuc 	int linno;		/* current line */
88*d90bee97SLionel Sambuc 	int fd;			/* file descriptor (or -1 if string) */
89*d90bee97SLionel Sambuc 	int nleft;		/* number of chars left in this line */
90*d90bee97SLionel Sambuc 	int lleft;		/* number of chars left in this buffer */
91*d90bee97SLionel Sambuc 	char *nextc;		/* next char in buffer */
92*d90bee97SLionel Sambuc 	char *buf;		/* input buffer */
93*d90bee97SLionel Sambuc 	struct strpush *strpush; /* for pushing strings at this level */
94*d90bee97SLionel Sambuc 	struct strpush basestrpush; /* so pushing one is fast */
95*d90bee97SLionel Sambuc };
96*d90bee97SLionel Sambuc 
97*d90bee97SLionel Sambuc 
98*d90bee97SLionel Sambuc int plinno = 1;			/* input line number */
99*d90bee97SLionel Sambuc int parsenleft;			/* copy of parsefile->nleft */
100*d90bee97SLionel Sambuc MKINIT int parselleft;		/* copy of parsefile->lleft */
101*d90bee97SLionel Sambuc char *parsenextc;		/* copy of parsefile->nextc */
102*d90bee97SLionel Sambuc MKINIT struct parsefile basepf;	/* top level input file */
103*d90bee97SLionel Sambuc MKINIT char basebuf[BUFSIZ];	/* buffer for top level input file */
104*d90bee97SLionel Sambuc struct parsefile *parsefile = &basepf;	/* current input file */
105*d90bee97SLionel Sambuc int init_editline = 0;		/* editline library initialized? */
106*d90bee97SLionel Sambuc int whichprompt;		/* 1 == PS1, 2 == PS2 */
107*d90bee97SLionel Sambuc 
108*d90bee97SLionel Sambuc STATIC void pushfile(void);
109*d90bee97SLionel Sambuc static int preadfd(void);
110*d90bee97SLionel Sambuc 
111*d90bee97SLionel Sambuc #ifdef mkinit
112*d90bee97SLionel Sambuc INCLUDE <stdio.h>
113*d90bee97SLionel Sambuc INCLUDE "input.h"
114*d90bee97SLionel Sambuc INCLUDE "error.h"
115*d90bee97SLionel Sambuc 
116*d90bee97SLionel Sambuc INIT {
117*d90bee97SLionel Sambuc 	basepf.nextc = basepf.buf = basebuf;
118*d90bee97SLionel Sambuc }
119*d90bee97SLionel Sambuc 
120*d90bee97SLionel Sambuc RESET {
121*d90bee97SLionel Sambuc 	if (exception != EXSHELLPROC)
122*d90bee97SLionel Sambuc 		parselleft = parsenleft = 0;	/* clear input buffer */
123*d90bee97SLionel Sambuc 	popallfiles();
124*d90bee97SLionel Sambuc }
125*d90bee97SLionel Sambuc 
126*d90bee97SLionel Sambuc SHELLPROC {
127*d90bee97SLionel Sambuc 	popallfiles();
128*d90bee97SLionel Sambuc }
129*d90bee97SLionel Sambuc #endif
130*d90bee97SLionel Sambuc 
131*d90bee97SLionel Sambuc 
132*d90bee97SLionel Sambuc /*
133*d90bee97SLionel Sambuc  * Read a line from the script.
134*d90bee97SLionel Sambuc  */
135*d90bee97SLionel Sambuc 
136*d90bee97SLionel Sambuc char *
pfgets(char * line,int len)137*d90bee97SLionel Sambuc pfgets(char *line, int len)
138*d90bee97SLionel Sambuc {
139*d90bee97SLionel Sambuc 	char *p = line;
140*d90bee97SLionel Sambuc 	int nleft = len;
141*d90bee97SLionel Sambuc 	int c;
142*d90bee97SLionel Sambuc 
143*d90bee97SLionel Sambuc 	while (--nleft > 0) {
144*d90bee97SLionel Sambuc 		c = pgetc_macro();
145*d90bee97SLionel Sambuc 		if (c == PEOF) {
146*d90bee97SLionel Sambuc 			if (p == line)
147*d90bee97SLionel Sambuc 				return NULL;
148*d90bee97SLionel Sambuc 			break;
149*d90bee97SLionel Sambuc 		}
150*d90bee97SLionel Sambuc 		*p++ = c;
151*d90bee97SLionel Sambuc 		if (c == '\n')
152*d90bee97SLionel Sambuc 			break;
153*d90bee97SLionel Sambuc 	}
154*d90bee97SLionel Sambuc 	*p = '\0';
155*d90bee97SLionel Sambuc 	return line;
156*d90bee97SLionel Sambuc }
157*d90bee97SLionel Sambuc 
158*d90bee97SLionel Sambuc 
159*d90bee97SLionel Sambuc 
160*d90bee97SLionel Sambuc /*
161*d90bee97SLionel Sambuc  * Read a character from the script, returning PEOF on end of file.
162*d90bee97SLionel Sambuc  * Nul characters in the input are silently discarded.
163*d90bee97SLionel Sambuc  */
164*d90bee97SLionel Sambuc 
165*d90bee97SLionel Sambuc int
pgetc(void)166*d90bee97SLionel Sambuc pgetc(void)
167*d90bee97SLionel Sambuc {
168*d90bee97SLionel Sambuc 	return pgetc_macro();
169*d90bee97SLionel Sambuc }
170*d90bee97SLionel Sambuc 
171*d90bee97SLionel Sambuc 
172*d90bee97SLionel Sambuc static int
preadfd(void)173*d90bee97SLionel Sambuc preadfd(void)
174*d90bee97SLionel Sambuc {
175*d90bee97SLionel Sambuc 	int nr;
176*d90bee97SLionel Sambuc 	char *buf =  parsefile->buf;
177*d90bee97SLionel Sambuc 	parsenextc = buf;
178*d90bee97SLionel Sambuc 
179*d90bee97SLionel Sambuc retry:
180*d90bee97SLionel Sambuc #ifndef SMALL
181*d90bee97SLionel Sambuc 	if (parsefile->fd == 0 && el) {
182*d90bee97SLionel Sambuc 		static const char *rl_cp;
183*d90bee97SLionel Sambuc 		static int el_len;
184*d90bee97SLionel Sambuc 
185*d90bee97SLionel Sambuc 		if (rl_cp == NULL)
186*d90bee97SLionel Sambuc 			rl_cp = el_gets(el, &el_len);
187*d90bee97SLionel Sambuc 		if (rl_cp == NULL)
188*d90bee97SLionel Sambuc 			nr = el_len == 0 ? 0 : -1;
189*d90bee97SLionel Sambuc 		else {
190*d90bee97SLionel Sambuc 			nr = el_len;
191*d90bee97SLionel Sambuc 			if (nr > BUFSIZ - 8)
192*d90bee97SLionel Sambuc 				nr = BUFSIZ - 8;
193*d90bee97SLionel Sambuc 			memcpy(buf, rl_cp, nr);
194*d90bee97SLionel Sambuc 			if (nr != el_len) {
195*d90bee97SLionel Sambuc 				el_len -= nr;
196*d90bee97SLionel Sambuc 				rl_cp += nr;
197*d90bee97SLionel Sambuc 			} else
198*d90bee97SLionel Sambuc 				rl_cp = 0;
199*d90bee97SLionel Sambuc 		}
200*d90bee97SLionel Sambuc 
201*d90bee97SLionel Sambuc 	} else
202*d90bee97SLionel Sambuc #endif
203*d90bee97SLionel Sambuc 		nr = read(parsefile->fd, buf, BUFSIZ - 8);
204*d90bee97SLionel Sambuc 
205*d90bee97SLionel Sambuc 
206*d90bee97SLionel Sambuc 	if (nr <= 0) {
207*d90bee97SLionel Sambuc                 if (nr < 0) {
208*d90bee97SLionel Sambuc                         if (errno == EINTR)
209*d90bee97SLionel Sambuc                                 goto retry;
210*d90bee97SLionel Sambuc                         if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
211*d90bee97SLionel Sambuc                                 int flags = fcntl(0, F_GETFL, 0);
212*d90bee97SLionel Sambuc                                 if (flags >= 0 && flags & O_NONBLOCK) {
213*d90bee97SLionel Sambuc                                         flags &=~ O_NONBLOCK;
214*d90bee97SLionel Sambuc                                         if (fcntl(0, F_SETFL, flags) >= 0) {
215*d90bee97SLionel Sambuc 						out2str("sh: turning off NDELAY mode\n");
216*d90bee97SLionel Sambuc                                                 goto retry;
217*d90bee97SLionel Sambuc                                         }
218*d90bee97SLionel Sambuc                                 }
219*d90bee97SLionel Sambuc                         }
220*d90bee97SLionel Sambuc                 }
221*d90bee97SLionel Sambuc                 nr = -1;
222*d90bee97SLionel Sambuc 	}
223*d90bee97SLionel Sambuc 	return nr;
224*d90bee97SLionel Sambuc }
225*d90bee97SLionel Sambuc 
226*d90bee97SLionel Sambuc /*
227*d90bee97SLionel Sambuc  * Refill the input buffer and return the next input character:
228*d90bee97SLionel Sambuc  *
229*d90bee97SLionel Sambuc  * 1) If a string was pushed back on the input, pop it;
230*d90bee97SLionel Sambuc  * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
231*d90bee97SLionel Sambuc  *    from a string so we can't refill the buffer, return EOF.
232*d90bee97SLionel Sambuc  * 3) If the is more stuff in this buffer, use it else call read to fill it.
233*d90bee97SLionel Sambuc  * 4) Process input up to the next newline, deleting nul characters.
234*d90bee97SLionel Sambuc  */
235*d90bee97SLionel Sambuc 
236*d90bee97SLionel Sambuc int
preadbuffer(void)237*d90bee97SLionel Sambuc preadbuffer(void)
238*d90bee97SLionel Sambuc {
239*d90bee97SLionel Sambuc 	char *p, *q;
240*d90bee97SLionel Sambuc 	int more;
241*d90bee97SLionel Sambuc #ifndef SMALL
242*d90bee97SLionel Sambuc 	int something;
243*d90bee97SLionel Sambuc #endif
244*d90bee97SLionel Sambuc 	char savec;
245*d90bee97SLionel Sambuc 
246*d90bee97SLionel Sambuc 	if (parsefile->strpush) {
247*d90bee97SLionel Sambuc 		popstring();
248*d90bee97SLionel Sambuc 		if (--parsenleft >= 0)
249*d90bee97SLionel Sambuc 			return (*parsenextc++);
250*d90bee97SLionel Sambuc 	}
251*d90bee97SLionel Sambuc 	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
252*d90bee97SLionel Sambuc 		return PEOF;
253*d90bee97SLionel Sambuc 	flushout(&output);
254*d90bee97SLionel Sambuc 	flushout(&errout);
255*d90bee97SLionel Sambuc 
256*d90bee97SLionel Sambuc again:
257*d90bee97SLionel Sambuc 	if (parselleft <= 0) {
258*d90bee97SLionel Sambuc 		if ((parselleft = preadfd()) == -1) {
259*d90bee97SLionel Sambuc 			parselleft = parsenleft = EOF_NLEFT;
260*d90bee97SLionel Sambuc 			return PEOF;
261*d90bee97SLionel Sambuc 		}
262*d90bee97SLionel Sambuc 	}
263*d90bee97SLionel Sambuc 
264*d90bee97SLionel Sambuc 	q = p = parsenextc;
265*d90bee97SLionel Sambuc 
266*d90bee97SLionel Sambuc 	/* delete nul characters */
267*d90bee97SLionel Sambuc #ifndef SMALL
268*d90bee97SLionel Sambuc 	something = 0;
269*d90bee97SLionel Sambuc #endif
270*d90bee97SLionel Sambuc 	for (more = 1; more;) {
271*d90bee97SLionel Sambuc 		switch (*p) {
272*d90bee97SLionel Sambuc 		case '\0':
273*d90bee97SLionel Sambuc 			p++;	/* Skip nul */
274*d90bee97SLionel Sambuc 			goto check;
275*d90bee97SLionel Sambuc 
276*d90bee97SLionel Sambuc 		case '\t':
277*d90bee97SLionel Sambuc 		case ' ':
278*d90bee97SLionel Sambuc 			break;
279*d90bee97SLionel Sambuc 
280*d90bee97SLionel Sambuc 		case '\n':
281*d90bee97SLionel Sambuc 			parsenleft = q - parsenextc;
282*d90bee97SLionel Sambuc 			more = 0; /* Stop processing here */
283*d90bee97SLionel Sambuc 			break;
284*d90bee97SLionel Sambuc 
285*d90bee97SLionel Sambuc 		default:
286*d90bee97SLionel Sambuc #ifndef SMALL
287*d90bee97SLionel Sambuc 			something = 1;
288*d90bee97SLionel Sambuc #endif
289*d90bee97SLionel Sambuc 			break;
290*d90bee97SLionel Sambuc 		}
291*d90bee97SLionel Sambuc 
292*d90bee97SLionel Sambuc 		*q++ = *p++;
293*d90bee97SLionel Sambuc check:
294*d90bee97SLionel Sambuc 		if (--parselleft <= 0) {
295*d90bee97SLionel Sambuc 			parsenleft = q - parsenextc - 1;
296*d90bee97SLionel Sambuc 			if (parsenleft < 0)
297*d90bee97SLionel Sambuc 				goto again;
298*d90bee97SLionel Sambuc 			*q = '\0';
299*d90bee97SLionel Sambuc 			more = 0;
300*d90bee97SLionel Sambuc 		}
301*d90bee97SLionel Sambuc 	}
302*d90bee97SLionel Sambuc 
303*d90bee97SLionel Sambuc 	savec = *q;
304*d90bee97SLionel Sambuc 	*q = '\0';
305*d90bee97SLionel Sambuc 
306*d90bee97SLionel Sambuc #ifndef SMALL
307*d90bee97SLionel Sambuc 	if (parsefile->fd == 0 && hist && something) {
308*d90bee97SLionel Sambuc 		HistEvent he;
309*d90bee97SLionel Sambuc 		INTOFF;
310*d90bee97SLionel Sambuc 		history(hist, &he, whichprompt == 1? H_ENTER : H_APPEND,
311*d90bee97SLionel Sambuc 		    parsenextc);
312*d90bee97SLionel Sambuc 		INTON;
313*d90bee97SLionel Sambuc 	}
314*d90bee97SLionel Sambuc #endif
315*d90bee97SLionel Sambuc 
316*d90bee97SLionel Sambuc 	if (vflag) {
317*d90bee97SLionel Sambuc 		out2str(parsenextc);
318*d90bee97SLionel Sambuc 		flushout(out2);
319*d90bee97SLionel Sambuc 	}
320*d90bee97SLionel Sambuc 
321*d90bee97SLionel Sambuc 	*q = savec;
322*d90bee97SLionel Sambuc 
323*d90bee97SLionel Sambuc 	return *parsenextc++;
324*d90bee97SLionel Sambuc }
325*d90bee97SLionel Sambuc 
326*d90bee97SLionel Sambuc /*
327*d90bee97SLionel Sambuc  * Undo the last call to pgetc.  Only one character may be pushed back.
328*d90bee97SLionel Sambuc  * PEOF may be pushed back.
329*d90bee97SLionel Sambuc  */
330*d90bee97SLionel Sambuc 
331*d90bee97SLionel Sambuc void
pungetc(void)332*d90bee97SLionel Sambuc pungetc(void)
333*d90bee97SLionel Sambuc {
334*d90bee97SLionel Sambuc 	parsenleft++;
335*d90bee97SLionel Sambuc 	parsenextc--;
336*d90bee97SLionel Sambuc }
337*d90bee97SLionel Sambuc 
338*d90bee97SLionel Sambuc /*
339*d90bee97SLionel Sambuc  * Push a string back onto the input at this current parsefile level.
340*d90bee97SLionel Sambuc  * We handle aliases this way.
341*d90bee97SLionel Sambuc  */
342*d90bee97SLionel Sambuc void
pushstring(char * s,int len,void * ap)343*d90bee97SLionel Sambuc pushstring(char *s, int len, void *ap)
344*d90bee97SLionel Sambuc {
345*d90bee97SLionel Sambuc 	struct strpush *sp;
346*d90bee97SLionel Sambuc 
347*d90bee97SLionel Sambuc 	INTOFF;
348*d90bee97SLionel Sambuc /*debugprintf("*** calling pushstring: %s, %d\n", s, len);*/
349*d90bee97SLionel Sambuc 	if (parsefile->strpush) {
350*d90bee97SLionel Sambuc 		sp = ckmalloc(sizeof (struct strpush));
351*d90bee97SLionel Sambuc 		sp->prev = parsefile->strpush;
352*d90bee97SLionel Sambuc 		parsefile->strpush = sp;
353*d90bee97SLionel Sambuc 	} else
354*d90bee97SLionel Sambuc 		sp = parsefile->strpush = &(parsefile->basestrpush);
355*d90bee97SLionel Sambuc 	sp->prevstring = parsenextc;
356*d90bee97SLionel Sambuc 	sp->prevnleft = parsenleft;
357*d90bee97SLionel Sambuc 	sp->prevlleft = parselleft;
358*d90bee97SLionel Sambuc 	sp->ap = (struct alias *)ap;
359*d90bee97SLionel Sambuc 	if (ap)
360*d90bee97SLionel Sambuc 		((struct alias *)ap)->flag |= ALIASINUSE;
361*d90bee97SLionel Sambuc 	parsenextc = s;
362*d90bee97SLionel Sambuc 	parsenleft = len;
363*d90bee97SLionel Sambuc 	INTON;
364*d90bee97SLionel Sambuc }
365*d90bee97SLionel Sambuc 
366*d90bee97SLionel Sambuc void
popstring(void)367*d90bee97SLionel Sambuc popstring(void)
368*d90bee97SLionel Sambuc {
369*d90bee97SLionel Sambuc 	struct strpush *sp = parsefile->strpush;
370*d90bee97SLionel Sambuc 
371*d90bee97SLionel Sambuc 	INTOFF;
372*d90bee97SLionel Sambuc 	parsenextc = sp->prevstring;
373*d90bee97SLionel Sambuc 	parsenleft = sp->prevnleft;
374*d90bee97SLionel Sambuc 	parselleft = sp->prevlleft;
375*d90bee97SLionel Sambuc /*debugprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
376*d90bee97SLionel Sambuc 	if (sp->ap)
377*d90bee97SLionel Sambuc 		sp->ap->flag &= ~ALIASINUSE;
378*d90bee97SLionel Sambuc 	parsefile->strpush = sp->prev;
379*d90bee97SLionel Sambuc 	if (sp != &(parsefile->basestrpush))
380*d90bee97SLionel Sambuc 		ckfree(sp);
381*d90bee97SLionel Sambuc 	INTON;
382*d90bee97SLionel Sambuc }
383*d90bee97SLionel Sambuc 
384*d90bee97SLionel Sambuc /*
385*d90bee97SLionel Sambuc  * Set the input to take input from a file.  If push is set, push the
386*d90bee97SLionel Sambuc  * old input onto the stack first.
387*d90bee97SLionel Sambuc  */
388*d90bee97SLionel Sambuc 
389*d90bee97SLionel Sambuc void
setinputfile(const char * fname,int push)390*d90bee97SLionel Sambuc setinputfile(const char *fname, int push)
391*d90bee97SLionel Sambuc {
392*d90bee97SLionel Sambuc 	unsigned char magic[4];
393*d90bee97SLionel Sambuc 	int fd;
394*d90bee97SLionel Sambuc 	int fd2;
395*d90bee97SLionel Sambuc 
396*d90bee97SLionel Sambuc 	INTOFF;
397*d90bee97SLionel Sambuc 	if ((fd = open(fname, O_RDONLY)) < 0)
398*d90bee97SLionel Sambuc 		error("Can't open %s", fname);
399*d90bee97SLionel Sambuc 
400*d90bee97SLionel Sambuc 	/* Since the message "Syntax error: "(" unexpected" is not very
401*d90bee97SLionel Sambuc 	 * helpful, we check if the file starts with the ELF magic to
402*d90bee97SLionel Sambuc 	 * avoid that message. The first lseek tries to make sure that
403*d90bee97SLionel Sambuc 	 * we can later rewind the file.
404*d90bee97SLionel Sambuc 	 */
405*d90bee97SLionel Sambuc 	if (lseek(fd, 0, SEEK_SET) == 0) {
406*d90bee97SLionel Sambuc 		if (read(fd, magic, 4) == 4) {
407*d90bee97SLionel Sambuc 			if (memcmp(magic, "\177ELF", 4) == 0)
408*d90bee97SLionel Sambuc 				error("Cannot execute ELF binary %s", fname);
409*d90bee97SLionel Sambuc 		}
410*d90bee97SLionel Sambuc 		if (lseek(fd, 0, SEEK_SET) != 0)
411*d90bee97SLionel Sambuc 			error("Cannot rewind the file %s", fname);
412*d90bee97SLionel Sambuc 	}
413*d90bee97SLionel Sambuc 
414*d90bee97SLionel Sambuc 	if (fd < 10) {
415*d90bee97SLionel Sambuc 		fd2 = copyfd(fd, 10, 0);
416*d90bee97SLionel Sambuc 		close(fd);
417*d90bee97SLionel Sambuc 		if (fd2 < 0)
418*d90bee97SLionel Sambuc 			error("Out of file descriptors");
419*d90bee97SLionel Sambuc 		fd = fd2;
420*d90bee97SLionel Sambuc 	}
421*d90bee97SLionel Sambuc 	setinputfd(fd, push);
422*d90bee97SLionel Sambuc 	INTON;
423*d90bee97SLionel Sambuc }
424*d90bee97SLionel Sambuc 
425*d90bee97SLionel Sambuc 
426*d90bee97SLionel Sambuc /*
427*d90bee97SLionel Sambuc  * Like setinputfile, but takes an open file descriptor.  Call this with
428*d90bee97SLionel Sambuc  * interrupts off.
429*d90bee97SLionel Sambuc  */
430*d90bee97SLionel Sambuc 
431*d90bee97SLionel Sambuc void
setinputfd(int fd,int push)432*d90bee97SLionel Sambuc setinputfd(int fd, int push)
433*d90bee97SLionel Sambuc {
434*d90bee97SLionel Sambuc 	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
435*d90bee97SLionel Sambuc 	if (push) {
436*d90bee97SLionel Sambuc 		pushfile();
437*d90bee97SLionel Sambuc 		parsefile->buf = ckmalloc(BUFSIZ);
438*d90bee97SLionel Sambuc 	}
439*d90bee97SLionel Sambuc 	if (parsefile->fd > 0)
440*d90bee97SLionel Sambuc 		close(parsefile->fd);
441*d90bee97SLionel Sambuc 	parsefile->fd = fd;
442*d90bee97SLionel Sambuc 	if (parsefile->buf == NULL)
443*d90bee97SLionel Sambuc 		parsefile->buf = ckmalloc(BUFSIZ);
444*d90bee97SLionel Sambuc 	parselleft = parsenleft = 0;
445*d90bee97SLionel Sambuc 	plinno = 1;
446*d90bee97SLionel Sambuc }
447*d90bee97SLionel Sambuc 
448*d90bee97SLionel Sambuc 
449*d90bee97SLionel Sambuc /*
450*d90bee97SLionel Sambuc  * Like setinputfile, but takes input from a string.
451*d90bee97SLionel Sambuc  */
452*d90bee97SLionel Sambuc 
453*d90bee97SLionel Sambuc void
setinputstring(char * string,int push)454*d90bee97SLionel Sambuc setinputstring(char *string, int push)
455*d90bee97SLionel Sambuc {
456*d90bee97SLionel Sambuc 	INTOFF;
457*d90bee97SLionel Sambuc 	if (push)
458*d90bee97SLionel Sambuc 		pushfile();
459*d90bee97SLionel Sambuc 	parsenextc = string;
460*d90bee97SLionel Sambuc 	parselleft = parsenleft = strlen(string);
461*d90bee97SLionel Sambuc 	parsefile->buf = NULL;
462*d90bee97SLionel Sambuc 	plinno = 1;
463*d90bee97SLionel Sambuc 	INTON;
464*d90bee97SLionel Sambuc }
465*d90bee97SLionel Sambuc 
466*d90bee97SLionel Sambuc 
467*d90bee97SLionel Sambuc 
468*d90bee97SLionel Sambuc /*
469*d90bee97SLionel Sambuc  * To handle the "." command, a stack of input files is used.  Pushfile
470*d90bee97SLionel Sambuc  * adds a new entry to the stack and popfile restores the previous level.
471*d90bee97SLionel Sambuc  */
472*d90bee97SLionel Sambuc 
473*d90bee97SLionel Sambuc STATIC void
pushfile(void)474*d90bee97SLionel Sambuc pushfile(void)
475*d90bee97SLionel Sambuc {
476*d90bee97SLionel Sambuc 	struct parsefile *pf;
477*d90bee97SLionel Sambuc 
478*d90bee97SLionel Sambuc 	parsefile->nleft = parsenleft;
479*d90bee97SLionel Sambuc 	parsefile->lleft = parselleft;
480*d90bee97SLionel Sambuc 	parsefile->nextc = parsenextc;
481*d90bee97SLionel Sambuc 	parsefile->linno = plinno;
482*d90bee97SLionel Sambuc 	pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
483*d90bee97SLionel Sambuc 	pf->prev = parsefile;
484*d90bee97SLionel Sambuc 	pf->fd = -1;
485*d90bee97SLionel Sambuc 	pf->strpush = NULL;
486*d90bee97SLionel Sambuc 	pf->basestrpush.prev = NULL;
487*d90bee97SLionel Sambuc 	parsefile = pf;
488*d90bee97SLionel Sambuc }
489*d90bee97SLionel Sambuc 
490*d90bee97SLionel Sambuc 
491*d90bee97SLionel Sambuc void
popfile(void)492*d90bee97SLionel Sambuc popfile(void)
493*d90bee97SLionel Sambuc {
494*d90bee97SLionel Sambuc 	struct parsefile *pf = parsefile;
495*d90bee97SLionel Sambuc 
496*d90bee97SLionel Sambuc 	INTOFF;
497*d90bee97SLionel Sambuc 	if (pf->fd >= 0)
498*d90bee97SLionel Sambuc 		close(pf->fd);
499*d90bee97SLionel Sambuc 	if (pf->buf)
500*d90bee97SLionel Sambuc 		ckfree(pf->buf);
501*d90bee97SLionel Sambuc 	while (pf->strpush)
502*d90bee97SLionel Sambuc 		popstring();
503*d90bee97SLionel Sambuc 	parsefile = pf->prev;
504*d90bee97SLionel Sambuc 	ckfree(pf);
505*d90bee97SLionel Sambuc 	parsenleft = parsefile->nleft;
506*d90bee97SLionel Sambuc 	parselleft = parsefile->lleft;
507*d90bee97SLionel Sambuc 	parsenextc = parsefile->nextc;
508*d90bee97SLionel Sambuc 	plinno = parsefile->linno;
509*d90bee97SLionel Sambuc 	INTON;
510*d90bee97SLionel Sambuc }
511*d90bee97SLionel Sambuc 
512*d90bee97SLionel Sambuc 
513*d90bee97SLionel Sambuc /*
514*d90bee97SLionel Sambuc  * Return to top level.
515*d90bee97SLionel Sambuc  */
516*d90bee97SLionel Sambuc 
517*d90bee97SLionel Sambuc void
popallfiles(void)518*d90bee97SLionel Sambuc popallfiles(void)
519*d90bee97SLionel Sambuc {
520*d90bee97SLionel Sambuc 	while (parsefile != &basepf)
521*d90bee97SLionel Sambuc 		popfile();
522*d90bee97SLionel Sambuc }
523*d90bee97SLionel Sambuc 
524*d90bee97SLionel Sambuc 
525*d90bee97SLionel Sambuc 
526*d90bee97SLionel Sambuc /*
527*d90bee97SLionel Sambuc  * Close the file(s) that the shell is reading commands from.  Called
528*d90bee97SLionel Sambuc  * after a fork is done.
529*d90bee97SLionel Sambuc  *
530*d90bee97SLionel Sambuc  * Takes one arg, vfork, which tells it to not modify its global vars
531*d90bee97SLionel Sambuc  * as it is still running in the parent.
532*d90bee97SLionel Sambuc  *
533*d90bee97SLionel Sambuc  * This code is (probably) unnecessary as the 'close on exec' flag is
534*d90bee97SLionel Sambuc  * set and should be enough.  In the vfork case it is definitely wrong
535*d90bee97SLionel Sambuc  * to close the fds as another fork() may be done later to feed data
536*d90bee97SLionel Sambuc  * from a 'here' document into a pipe and we don't want to close the
537*d90bee97SLionel Sambuc  * pipe!
538*d90bee97SLionel Sambuc  */
539*d90bee97SLionel Sambuc 
540*d90bee97SLionel Sambuc void
closescript(int vforked)541*d90bee97SLionel Sambuc closescript(int vforked)
542*d90bee97SLionel Sambuc {
543*d90bee97SLionel Sambuc 	if (vforked)
544*d90bee97SLionel Sambuc 		return;
545*d90bee97SLionel Sambuc 	popallfiles();
546*d90bee97SLionel Sambuc 	if (parsefile->fd > 0) {
547*d90bee97SLionel Sambuc 		close(parsefile->fd);
548*d90bee97SLionel Sambuc 		parsefile->fd = 0;
549*d90bee97SLionel Sambuc 	}
550*d90bee97SLionel Sambuc }
551