Home | History | Annotate | Line # | Download | only in sh
input.c revision 1.40
      1 /*	$NetBSD: input.c,v 1.40 2007/02/15 12:02:59 rillig 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.40 2007/02/15 12:02:59 rillig 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 EditLine *el;			/* cookie for editline package */
    108 
    109 STATIC void pushfile(void);
    110 static int preadfd(void);
    111 
    112 #ifdef mkinit
    113 INCLUDE <stdio.h>
    114 INCLUDE "input.h"
    115 INCLUDE "error.h"
    116 
    117 INIT {
    118 	basepf.nextc = basepf.buf = basebuf;
    119 }
    120 
    121 RESET {
    122 	if (exception != EXSHELLPROC)
    123 		parselleft = parsenleft = 0;	/* clear input buffer */
    124 	popallfiles();
    125 }
    126 
    127 SHELLPROC {
    128 	popallfiles();
    129 }
    130 #endif
    131 
    132 
    133 /*
    134  * Read a line from the script.
    135  */
    136 
    137 char *
    138 pfgets(char *line, int len)
    139 {
    140 	char *p = line;
    141 	int nleft = len;
    142 	int c;
    143 
    144 	while (--nleft > 0) {
    145 		c = pgetc_macro();
    146 		if (c == PEOF) {
    147 			if (p == line)
    148 				return NULL;
    149 			break;
    150 		}
    151 		*p++ = c;
    152 		if (c == '\n')
    153 			break;
    154 	}
    155 	*p = '\0';
    156 	return line;
    157 }
    158 
    159 
    160 
    161 /*
    162  * Read a character from the script, returning PEOF on end of file.
    163  * Nul characters in the input are silently discarded.
    164  */
    165 
    166 int
    167 pgetc(void)
    168 {
    169 	return pgetc_macro();
    170 }
    171 
    172 
    173 static int
    174 preadfd(void)
    175 {
    176 	int nr;
    177 	char *buf =  parsefile->buf;
    178 	parsenextc = buf;
    179 
    180 retry:
    181 #ifndef SMALL
    182 	if (parsefile->fd == 0 && el) {
    183 		static const char *rl_cp;
    184 		static int el_len;
    185 
    186 		if (rl_cp == NULL)
    187 			rl_cp = el_gets(el, &el_len);
    188 		if (rl_cp == NULL)
    189 			nr = 0;
    190 		else {
    191 			nr = el_len;
    192 			if (nr > BUFSIZ - 8)
    193 				nr = BUFSIZ - 8;
    194 			memcpy(buf, rl_cp, nr);
    195 			if (nr != el_len) {
    196 				el_len -= nr;
    197 				rl_cp += nr;
    198 			} else
    199 				rl_cp = 0;
    200 		}
    201 
    202 	} else
    203 #endif
    204 		nr = read(parsefile->fd, buf, BUFSIZ - 8);
    205 
    206 
    207 	if (nr <= 0) {
    208                 if (nr < 0) {
    209                         if (errno == EINTR)
    210                                 goto retry;
    211                         if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
    212                                 int flags = fcntl(0, F_GETFL, 0);
    213                                 if (flags >= 0 && flags & O_NONBLOCK) {
    214                                         flags &=~ O_NONBLOCK;
    215                                         if (fcntl(0, F_SETFL, flags) >= 0) {
    216 						out2str("sh: turning off NDELAY mode\n");
    217                                                 goto retry;
    218                                         }
    219                                 }
    220                         }
    221                 }
    222                 nr = -1;
    223 	}
    224 	return nr;
    225 }
    226 
    227 /*
    228  * Refill the input buffer and return the next input character:
    229  *
    230  * 1) If a string was pushed back on the input, pop it;
    231  * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
    232  *    from a string so we can't refill the buffer, return EOF.
    233  * 3) If the is more stuff in this buffer, use it else call read to fill it.
    234  * 4) Process input up to the next newline, deleting nul characters.
    235  */
    236 
    237 int
    238 preadbuffer(void)
    239 {
    240 	char *p, *q;
    241 	int more;
    242 	int something;
    243 	char savec;
    244 
    245 	if (parsefile->strpush) {
    246 		popstring();
    247 		if (--parsenleft >= 0)
    248 			return (*parsenextc++);
    249 	}
    250 	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
    251 		return PEOF;
    252 	flushout(&output);
    253 	flushout(&errout);
    254 
    255 again:
    256 	if (parselleft <= 0) {
    257 		if ((parselleft = preadfd()) == -1) {
    258 			parselleft = parsenleft = EOF_NLEFT;
    259 			return PEOF;
    260 		}
    261 	}
    262 
    263 	q = p = parsenextc;
    264 
    265 	/* delete nul characters */
    266 	something = 0;
    267 	for (more = 1; more;) {
    268 		switch (*p) {
    269 		case '\0':
    270 			p++;	/* Skip nul */
    271 			goto check;
    272 
    273 		case '\t':
    274 		case ' ':
    275 			break;
    276 
    277 		case '\n':
    278 			parsenleft = q - parsenextc;
    279 			more = 0; /* Stop processing here */
    280 			break;
    281 
    282 		default:
    283 			something = 1;
    284 			break;
    285 		}
    286 
    287 		*q++ = *p++;
    288 check:
    289 		if (--parselleft <= 0) {
    290 			parsenleft = q - parsenextc - 1;
    291 			if (parsenleft < 0)
    292 				goto again;
    293 			*q = '\0';
    294 			more = 0;
    295 		}
    296 	}
    297 
    298 	savec = *q;
    299 	*q = '\0';
    300 
    301 #ifndef SMALL
    302 	if (parsefile->fd == 0 && hist && something) {
    303 		HistEvent he;
    304 		INTOFF;
    305 		history(hist, &he, whichprompt == 1? H_ENTER : H_APPEND,
    306 		    parsenextc);
    307 		INTON;
    308 	}
    309 #endif
    310 
    311 	if (vflag) {
    312 		out2str(parsenextc);
    313 		flushout(out2);
    314 	}
    315 
    316 	*q = savec;
    317 
    318 	return *parsenextc++;
    319 }
    320 
    321 /*
    322  * Undo the last call to pgetc.  Only one character may be pushed back.
    323  * PEOF may be pushed back.
    324  */
    325 
    326 void
    327 pungetc(void)
    328 {
    329 	parsenleft++;
    330 	parsenextc--;
    331 }
    332 
    333 /*
    334  * Push a string back onto the input at this current parsefile level.
    335  * We handle aliases this way.
    336  */
    337 void
    338 pushstring(char *s, int len, void *ap)
    339 {
    340 	struct strpush *sp;
    341 
    342 	INTOFF;
    343 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
    344 	if (parsefile->strpush) {
    345 		sp = ckmalloc(sizeof (struct strpush));
    346 		sp->prev = parsefile->strpush;
    347 		parsefile->strpush = sp;
    348 	} else
    349 		sp = parsefile->strpush = &(parsefile->basestrpush);
    350 	sp->prevstring = parsenextc;
    351 	sp->prevnleft = parsenleft;
    352 	sp->prevlleft = parselleft;
    353 	sp->ap = (struct alias *)ap;
    354 	if (ap)
    355 		((struct alias *)ap)->flag |= ALIASINUSE;
    356 	parsenextc = s;
    357 	parsenleft = len;
    358 	INTON;
    359 }
    360 
    361 void
    362 popstring(void)
    363 {
    364 	struct strpush *sp = parsefile->strpush;
    365 
    366 	INTOFF;
    367 	parsenextc = sp->prevstring;
    368 	parsenleft = sp->prevnleft;
    369 	parselleft = sp->prevlleft;
    370 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
    371 	if (sp->ap)
    372 		sp->ap->flag &= ~ALIASINUSE;
    373 	parsefile->strpush = sp->prev;
    374 	if (sp != &(parsefile->basestrpush))
    375 		ckfree(sp);
    376 	INTON;
    377 }
    378 
    379 /*
    380  * Set the input to take input from a file.  If push is set, push the
    381  * old input onto the stack first.
    382  */
    383 
    384 void
    385 setinputfile(const char *fname, int push)
    386 {
    387 	unsigned char magic[4];
    388 	int fd;
    389 	int fd2;
    390 
    391 	INTOFF;
    392 	if ((fd = open(fname, O_RDONLY)) < 0)
    393 		error("Can't open %s", fname);
    394 
    395 	/* Since the message "Syntax error: "(" unexpected" is not very
    396 	 * helpful, we check if the file starts with the ELF magic to
    397 	 * avoid that message. The first lseek tries to make sure that
    398 	 * we can later rewind the file.
    399 	 */
    400 	if (lseek(fd, 0, SEEK_SET) == 0) {
    401 		if (read(fd, magic, 4) == 4) {
    402 			if (memcmp(magic, "\177ELF", 4) == 0)
    403 				error("Cannot execute ELF binary %s", fname);
    404 		}
    405 		if (lseek(fd, 0, SEEK_SET) != 0)
    406 			error("Cannot rewind the file %s", fname);
    407 	}
    408 
    409 	if (fd < 10) {
    410 		fd2 = copyfd(fd, 10);
    411 		close(fd);
    412 		if (fd2 < 0)
    413 			error("Out of file descriptors");
    414 		fd = fd2;
    415 	}
    416 	setinputfd(fd, push);
    417 	INTON;
    418 }
    419 
    420 
    421 /*
    422  * Like setinputfile, but takes an open file descriptor.  Call this with
    423  * interrupts off.
    424  */
    425 
    426 void
    427 setinputfd(int fd, int push)
    428 {
    429 	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
    430 	if (push) {
    431 		pushfile();
    432 		parsefile->buf = ckmalloc(BUFSIZ);
    433 	}
    434 	if (parsefile->fd > 0)
    435 		close(parsefile->fd);
    436 	parsefile->fd = fd;
    437 	if (parsefile->buf == NULL)
    438 		parsefile->buf = ckmalloc(BUFSIZ);
    439 	parselleft = parsenleft = 0;
    440 	plinno = 1;
    441 }
    442 
    443 
    444 /*
    445  * Like setinputfile, but takes input from a string.
    446  */
    447 
    448 void
    449 setinputstring(char *string, int push)
    450 {
    451 	INTOFF;
    452 	if (push)
    453 		pushfile();
    454 	parsenextc = string;
    455 	parselleft = parsenleft = strlen(string);
    456 	parsefile->buf = NULL;
    457 	plinno = 1;
    458 	INTON;
    459 }
    460 
    461 
    462 
    463 /*
    464  * To handle the "." command, a stack of input files is used.  Pushfile
    465  * adds a new entry to the stack and popfile restores the previous level.
    466  */
    467 
    468 STATIC void
    469 pushfile(void)
    470 {
    471 	struct parsefile *pf;
    472 
    473 	parsefile->nleft = parsenleft;
    474 	parsefile->lleft = parselleft;
    475 	parsefile->nextc = parsenextc;
    476 	parsefile->linno = plinno;
    477 	pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
    478 	pf->prev = parsefile;
    479 	pf->fd = -1;
    480 	pf->strpush = NULL;
    481 	pf->basestrpush.prev = NULL;
    482 	parsefile = pf;
    483 }
    484 
    485 
    486 void
    487 popfile(void)
    488 {
    489 	struct parsefile *pf = parsefile;
    490 
    491 	INTOFF;
    492 	if (pf->fd >= 0)
    493 		close(pf->fd);
    494 	if (pf->buf)
    495 		ckfree(pf->buf);
    496 	while (pf->strpush)
    497 		popstring();
    498 	parsefile = pf->prev;
    499 	ckfree(pf);
    500 	parsenleft = parsefile->nleft;
    501 	parselleft = parsefile->lleft;
    502 	parsenextc = parsefile->nextc;
    503 	plinno = parsefile->linno;
    504 	INTON;
    505 }
    506 
    507 
    508 /*
    509  * Return to top level.
    510  */
    511 
    512 void
    513 popallfiles(void)
    514 {
    515 	while (parsefile != &basepf)
    516 		popfile();
    517 }
    518 
    519 
    520 
    521 /*
    522  * Close the file(s) that the shell is reading commands from.  Called
    523  * after a fork is done.
    524  *
    525  * Takes one arg, vfork, which tells it to not modify its global vars
    526  * as it is still running in the parent.
    527  *
    528  * This code is (probably) unnecessary as the 'close on exec' flag is
    529  * set and should be enough.  In the vfork case it is definitely wrong
    530  * to close the fds as another fork() may be done later to feed data
    531  * from a 'here' document into a pipe and we don't want to close the
    532  * pipe!
    533  */
    534 
    535 void
    536 closescript(int vforked)
    537 {
    538 	if (vforked)
    539 		return;
    540 	popallfiles();
    541 	if (parsefile->fd > 0) {
    542 		close(parsefile->fd);
    543 		parsefile->fd = 0;
    544 	}
    545 }
    546