Home | History | Annotate | Line # | Download | only in sh
input.c revision 1.55
      1 /*	$NetBSD: input.c,v 1.55 2017/05/03 04:51:04 kre 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.55 2017/05/03 04:51:04 kre 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 <limits.h>
     49 #include <stdlib.h>
     50 #include <string.h>
     51 #include <sys/stat.h>
     52 
     53 /*
     54  * This file implements the input routines used by the parser.
     55  */
     56 
     57 #include "shell.h"
     58 #include "redir.h"
     59 #include "syntax.h"
     60 #include "input.h"
     61 #include "output.h"
     62 #include "options.h"
     63 #include "memalloc.h"
     64 #include "error.h"
     65 #include "alias.h"
     66 #include "parser.h"
     67 #include "myhistedit.h"
     68 
     69 #define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
     70 
     71 MKINIT
     72 struct strpush {
     73 	struct strpush *prev;	/* preceding string on stack */
     74 	const char *prevstring;
     75 	int prevnleft;
     76 	int prevlleft;
     77 	struct alias *ap;	/* if push was associated with an alias */
     78 };
     79 
     80 /*
     81  * The parsefile structure pointed to by the global variable parsefile
     82  * contains information about the current file being read.
     83  */
     84 
     85 MKINIT
     86 struct parsefile {
     87 	struct parsefile *prev;	/* preceding file on stack */
     88 	int linno;		/* current line */
     89 	int fd;			/* file descriptor (or -1 if string) */
     90 	int nleft;		/* number of chars left in this line */
     91 	int lleft;		/* number of chars left in this buffer */
     92 	const char *nextc;	/* next char in buffer */
     93 	char *buf;		/* input buffer */
     94 	struct strpush *strpush; /* for pushing strings at this level */
     95 	struct strpush basestrpush; /* so pushing one is fast */
     96 };
     97 
     98 
     99 int plinno = 1;			/* input line number */
    100 int parsenleft;			/* copy of parsefile->nleft */
    101 MKINIT int parselleft;		/* copy of parsefile->lleft */
    102 const char *parsenextc;		/* copy of parsefile->nextc */
    103 MKINIT struct parsefile basepf;	/* top level input file */
    104 MKINIT char basebuf[BUFSIZ];	/* buffer for top level input file */
    105 struct parsefile *parsefile = &basepf;	/* current input file */
    106 int init_editline = 0;		/* editline library initialized? */
    107 int whichprompt;		/* 1 == PS1, 2 == PS2 */
    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 = el_len == 0 ? 0 : -1;
    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 #ifndef SMALL
    243 	int something;
    244 #endif
    245 	char savec;
    246 
    247 	if (parsefile->strpush) {
    248 		popstring();
    249 		if (--parsenleft >= 0)
    250 			return (*parsenextc++);
    251 	}
    252 	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
    253 		return PEOF;
    254 	flushout(&output);
    255 	flushout(&errout);
    256 
    257 again:
    258 	if (parselleft <= 0) {
    259 		if ((parselleft = preadfd()) == -1) {
    260 			parselleft = parsenleft = EOF_NLEFT;
    261 			return PEOF;
    262 		}
    263 	}
    264 
    265 		/* p = (not const char *)parsenextc; */
    266 	p = parsefile->buf + (parsenextc - parsefile->buf);
    267 	q = p;
    268 
    269 	/* delete nul characters */
    270 #ifndef SMALL
    271 	something = 0;
    272 #endif
    273 	for (more = 1; more;) {
    274 		switch (*p) {
    275 		case '\0':
    276 			p++;	/* Skip nul */
    277 			goto check;
    278 
    279 		case '\t':
    280 		case ' ':
    281 			break;
    282 
    283 		case '\n':
    284 			parsenleft = q - parsenextc;
    285 			more = 0; /* Stop processing here */
    286 			break;
    287 
    288 		default:
    289 #ifndef SMALL
    290 			something = 1;
    291 #endif
    292 			break;
    293 		}
    294 
    295 		*q++ = *p++;
    296 check:
    297 		if (--parselleft <= 0) {
    298 			parsenleft = q - parsenextc - 1;
    299 			if (parsenleft < 0)
    300 				goto again;
    301 			*q = '\0';
    302 			more = 0;
    303 		}
    304 	}
    305 
    306 	savec = *q;
    307 	*q = '\0';
    308 
    309 #ifndef SMALL
    310 	if (parsefile->fd == 0 && hist && something) {
    311 		HistEvent he;
    312 		INTOFF;
    313 		history(hist, &he, whichprompt == 1? H_ENTER : H_APPEND,
    314 		    parsenextc);
    315 		INTON;
    316 	}
    317 #endif
    318 
    319 	if (vflag) {
    320 		out2str(parsenextc);
    321 		flushout(out2);
    322 	}
    323 
    324 	*q = savec;
    325 
    326 	return *parsenextc++;
    327 }
    328 
    329 /*
    330  * Undo the last call to pgetc.  Only one character may be pushed back.
    331  * PEOF may be pushed back.
    332  */
    333 
    334 void
    335 pungetc(void)
    336 {
    337 	parsenleft++;
    338 	parsenextc--;
    339 }
    340 
    341 /*
    342  * Push a string back onto the input at this current parsefile level.
    343  * We handle aliases this way.
    344  */
    345 void
    346 pushstring(const char *s, int len, struct alias *ap)
    347 {
    348 	struct strpush *sp;
    349 
    350 	INTOFF;
    351 /*debugprintf("*** calling pushstring: %s, %d\n", s, len);*/
    352 	if (parsefile->strpush) {
    353 		sp = ckmalloc(sizeof (struct strpush));
    354 		sp->prev = parsefile->strpush;
    355 		parsefile->strpush = sp;
    356 	} else
    357 		sp = parsefile->strpush = &(parsefile->basestrpush);
    358 	sp->prevstring = parsenextc;
    359 	sp->prevnleft = parsenleft;
    360 	sp->prevlleft = parselleft;
    361 	sp->ap = ap;
    362 	if (ap)
    363 		ap->flag |= ALIASINUSE;
    364 	parsenextc = s;
    365 	parsenleft = len;
    366 	INTON;
    367 }
    368 
    369 void
    370 popstring(void)
    371 {
    372 	struct strpush *sp = parsefile->strpush;
    373 
    374 	INTOFF;
    375 	parsenextc = sp->prevstring;
    376 	parsenleft = sp->prevnleft;
    377 	parselleft = sp->prevlleft;
    378 /*debugprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
    379 	if (sp->ap)
    380 		sp->ap->flag &= ~ALIASINUSE;
    381 	parsefile->strpush = sp->prev;
    382 	if (sp != &(parsefile->basestrpush))
    383 		ckfree(sp);
    384 	INTON;
    385 }
    386 
    387 /*
    388  * Set the input to take input from a file.  If push is set, push the
    389  * old input onto the stack first.
    390  */
    391 
    392 void
    393 setinputfile(const char *fname, int push)
    394 {
    395 	unsigned char magic[4];
    396 	int fd;
    397 	int fd2;
    398 	struct stat sb;
    399 
    400 	INTOFF;
    401 	if ((fd = open(fname, O_RDONLY)) < 0)
    402 		error("Can't open %s", fname);
    403 
    404 	/* Since the message "Syntax error: "(" unexpected" is not very
    405 	 * helpful, we check if the file starts with the ELF magic to
    406 	 * avoid that message. The first lseek tries to make sure that
    407 	 * we can later rewind the file.
    408 	 */
    409 	if (fstat(fd, &sb) == 0 && S_ISREG(sb.st_mode) &&
    410 	    lseek(fd, 0, SEEK_SET) == 0) {
    411 		if (read(fd, magic, 4) == 4) {
    412 			if (memcmp(magic, "\177ELF", 4) == 0) {
    413 				(void)close(fd);
    414 				error("Cannot execute ELF binary %s", fname);
    415 			}
    416 		}
    417 		if (lseek(fd, 0, SEEK_SET) != 0) {
    418 			(void)close(fd);
    419 			error("Cannot rewind the file %s", fname);
    420 		}
    421 	}
    422 
    423 	fd2 = to_upper_fd(fd);	/* closes fd, returns higher equiv */
    424 	if (fd2 == fd) {
    425 		(void) close(fd);
    426 		error("Out of file descriptors");
    427 	}
    428 
    429 	setinputfd(fd2, push);
    430 	INTON;
    431 }
    432 
    433 /*
    434  * When a shell fd needs to be altered (when the user wants to use
    435  * the same fd - rare, but happens - we need to locate the ref to
    436  * the fd, and update it.  This happens via a callback.
    437  * This is the callback func for fd's used for shell input
    438  */
    439 static void
    440 input_fd_swap(int from, int to)
    441 {
    442 	struct parsefile *pf;
    443 
    444 	pf = parsefile;
    445 	while (pf != NULL) {		/* don't need to stop at basepf */
    446 		if (pf->fd == from)
    447 			pf->fd = to;
    448 		pf = pf->prev;
    449 	}
    450 }
    451 
    452 /*
    453  * Like setinputfile, but takes an open file descriptor.  Call this with
    454  * interrupts off.
    455  */
    456 
    457 void
    458 setinputfd(int fd, int push)
    459 {
    460 	register_sh_fd(fd, input_fd_swap);
    461 	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
    462 	if (push) {
    463 		pushfile();
    464 		parsefile->buf = ckmalloc(BUFSIZ);
    465 	}
    466 	if (parsefile->fd > 0)
    467 		sh_close(parsefile->fd);
    468 	parsefile->fd = fd;
    469 	if (parsefile->buf == NULL)
    470 		parsefile->buf = ckmalloc(BUFSIZ);
    471 	parselleft = parsenleft = 0;
    472 	plinno = 1;
    473 }
    474 
    475 
    476 /*
    477  * Like setinputfile, but takes input from a string.
    478  */
    479 
    480 void
    481 setinputstring(char *string, int push)
    482 {
    483 
    484 	INTOFF;
    485 	if (push)
    486 		pushfile();
    487 	parsenextc = string;
    488 	parselleft = parsenleft = strlen(string);
    489 	parsefile->buf = NULL;
    490 	plinno = 1;
    491 	INTON;
    492 }
    493 
    494 
    495 
    496 /*
    497  * To handle the "." command, a stack of input files is used.  Pushfile
    498  * adds a new entry to the stack and popfile restores the previous level.
    499  */
    500 
    501 STATIC void
    502 pushfile(void)
    503 {
    504 	struct parsefile *pf;
    505 
    506 	parsefile->nleft = parsenleft;
    507 	parsefile->lleft = parselleft;
    508 	parsefile->nextc = parsenextc;
    509 	parsefile->linno = plinno;
    510 	pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
    511 	pf->prev = parsefile;
    512 	pf->fd = -1;
    513 	pf->strpush = NULL;
    514 	pf->basestrpush.prev = NULL;
    515 	parsefile = pf;
    516 }
    517 
    518 
    519 void
    520 popfile(void)
    521 {
    522 	struct parsefile *pf = parsefile;
    523 
    524 	INTOFF;
    525 	if (pf->fd >= 0)
    526 		sh_close(pf->fd);
    527 	if (pf->buf)
    528 		ckfree(pf->buf);
    529 	while (pf->strpush)
    530 		popstring();
    531 	parsefile = pf->prev;
    532 	ckfree(pf);
    533 	parsenleft = parsefile->nleft;
    534 	parselleft = parsefile->lleft;
    535 	parsenextc = parsefile->nextc;
    536 	plinno = parsefile->linno;
    537 	INTON;
    538 }
    539 
    540 
    541 /*
    542  * Return to top level.
    543  */
    544 
    545 void
    546 popallfiles(void)
    547 {
    548 	while (parsefile != &basepf)
    549 		popfile();
    550 }
    551 
    552 
    553 
    554 /*
    555  * Close the file(s) that the shell is reading commands from.  Called
    556  * after a fork is done.
    557  *
    558  * Takes one arg, vfork, which tells it to not modify its global vars
    559  * as it is still running in the parent.
    560  *
    561  * This code is (probably) unnecessary as the 'close on exec' flag is
    562  * set and should be enough.  In the vfork case it is definitely wrong
    563  * to close the fds as another fork() may be done later to feed data
    564  * from a 'here' document into a pipe and we don't want to close the
    565  * pipe!
    566  */
    567 
    568 void
    569 closescript(int vforked)
    570 {
    571 	if (vforked)
    572 		return;
    573 	popallfiles();
    574 	if (parsefile->fd > 0) {
    575 		sh_close(parsefile->fd);
    576 		parsefile->fd = 0;
    577 	}
    578 }
    579