input.c revision 200956
150276Speter/*-
2262685Sdelphij * Copyright (c) 1991, 1993
350276Speter *	The Regents of the University of California.  All rights reserved.
450276Speter *
550276Speter * This code is derived from software contributed to Berkeley by
650276Speter * Kenneth Almquist.
750276Speter *
850276Speter * Redistribution and use in source and binary forms, with or without
950276Speter * modification, are permitted provided that the following conditions
1050276Speter * are met:
1150276Speter * 1. Redistributions of source code must retain the above copyright
1250276Speter *    notice, this list of conditions and the following disclaimer.
1350276Speter * 2. Redistributions in binary form must reproduce the above copyright
1450276Speter *    notice, this list of conditions and the following disclaimer in the
1550276Speter *    documentation and/or other materials provided with the distribution.
1650276Speter * 4. Neither the name of the University nor the names of its contributors
1750276Speter *    may be used to endorse or promote products derived from this software
1850276Speter *    without specific prior written permission.
1950276Speter *
2050276Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2150276Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2250276Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2350276Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2450276Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2550276Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2650276Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2750276Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2850276Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2950276Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3050276Speter * SUCH DAMAGE.
3150276Speter */
32166124Srafan
33262629Sdelphij#ifndef lint
3450276Speter#if 0
3550276Speterstatic char sccsid[] = "@(#)input.c	8.3 (Berkeley) 6/9/95";
3650276Speter#endif
3750276Speter#endif /* not lint */
3850276Speter#include <sys/cdefs.h>
3950276Speter__FBSDID("$FreeBSD: head/bin/sh/input.c 200956 2009-12-24 18:41:14Z jilles $");
4050276Speter
4150276Speter#include <stdio.h>	/* defines BUFSIZ */
4250276Speter#include <fcntl.h>
4350276Speter#include <errno.h>
4450276Speter#include <unistd.h>
45262629Sdelphij#include <stdlib.h>
46262629Sdelphij#include <string.h>
47262629Sdelphij
48262629Sdelphij/*
4962449Speter * This file implements the input routines used by the parser.
5050276Speter */
51262685Sdelphij
5250276Speter#include "shell.h"
53262629Sdelphij#include "redir.h"
54262629Sdelphij#include "syntax.h"
55262629Sdelphij#include "input.h"
56262629Sdelphij#include "output.h"
57262629Sdelphij#include "options.h"
58262629Sdelphij#include "memalloc.h"
5962449Speter#include "error.h"
6050276Speter#include "alias.h"
6150276Speter#include "parser.h"
6250276Speter#include "myhistedit.h"
6350276Speter#include "trap.h"
6450276Speter
6550276Speter#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
6650276Speter
6750276SpeterMKINIT
6850276Speterstruct strpush {
6950276Speter	struct strpush *prev;	/* preceding string on stack */
7050276Speter	char *prevstring;
71166124Srafan	int prevnleft;
72262629Sdelphij	int prevlleft;
7350276Speter	struct alias *ap;	/* if push was associated with an alias */
74166124Srafan};
75262629Sdelphij
76166124Srafan/*
7762449Speter * The parsefile structure pointed to by the global variable parsefile
7862449Speter * contains information about the current file being read.
79262629Sdelphij */
80166124Srafan
8150276SpeterMKINIT
82262629Sdelphijstruct parsefile {
8350276Speter	struct parsefile *prev;	/* preceding file on stack */
84262629Sdelphij	int linno;		/* current line */
85262629Sdelphij	int fd;			/* file descriptor (or -1 if string) */
86262629Sdelphij	int nleft;		/* number of chars left in this line */
87166124Srafan	int lleft;		/* number of lines left in this buffer */
88166124Srafan	char *nextc;		/* next char in buffer */
8950276Speter	char *buf;		/* input buffer */
90166124Srafan	struct strpush *strpush; /* for pushing strings at this level */
9150276Speter	struct strpush basestrpush; /* so pushing one is fast */
92262629Sdelphij};
93262629Sdelphij
94262629Sdelphij
95166124Srafanint plinno = 1;			/* input line number */
96166124SrafanMKINIT int parsenleft;		/* copy of parsefile->nleft */
9750276SpeterMKINIT int parselleft;		/* copy of parsefile->lleft */
9850276Speterchar *parsenextc;		/* copy of parsefile->nextc */
9950276SpeterMKINIT struct parsefile basepf;	/* top level input file */
10050276Speterchar basebuf[BUFSIZ];		/* buffer for top level input file */
10150276SpeterSTATIC struct parsefile *parsefile = &basepf;	/* current input file */
10250276Speterint init_editline = 0;		/* editline library initialized? */
10350276Speterint whichprompt;		/* 1 == PS1, 2 == PS2 */
10450276Speter
10576726SpeterEditLine *el;			/* cookie for editline package */
106262629Sdelphij
107262629SdelphijSTATIC void pushfile(void);
108262629Sdelphijstatic int preadfd(void);
109262629Sdelphij
110262629Sdelphij#ifdef mkinit
111262629SdelphijINCLUDE "input.h"
112262629SdelphijINCLUDE "error.h"
113262629Sdelphij
114262629SdelphijINIT {
115262629Sdelphij	extern char basebuf[];
116262629Sdelphij
117262629Sdelphij	basepf.nextc = basepf.buf = basebuf;
118262629Sdelphij}
119262629Sdelphij
120262629SdelphijRESET {
121262629Sdelphij	popallfiles();
12262449Speter	if (exception != EXSHELLPROC)
12350276Speter		parselleft = parsenleft = 0;	/* clear input buffer */
124166124Srafan}
125262629Sdelphij
126174993SrafanSHELLPROC {
12797049Speter	popallfiles();
12850276Speter}
129262629Sdelphij#endif
13050276Speter
131166124Srafan
132166124Srafan/*
133166124Srafan * Read a line from the script.
134166124Srafan */
135166124Srafan
136166124Srafanchar *
137262629Sdelphijpfgets(char *line, int len)
138262629Sdelphij{
139262629Sdelphij	char *p = line;
140262629Sdelphij	int nleft = len;
141262629Sdelphij	int c;
142262629Sdelphij
143262629Sdelphij	while (--nleft > 0) {
144262629Sdelphij		c = pgetc_macro();
145262629Sdelphij		if (c == PEOF) {
146262629Sdelphij			if (p == line)
147262629Sdelphij				return NULL;
148262629Sdelphij			break;
149262629Sdelphij		}
150262629Sdelphij		*p++ = c;
151262629Sdelphij		if (c == '\n')
152262629Sdelphij			break;
153166124Srafan	}
154166124Srafan	*p = '\0';
155166124Srafan	return line;
156262629Sdelphij}
157174993Srafan
158166124Srafan
159166124Srafan
160166124Srafan/*
161262629Sdelphij * Read a character from the script, returning PEOF on end of file.
162166124Srafan * Nul characters in the input are silently discarded.
16376726Speter */
164262629Sdelphij
165262629Sdelphijint
166262629Sdelphijpgetc(void)
167262629Sdelphij{
16850276Speter	return pgetc_macro();
169166124Srafan}
17062449Speter
171262629Sdelphij
17262449Speterstatic int
173184989Srafanpreadfd(void)
174262629Sdelphij{
175262629Sdelphij	int nr;
176262629Sdelphij	parsenextc = parsefile->buf;
177262629Sdelphij
178262629Sdelphij#ifndef NO_HISTORY
179262629Sdelphij	if (el != NULL && gotwinch) {
18050276Speter		gotwinch = 0;
181166124Srafan		el_resize(el);
182262629Sdelphij	}
183262629Sdelphij#endif
184262685Sdelphijretry:
185262629Sdelphij#ifndef NO_HISTORY
186262629Sdelphij	if (parsefile->fd == 0 && el) {
18750276Speter		static const char *rl_cp;
188262629Sdelphij		static int el_len;
189262629Sdelphij
190262629Sdelphij		if (rl_cp == NULL)
191262629Sdelphij			rl_cp = el_gets(el, &el_len);
192262629Sdelphij		if (rl_cp == NULL)
193262629Sdelphij			nr = 0;
194184989Srafan		else {
195184989Srafan			nr = el_len;
196184989Srafan			if (nr > BUFSIZ - 1)
197262629Sdelphij				nr = BUFSIZ - 1;
198262629Sdelphij			memcpy(parsenextc, rl_cp, nr);
199184989Srafan			if (nr != el_len) {
200262629Sdelphij				el_len -= nr;
201166124Srafan				rl_cp += nr;
202262629Sdelphij			} else
203262629Sdelphij				rl_cp = NULL;
204262629Sdelphij		}
205262629Sdelphij	} else
206262629Sdelphij#endif
207262629Sdelphij		nr = read(parsefile->fd, parsenextc, BUFSIZ - 1);
208178866Srafan
209262629Sdelphij	if (nr <= 0) {
210262629Sdelphij                if (nr < 0) {
211262629Sdelphij                        if (errno == EINTR)
212262629Sdelphij                                goto retry;
213262629Sdelphij                        if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
214262629Sdelphij                                int flags = fcntl(0, F_GETFL, 0);
215262629Sdelphij                                if (flags >= 0 && flags & O_NONBLOCK) {
216262629Sdelphij                                        flags &=~ O_NONBLOCK;
217262629Sdelphij                                        if (fcntl(0, F_SETFL, flags) >= 0) {
218262629Sdelphij						out2fmt_flush("sh: turning off NDELAY mode\n");
219262629Sdelphij                                                goto retry;
220262629Sdelphij                                        }
221262629Sdelphij                                }
222166124Srafan                        }
223166124Srafan                }
224166124Srafan                nr = -1;
225166124Srafan	}
226262629Sdelphij	return nr;
227262629Sdelphij}
228262629Sdelphij
229262629Sdelphij/*
230262629Sdelphij * Refill the input buffer and return the next input character:
231262629Sdelphij *
232262629Sdelphij * 1) If a string was pushed back on the input, pop it;
233262629Sdelphij * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
234262629Sdelphij *    from a string so we can't refill the buffer, return EOF.
235166124Srafan * 3) If there is more in this buffer, use it else call read to fill it.
236166124Srafan * 4) Process input up to the next newline, deleting nul characters.
237166124Srafan */
238262629Sdelphij
239262629Sdelphijint
240262629Sdelphijpreadbuffer(void)
241262629Sdelphij{
242262629Sdelphij	char *p, *q;
243262629Sdelphij	int more;
244262629Sdelphij	int something;
245262629Sdelphij	char savec;
246262629Sdelphij
247262629Sdelphij	if (parsefile->strpush) {
248262629Sdelphij		popstring();
249262629Sdelphij		if (--parsenleft >= 0)
250184989Srafan			return (*parsenextc++);
251184989Srafan	}
252262629Sdelphij	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
253262629Sdelphij		return PEOF;
254262629Sdelphij	flushout(&output);
255262629Sdelphij	flushout(&errout);
256184989Srafan
257184989Srafanagain:
258184989Srafan	if (parselleft <= 0) {
259184989Srafan		if ((parselleft = preadfd()) == -1) {
260184989Srafan			parselleft = parsenleft = EOF_NLEFT;
261184989Srafan			return PEOF;
262184989Srafan		}
263262629Sdelphij	}
264262629Sdelphij
265262629Sdelphij	q = p = parsenextc;
266262629Sdelphij
267262629Sdelphij	/* delete nul characters */
268262629Sdelphij	something = 0;
269262629Sdelphij	for (more = 1; more;) {
270262629Sdelphij		switch (*p) {
271262629Sdelphij		case '\0':
272262629Sdelphij			p++;	/* Skip nul */
273262629Sdelphij			goto check;
274166124Srafan
275262629Sdelphij		case '\t':
276262629Sdelphij		case ' ':
27750276Speter			break;
278262629Sdelphij
279262629Sdelphij		case '\n':
28050276Speter			parsenleft = q - parsenextc;
281262629Sdelphij			more = 0; /* Stop processing here */
282262685Sdelphij			break;
283262685Sdelphij
28450276Speter		default:
285262629Sdelphij			something = 1;
28650276Speter			break;
287262629Sdelphij		}
288262629Sdelphij
289166124Srafan		*q++ = *p++;
290166124Srafancheck:
291166124Srafan		if (--parselleft <= 0) {
292166124Srafan			parsenleft = q - parsenextc - 1;
293166124Srafan			if (parsenleft < 0)
294262629Sdelphij				goto again;
295262629Sdelphij			*q = '\0';
296262629Sdelphij			more = 0;
297262629Sdelphij		}
298262629Sdelphij	}
299262629Sdelphij
300262629Sdelphij	savec = *q;
301262629Sdelphij	*q = '\0';
30250276Speter
303262629Sdelphij#ifndef NO_HISTORY
30450276Speter	if (parsefile->fd == 0 && hist && something) {
305262629Sdelphij		HistEvent he;
30650276Speter		INTOFF;
307262629Sdelphij		history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD,
308262629Sdelphij		    parsenextc);
309262629Sdelphij		INTON;
310262685Sdelphij	}
311166124Srafan#endif
312166124Srafan
313166124Srafan	if (vflag) {
314166124Srafan		out2str(parsenextc);
315166124Srafan		flushout(out2);
316166124Srafan	}
317166124Srafan
318166124Srafan	*q = savec;
319166124Srafan
32050276Speter	return *parsenextc++;
321262629Sdelphij}
322262629Sdelphij
323262685Sdelphij/*
324262685Sdelphij * Returns if we are certain we are at EOF. Does not cause any more input
325262685Sdelphij * to be read from the outside world.
32650276Speter */
327166124Srafan
328166124Srafanint
32950276Speterpreadateof(void)
330166124Srafan{
331166124Srafan	if (parsenleft > 0)
332262685Sdelphij		return 0;
33350276Speter	if (parsefile->strpush)
334166124Srafan		return 0;
335262629Sdelphij	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
33650276Speter		return 1;
337166124Srafan	return 0;
338262629Sdelphij}
339166124Srafan
340166124Srafan/*
341184989Srafan * Undo the last call to pgetc.  Only one character may be pushed back.
342166124Srafan * PEOF may be pushed back.
34350276Speter */
344262629Sdelphij
345262629Sdelphijvoid
346262629Sdelphijpungetc(void)
347262629Sdelphij{
348262629Sdelphij	parsenleft++;
349262629Sdelphij	parsenextc--;
350262629Sdelphij}
351262629Sdelphij
352/*
353 * Push a string back onto the input at this current parsefile level.
354 * We handle aliases this way.
355 */
356void
357pushstring(char *s, int len, void *ap)
358{
359	struct strpush *sp;
360
361	INTOFF;
362/*out2fmt_flush("*** calling pushstring: %s, %d\n", s, len);*/
363	if (parsefile->strpush) {
364		sp = ckmalloc(sizeof (struct strpush));
365		sp->prev = parsefile->strpush;
366		parsefile->strpush = sp;
367	} else
368		sp = parsefile->strpush = &(parsefile->basestrpush);
369	sp->prevstring = parsenextc;
370	sp->prevnleft = parsenleft;
371	sp->prevlleft = parselleft;
372	sp->ap = (struct alias *)ap;
373	if (ap)
374		((struct alias *)ap)->flag |= ALIASINUSE;
375	parsenextc = s;
376	parsenleft = len;
377	INTON;
378}
379
380void
381popstring(void)
382{
383	struct strpush *sp = parsefile->strpush;
384
385	INTOFF;
386	parsenextc = sp->prevstring;
387	parsenleft = sp->prevnleft;
388	parselleft = sp->prevlleft;
389/*out2fmt_flush("*** calling popstring: restoring to '%s'\n", parsenextc);*/
390	if (sp->ap)
391		sp->ap->flag &= ~ALIASINUSE;
392	parsefile->strpush = sp->prev;
393	if (sp != &(parsefile->basestrpush))
394		ckfree(sp);
395	INTON;
396}
397
398/*
399 * Set the input to take input from a file.  If push is set, push the
400 * old input onto the stack first.
401 */
402
403void
404setinputfile(const char *fname, int push)
405{
406	int fd;
407	int fd2;
408
409	INTOFF;
410	if ((fd = open(fname, O_RDONLY)) < 0)
411		error("Can't open %s: %s", fname, strerror(errno));
412	if (fd < 10) {
413		fd2 = fcntl(fd, F_DUPFD, 10);
414		close(fd);
415		if (fd2 < 0)
416			error("Out of file descriptors");
417		fd = fd2;
418	}
419	setinputfd(fd, push);
420	INTON;
421}
422
423
424/*
425 * Like setinputfile, but takes an open file descriptor.  Call this with
426 * interrupts off.
427 */
428
429void
430setinputfd(int fd, int push)
431{
432	(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
433	if (push) {
434		pushfile();
435		parsefile->buf = ckmalloc(BUFSIZ);
436	}
437	if (parsefile->fd > 0)
438		close(parsefile->fd);
439	parsefile->fd = fd;
440	if (parsefile->buf == NULL)
441		parsefile->buf = ckmalloc(BUFSIZ);
442	parselleft = parsenleft = 0;
443	plinno = 1;
444}
445
446
447/*
448 * Like setinputfile, but takes input from a string.
449 */
450
451void
452setinputstring(char *string, int push)
453{
454	INTOFF;
455	if (push)
456		pushfile();
457	parsenextc = string;
458	parselleft = parsenleft = strlen(string);
459	parsefile->buf = NULL;
460	plinno = 1;
461	INTON;
462}
463
464
465
466/*
467 * To handle the "." command, a stack of input files is used.  Pushfile
468 * adds a new entry to the stack and popfile restores the previous level.
469 */
470
471STATIC void
472pushfile(void)
473{
474	struct parsefile *pf;
475
476	parsefile->nleft = parsenleft;
477	parsefile->lleft = parselleft;
478	parsefile->nextc = parsenextc;
479	parsefile->linno = plinno;
480	pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
481	pf->prev = parsefile;
482	pf->fd = -1;
483	pf->strpush = NULL;
484	pf->basestrpush.prev = NULL;
485	parsefile = pf;
486}
487
488
489void
490popfile(void)
491{
492	struct parsefile *pf = parsefile;
493
494	INTOFF;
495	if (pf->fd >= 0)
496		close(pf->fd);
497	if (pf->buf)
498		ckfree(pf->buf);
499	while (pf->strpush)
500		popstring();
501	parsefile = pf->prev;
502	ckfree(pf);
503	parsenleft = parsefile->nleft;
504	parselleft = parsefile->lleft;
505	parsenextc = parsefile->nextc;
506	plinno = parsefile->linno;
507	INTON;
508}
509
510
511/*
512 * Return current file (to go back to it later using popfilesupto()).
513 */
514
515struct parsefile *
516getcurrentfile(void)
517{
518	return parsefile;
519}
520
521
522/*
523 * Pop files until the given file is on top again. Useful for regular
524 * builtins that read shell commands from files or strings.
525 * If the given file is not an active file, an error is raised.
526 */
527
528void
529popfilesupto(struct parsefile *file)
530{
531	while (parsefile != file && parsefile != &basepf)
532		popfile();
533	if (parsefile != file)
534		error("popfilesupto() misused");
535}
536
537/*
538 * Return to top level.
539 */
540
541void
542popallfiles(void)
543{
544	while (parsefile != &basepf)
545		popfile();
546}
547
548
549
550/*
551 * Close the file(s) that the shell is reading commands from.  Called
552 * after a fork is done.
553 */
554
555void
556closescript(void)
557{
558	popallfiles();
559	if (parsefile->fd > 0) {
560		close(parsefile->fd);
561		parsefile->fd = 0;
562	}
563}
564