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