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