input.c revision 262951
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 * 4. 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#ifndef lint
34#if 0
35static char sccsid[] = "@(#)input.c	8.3 (Berkeley) 6/9/95";
36#endif
37#endif /* not lint */
38#include <sys/cdefs.h>
39__FBSDID("$FreeBSD: stable/10/bin/sh/input.c 262951 2014-03-09 17:04:31Z jmmv $");
40
41#include <stdio.h>	/* defines BUFSIZ */
42#include <fcntl.h>
43#include <errno.h>
44#include <unistd.h>
45#include <stdlib.h>
46#include <string.h>
47
48/*
49 * This file implements the input routines used by the parser.
50 */
51
52#include "shell.h"
53#include "redir.h"
54#include "syntax.h"
55#include "input.h"
56#include "output.h"
57#include "options.h"
58#include "memalloc.h"
59#include "error.h"
60#include "alias.h"
61#include "parser.h"
62#include "myhistedit.h"
63#include "trap.h"
64
65#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
66
67struct strpush {
68	struct strpush *prev;	/* preceding string on stack */
69	const char *prevstring;
70	int prevnleft;
71	int prevlleft;
72	struct alias *ap;	/* if push was associated with an alias */
73};
74
75/*
76 * The parsefile structure pointed to by the global variable parsefile
77 * contains information about the current file being read.
78 */
79
80struct parsefile {
81	struct parsefile *prev;	/* preceding file on stack */
82	int linno;		/* current line */
83	int fd;			/* file descriptor (or -1 if string) */
84	int nleft;		/* number of chars left in this line */
85	int lleft;		/* number of lines left in this buffer */
86	const char *nextc;	/* next char in buffer */
87	char *buf;		/* input buffer */
88	struct strpush *strpush; /* for pushing strings at this level */
89	struct strpush basestrpush; /* so pushing one is fast */
90};
91
92
93int plinno = 1;			/* input line number */
94int parsenleft;			/* copy of parsefile->nleft */
95static int parselleft;		/* copy of parsefile->lleft */
96const char *parsenextc;		/* copy of parsefile->nextc */
97static char basebuf[BUFSIZ + 1];/* buffer for top level input file */
98static struct parsefile basepf = {	/* top level input file */
99	.nextc = basebuf,
100	.buf = basebuf
101};
102static struct parsefile *parsefile = &basepf;	/* current input file */
103int whichprompt;		/* 1 == PS1, 2 == PS2 */
104
105EditLine *el;			/* cookie for editline package */
106
107static void pushfile(void);
108static int preadfd(void);
109static void popstring(void);
110
111void
112resetinput(void)
113{
114	popallfiles();
115	parselleft = parsenleft = 0;	/* clear input buffer */
116}
117
118
119/*
120 * Read a line from the script.
121 */
122
123char *
124pfgets(char *line, int len)
125{
126	char *p = line;
127	int nleft = len;
128	int c;
129
130	while (--nleft > 0) {
131		c = pgetc_macro();
132		if (c == PEOF) {
133			if (p == line)
134				return NULL;
135			break;
136		}
137		*p++ = c;
138		if (c == '\n')
139			break;
140	}
141	*p = '\0';
142	return line;
143}
144
145
146
147/*
148 * Read a character from the script, returning PEOF on end of file.
149 * Nul characters in the input are silently discarded.
150 */
151
152int
153pgetc(void)
154{
155	return pgetc_macro();
156}
157
158
159static int
160preadfd(void)
161{
162	int nr;
163	parsenextc = parsefile->buf;
164
165retry:
166#ifndef NO_HISTORY
167	if (parsefile->fd == 0 && el) {
168		static const char *rl_cp;
169		static int el_len;
170
171		if (rl_cp == NULL) {
172			el_resize(el);
173			rl_cp = el_gets(el, &el_len);
174		}
175		if (rl_cp == NULL)
176			nr = el_len == 0 ? 0 : -1;
177		else {
178			nr = el_len;
179			if (nr > BUFSIZ)
180				nr = BUFSIZ;
181			memcpy(parsefile->buf, rl_cp, nr);
182			if (nr != el_len) {
183				el_len -= nr;
184				rl_cp += nr;
185			} else
186				rl_cp = NULL;
187		}
188	} else
189#endif
190		nr = read(parsefile->fd, parsefile->buf, BUFSIZ);
191
192	if (nr <= 0) {
193                if (nr < 0) {
194                        if (errno == EINTR)
195                                goto retry;
196                        if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
197                                int flags = fcntl(0, F_GETFL, 0);
198                                if (flags >= 0 && flags & O_NONBLOCK) {
199                                        flags &=~ O_NONBLOCK;
200                                        if (fcntl(0, F_SETFL, flags) >= 0) {
201						out2fmt_flush("sh: turning off NDELAY mode\n");
202                                                goto retry;
203                                        }
204                                }
205                        }
206                }
207                nr = -1;
208	}
209	return nr;
210}
211
212/*
213 * Refill the input buffer and return the next input character:
214 *
215 * 1) If a string was pushed back on the input, pop it;
216 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
217 *    from a string so we can't refill the buffer, return EOF.
218 * 3) If there is more in this buffer, use it else call read to fill it.
219 * 4) Process input up to the next newline, deleting nul characters.
220 */
221
222int
223preadbuffer(void)
224{
225	char *p, *q;
226	int more;
227	char savec;
228
229	while (parsefile->strpush) {
230		/*
231		 * Add a space to the end of an alias to ensure that the
232		 * alias remains in use while parsing its last word.
233		 * This avoids alias recursions.
234		 */
235		if (parsenleft == -1 && parsefile->strpush->ap != NULL)
236			return ' ';
237		popstring();
238		if (--parsenleft >= 0)
239			return (*parsenextc++);
240	}
241	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
242		return PEOF;
243	flushout(&output);
244	flushout(&errout);
245
246again:
247	if (parselleft <= 0) {
248		if ((parselleft = preadfd()) == -1) {
249			parselleft = parsenleft = EOF_NLEFT;
250			return PEOF;
251		}
252	}
253
254	q = p = parsefile->buf + (parsenextc - parsefile->buf);
255
256	/* delete nul characters */
257	for (more = 1; more;) {
258		switch (*p) {
259		case '\0':
260			p++;	/* Skip nul */
261			goto check;
262
263		case '\n':
264			parsenleft = q - parsenextc;
265			more = 0; /* Stop processing here */
266			break;
267
268		default:
269			break;
270		}
271
272		*q++ = *p++;
273check:
274		if (--parselleft <= 0) {
275			parsenleft = q - parsenextc - 1;
276			if (parsenleft < 0)
277				goto again;
278			*q = '\0';
279			more = 0;
280		}
281	}
282
283	savec = *q;
284	*q = '\0';
285
286#ifndef NO_HISTORY
287	if (parsefile->fd == 0 && hist &&
288	    parsenextc[strspn(parsenextc, " \t\n")] != '\0') {
289		HistEvent he;
290		INTOFF;
291		history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD,
292		    parsenextc);
293		INTON;
294	}
295#endif
296
297	if (vflag) {
298		out2str(parsenextc);
299		flushout(out2);
300	}
301
302	*q = savec;
303
304	return *parsenextc++;
305}
306
307/*
308 * Returns if we are certain we are at EOF. Does not cause any more input
309 * to be read from the outside world.
310 */
311
312int
313preadateof(void)
314{
315	if (parsenleft > 0)
316		return 0;
317	if (parsefile->strpush)
318		return 0;
319	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
320		return 1;
321	return 0;
322}
323
324/*
325 * Undo the last call to pgetc.  Only one character may be pushed back.
326 * PEOF may be pushed back.
327 */
328
329void
330pungetc(void)
331{
332	parsenleft++;
333	parsenextc--;
334}
335
336/*
337 * Push a string back onto the input at this current parsefile level.
338 * We handle aliases this way.
339 */
340void
341pushstring(char *s, int len, struct alias *ap)
342{
343	struct strpush *sp;
344
345	INTOFF;
346/*out2fmt_flush("*** calling pushstring: %s, %d\n", s, len);*/
347	if (parsefile->strpush) {
348		sp = ckmalloc(sizeof (struct strpush));
349		sp->prev = parsefile->strpush;
350		parsefile->strpush = sp;
351	} else
352		sp = parsefile->strpush = &(parsefile->basestrpush);
353	sp->prevstring = parsenextc;
354	sp->prevnleft = parsenleft;
355	sp->prevlleft = parselleft;
356	sp->ap = ap;
357	if (ap)
358		ap->flag |= ALIASINUSE;
359	parsenextc = s;
360	parsenleft = len;
361	INTON;
362}
363
364static void
365popstring(void)
366{
367	struct strpush *sp = parsefile->strpush;
368
369	INTOFF;
370	if (sp->ap) {
371		if (parsenextc != sp->ap->val &&
372		    (parsenextc[-1] == ' ' || parsenextc[-1] == '\t'))
373			forcealias();
374		sp->ap->flag &= ~ALIASINUSE;
375	}
376	parsenextc = sp->prevstring;
377	parsenleft = sp->prevnleft;
378	parselleft = sp->prevlleft;
379/*out2fmt_flush("*** calling popstring: restoring to '%s'\n", parsenextc);*/
380	parsefile->strpush = sp->prev;
381	if (sp != &(parsefile->basestrpush))
382		ckfree(sp);
383	INTON;
384}
385
386/*
387 * Set the input to take input from a file.  If push is set, push the
388 * old input onto the stack first.
389 */
390
391void
392setinputfile(const char *fname, int push)
393{
394	int fd;
395	int fd2;
396
397	INTOFF;
398	if ((fd = open(fname, O_RDONLY | O_CLOEXEC)) < 0)
399		error("cannot open %s: %s", fname, strerror(errno));
400	if (fd < 10) {
401		fd2 = fcntl(fd, F_DUPFD_CLOEXEC, 10);
402		close(fd);
403		if (fd2 < 0)
404			error("Out of file descriptors");
405		fd = fd2;
406	}
407	setinputfd(fd, push);
408	INTON;
409}
410
411
412/*
413 * Like setinputfile, but takes an open file descriptor (which should have
414 * its FD_CLOEXEC flag already set).  Call this with interrupts off.
415 */
416
417void
418setinputfd(int fd, int push)
419{
420	if (push) {
421		pushfile();
422		parsefile->buf = ckmalloc(BUFSIZ + 1);
423	}
424	if (parsefile->fd > 0)
425		close(parsefile->fd);
426	parsefile->fd = fd;
427	if (parsefile->buf == NULL)
428		parsefile->buf = ckmalloc(BUFSIZ + 1);
429	parselleft = parsenleft = 0;
430	plinno = 1;
431}
432
433
434/*
435 * Like setinputfile, but takes input from a string.
436 */
437
438void
439setinputstring(const char *string, int push)
440{
441	INTOFF;
442	if (push)
443		pushfile();
444	parsenextc = string;
445	parselleft = parsenleft = strlen(string);
446	parsefile->buf = NULL;
447	plinno = 1;
448	INTON;
449}
450
451
452
453/*
454 * To handle the "." command, a stack of input files is used.  Pushfile
455 * adds a new entry to the stack and popfile restores the previous level.
456 */
457
458static void
459pushfile(void)
460{
461	struct parsefile *pf;
462
463	parsefile->nleft = parsenleft;
464	parsefile->lleft = parselleft;
465	parsefile->nextc = parsenextc;
466	parsefile->linno = plinno;
467	pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
468	pf->prev = parsefile;
469	pf->fd = -1;
470	pf->strpush = NULL;
471	pf->basestrpush.prev = NULL;
472	parsefile = pf;
473}
474
475
476void
477popfile(void)
478{
479	struct parsefile *pf = parsefile;
480
481	INTOFF;
482	if (pf->fd >= 0)
483		close(pf->fd);
484	if (pf->buf)
485		ckfree(pf->buf);
486	while (pf->strpush)
487		popstring();
488	parsefile = pf->prev;
489	ckfree(pf);
490	parsenleft = parsefile->nleft;
491	parselleft = parsefile->lleft;
492	parsenextc = parsefile->nextc;
493	plinno = parsefile->linno;
494	INTON;
495}
496
497
498/*
499 * Return current file (to go back to it later using popfilesupto()).
500 */
501
502struct parsefile *
503getcurrentfile(void)
504{
505	return parsefile;
506}
507
508
509/*
510 * Pop files until the given file is on top again. Useful for regular
511 * builtins that read shell commands from files or strings.
512 * If the given file is not an active file, an error is raised.
513 */
514
515void
516popfilesupto(struct parsefile *file)
517{
518	while (parsefile != file && parsefile != &basepf)
519		popfile();
520	if (parsefile != file)
521		error("popfilesupto() misused");
522}
523
524/*
525 * Return to top level.
526 */
527
528void
529popallfiles(void)
530{
531	while (parsefile != &basepf)
532		popfile();
533}
534
535
536
537/*
538 * Close the file(s) that the shell is reading commands from.  Called
539 * after a fork is done.
540 */
541
542void
543closescript(void)
544{
545	popallfiles();
546	if (parsefile->fd > 0) {
547		close(parsefile->fd);
548		parsefile->fd = 0;
549	}
550}
551