input.c revision 117261
11553Srgrimes/*-
21553Srgrimes * Copyright (c) 1991, 1993
31553Srgrimes *	The Regents of the University of California.  All rights reserved.
41553Srgrimes *
51553Srgrimes * This code is derived from software contributed to Berkeley by
61553Srgrimes * Kenneth Almquist.
71553Srgrimes *
81553Srgrimes * Redistribution and use in source and binary forms, with or without
91553Srgrimes * modification, are permitted provided that the following conditions
101553Srgrimes * are met:
111553Srgrimes * 1. Redistributions of source code must retain the above copyright
121553Srgrimes *    notice, this list of conditions and the following disclaimer.
131553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141553Srgrimes *    notice, this list of conditions and the following disclaimer in the
151553Srgrimes *    documentation and/or other materials provided with the distribution.
161553Srgrimes * 3. All advertising materials mentioning features or use of this software
171553Srgrimes *    must display the following acknowledgement:
181553Srgrimes *	This product includes software developed by the University of
191553Srgrimes *	California, Berkeley and its contributors.
201553Srgrimes * 4. Neither the name of the University nor the names of its contributors
211553Srgrimes *    may be used to endorse or promote products derived from this software
221553Srgrimes *    without specific prior written permission.
231553Srgrimes *
241553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271553Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
301553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
331553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
341553Srgrimes * SUCH DAMAGE.
3530642Scharnier */
361553Srgrimes
3730642Scharnier#ifndef lint
3830642Scharnier#if 0
3930761Scharnierstatic char sccsid[] = "@(#)input.c	8.3 (Berkeley) 6/9/95";
401553Srgrimes#endif
411553Srgrimes#endif /* not lint */
421553Srgrimes#include <sys/cdefs.h>
431553Srgrimes__FBSDID("$FreeBSD: head/bin/sh/input.c 117261 2003-07-05 15:18:44Z dds $");
441553Srgrimes
451553Srgrimes#include <stdio.h>	/* defines BUFSIZ */
461553Srgrimes#include <fcntl.h>
471553Srgrimes#include <errno.h>
481553Srgrimes#include <unistd.h>
491553Srgrimes#include <stdlib.h>
501553Srgrimes#include <string.h>
511553Srgrimes
521553Srgrimes/*
531553Srgrimes * This file implements the input routines used by the parser.
541553Srgrimes */
551553Srgrimes
561553Srgrimes#include "shell.h"
571553Srgrimes#include "redir.h"
581553Srgrimes#include "syntax.h"
591553Srgrimes#include "input.h"
601553Srgrimes#include "output.h"
611553Srgrimes#include "options.h"
621553Srgrimes#include "memalloc.h"
631553Srgrimes#include "error.h"
641553Srgrimes#include "alias.h"
651553Srgrimes#include "parser.h"
661553Srgrimes#include "myhistedit.h"
671553Srgrimes#include "trap.h"
681553Srgrimes
691553Srgrimes#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
701553Srgrimes
711553SrgrimesMKINIT
721553Srgrimesstruct strpush {
731553Srgrimes	struct strpush *prev;	/* preceding string on stack */
741553Srgrimes	char *prevstring;
751553Srgrimes	int prevnleft;
761553Srgrimes	int prevlleft;
771553Srgrimes	struct alias *ap;	/* if push was associated with an alias */
781553Srgrimes};
791553Srgrimes
801553Srgrimes/*
811553Srgrimes * The parsefile structure pointed to by the global variable parsefile
821553Srgrimes * contains information about the current file being read.
831553Srgrimes */
841553Srgrimes
851553SrgrimesMKINIT
861553Srgrimesstruct parsefile {
871553Srgrimes	struct parsefile *prev;	/* preceding file on stack */
881553Srgrimes	int linno;		/* current line */
891553Srgrimes	int fd;			/* file descriptor (or -1 if string) */
901553Srgrimes	int nleft;		/* number of chars left in this line */
911553Srgrimes	int lleft;		/* number of lines left in this buffer */
921553Srgrimes	char *nextc;		/* next char in buffer */
931553Srgrimes	char *buf;		/* input buffer */
941553Srgrimes	struct strpush *strpush; /* for pushing strings at this level */
951553Srgrimes	struct strpush basestrpush; /* so pushing one is fast */
961553Srgrimes};
971553Srgrimes
981553Srgrimes
991553Srgrimesint plinno = 1;			/* input line number */
1008857SrgrimesMKINIT int parsenleft;		/* copy of parsefile->nleft */
1011553SrgrimesMKINIT int parselleft;		/* copy of parsefile->lleft */
1021553Srgrimeschar *parsenextc;		/* copy of parsefile->nextc */
1031553SrgrimesMKINIT struct parsefile basepf;	/* top level input file */
1041553Srgrimeschar basebuf[BUFSIZ];		/* buffer for top level input file */
1051553SrgrimesSTATIC struct parsefile *parsefile = &basepf;	/* current input file */
1061553Srgrimesint init_editline = 0;		/* editline library initialized? */
1071553Srgrimesint whichprompt;		/* 1 == PS1, 2 == PS2 */
1081553Srgrimes
1091553SrgrimesEditLine *el;			/* cookie for editline package */
1101553Srgrimes
1111553SrgrimesSTATIC void pushfile(void);
1121553Srgrimesstatic int preadfd(void);
1131553Srgrimes
1141553Srgrimes#ifdef mkinit
1151553SrgrimesINCLUDE "input.h"
1161553SrgrimesINCLUDE "error.h"
1171553Srgrimes
1181553SrgrimesINIT {
1191553Srgrimes	extern char basebuf[];
1201553Srgrimes
1211553Srgrimes	basepf.nextc = basepf.buf = basebuf;
1221553Srgrimes}
1231553Srgrimes
1241553SrgrimesRESET {
1251553Srgrimes	if (exception != EXSHELLPROC)
1261553Srgrimes		parselleft = parsenleft = 0;	/* clear input buffer */
1271553Srgrimes	popallfiles();
1281553Srgrimes}
1291553Srgrimes
1301553SrgrimesSHELLPROC {
1311553Srgrimes	popallfiles();
1321553Srgrimes}
1331553Srgrimes#endif
1341553Srgrimes
1351553Srgrimes
1361553Srgrimes/*
1371553Srgrimes * Read a line from the script.
1381553Srgrimes */
1391553Srgrimes
1401553Srgrimeschar *
1411553Srgrimespfgets(char *line, int len)
1421553Srgrimes{
1431553Srgrimes	char *p = line;
1441553Srgrimes	int nleft = len;
1451553Srgrimes	int c;
1461553Srgrimes
1471553Srgrimes	while (--nleft > 0) {
1481553Srgrimes		c = pgetc_macro();
1491553Srgrimes		if (c == PEOF) {
1501553Srgrimes			if (p == line)
1511553Srgrimes				return NULL;
1521553Srgrimes			break;
1531553Srgrimes		}
15430761Scharnier		*p++ = c;
1554840Sbde		if (c == '\n')
1561553Srgrimes			break;
1571553Srgrimes	}
1581553Srgrimes	*p = '\0';
1591553Srgrimes	return line;
1601553Srgrimes}
1611553Srgrimes
1621553Srgrimes
1631553Srgrimes
1641553Srgrimes/*
1651553Srgrimes * Read a character from the script, returning PEOF on end of file.
1661553Srgrimes * Nul characters in the input are silently discarded.
1671553Srgrimes */
1681553Srgrimes
1691553Srgrimesint
1701553Srgrimespgetc(void)
1711553Srgrimes{
1721553Srgrimes	return pgetc_macro();
1731553Srgrimes}
1741553Srgrimes
1751553Srgrimes
1761553Srgrimesstatic int
1771553Srgrimespreadfd(void)
1781553Srgrimes{
1791553Srgrimes	int nr;
1801553Srgrimes	parsenextc = parsefile->buf;
1811553Srgrimes
1821553Srgrimes#ifndef NO_HISTORY
1831553Srgrimes	if (el != NULL && gotwinch) {
1841553Srgrimes		gotwinch = 0;
1851553Srgrimes		el_resize(el);
1861553Srgrimes	}
1871553Srgrimes#endif
1881553Srgrimesretry:
1891553Srgrimes#ifndef NO_HISTORY
1901553Srgrimes	if (parsefile->fd == 0 && el) {
1911553Srgrimes		const char *rl_cp;
1921553Srgrimes
1931553Srgrimes		rl_cp = el_gets(el, &nr);
1948857Srgrimes		if (rl_cp == NULL)
1951553Srgrimes			nr = 0;
1961553Srgrimes		else {
1971553Srgrimes			/* XXX - BUFSIZE should redesign so not necessary */
1981553Srgrimes			(void) strcpy(parsenextc, rl_cp);
1991553Srgrimes		}
2001553Srgrimes	} else
2011553Srgrimes#endif
2021553Srgrimes		nr = read(parsefile->fd, parsenextc, BUFSIZ - 1);
2031553Srgrimes
2041553Srgrimes	if (nr <= 0) {
2051553Srgrimes                if (nr < 0) {
2061553Srgrimes                        if (errno == EINTR)
2071553Srgrimes                                goto retry;
2081553Srgrimes                        if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
2091553Srgrimes                                int flags = fcntl(0, F_GETFL, 0);
2101553Srgrimes                                if (flags >= 0 && flags & O_NONBLOCK) {
2111553Srgrimes                                        flags &=~ O_NONBLOCK;
2121553Srgrimes                                        if (fcntl(0, F_SETFL, flags) >= 0) {
2131553Srgrimes						out2str("sh: turning off NDELAY mode\n");
2141553Srgrimes                                                goto retry;
2151553Srgrimes                                        }
2161553Srgrimes                                }
2171553Srgrimes                        }
2181553Srgrimes                }
2191553Srgrimes                nr = -1;
2201553Srgrimes	}
2211553Srgrimes	return nr;
2221553Srgrimes}
2231553Srgrimes
2241553Srgrimes/*
2251553Srgrimes * Refill the input buffer and return the next input character:
2261553Srgrimes *
2271553Srgrimes * 1) If a string was pushed back on the input, pop it;
2281553Srgrimes * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
2291553Srgrimes *    from a string so we can't refill the buffer, return EOF.
2301553Srgrimes * 3) If there is more in this buffer, use it else call read to fill it.
2311553Srgrimes * 4) Process input up to the next newline, deleting nul characters.
2321553Srgrimes */
2331553Srgrimes
2341553Srgrimesint
2351553Srgrimespreadbuffer(void)
2361553Srgrimes{
2371553Srgrimes	char *p, *q;
2381553Srgrimes	int more;
2391553Srgrimes	int something;
2401553Srgrimes	char savec;
2411553Srgrimes
2421553Srgrimes	if (parsefile->strpush) {
2431553Srgrimes		popstring();
2441553Srgrimes		if (--parsenleft >= 0)
2451553Srgrimes			return (*parsenextc++);
2461553Srgrimes	}
2471553Srgrimes	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
2481553Srgrimes		return PEOF;
2491553Srgrimes	flushout(&output);
2501553Srgrimes	flushout(&errout);
2511553Srgrimes
2521553Srgrimesagain:
2531553Srgrimes	if (parselleft <= 0) {
2541553Srgrimes		if ((parselleft = preadfd()) == -1) {
2551553Srgrimes			parselleft = parsenleft = EOF_NLEFT;
2561553Srgrimes			return PEOF;
2571553Srgrimes		}
2581553Srgrimes	}
2591553Srgrimes
2601553Srgrimes	q = p = parsenextc;
2611553Srgrimes
2621553Srgrimes	/* delete nul characters */
2631553Srgrimes	something = 0;
2641553Srgrimes	for (more = 1; more;) {
2651553Srgrimes		switch (*p) {
2661553Srgrimes		case '\0':
2671553Srgrimes			p++;	/* Skip nul */
2681553Srgrimes			goto check;
2691553Srgrimes
2701553Srgrimes		case '\t':
2711553Srgrimes		case ' ':
2721553Srgrimes			break;
2731553Srgrimes
2741553Srgrimes		case '\n':
2751553Srgrimes			parsenleft = q - parsenextc;
2761553Srgrimes			more = 0; /* Stop processing here */
27730642Scharnier			break;
2781553Srgrimes
2791553Srgrimes		default:
2801553Srgrimes			something = 1;
2811553Srgrimes			break;
2821553Srgrimes		}
2831553Srgrimes
2841553Srgrimes		*q++ = *p++;
2851553Srgrimescheck:
2861553Srgrimes		if (--parselleft <= 0) {
2871553Srgrimes			parsenleft = q - parsenextc - 1;
2881553Srgrimes			if (parsenleft < 0)
2891553Srgrimes				goto again;
2901553Srgrimes			*q = '\0';
2911553Srgrimes			more = 0;
2921553Srgrimes		}
2931553Srgrimes	}
2941553Srgrimes
2951553Srgrimes	savec = *q;
2961553Srgrimes	*q = '\0';
2971553Srgrimes
2981553Srgrimes#ifndef NO_HISTORY
2991553Srgrimes	if (parsefile->fd == 0 && hist && something) {
3001553Srgrimes		HistEvent he;
3011553Srgrimes		INTOFF;
3021553Srgrimes		history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD,
3031553Srgrimes		    parsenextc);
3041553Srgrimes		INTON;
3051553Srgrimes	}
3061553Srgrimes#endif
3071553Srgrimes
3081553Srgrimes	if (vflag) {
3091553Srgrimes		out2str(parsenextc);
3101553Srgrimes		flushout(out2);
3111553Srgrimes	}
3121553Srgrimes
3131553Srgrimes	*q = savec;
3141553Srgrimes
3151553Srgrimes	return *parsenextc++;
3161553Srgrimes}
3171553Srgrimes
3181553Srgrimes/*
3191553Srgrimes * Undo the last call to pgetc.  Only one character may be pushed back.
3201553Srgrimes * PEOF may be pushed back.
3211553Srgrimes */
3221553Srgrimes
3231553Srgrimesvoid
3241553Srgrimespungetc(void)
3251553Srgrimes{
3261553Srgrimes	parsenleft++;
3271553Srgrimes	parsenextc--;
3281553Srgrimes}
3291553Srgrimes
3301553Srgrimes/*
3311553Srgrimes * Push a string back onto the input at this current parsefile level.
3321553Srgrimes * We handle aliases this way.
3331553Srgrimes */
3341553Srgrimesvoid
3351553Srgrimespushstring(char *s, int len, void *ap)
3361553Srgrimes{
3371553Srgrimes	struct strpush *sp;
3381553Srgrimes
3391553Srgrimes	INTOFF;
3401553Srgrimes/*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
3411553Srgrimes	if (parsefile->strpush) {
3421553Srgrimes		sp = ckmalloc(sizeof (struct strpush));
3431553Srgrimes		sp->prev = parsefile->strpush;
3441553Srgrimes		parsefile->strpush = sp;
3451553Srgrimes	} else
3461553Srgrimes		sp = parsefile->strpush = &(parsefile->basestrpush);
3471553Srgrimes	sp->prevstring = parsenextc;
3481553Srgrimes	sp->prevnleft = parsenleft;
3491553Srgrimes	sp->prevlleft = parselleft;
3501553Srgrimes	sp->ap = (struct alias *)ap;
3511553Srgrimes	if (ap)
3521553Srgrimes		((struct alias *)ap)->flag |= ALIASINUSE;
353	parsenextc = s;
354	parsenleft = len;
355	INTON;
356}
357
358void
359popstring(void)
360{
361	struct strpush *sp = parsefile->strpush;
362
363	INTOFF;
364	parsenextc = sp->prevstring;
365	parsenleft = sp->prevnleft;
366	parselleft = sp->prevlleft;
367/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
368	if (sp->ap)
369		sp->ap->flag &= ~ALIASINUSE;
370	parsefile->strpush = sp->prev;
371	if (sp != &(parsefile->basestrpush))
372		ckfree(sp);
373	INTON;
374}
375
376/*
377 * Set the input to take input from a file.  If push is set, push the
378 * old input onto the stack first.
379 */
380
381void
382setinputfile(char *fname, int push)
383{
384	int fd;
385	int fd2;
386
387	INTOFF;
388	if ((fd = open(fname, O_RDONLY)) < 0)
389		error("Can't open %s: %s", fname, strerror(errno));
390	if (fd < 10) {
391		fd2 = copyfd(fd, 10);
392		close(fd);
393		if (fd2 < 0)
394			error("Out of file descriptors");
395		fd = fd2;
396	}
397	setinputfd(fd, push);
398	INTON;
399}
400
401
402/*
403 * Like setinputfile, but takes an open file descriptor.  Call this with
404 * interrupts off.
405 */
406
407void
408setinputfd(int fd, int push)
409{
410	(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
411	if (push) {
412		pushfile();
413		parsefile->buf = ckmalloc(BUFSIZ);
414	}
415	if (parsefile->fd > 0)
416		close(parsefile->fd);
417	parsefile->fd = fd;
418	if (parsefile->buf == NULL)
419		parsefile->buf = ckmalloc(BUFSIZ);
420	parselleft = parsenleft = 0;
421	plinno = 1;
422}
423
424
425/*
426 * Like setinputfile, but takes input from a string.
427 */
428
429void
430setinputstring(char *string, int push)
431{
432	INTOFF;
433	if (push)
434		pushfile();
435	parsenextc = string;
436	parselleft = parsenleft = strlen(string);
437	parsefile->buf = NULL;
438	plinno = 1;
439	INTON;
440}
441
442
443
444/*
445 * To handle the "." command, a stack of input files is used.  Pushfile
446 * adds a new entry to the stack and popfile restores the previous level.
447 */
448
449STATIC void
450pushfile(void)
451{
452	struct parsefile *pf;
453
454	parsefile->nleft = parsenleft;
455	parsefile->lleft = parselleft;
456	parsefile->nextc = parsenextc;
457	parsefile->linno = plinno;
458	pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
459	pf->prev = parsefile;
460	pf->fd = -1;
461	pf->strpush = NULL;
462	pf->basestrpush.prev = NULL;
463	parsefile = pf;
464}
465
466
467void
468popfile(void)
469{
470	struct parsefile *pf = parsefile;
471
472	INTOFF;
473	if (pf->fd >= 0)
474		close(pf->fd);
475	if (pf->buf)
476		ckfree(pf->buf);
477	while (pf->strpush)
478		popstring();
479	parsefile = pf->prev;
480	ckfree(pf);
481	parsenleft = parsefile->nleft;
482	parselleft = parsefile->lleft;
483	parsenextc = parsefile->nextc;
484	plinno = parsefile->linno;
485	INTON;
486}
487
488
489/*
490 * Return to top level.
491 */
492
493void
494popallfiles(void)
495{
496	while (parsefile != &basepf)
497		popfile();
498}
499
500
501
502/*
503 * Close the file(s) that the shell is reading commands from.  Called
504 * after a fork is done.
505 */
506
507void
508closescript(void)
509{
510	popallfiles();
511	if (parsefile->fd > 0) {
512		close(parsefile->fd);
513		parsefile->fd = 0;
514	}
515}
516