Home | History | Annotate | Line # | Download | only in sh
input.c revision 1.10
      1 /*-
      2  * Copyright (c) 1991, 1993
      3  *	The Regents of the University of California.  All rights reserved.
      4  *
      5  * This code is derived from software contributed to Berkeley by
      6  * Kenneth Almquist.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *	This product includes software developed by the University of
     19  *	California, Berkeley and its contributors.
     20  * 4. Neither the name of the University nor the names of its contributors
     21  *    may be used to endorse or promote products derived from this software
     22  *    without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  * SUCH DAMAGE.
     35  */
     36 
     37 #ifndef lint
     38 /*static char sccsid[] = "from: @(#)input.c	8.1 (Berkeley) 5/31/93";*/
     39 static char *rcsid = "$Id: input.c,v 1.10 1994/06/11 16:11:59 mycroft Exp $";
     40 #endif /* not lint */
     41 
     42 /*
     43  * This file implements the input routines used by the parser.
     44  */
     45 
     46 #include <stdio.h>	/* defines BUFSIZ */
     47 #include <fcntl.h>
     48 #include <errno.h>
     49 #include <unistd.h>
     50 #include "shell.h"
     51 #include "syntax.h"
     52 #include "input.h"
     53 #include "output.h"
     54 #include "options.h"
     55 #include "memalloc.h"
     56 #include "error.h"
     57 #include "alias.h"
     58 #include "parser.h"
     59 #ifndef NO_HISTORY
     60 #include "myhistedit.h"
     61 #endif
     62 
     63 #define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
     64 
     65 MKINIT
     66 struct strpush {
     67 	struct strpush *prev;	/* preceding string on stack */
     68 	char *prevstring;
     69 	int prevnleft;
     70 	struct alias *ap;	/* if push was associated with an alias */
     71 };
     72 
     73 /*
     74  * The parsefile structure pointed to by the global variable parsefile
     75  * contains information about the current file being read.
     76  */
     77 
     78 MKINIT
     79 struct parsefile {
     80 	struct parsefile *prev;	/* preceding file on stack */
     81 	int linno;		/* current line */
     82 	int fd;			/* file descriptor (or -1 if string) */
     83 	int nleft;		/* number of chars left in buffer */
     84 	char *nextc;		/* next char in buffer */
     85 	char *buf;		/* input buffer */
     86 	struct strpush *strpush; /* for pushing strings at this level */
     87 	struct strpush basestrpush; /* so pushing one is fast */
     88 };
     89 
     90 
     91 int plinno = 1;			/* input line number */
     92 MKINIT int parsenleft;		/* copy of parsefile->nleft */
     93 char *parsenextc;		/* copy of parsefile->nextc */
     94 MKINIT struct parsefile basepf;	/* top level input file */
     95 char basebuf[BUFSIZ];		/* buffer for top level input file */
     96 struct parsefile *parsefile = &basepf;	/* current input file */
     97 char *pushedstring;		/* copy of parsenextc when text pushed back */
     98 int pushednleft;		/* copy of parsenleft when text pushed back */
     99 int init_editline = 0;		/* editline library initialized? */
    100 int whichprompt;		/* 1 == PS1, 2 == PS2 */
    101 
    102 #ifndef NO_HISTORY
    103 EditLine *el;			/* cookie for editline package */
    104 #endif
    105 
    106 #ifdef __STDC__
    107 STATIC void pushfile(void);
    108 #else
    109 STATIC void pushfile();
    110 #endif
    111 
    112 
    113 
    114 #ifdef mkinit
    115 INCLUDE "input.h"
    116 INCLUDE "error.h"
    117 
    118 INIT {
    119 	extern char basebuf[];
    120 
    121 	basepf.nextc = basepf.buf = basebuf;
    122 }
    123 
    124 RESET {
    125 	if (exception != EXSHELLPROC)
    126 		parsenleft = 0;            /* clear input buffer */
    127 	popallfiles();
    128 }
    129 
    130 SHELLPROC {
    131 	popallfiles();
    132 }
    133 #endif
    134 
    135 
    136 /*
    137  * Read a line from the script.
    138  */
    139 
    140 char *
    141 pfgets(line, len)
    142 	char *line;
    143 	{
    144 	register char *p = line;
    145 	int nleft = len;
    146 	int c;
    147 
    148 	while (--nleft > 0) {
    149 		c = pgetc_macro();
    150 		if (c == PEOF) {
    151 			if (p == line)
    152 				return NULL;
    153 			break;
    154 		}
    155 		*p++ = c;
    156 		if (c == '\n')
    157 			break;
    158 	}
    159 	*p = '\0';
    160 	return line;
    161 }
    162 
    163 
    164 
    165 /*
    166  * Read a character from the script, returning PEOF on end of file.
    167  * Nul characters in the input are silently discarded.
    168  */
    169 
    170 int
    171 pgetc() {
    172 	return pgetc_macro();
    173 }
    174 
    175 
    176 /*
    177  * Refill the input buffer and return the next input character:
    178  *
    179  * 1) If a string was pushed back on the input, pop it;
    180  * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
    181  *    from a string so we can't refill the buffer, return EOF.
    182  * 3) Call read to read in the characters.
    183  * 4) Delete all nul characters from the buffer.
    184  */
    185 
    186 int
    187 preadbuffer() {
    188 	register char *p, *q;
    189 	register int i;
    190 	register int something;
    191 #ifndef NO_HISTORY
    192 	extern EditLine *el;
    193 #endif
    194 
    195 	if (parsefile->strpush) {
    196 		popstring();
    197 		if (--parsenleft >= 0)
    198 			return (*parsenextc++);
    199 	}
    200 	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
    201 		return PEOF;
    202 	flushout(&output);
    203 	flushout(&errout);
    204 retry:
    205 	p = parsenextc = parsefile->buf;
    206 #ifndef NO_HISTORY
    207 	if (parsefile->fd == 0 && el) {
    208 		const char *rl_cp;
    209 		int len;
    210 
    211 		rl_cp = el_gets(el, &len);
    212 		if (rl_cp == NULL) {
    213 			i = 0;
    214 			goto eof;
    215 		}
    216 		strcpy(p, rl_cp);  /* XXX - BUFSIZE should redesign so not necessary */
    217 		i = len;
    218 
    219 	} else {
    220 #endif
    221 regular_read:
    222 		i = read(parsefile->fd, p, BUFSIZ - 1);
    223 #ifndef NO_HISTORY
    224 	}
    225 #endif
    226 eof:
    227 	if (i <= 0) {
    228                 if (i < 0) {
    229                         if (errno == EINTR)
    230                                 goto retry;
    231                         if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
    232                                 int flags = fcntl(0, F_GETFL, 0);
    233                                 if (flags >= 0 && flags & O_NONBLOCK) {
    234                                         flags &=~ O_NONBLOCK;
    235                                         if (fcntl(0, F_SETFL, flags) >= 0) {
    236 						out2str("sh: turning off NDELAY mode\n");
    237                                                 goto retry;
    238                                         }
    239                                 }
    240                         }
    241                 }
    242                 parsenleft = EOF_NLEFT;
    243                 return PEOF;
    244 	}
    245 	parsenleft = i - 1;	/* we're returning one char in this call */
    246 
    247 	/* delete nul characters */
    248 	something = 0;
    249 	for (;;) {
    250 		if (*p == '\0')
    251 			break;
    252 		if (*p != ' ' && *p != '\t' && *p != '\n')
    253 			something = 1;
    254 		p++;
    255 		if (--i <= 0) {
    256 			*p = '\0';
    257 			goto done;		/* no nul characters */
    258 		}
    259 	}
    260 	/*
    261 	 * remove nuls
    262 	 */
    263 	q = p++;
    264 	while (--i > 0) {
    265 		if (*p != '\0')
    266 			*q++ = *p;
    267 		p++;
    268 	}
    269 	*q = '\0';
    270 	if (q == parsefile->buf)
    271 		goto retry;			/* buffer contained nothing but nuls */
    272 	parsenleft = q - parsefile->buf - 1;
    273 
    274 done:
    275 #ifndef NO_HISTORY
    276 	if (parsefile->fd == 0 && hist && something) {
    277 		INTOFF;
    278 		history(hist, whichprompt == 1 ? H_ENTER : H_ADD,
    279 			   parsefile->buf);
    280 		INTON;
    281 	}
    282 #endif
    283 	if (vflag) {
    284 		/*
    285 		 * This isn't right.  Most shells coordinate it with
    286 		 * reading a line at a time.  I honestly don't know if its
    287 		 * worth it.
    288 		 */
    289 		i = parsenleft + 1;
    290 		p = parsefile->buf;
    291 		for (; i--; p++)
    292 			out2c(*p)
    293 		flushout(out2);
    294 	}
    295 	return *parsenextc++;
    296 }
    297 
    298 /*
    299  * Undo the last call to pgetc.  Only one character may be pushed back.
    300  * PEOF may be pushed back.
    301  */
    302 
    303 void
    304 pungetc() {
    305 	parsenleft++;
    306 	parsenextc--;
    307 }
    308 
    309 /*
    310  * Push a string back onto the input at this current parsefile level.
    311  * We handle aliases this way.
    312  */
    313 void
    314 pushstring(s, len, ap)
    315 	char *s;
    316 	int len;
    317 	void *ap;
    318 	{
    319 	struct strpush *sp;
    320 
    321 	INTOFF;
    322 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
    323 	if (parsefile->strpush) {
    324 		sp = ckmalloc(sizeof (struct strpush));
    325 		sp->prev = parsefile->strpush;
    326 		parsefile->strpush = sp;
    327 	} else
    328 		sp = parsefile->strpush = &(parsefile->basestrpush);
    329 	sp->prevstring = parsenextc;
    330 	sp->prevnleft = parsenleft;
    331 	sp->ap = (struct alias *)ap;
    332 	if (ap)
    333 		((struct alias *)ap)->flag |= ALIASINUSE;
    334 	parsenextc = s;
    335 	parsenleft = len;
    336 	INTON;
    337 }
    338 
    339 popstring()
    340 {
    341 	struct strpush *sp = parsefile->strpush;
    342 
    343 	INTOFF;
    344 	parsenextc = sp->prevstring;
    345 	parsenleft = sp->prevnleft;
    346 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
    347 	if (sp->ap)
    348 		sp->ap->flag &= ~ALIASINUSE;
    349 	parsefile->strpush = sp->prev;
    350 	if (sp != &(parsefile->basestrpush))
    351 		ckfree(sp);
    352 	INTON;
    353 }
    354 
    355 /*
    356  * Set the input to take input from a file.  If push is set, push the
    357  * old input onto the stack first.
    358  */
    359 
    360 void
    361 setinputfile(fname, push)
    362 	char *fname;
    363 	{
    364 	int fd;
    365 	int fd2;
    366 
    367 	INTOFF;
    368 	if ((fd = open(fname, O_RDONLY)) < 0)
    369 		error("Can't open %s", fname);
    370 	if (fd < 10) {
    371 		fd2 = copyfd(fd, 10);
    372 		close(fd);
    373 		if (fd2 < 0)
    374 			error("Out of file descriptors");
    375 		fd = fd2;
    376 	}
    377 	setinputfd(fd, push);
    378 	INTON;
    379 }
    380 
    381 
    382 /*
    383  * Like setinputfile, but takes an open file descriptor.  Call this with
    384  * interrupts off.
    385  */
    386 
    387 void
    388 setinputfd(fd, push) {
    389 	if (push) {
    390 		pushfile();
    391 		parsefile->buf = ckmalloc(BUFSIZ);
    392 	}
    393 	if (parsefile->fd > 0)
    394 		close(parsefile->fd);
    395 	parsefile->fd = fd;
    396 	if (parsefile->buf == NULL)
    397 		parsefile->buf = ckmalloc(BUFSIZ);
    398 	parsenleft = 0;
    399 	plinno = 1;
    400 }
    401 
    402 
    403 /*
    404  * Like setinputfile, but takes input from a string.
    405  */
    406 
    407 void
    408 setinputstring(string, push)
    409 	char *string;
    410 	{
    411 	INTOFF;
    412 	if (push)
    413 		pushfile();
    414 	parsenextc = string;
    415 	parsenleft = strlen(string);
    416 	parsefile->buf = NULL;
    417 	plinno = 1;
    418 	INTON;
    419 }
    420 
    421 
    422 
    423 /*
    424  * To handle the "." command, a stack of input files is used.  Pushfile
    425  * adds a new entry to the stack and popfile restores the previous level.
    426  */
    427 
    428 STATIC void
    429 pushfile() {
    430 	struct parsefile *pf;
    431 
    432 	parsefile->nleft = parsenleft;
    433 	parsefile->nextc = parsenextc;
    434 	parsefile->linno = plinno;
    435 	pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
    436 	pf->prev = parsefile;
    437 	pf->fd = -1;
    438 	pf->strpush = NULL;
    439 	pf->basestrpush.prev = NULL;
    440 	parsefile = pf;
    441 }
    442 
    443 
    444 void
    445 popfile() {
    446 	struct parsefile *pf = parsefile;
    447 
    448 	INTOFF;
    449 	if (pf->fd >= 0)
    450 		close(pf->fd);
    451 	if (pf->buf)
    452 		ckfree(pf->buf);
    453 	while (pf->strpush)
    454 		popstring();
    455 	parsefile = pf->prev;
    456 	ckfree(pf);
    457 	parsenleft = parsefile->nleft;
    458 	parsenextc = parsefile->nextc;
    459 	plinno = parsefile->linno;
    460 	INTON;
    461 }
    462 
    463 
    464 /*
    465  * Return to top level.
    466  */
    467 
    468 void
    469 popallfiles() {
    470 	while (parsefile != &basepf)
    471 		popfile();
    472 }
    473 
    474 
    475 
    476 /*
    477  * Close the file(s) that the shell is reading commands from.  Called
    478  * after a fork is done.
    479  */
    480 
    481 void
    482 closescript() {
    483 	popallfiles();
    484 	if (parsefile->fd > 0) {
    485 		close(parsefile->fd);
    486 		parsefile->fd = 0;
    487 	}
    488 }
    489