input.c revision 213760
1111314Snyan/*-
2111314Snyan * Copyright (c) 1991, 1993
3111314Snyan *	The Regents of the University of California.  All rights reserved.
4111314Snyan *
5111314Snyan * This code is derived from software contributed to Berkeley by
6111314Snyan * Kenneth Almquist.
7111314Snyan *
8111314Snyan * Redistribution and use in source and binary forms, with or without
9111314Snyan * modification, are permitted provided that the following conditions
10111314Snyan * are met:
11111314Snyan * 1. Redistributions of source code must retain the above copyright
12111314Snyan *    notice, this list of conditions and the following disclaimer.
13111314Snyan * 2. Redistributions in binary form must reproduce the above copyright
14111314Snyan *    notice, this list of conditions and the following disclaimer in the
15111314Snyan *    documentation and/or other materials provided with the distribution.
16111314Snyan * 4. Neither the name of the University nor the names of its contributors
17111314Snyan *    may be used to endorse or promote products derived from this software
18111314Snyan *    without specific prior written permission.
19111314Snyan *
20111314Snyan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21111314Snyan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22111314Snyan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23111314Snyan * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24111314Snyan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25111314Snyan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26122755Snyan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27122755Snyan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28122755Snyan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29122755Snyan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30111314Snyan * SUCH DAMAGE.
31111314Snyan */
32111314Snyan
33122755Snyan#ifndef lint
34111314Snyan#if 0
35122755Snyanstatic char sccsid[] = "@(#)input.c	8.3 (Berkeley) 6/9/95";
36122755Snyan#endif
37122755Snyan#endif /* not lint */
38122755Snyan#include <sys/cdefs.h>
39122755Snyan__FBSDID("$FreeBSD: head/bin/sh/input.c 213760 2010-10-13 04:01:01Z obrien $");
40122755Snyan
41122755Snyan#include <stdio.h>	/* defines BUFSIZ */
42111314Snyan#include <fcntl.h>
43111314Snyan#include <errno.h>
44111314Snyan#include <unistd.h>
45122056Snyan#include <stdlib.h>
46124795Snyan#include <string.h>
47124795Snyan
48122755Snyan/*
49111314Snyan * This file implements the input routines used by the parser.
50111314Snyan */
51111314Snyan
52111314Snyan#include "shell.h"
53111314Snyan#include "redir.h"
54111314Snyan#include "syntax.h"
55111314Snyan#include "input.h"
56111314Snyan#include "output.h"
57111314Snyan#include "options.h"
58111314Snyan#include "memalloc.h"
59111314Snyan#include "error.h"
60111314Snyan#include "alias.h"
61111314Snyan#include "parser.h"
62111314Snyan#include "myhistedit.h"
63111314Snyan#include "trap.h"
64111314Snyan
65111314Snyan#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
66111314Snyan
67111314SnyanMKINIT
68124795Snyanstruct strpush {
69124795Snyan	struct strpush *prev;	/* preceding string on stack */
70124795Snyan	char *prevstring;
71124795Snyan	int prevnleft;
72111314Snyan	int prevlleft;
73111314Snyan	struct alias *ap;	/* if push was associated with an alias */
74111314Snyan};
75111314Snyan
76111314Snyan/*
77111314Snyan * The parsefile structure pointed to by the global variable parsefile
78111314Snyan * contains information about the current file being read.
79111314Snyan */
80111314Snyan
81111314SnyanMKINIT
82124795Snyanstruct parsefile {
83124795Snyan	struct parsefile *prev;	/* preceding file on stack */
84124795Snyan	int linno;		/* current line */
85111314Snyan	int fd;			/* file descriptor (or -1 if string) */
86111314Snyan	int nleft;		/* number of chars left in this line */
87111314Snyan	int lleft;		/* number of lines left in this buffer */
88111314Snyan	char *nextc;		/* next char in buffer */
89124795Snyan	char *buf;		/* input buffer */
90124795Snyan	struct strpush *strpush; /* for pushing strings at this level */
91124795Snyan	struct strpush basestrpush; /* so pushing one is fast */
92124795Snyan};
93124795Snyan
94124795Snyan
95124795Snyanint plinno = 1;			/* input line number */
96111314Snyanint parsenleft;			/* copy of parsefile->nleft */
97111314SnyanMKINIT int parselleft;		/* copy of parsefile->lleft */
98111314Snyanchar *parsenextc;		/* copy of parsefile->nextc */
99111314SnyanMKINIT struct parsefile basepf;	/* top level input file */
100111314Snyanchar basebuf[BUFSIZ];		/* buffer for top level input file */
101111314Snyanstatic struct parsefile *parsefile = &basepf;	/* current input file */
102111314Snyanint init_editline = 0;		/* editline library initialized? */
103111314Snyanint whichprompt;		/* 1 == PS1, 2 == PS2 */
104111314Snyan
105111314SnyanEditLine *el;			/* cookie for editline package */
106111314Snyan
107111314SnyanSTATIC void pushfile(void);
108111314SnyanSTATIC int preadfd(void);
109111314Snyan
110111314Snyan#ifdef mkinit
111111314SnyanINCLUDE "input.h"
112111314SnyanINCLUDE "error.h"
113111314Snyan
114111314SnyanMKINIT char basebuf[];
115111314Snyan
116111314SnyanINIT {
117111314Snyan	basepf.nextc = basepf.buf = basebuf;
118111314Snyan}
119111314Snyan
120111314SnyanRESET {
121111314Snyan	popallfiles();
122111314Snyan	if (exception != EXSHELLPROC)
123111314Snyan		parselleft = parsenleft = 0;	/* clear input buffer */
124111314Snyan}
125111314Snyan
126111314SnyanSHELLPROC {
127111314Snyan	popallfiles();
128111314Snyan}
129111314Snyan#endif
130111314Snyan
131111314Snyan
132111314Snyan/*
133111314Snyan * Read a line from the script.
134111314Snyan */
135111314Snyan
136111314Snyanchar *
137111314Snyanpfgets(char *line, int len)
138111314Snyan{
139111314Snyan	char *p = line;
140111314Snyan	int nleft = len;
141111314Snyan	int c;
142111314Snyan
143111314Snyan	while (--nleft > 0) {
144111314Snyan		c = pgetc_macro();
145111314Snyan		if (c == PEOF) {
146111314Snyan			if (p == line)
147111314Snyan				return NULL;
148111314Snyan			break;
149111314Snyan		}
150111314Snyan		*p++ = c;
151111314Snyan		if (c == '\n')
152111314Snyan			break;
153111314Snyan	}
154111314Snyan	*p = '\0';
155111314Snyan	return line;
156111314Snyan}
157124795Snyan
158111314Snyan
159111314Snyan
160111314Snyan/*
161111314Snyan * Read a character from the script, returning PEOF on end of file.
162124795Snyan * Nul characters in the input are silently discarded.
163124795Snyan */
164111314Snyan
165111314Snyanint
166111314Snyanpgetc(void)
167111314Snyan{
168111314Snyan	return pgetc_macro();
169111314Snyan}
170111314Snyan
171111314Snyan
172111314SnyanSTATIC int
173111314Snyanpreadfd(void)
174111314Snyan{
175111314Snyan	int nr;
176111314Snyan	parsenextc = parsefile->buf;
177111314Snyan
178111314Snyan#ifndef NO_HISTORY
179111314Snyan	if (el != NULL && gotwinch) {
180124795Snyan		gotwinch = 0;
181111314Snyan		el_resize(el);
182111314Snyan	}
183111314Snyan#endif
184111314Snyanretry:
185111314Snyan#ifndef NO_HISTORY
186111314Snyan	if (parsefile->fd == 0 && el) {
187111314Snyan		static const char *rl_cp;
188111314Snyan		static int el_len;
189111314Snyan
190111314Snyan		if (rl_cp == NULL)
191111314Snyan			rl_cp = el_gets(el, &el_len);
192111314Snyan		if (rl_cp == NULL)
193111314Snyan			nr = 0;
194111314Snyan		else {
195111314Snyan			nr = el_len;
196111314Snyan			if (nr > BUFSIZ - 1)
197124795Snyan				nr = BUFSIZ - 1;
198111314Snyan			memcpy(parsenextc, rl_cp, nr);
199111314Snyan			if (nr != el_len) {
200111314Snyan				el_len -= nr;
201111314Snyan				rl_cp += nr;
202111314Snyan			} else
203111314Snyan				rl_cp = NULL;
204111314Snyan		}
205111314Snyan	} else
206124408Snyan#endif
207124408Snyan		nr = read(parsefile->fd, parsenextc, BUFSIZ - 1);
208111314Snyan
209111314Snyan	if (nr <= 0) {
210111314Snyan                if (nr < 0) {
211111314Snyan                        if (errno == EINTR)
212111314Snyan                                goto retry;
213111314Snyan                        if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
214111314Snyan                                int flags = fcntl(0, F_GETFL, 0);
215111314Snyan                                if (flags >= 0 && flags & O_NONBLOCK) {
216111314Snyan                                        flags &=~ O_NONBLOCK;
217111314Snyan                                        if (fcntl(0, F_SETFL, flags) >= 0) {
218123984Sbde						out2fmt_flush("sh: turning off NDELAY mode\n");
219123984Sbde                                                goto retry;
220123984Sbde                                        }
221123984Sbde                                }
222111314Snyan                        }
223111314Snyan                }
224123984Sbde                nr = -1;
225123984Sbde	}
226111314Snyan	return nr;
227111314Snyan}
228111314Snyan
229111314Snyan/*
230111314Snyan * Refill the input buffer and return the next input character:
231111314Snyan *
232111314Snyan * 1) If a string was pushed back on the input, pop it;
233111314Snyan * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
234111314Snyan *    from a string so we can't refill the buffer, return EOF.
235124795Snyan * 3) If there is more in this buffer, use it else call read to fill it.
236111314Snyan * 4) Process input up to the next newline, deleting nul characters.
237111314Snyan */
238111314Snyan
239111314Snyanint
240111314Snyanpreadbuffer(void)
241111314Snyan{
242111314Snyan	char *p, *q;
243111314Snyan	int more;
244111314Snyan	int something;
245111314Snyan	char savec;
246111314Snyan
247111314Snyan	if (parsefile->strpush) {
248111314Snyan		popstring();
249111314Snyan		if (--parsenleft >= 0)
250111314Snyan			return (*parsenextc++);
251111314Snyan	}
252111314Snyan	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
253111314Snyan		return PEOF;
254111314Snyan	flushout(&output);
255111314Snyan	flushout(&errout);
256111314Snyan
257111314Snyanagain:
258111314Snyan	if (parselleft <= 0) {
259111314Snyan		if ((parselleft = preadfd()) == -1) {
260111314Snyan			parselleft = parsenleft = EOF_NLEFT;
261111314Snyan			return PEOF;
262111314Snyan		}
263111314Snyan	}
264111314Snyan
265111314Snyan	q = p = parsenextc;
266111314Snyan
267111314Snyan	/* delete nul characters */
268111314Snyan	something = 0;
269111314Snyan	for (more = 1; more;) {
270111314Snyan		switch (*p) {
271111314Snyan		case '\0':
272111314Snyan			p++;	/* Skip nul */
273111314Snyan			goto check;
274111314Snyan
275111314Snyan		case '\t':
276111314Snyan		case ' ':
277111314Snyan			break;
278111314Snyan
279111314Snyan		case '\n':
280111314Snyan			parsenleft = q - parsenextc;
281111314Snyan			more = 0; /* Stop processing here */
282111314Snyan			break;
283111314Snyan
284111314Snyan		default:
285111314Snyan			something = 1;
286111314Snyan			break;
287111314Snyan		}
288111314Snyan
289111314Snyan		*q++ = *p++;
290111314Snyancheck:
291111314Snyan		if (--parselleft <= 0) {
292111314Snyan			parsenleft = q - parsenextc - 1;
293111314Snyan			if (parsenleft < 0)
294111314Snyan				goto again;
295111314Snyan			*q = '\0';
296111314Snyan			more = 0;
297111314Snyan		}
298111314Snyan	}
299111314Snyan
300111314Snyan	savec = *q;
301111314Snyan	*q = '\0';
302111314Snyan
303111314Snyan#ifndef NO_HISTORY
304111314Snyan	if (parsefile->fd == 0 && hist && something) {
305111314Snyan		HistEvent he;
306111314Snyan		INTOFF;
307111314Snyan		history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD,
308111314Snyan		    parsenextc);
309111314Snyan		INTON;
310111314Snyan	}
311111314Snyan#endif
312111314Snyan
313111314Snyan	if (vflag) {
314111314Snyan		out2str(parsenextc);
315111314Snyan		flushout(out2);
316111314Snyan	}
317111314Snyan
318111314Snyan	*q = savec;
319111314Snyan
320111314Snyan	return *parsenextc++;
321111314Snyan}
322111314Snyan
323111314Snyan/*
324111314Snyan * Returns if we are certain we are at EOF. Does not cause any more input
325111314Snyan * to be read from the outside world.
326111314Snyan */
327111314Snyan
328111314Snyanint
329111314Snyanpreadateof(void)
330111314Snyan{
331111314Snyan	if (parsenleft > 0)
332111314Snyan		return 0;
333111314Snyan	if (parsefile->strpush)
334111314Snyan		return 0;
335124795Snyan	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
336124795Snyan		return 1;
337124795Snyan	return 0;
338111314Snyan}
339111314Snyan
340111314Snyan/*
341124795Snyan * Undo the last call to pgetc.  Only one character may be pushed back.
342111314Snyan * PEOF may be pushed back.
343111314Snyan */
344111314Snyan
345111314Snyanvoid
346111314Snyanpungetc(void)
347111314Snyan{
348111314Snyan	parsenleft++;
349112034Snyan	parsenextc--;
350112034Snyan}
351119985Snyan
352119985Snyan/*
353112034Snyan * Push a string back onto the input at this current parsefile level.
354111314Snyan * We handle aliases this way.
355112034Snyan */
356112034Snyanvoid
357111314Snyanpushstring(char *s, int len, void *ap)
358111314Snyan{
359111314Snyan	struct strpush *sp;
360111314Snyan
361119985Snyan	INTOFF;
362111314Snyan/*out2fmt_flush("*** calling pushstring: %s, %d\n", s, len);*/
363111314Snyan	if (parsefile->strpush) {
364111314Snyan		sp = ckmalloc(sizeof (struct strpush));
365111314Snyan		sp->prev = parsefile->strpush;
366111314Snyan		parsefile->strpush = sp;
367111314Snyan	} else
368111314Snyan		sp = parsefile->strpush = &(parsefile->basestrpush);
369111314Snyan	sp->prevstring = parsenextc;
370111314Snyan	sp->prevnleft = parsenleft;
371111314Snyan	sp->prevlleft = parselleft;
372111314Snyan	sp->ap = (struct alias *)ap;
373111314Snyan	if (ap)
374111314Snyan		((struct alias *)ap)->flag |= ALIASINUSE;
375111314Snyan	parsenextc = s;
376111314Snyan	parsenleft = len;
377111314Snyan	INTON;
378111314Snyan}
379111314Snyan
380111314Snyanvoid
381111314Snyanpopstring(void)
382111314Snyan{
383111314Snyan	struct strpush *sp = parsefile->strpush;
384111314Snyan
385111314Snyan	INTOFF;
386111314Snyan	parsenextc = sp->prevstring;
387111314Snyan	parsenleft = sp->prevnleft;
388111314Snyan	parselleft = sp->prevlleft;
389111314Snyan/*out2fmt_flush("*** calling popstring: restoring to '%s'\n", parsenextc);*/
390111314Snyan	if (sp->ap)
391111314Snyan		sp->ap->flag &= ~ALIASINUSE;
392111314Snyan	parsefile->strpush = sp->prev;
393111314Snyan	if (sp != &(parsefile->basestrpush))
394111314Snyan		ckfree(sp);
395111314Snyan	INTON;
396111314Snyan}
397111314Snyan
398111314Snyan/*
399111314Snyan * Set the input to take input from a file.  If push is set, push the
400111314Snyan * old input onto the stack first.
401111314Snyan */
402111314Snyan
403111314Snyanvoid
404111314Snyansetinputfile(const char *fname, int push)
405111314Snyan{
406111314Snyan	int fd;
407111314Snyan	int fd2;
408111314Snyan
409111314Snyan	INTOFF;
410111314Snyan	if ((fd = open(fname, O_RDONLY)) < 0)
411111314Snyan		error("Can't open %s: %s", fname, strerror(errno));
412111314Snyan	if (fd < 10) {
413111314Snyan		fd2 = fcntl(fd, F_DUPFD, 10);
414111314Snyan		close(fd);
415111314Snyan		if (fd2 < 0)
416112840Smdodd			error("Out of file descriptors");
417112840Smdodd		fd = fd2;
418112840Smdodd	}
419112840Smdodd	setinputfd(fd, push);
420112840Smdodd	INTON;
421111314Snyan}
422111314Snyan
423111314Snyan
424111314Snyan/*
425111314Snyan * Like setinputfile, but takes an open file descriptor.  Call this with
426111314Snyan * interrupts off.
427111314Snyan */
428111314Snyan
429111314Snyanvoid
430111314Snyansetinputfd(int fd, int push)
431111314Snyan{
432111314Snyan	(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
433111314Snyan	if (push) {
434111314Snyan		pushfile();
435111314Snyan		parsefile->buf = ckmalloc(BUFSIZ);
436111314Snyan	}
437111314Snyan	if (parsefile->fd > 0)
438111314Snyan		close(parsefile->fd);
439111314Snyan	parsefile->fd = fd;
440111314Snyan	if (parsefile->buf == NULL)
441111314Snyan		parsefile->buf = ckmalloc(BUFSIZ);
442111314Snyan	parselleft = parsenleft = 0;
443111314Snyan	plinno = 1;
444111314Snyan}
445111314Snyan
446111314Snyan
447111314Snyan/*
448111314Snyan * Like setinputfile, but takes input from a string.
449111314Snyan */
450111314Snyan
451111314Snyanvoid
452111314Snyansetinputstring(char *string, int push)
453111314Snyan{
454111314Snyan	INTOFF;
455111314Snyan	if (push)
456111314Snyan		pushfile();
457111314Snyan	parsenextc = string;
458111314Snyan	parselleft = parsenleft = strlen(string);
459111314Snyan	parsefile->buf = NULL;
460111314Snyan	plinno = 1;
461111314Snyan	INTON;
462111314Snyan}
463111314Snyan
464111314Snyan
465111314Snyan
466111314Snyan/*
467111314Snyan * To handle the "." command, a stack of input files is used.  Pushfile
468111314Snyan * adds a new entry to the stack and popfile restores the previous level.
469111314Snyan */
470111314Snyan
471111314SnyanSTATIC void
472111314Snyanpushfile(void)
473111314Snyan{
474111314Snyan	struct parsefile *pf;
475111314Snyan
476111314Snyan	parsefile->nleft = parsenleft;
477117918Snyan	parsefile->lleft = parselleft;
478117918Snyan	parsefile->nextc = parsenextc;
479117918Snyan	parsefile->linno = plinno;
480117918Snyan	pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
481117918Snyan	pf->prev = parsefile;
482117918Snyan	pf->fd = -1;
483117918Snyan	pf->strpush = NULL;
484117918Snyan	pf->basestrpush.prev = NULL;
485117918Snyan	parsefile = pf;
486117918Snyan}
487111314Snyan
488111314Snyan
489111314Snyanvoid
490111314Snyanpopfile(void)
491111314Snyan{
492111314Snyan	struct parsefile *pf = parsefile;
493111314Snyan
494124795Snyan	INTOFF;
495111314Snyan	if (pf->fd >= 0)
496111314Snyan		close(pf->fd);
497111314Snyan	if (pf->buf)
498111314Snyan		ckfree(pf->buf);
499111314Snyan	while (pf->strpush)
500111314Snyan		popstring();
501111314Snyan	parsefile = pf->prev;
502111314Snyan	ckfree(pf);
503111314Snyan	parsenleft = parsefile->nleft;
504111314Snyan	parselleft = parsefile->lleft;
505111314Snyan	parsenextc = parsefile->nextc;
506111314Snyan	plinno = parsefile->linno;
507111314Snyan	INTON;
508111314Snyan}
509111314Snyan
510111314Snyan
511111314Snyan/*
512111314Snyan * Return current file (to go back to it later using popfilesupto()).
513111314Snyan */
514111314Snyan
515111314Snyanstruct parsefile *
516111314Snyangetcurrentfile(void)
517111314Snyan{
518111314Snyan	return parsefile;
519111314Snyan}
520111314Snyan
521111314Snyan
522111314Snyan/*
523124795Snyan * Pop files until the given file is on top again. Useful for regular
524111314Snyan * builtins that read shell commands from files or strings.
525111314Snyan * If the given file is not an active file, an error is raised.
526124795Snyan */
527124795Snyan
528111314Snyanvoid
529124795Snyanpopfilesupto(struct parsefile *file)
530111314Snyan{
531111314Snyan	while (parsefile != file && parsefile != &basepf)
532111314Snyan		popfile();
533111314Snyan	if (parsefile != file)
534111314Snyan		error("popfilesupto() misused");
535111314Snyan}
536111314Snyan
537111314Snyan/*
538111314Snyan * Return to top level.
539111314Snyan */
540111314Snyan
541111314Snyanvoid
542111314Snyanpopallfiles(void)
543111314Snyan{
544111314Snyan	while (parsefile != &basepf)
545111314Snyan		popfile();
546111314Snyan}
547111314Snyan
548111314Snyan
549111314Snyan
550111314Snyan/*
551111314Snyan * Close the file(s) that the shell is reading commands from.  Called
552111314Snyan * after a fork is done.
553115469Sphk */
554111314Snyan
555111314Snyanvoid
556111314Snyanclosescript(void)
557111314Snyan{
558111314Snyan	popallfiles();
559111314Snyan	if (parsefile->fd > 0) {
560111314Snyan		close(parsefile->fd);
561111314Snyan		parsefile->fd = 0;
562111314Snyan	}
563111314Snyan}
564111314Snyan