input.c revision 242895
150027Speter/*-
272376Sjake * Copyright (c) 1991, 1993
372376Sjake *	The Regents of the University of California.  All rights reserved.
450027Speter *
550027Speter * This code is derived from software contributed to Berkeley by
650027Speter * Kenneth Almquist.
750027Speter *
850027Speter * Redistribution and use in source and binary forms, with or without
950027Speter * modification, are permitted provided that the following conditions
1050027Speter * are met:
1150027Speter * 1. Redistributions of source code must retain the above copyright
1250027Speter *    notice, this list of conditions and the following disclaimer.
1350027Speter * 2. Redistributions in binary form must reproduce the above copyright
1450027Speter *    notice, this list of conditions and the following disclaimer in the
1550027Speter *    documentation and/or other materials provided with the distribution.
1650027Speter * 4. Neither the name of the University nor the names of its contributors
1750027Speter *    may be used to endorse or promote products derived from this software
1850027Speter *    without specific prior written permission.
1950027Speter *
2050027Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2150027Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2250027Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2350027Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2450027Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2550027Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2650027Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2799072Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2899072Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2999072Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3099072Sjulian * SUCH DAMAGE.
3199072Sjulian */
32123499Srwatson
3399072Sjulian#ifndef lint
3499072Sjulian#if 0
3599072Sjulianstatic char sccsid[] = "@(#)input.c	8.3 (Berkeley) 6/9/95";
3699072Sjulian#endif
3799072Sjulian#endif /* not lint */
3899072Sjulian#include <sys/cdefs.h>
3999072Sjulian__FBSDID("$FreeBSD: head/bin/sh/input.c 242895 2012-11-11 15:13:24Z jilles $");
4099072Sjulian
4199072Sjulian#include <stdio.h>	/* defines BUFSIZ */
4299072Sjulian#include <fcntl.h>
4399072Sjulian#include <errno.h>
4499072Sjulian#include <unistd.h>
4599072Sjulian#include <stdlib.h>
4699072Sjulian#include <string.h>
4799072Sjulian
4899072Sjulian/*
4999072Sjulian * This file implements the input routines used by the parser.
5099072Sjulian */
5199072Sjulian
5299072Sjulian#include "shell.h"
5399072Sjulian#include "redir.h"
5499072Sjulian#include "syntax.h"
5599072Sjulian#include "input.h"
5699072Sjulian#include "output.h"
5799072Sjulian#include "options.h"
5899072Sjulian#include "memalloc.h"
5999072Sjulian#include "error.h"
6099072Sjulian#include "alias.h"
6199072Sjulian#include "parser.h"
6299072Sjulian#include "myhistedit.h"
6399072Sjulian#include "trap.h"
6499072Sjulian
6599072Sjulian#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
6699072Sjulian
6799072SjulianMKINIT
6899072Sjulianstruct strpush {
6999072Sjulian	struct strpush *prev;	/* preceding string on stack */
7099072Sjulian	char *prevstring;
7199072Sjulian	int prevnleft;
7299072Sjulian	int prevlleft;
7399072Sjulian	struct alias *ap;	/* if push was associated with an alias */
7499072Sjulian};
7599072Sjulian
7699072Sjulian/*
7799072Sjulian * The parsefile structure pointed to by the global variable parsefile
7899072Sjulian * contains information about the current file being read.
7999072Sjulian */
8099072Sjulian
8199072SjulianMKINIT
8299072Sjulianstruct parsefile {
8399072Sjulian	struct parsefile *prev;	/* preceding file on stack */
8499072Sjulian	int linno;		/* current line */
8599072Sjulian	int fd;			/* file descriptor (or -1 if string) */
86116182Sobrien	int nleft;		/* number of chars left in this line */
8799072Sjulian	int lleft;		/* number of lines left in this buffer */
88116182Sobrien	char *nextc;		/* next char in buffer */
89116182Sobrien	char *buf;		/* input buffer */
90116182Sobrien	struct strpush *strpush; /* for pushing strings at this level */
91131481Sjhb	struct strpush basestrpush; /* so pushing one is fast */
92134591Sjulian};
93131481Sjhb
9450027Speter
9550027Speterint plinno = 1;			/* input line number */
96131927Smarcelint parsenleft;			/* copy of parsefile->nleft */
9750027SpeterMKINIT int parselleft;		/* copy of parsefile->lleft */
9865557Sjasonechar *parsenextc;		/* copy of parsefile->nextc */
9974914SjhbMKINIT struct parsefile basepf;	/* top level input file */
10067365Sjhbchar basebuf[BUFSIZ + 1];	/* buffer for top level input file */
10150027Speterstatic struct parsefile *parsefile = &basepf;	/* current input file */
10250027Speterint init_editline = 0;		/* editline library initialized? */
103104964Sjeffint whichprompt;		/* 1 == PS1, 2 == PS2 */
104122849Speter
105112993SpeterEditLine *el;			/* cookie for editline package */
106112993Speter
10793607Sdillonstatic void pushfile(void);
108134591Sjulianstatic int preadfd(void);
109134591Sjulianstatic void popstring(void);
110134591Sjulian
11150027Speter#ifdef mkinit
112134591SjulianINCLUDE "input.h"
11397261SjakeINCLUDE "error.h"
11497261Sjake
115104695SjulianMKINIT char basebuf[];
116104695Sjulian
117104695SjulianINIT {
11899072Sjulian	basepf.nextc = basepf.buf = basebuf;
119104695Sjulian}
12099072Sjulian
12199072SjulianRESET {
12299072Sjulian	popallfiles();
12350027Speter	parselleft = parsenleft = 0;	/* clear input buffer */
124111028Sjeff}
12599072Sjulian#endif
12699072Sjulian
12750027Speter
12883366Sjulian/*
12983366Sjulian * Read a line from the script.
13050027Speter */
13199072Sjulian
13299072Sjulianchar *
13399072Sjulianpfgets(char *line, int len)
13499072Sjulian{
135122849Speter	char *p = line;
136112993Speter	int nleft = len;
137112993Speter	int c;
138112993Speter
139112993Speter	while (--nleft > 0) {
140112993Speter		c = pgetc_macro();
141112993Speter		if (c == PEOF) {
142112993Speter			if (p == line)
143112993Speter				return NULL;
144112993Speter			break;
145112993Speter		}
146112993Speter		*p++ = c;
147100209Sgallatin		if (c == '\n')
148112993Speter			break;
149112993Speter	}
15099072Sjulian	*p = '\0';
15199072Sjulian	return line;
15299072Sjulian}
153116361Sdavidxu
154103832Sjulian
15599072Sjulian
15699072Sjulian/*
157103832Sjulian * Read a character from the script, returning PEOF on end of file.
158112021Sdavidxu * Nul characters in the input are silently discarded.
159133404Sjulian */
16099072Sjulian
16199072Sjulianint
16299072Sjulianpgetc(void)
16399072Sjulian{
16499889Sjulian	return pgetc_macro();
16599072Sjulian}
166102592Sjulian
16799072Sjulian
16899072Sjulianstatic int
169102592Sjulianpreadfd(void)
170108338Sjulian{
171108338Sjulian	int nr;
172115215Sjulian	parsenextc = parsefile->buf;
173115215Sjulian
174108338Sjulian#ifndef NO_HISTORY
175100209Sgallatin	if (el != NULL && gotwinch) {
176115215Sjulian		gotwinch = 0;
177115215Sjulian		el_resize(el);
178115215Sjulian	}
179100209Sgallatin#endif
180115215Sjulianretry:
181108338Sjulian#ifndef NO_HISTORY
182103216Sjulian	if (parsefile->fd == 0 && el) {
18399072Sjulian		static const char *rl_cp;
18472376Sjake		static int el_len;
18550027Speter
18699072Sjulian		if (rl_cp == NULL)
187111028Sjeff			rl_cp = el_gets(el, &el_len);
188111028Sjeff		if (rl_cp == NULL)
189111128Sdavidxu			nr = el_len == 0 ? 0 : -1;
19099072Sjulian		else {
19199072Sjulian			nr = el_len;
19299072Sjulian			if (nr > BUFSIZ)
19399072Sjulian				nr = BUFSIZ;
19499072Sjulian			memcpy(parsenextc, rl_cp, nr);
19599072Sjulian			if (nr != el_len) {
196104695Sjulian				el_len -= nr;
19799072Sjulian				rl_cp += nr;
198103832Sjulian			} else
199111028Sjeff				rl_cp = NULL;
200111028Sjeff		}
201111028Sjeff	} else
202110190Sjulian#endif
203112397Sdavidxu		nr = read(parsefile->fd, parsenextc, BUFSIZ);
204111028Sjeff
205108338Sjulian	if (nr <= 0) {
20699072Sjulian                if (nr < 0) {
20799072Sjulian                        if (errno == EINTR)
20899072Sjulian                                goto retry;
209111028Sjeff                        if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
21099072Sjulian                                int flags = fcntl(0, F_GETFL, 0);
211111028Sjeff                                if (flags >= 0 && flags & O_NONBLOCK) {
21299072Sjulian                                        flags &=~ O_NONBLOCK;
21399072Sjulian                                        if (fcntl(0, F_SETFL, flags) >= 0) {
21499072Sjulian						out2fmt_flush("sh: turning off NDELAY mode\n");
215111028Sjeff                                                goto retry;
21699072Sjulian                                        }
21799072Sjulian                                }
21899072Sjulian                        }
21999072Sjulian                }
22099072Sjulian                nr = -1;
221133396Sjulian	}
222134586Sjulian	return nr;
223104695Sjulian}
224104695Sjulian
225104695Sjulian/*
226111028Sjeff * Refill the input buffer and return the next input character:
227111028Sjeff *
228111028Sjeff * 1) If a string was pushed back on the input, pop it;
229111028Sjeff * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
230111028Sjeff *    from a string so we can't refill the buffer, return EOF.
231108338Sjulian * 3) If there is more in this buffer, use it else call read to fill it.
23299072Sjulian * 4) Process input up to the next newline, deleting nul characters.
23399072Sjulian */
234105127Sjulian
23599072Sjulianint
23699072Sjulianpreadbuffer(void)
23799072Sjulian{
23899072Sjulian	char *p, *q;
239111028Sjeff	int more;
24099072Sjulian	int something;
241105127Sjulian	char savec;
24283366Sjulian
24372376Sjake	if (parsefile->strpush) {
244104695Sjulian		popstring();
24599072Sjulian		if (--parsenleft >= 0)
24699072Sjulian			return (*parsenextc++);
24799072Sjulian	}
24899072Sjulian	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
249111028Sjeff		return PEOF;
25099072Sjulian	flushout(&output);
25199072Sjulian	flushout(&errout);
25299072Sjulian
253103216Sjulianagain:
254111028Sjeff	if (parselleft <= 0) {
255111028Sjeff		if ((parselleft = preadfd()) == -1) {
256111028Sjeff			parselleft = parsenleft = EOF_NLEFT;
257116361Sdavidxu			return PEOF;
25899072Sjulian		}
259121127Sjeff	}
26099942Sjulian
26199072Sjulian	q = p = parsenextc;
26299072Sjulian
263104695Sjulian	/* delete nul characters */
264104695Sjulian	something = 0;
265133404Sjulian	for (more = 1; more;) {
26699072Sjulian		switch (*p) {
26799072Sjulian		case '\0':
26899072Sjulian			p++;	/* Skip nul */
26999072Sjulian			goto check;
27099072Sjulian
27199072Sjulian		case '\t':
27299072Sjulian		case ' ':
273121127Sjeff			break;
274108338Sjulian
27599072Sjulian		case '\n':
276111028Sjeff			parsenleft = q - parsenextc;
277104695Sjulian			more = 0; /* Stop processing here */
278104695Sjulian			break;
279104695Sjulian
28099072Sjulian		default:
28172376Sjake			something = 1;
282105127Sjulian			break;
28372376Sjake		}
284105127Sjulian
285105127Sjulian		*q++ = *p++;
286105127Sjuliancheck:
28772376Sjake		if (--parselleft <= 0) {
288105127Sjulian			parsenleft = q - parsenextc - 1;
289105127Sjulian			if (parsenleft < 0)
290105127Sjulian				goto again;
291105127Sjulian			*q = '\0';
292105127Sjulian			more = 0;
293105127Sjulian		}
294111028Sjeff	}
295111028Sjeff
296111028Sjeff	savec = *q;
297111028Sjeff	*q = '\0';
298110190Sjulian
299111028Sjeff#ifndef NO_HISTORY
300110190Sjulian	if (parsefile->fd == 0 && hist && something) {
301116361Sdavidxu		HistEvent he;
302105127Sjulian		INTOFF;
303105129Sjulian		history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD,
304105127Sjulian		    parsenextc);
305121127Sjeff		INTON;
306134586Sjulian	}
307105127Sjulian#endif
308105127Sjulian
309105127Sjulian	if (vflag) {
310111028Sjeff		out2str(parsenextc);
311111028Sjeff		flushout(out2);
312105127Sjulian	}
313105127Sjulian
314105127Sjulian	*q = savec;
315105127Sjulian
316105127Sjulian	return *parsenextc++;
317105127Sjulian}
318105127Sjulian
319121127Sjeff/*
320105127Sjulian * Returns if we are certain we are at EOF. Does not cause any more input
321105127Sjulian * to be read from the outside world.
322133404Sjulian */
323105127Sjulian
324134586Sjulianint
325105127Sjulianpreadateof(void)
326105127Sjulian{
327105127Sjulian	if (parsenleft > 0)
328134586Sjulian		return 0;
32950027Speter	if (parsefile->strpush)
33099072Sjulian		return 0;
33199072Sjulian	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
33299072Sjulian		return 1;
33399072Sjulian	return 0;
334133414Sscottl}
33599072Sjulian
336133396Sjulian/*
337133396Sjulian * Undo the last call to pgetc.  Only one character may be pushed back.
33899072Sjulian * PEOF may be pushed back.
339103216Sjulian */
340103216Sjulian
341103216Sjulianvoid
34299072Sjulianpungetc(void)
343116361Sdavidxu{
344104695Sjulian	parsenleft++;
345104695Sjulian	parsenextc--;
346104695Sjulian}
347104695Sjulian
348104695Sjulian/*
349134586Sjulian * Push a string back onto the input at this current parsefile level.
350104695Sjulian * We handle aliases this way.
351104695Sjulian */
352104695Sjulianvoid
35399072Sjulianpushstring(char *s, int len, struct alias *ap)
35499072Sjulian{
355111028Sjeff	struct strpush *sp;
35699072Sjulian
357111028Sjeff	INTOFF;
358104695Sjulian/*out2fmt_flush("*** calling pushstring: %s, %d\n", s, len);*/
359111028Sjeff	if (parsefile->strpush) {
360133396Sjulian		sp = ckmalloc(sizeof (struct strpush));
361133396Sjulian		sp->prev = parsefile->strpush;
362111028Sjeff		parsefile->strpush = sp;
363104157Sjulian	} else
364111028Sjeff		sp = parsefile->strpush = &(parsefile->basestrpush);
36599072Sjulian	sp->prevstring = parsenextc;
36699072Sjulian	sp->prevnleft = parsenleft;
36799072Sjulian	sp->prevlleft = parselleft;
36899072Sjulian	sp->ap = ap;
36999072Sjulian	if (ap)
370133396Sjulian		ap->flag |= ALIASINUSE;
371133396Sjulian	parsenextc = s;
372133396Sjulian	parsenleft = len;
373121171Sjeff	INTON;
37499072Sjulian}
37599072Sjulian
37699072Sjulianstatic void
37799072Sjulianpopstring(void)
37899072Sjulian{
37999072Sjulian	struct strpush *sp = parsefile->strpush;
38099942Sjulian
38199942Sjulian	INTOFF;
38299942Sjulian	parsenextc = sp->prevstring;
38399072Sjulian	parsenleft = sp->prevnleft;
38499072Sjulian	parselleft = sp->prevlleft;
38599072Sjulian/*out2fmt_flush("*** calling popstring: restoring to '%s'\n", parsenextc);*/
38699072Sjulian	if (sp->ap)
38799072Sjulian		sp->ap->flag &= ~ALIASINUSE;
38899072Sjulian	parsefile->strpush = sp->prev;
38999072Sjulian	if (sp != &(parsefile->basestrpush))
39099072Sjulian		ckfree(sp);
391133414Sscottl	INTON;
39299072Sjulian}
39399072Sjulian
394133404Sjulian/*
39599072Sjulian * Set the input to take input from a file.  If push is set, push the
39699072Sjulian * old input onto the stack first.
39799072Sjulian */
398133414Sscottl
399133414Sscottlvoid
400133414Sscottlsetinputfile(const char *fname, int push)
401133414Sscottl{
402133414Sscottl	int fd;
40399072Sjulian	int fd2;
40499072Sjulian
40599072Sjulian	INTOFF;
406133404Sjulian	if ((fd = open(fname, O_RDONLY)) < 0)
40799072Sjulian		error("cannot open %s: %s", fname, strerror(errno));
40899072Sjulian	if (fd < 10) {
40999072Sjulian		fd2 = fcntl(fd, F_DUPFD, 10);
41099072Sjulian		close(fd);
41199072Sjulian		if (fd2 < 0)
41299072Sjulian			error("Out of file descriptors");
41399072Sjulian		fd = fd2;
41499072Sjulian	}
41599072Sjulian	setinputfd(fd, push);
41699072Sjulian	INTON;
41799072Sjulian}
41899942Sjulian
41999072Sjulian
42099072Sjulian/*
42199072Sjulian * Like setinputfile, but takes an open file descriptor.  Call this with
42299072Sjulian * interrupts off.
42399072Sjulian */
42499072Sjulian
42599072Sjulianvoid
42699072Sjuliansetinputfd(int fd, int push)
42799072Sjulian{
42899072Sjulian	(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
42999072Sjulian	if (push) {
43099072Sjulian		pushfile();
43199072Sjulian		parsefile->buf = ckmalloc(BUFSIZ + 1);
43299072Sjulian	}
43399072Sjulian	if (parsefile->fd > 0)
43499072Sjulian		close(parsefile->fd);
43599072Sjulian	parsefile->fd = fd;
43699072Sjulian	if (parsefile->buf == NULL)
43799072Sjulian		parsefile->buf = ckmalloc(BUFSIZ + 1);
43899072Sjulian	parselleft = parsenleft = 0;
43999072Sjulian	plinno = 1;
44099072Sjulian}
44199072Sjulian
44299072Sjulian
44399072Sjulian/*
444134586Sjulian * Like setinputfile, but takes input from a string.
445133396Sjulian */
446133396Sjulian
447133396Sjulianvoid
44899072Sjuliansetinputstring(char *string, int push)
44972376Sjake{
45050027Speter	INTOFF;
451131481Sjhb	if (push)
452131481Sjhb		pushfile();
453131481Sjhb	parsenextc = string;
454131481Sjhb	parselleft = parsenleft = strlen(string);
45588088Sjhb	parsefile->buf = NULL;
45688088Sjhb	plinno = 1;
45788088Sjhb	INTON;
45888088Sjhb}
45988088Sjhb
46088088Sjhb
46188088Sjhb
462132700Srwatson/*
46388088Sjhb * To handle the "." command, a stack of input files is used.  Pushfile
46488088Sjhb * adds a new entry to the stack and popfile restores the previous level.
46588088Sjhb */
46688088Sjhb
46788088Sjhbstatic void
46888088Sjhbpushfile(void)
46988088Sjhb{
47088088Sjhb	struct parsefile *pf;
47188088Sjhb
472125315Sjeff	parsefile->nleft = parsenleft;
473125315Sjeff	parsefile->lleft = parselleft;
47488088Sjhb	parsefile->nextc = parsenextc;
475131481Sjhb	parsefile->linno = plinno;
476132266Sjhb	pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
477132266Sjhb	pf->prev = parsefile;
478131481Sjhb	pf->fd = -1;
479131481Sjhb	pf->strpush = NULL;
480131481Sjhb	pf->basestrpush.prev = NULL;
481131481Sjhb	parsefile = pf;
482131481Sjhb}
48388088Sjhb
484132700Srwatson
48593264Sdillonvoid
48688088Sjhbpopfile(void)
48793264Sdillon{
48888088Sjhb	struct parsefile *pf = parsefile;
48988088Sjhb
490131481Sjhb	INTOFF;
491131481Sjhb	if (pf->fd >= 0)
492131481Sjhb		close(pf->fd);
493131481Sjhb	if (pf->buf)
494131481Sjhb		ckfree(pf->buf);
495131481Sjhb	while (pf->strpush)
496131481Sjhb		popstring();
497131481Sjhb	parsefile = pf->prev;
498131481Sjhb	ckfree(pf);
499131481Sjhb	parsenleft = parsefile->nleft;
500131508Smarcel	parselleft = parsefile->lleft;
501131481Sjhb	parsenextc = parsefile->nextc;
502131481Sjhb	plinno = parsefile->linno;
503131508Smarcel	INTON;
50499072Sjulian}
505131481Sjhb
506131481Sjhb
507131481Sjhb/*
508131481Sjhb * Return current file (to go back to it later using popfilesupto()).
509131481Sjhb */
510131481Sjhb
511132266Sjhbstruct parsefile *
512132266Sjhbgetcurrentfile(void)
513132266Sjhb{
514131481Sjhb	return parsefile;
515131481Sjhb}
516131481Sjhb
517131481Sjhb
518131481Sjhb/*
519131481Sjhb * Pop files until the given file is on top again. Useful for regular
520131481Sjhb * builtins that read shell commands from files or strings.
521131481Sjhb * If the given file is not an active file, an error is raised.
522131481Sjhb */
523131481Sjhb
524131481Sjhbvoid
525131481Sjhbpopfilesupto(struct parsefile *file)
526131481Sjhb{
527131481Sjhb	while (parsefile != file && parsefile != &basepf)
528131481Sjhb		popfile();
529131481Sjhb	if (parsefile != file)
530134417Speter		error("popfilesupto() misused");
531134417Speter}
532131481Sjhb
533131481Sjhb/*
534131481Sjhb * Return to top level.
535131481Sjhb */
536131481Sjhb
537131481Sjhbvoid
538131481Sjhbpopallfiles(void)
539131481Sjhb{
540131481Sjhb	while (parsefile != &basepf)
541131481Sjhb		popfile();
542131481Sjhb}
543131481Sjhb
544131481Sjhb
545132266Sjhb
546131481Sjhb/*
547131481Sjhb * Close the file(s) that the shell is reading commands from.  Called
548131481Sjhb * after a fork is done.
549131481Sjhb */
550131481Sjhb
551131481Sjhbvoid
552131481Sjhbclosescript(void)
553131481Sjhb{
554131481Sjhb	popallfiles();
555131481Sjhb	if (parsefile->fd > 0) {
556131481Sjhb		close(parsefile->fd);
557131481Sjhb		parsefile->fd = 0;
558131481Sjhb	}
559131481Sjhb}
560131481Sjhb