input.c revision 248980
1153592Ssam/*-
2153592Ssam * Copyright (c) 1991, 1993
3153592Ssam *	The Regents of the University of California.  All rights reserved.
4153592Ssam *
5153592Ssam * This code is derived from software contributed to Berkeley by
6153592Ssam * Kenneth Almquist.
7153592Ssam *
8153592Ssam * Redistribution and use in source and binary forms, with or without
9153592Ssam * modification, are permitted provided that the following conditions
10153592Ssam * are met:
11153592Ssam * 1. Redistributions of source code must retain the above copyright
12153592Ssam *    notice, this list of conditions and the following disclaimer.
13174632Smarcel * 2. Redistributions in binary form must reproduce the above copyright
14176780Smarcel *    notice, this list of conditions and the following disclaimer in the
15153592Ssam *    documentation and/or other materials provided with the distribution.
16176495Smarcel * 4. Neither the name of the University nor the names of its contributors
17176495Smarcel *    may be used to endorse or promote products derived from this software
18176782Smarcel *    without specific prior written permission.
19153592Ssam *
20153592Ssam * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21153592Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22153592Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23153592Ssam * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24153592Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25153592Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26153592Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27179646Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28153592Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29185755Snwhitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30185755Snwhitehorn * SUCH DAMAGE.
31185755Snwhitehorn */
32153592Ssam
33153592Ssam#ifndef lint
34153592Ssam#if 0
35153592Ssamstatic char sccsid[] = "@(#)input.c	8.3 (Berkeley) 6/9/95";
36153592Ssam#endif
37153592Ssam#endif /* not lint */
38153592Ssam#include <sys/cdefs.h>
39163630Sru__FBSDID("$FreeBSD: head/bin/sh/input.c 248980 2013-04-01 17:18:22Z jilles $");
40153592Ssam
41153592Ssam#include <stdio.h>	/* defines BUFSIZ */
42153592Ssam#include <fcntl.h>
43153592Ssam#include <errno.h>
44153592Ssam#include <unistd.h>
45153592Ssam#include <stdlib.h>
46153592Ssam#include <string.h>
47153592Ssam
48153592Ssam/*
49153592Ssam * This file implements the input routines used by the parser.
50153592Ssam */
51153592Ssam
52153592Ssam#include "shell.h"
53153592Ssam#include "redir.h"
54153592Ssam#include "syntax.h"
55153592Ssam#include "input.h"
56153592Ssam#include "output.h"
57153592Ssam#include "options.h"
58174782Smarcel#include "memalloc.h"
59174782Smarcel#include "error.h"
60153592Ssam#include "alias.h"
61153592Ssam#include "parser.h"
62153592Ssam#include "myhistedit.h"
63153592Ssam#include "trap.h"
64153592Ssam
65153592Ssam#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
66153592Ssam
67153592Ssamstruct strpush {
68153592Ssam	struct strpush *prev;	/* preceding string on stack */
69153592Ssam	const char *prevstring;
70165926Smarius	int prevnleft;
71153592Ssam	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 */
95MKINIT 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
111#ifdef mkinit
112INCLUDE "input.h"
113INCLUDE "error.h"
114
115RESET {
116	popallfiles();
117	parselleft = parsenleft = 0;	/* clear input buffer */
118}
119#endif
120
121
122/*
123 * Read a line from the script.
124 */
125
126char *
127pfgets(char *line, int len)
128{
129	char *p = line;
130	int nleft = len;
131	int c;
132
133	while (--nleft > 0) {
134		c = pgetc_macro();
135		if (c == PEOF) {
136			if (p == line)
137				return NULL;
138			break;
139		}
140		*p++ = c;
141		if (c == '\n')
142			break;
143	}
144	*p = '\0';
145	return line;
146}
147
148
149
150/*
151 * Read a character from the script, returning PEOF on end of file.
152 * Nul characters in the input are silently discarded.
153 */
154
155int
156pgetc(void)
157{
158	return pgetc_macro();
159}
160
161
162static int
163preadfd(void)
164{
165	int nr;
166	parsenextc = parsefile->buf;
167
168#ifndef NO_HISTORY
169	if (el != NULL && gotwinch) {
170		gotwinch = 0;
171		el_resize(el);
172	}
173#endif
174retry:
175#ifndef NO_HISTORY
176	if (parsefile->fd == 0 && el) {
177		static const char *rl_cp;
178		static int el_len;
179
180		if (rl_cp == NULL)
181			rl_cp = el_gets(el, &el_len);
182		if (rl_cp == NULL)
183			nr = el_len == 0 ? 0 : -1;
184		else {
185			nr = el_len;
186			if (nr > BUFSIZ)
187				nr = BUFSIZ;
188			memcpy(parsefile->buf, rl_cp, nr);
189			if (nr != el_len) {
190				el_len -= nr;
191				rl_cp += nr;
192			} else
193				rl_cp = NULL;
194		}
195	} else
196#endif
197		nr = read(parsefile->fd, parsefile->buf, BUFSIZ);
198
199	if (nr <= 0) {
200                if (nr < 0) {
201                        if (errno == EINTR)
202                                goto retry;
203                        if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
204                                int flags = fcntl(0, F_GETFL, 0);
205                                if (flags >= 0 && flags & O_NONBLOCK) {
206                                        flags &=~ O_NONBLOCK;
207                                        if (fcntl(0, F_SETFL, flags) >= 0) {
208						out2fmt_flush("sh: turning off NDELAY mode\n");
209                                                goto retry;
210                                        }
211                                }
212                        }
213                }
214                nr = -1;
215	}
216	return nr;
217}
218
219/*
220 * Refill the input buffer and return the next input character:
221 *
222 * 1) If a string was pushed back on the input, pop it;
223 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
224 *    from a string so we can't refill the buffer, return EOF.
225 * 3) If there is more in this buffer, use it else call read to fill it.
226 * 4) Process input up to the next newline, deleting nul characters.
227 */
228
229int
230preadbuffer(void)
231{
232	char *p, *q;
233	int more;
234	int something;
235	char savec;
236
237	if (parsefile->strpush) {
238		popstring();
239		if (--parsenleft >= 0)
240			return (*parsenextc++);
241	}
242	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
243		return PEOF;
244	flushout(&output);
245	flushout(&errout);
246
247again:
248	if (parselleft <= 0) {
249		if ((parselleft = preadfd()) == -1) {
250			parselleft = parsenleft = EOF_NLEFT;
251			return PEOF;
252		}
253	}
254
255	q = p = parsefile->buf + (parsenextc - parsefile->buf);
256
257	/* delete nul characters */
258	something = 0;
259	for (more = 1; more;) {
260		switch (*p) {
261		case '\0':
262			p++;	/* Skip nul */
263			goto check;
264
265		case '\t':
266		case ' ':
267			break;
268
269		case '\n':
270			parsenleft = q - parsenextc;
271			more = 0; /* Stop processing here */
272			break;
273
274		default:
275			something = 1;
276			break;
277		}
278
279		*q++ = *p++;
280check:
281		if (--parselleft <= 0) {
282			parsenleft = q - parsenextc - 1;
283			if (parsenleft < 0)
284				goto again;
285			*q = '\0';
286			more = 0;
287		}
288	}
289
290	savec = *q;
291	*q = '\0';
292
293#ifndef NO_HISTORY
294	if (parsefile->fd == 0 && hist && something) {
295		HistEvent he;
296		INTOFF;
297		history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD,
298		    parsenextc);
299		INTON;
300	}
301#endif
302
303	if (vflag) {
304		out2str(parsenextc);
305		flushout(out2);
306	}
307
308	*q = savec;
309
310	return *parsenextc++;
311}
312
313/*
314 * Returns if we are certain we are at EOF. Does not cause any more input
315 * to be read from the outside world.
316 */
317
318int
319preadateof(void)
320{
321	if (parsenleft > 0)
322		return 0;
323	if (parsefile->strpush)
324		return 0;
325	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
326		return 1;
327	return 0;
328}
329
330/*
331 * Undo the last call to pgetc.  Only one character may be pushed back.
332 * PEOF may be pushed back.
333 */
334
335void
336pungetc(void)
337{
338	parsenleft++;
339	parsenextc--;
340}
341
342/*
343 * Push a string back onto the input at this current parsefile level.
344 * We handle aliases this way.
345 */
346void
347pushstring(char *s, int len, struct alias *ap)
348{
349	struct strpush *sp;
350
351	INTOFF;
352/*out2fmt_flush("*** calling pushstring: %s, %d\n", s, len);*/
353	if (parsefile->strpush) {
354		sp = ckmalloc(sizeof (struct strpush));
355		sp->prev = parsefile->strpush;
356		parsefile->strpush = sp;
357	} else
358		sp = parsefile->strpush = &(parsefile->basestrpush);
359	sp->prevstring = parsenextc;
360	sp->prevnleft = parsenleft;
361	sp->prevlleft = parselleft;
362	sp->ap = ap;
363	if (ap)
364		ap->flag |= ALIASINUSE;
365	parsenextc = s;
366	parsenleft = len;
367	INTON;
368}
369
370static void
371popstring(void)
372{
373	struct strpush *sp = parsefile->strpush;
374
375	INTOFF;
376	parsenextc = sp->prevstring;
377	parsenleft = sp->prevnleft;
378	parselleft = sp->prevlleft;
379/*out2fmt_flush("*** calling popstring: restoring to '%s'\n", parsenextc);*/
380	if (sp->ap)
381		sp->ap->flag &= ~ALIASINUSE;
382	parsefile->strpush = sp->prev;
383	if (sp != &(parsefile->basestrpush))
384		ckfree(sp);
385	INTON;
386}
387
388/*
389 * Set the input to take input from a file.  If push is set, push the
390 * old input onto the stack first.
391 */
392
393void
394setinputfile(const char *fname, int push)
395{
396	int fd;
397	int fd2;
398
399	INTOFF;
400	if ((fd = open(fname, O_RDONLY)) < 0)
401		error("cannot open %s: %s", fname, strerror(errno));
402	if (fd < 10) {
403		fd2 = fcntl(fd, F_DUPFD, 10);
404		close(fd);
405		if (fd2 < 0)
406			error("Out of file descriptors");
407		fd = fd2;
408	}
409	setinputfd(fd, push);
410	INTON;
411}
412
413
414/*
415 * Like setinputfile, but takes an open file descriptor.  Call this with
416 * interrupts off.
417 */
418
419void
420setinputfd(int fd, int push)
421{
422	(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
423	if (push) {
424		pushfile();
425		parsefile->buf = ckmalloc(BUFSIZ + 1);
426	}
427	if (parsefile->fd > 0)
428		close(parsefile->fd);
429	parsefile->fd = fd;
430	if (parsefile->buf == NULL)
431		parsefile->buf = ckmalloc(BUFSIZ + 1);
432	parselleft = parsenleft = 0;
433	plinno = 1;
434}
435
436
437/*
438 * Like setinputfile, but takes input from a string.
439 */
440
441void
442setinputstring(const char *string, int push)
443{
444	INTOFF;
445	if (push)
446		pushfile();
447	parsenextc = string;
448	parselleft = parsenleft = strlen(string);
449	parsefile->buf = NULL;
450	plinno = 1;
451	INTON;
452}
453
454
455
456/*
457 * To handle the "." command, a stack of input files is used.  Pushfile
458 * adds a new entry to the stack and popfile restores the previous level.
459 */
460
461static void
462pushfile(void)
463{
464	struct parsefile *pf;
465
466	parsefile->nleft = parsenleft;
467	parsefile->lleft = parselleft;
468	parsefile->nextc = parsenextc;
469	parsefile->linno = plinno;
470	pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
471	pf->prev = parsefile;
472	pf->fd = -1;
473	pf->strpush = NULL;
474	pf->basestrpush.prev = NULL;
475	parsefile = pf;
476}
477
478
479void
480popfile(void)
481{
482	struct parsefile *pf = parsefile;
483
484	INTOFF;
485	if (pf->fd >= 0)
486		close(pf->fd);
487	if (pf->buf)
488		ckfree(pf->buf);
489	while (pf->strpush)
490		popstring();
491	parsefile = pf->prev;
492	ckfree(pf);
493	parsenleft = parsefile->nleft;
494	parselleft = parsefile->lleft;
495	parsenextc = parsefile->nextc;
496	plinno = parsefile->linno;
497	INTON;
498}
499
500
501/*
502 * Return current file (to go back to it later using popfilesupto()).
503 */
504
505struct parsefile *
506getcurrentfile(void)
507{
508	return parsefile;
509}
510
511
512/*
513 * Pop files until the given file is on top again. Useful for regular
514 * builtins that read shell commands from files or strings.
515 * If the given file is not an active file, an error is raised.
516 */
517
518void
519popfilesupto(struct parsefile *file)
520{
521	while (parsefile != file && parsefile != &basepf)
522		popfile();
523	if (parsefile != file)
524		error("popfilesupto() misused");
525}
526
527/*
528 * Return to top level.
529 */
530
531void
532popallfiles(void)
533{
534	while (parsefile != &basepf)
535		popfile();
536}
537
538
539
540/*
541 * Close the file(s) that the shell is reading commands from.  Called
542 * after a fork is done.
543 */
544
545void
546closescript(void)
547{
548	popallfiles();
549	if (parsefile->fd > 0) {
550		close(parsefile->fd);
551		parsefile->fd = 0;
552	}
553}
554