input.c revision 1.64
1/* $NetBSD: input.c,v 1.64 2018/12/03 06:40:26 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 38static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95"; 39#else 40__RCSID("$NetBSD: input.c,v 1.64 2018/12/03 06:40:26 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#include "show.h" 69 70#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ 71 72MKINIT 73struct strpush { 74 struct strpush *prev; /* preceding string on stack */ 75 const char *prevstring; 76 int prevnleft; 77 int prevlleft; 78 struct alias *ap; /* if push was associated with an alias */ 79}; 80 81/* 82 * The parsefile structure pointed to by the global variable parsefile 83 * contains information about the current file being read. 84 */ 85 86MKINIT 87struct parsefile { 88 struct parsefile *prev; /* preceding file on stack */ 89 int linno; /* current line */ 90 int fd; /* file descriptor (or -1 if string) */ 91 int nleft; /* number of chars left in this line */ 92 int lleft; /* number of chars left in this buffer */ 93 const char *nextc; /* next char in buffer */ 94 char *buf; /* input buffer */ 95 struct strpush *strpush; /* for pushing strings at this level */ 96 struct strpush basestrpush; /* so pushing one is fast */ 97}; 98 99 100int plinno = 1; /* input line number */ 101int parsenleft; /* copy of parsefile->nleft */ 102MKINIT int parselleft; /* copy of parsefile->lleft */ 103const char *parsenextc; /* copy of parsefile->nextc */ 104MKINIT struct parsefile basepf; /* top level input file */ 105MKINIT char basebuf[BUFSIZ]; /* buffer for top level input file */ 106struct parsefile *parsefile = &basepf; /* current input file */ 107int init_editline = 0; /* editline library initialized? */ 108int whichprompt; /* 1 == PS1, 2 == PS2 */ 109 110STATIC void pushfile(void); 111static int preadfd(void); 112 113#ifdef mkinit 114INCLUDE <stdio.h> 115INCLUDE "input.h" 116INCLUDE "error.h" 117 118INIT { 119 basepf.nextc = basepf.buf = basebuf; 120} 121 122RESET { 123 if (exception != EXSHELLPROC) 124 parselleft = parsenleft = 0; /* clear input buffer */ 125 popallfiles(); 126} 127 128SHELLPROC { 129 popallfiles(); 130} 131#endif 132 133 134#if 0 /* this is unused */ 135/* 136 * Read a line from the script. 137 */ 138 139char * 140pfgets(char *line, int len) 141{ 142 char *p = line; 143 int nleft = len; 144 int c; 145 146 while (--nleft > 0) { 147 c = pgetc_macro(); 148 if (c == PEOF) { 149 if (p == line) 150 return NULL; 151 break; 152 } 153 *p++ = c; 154 if (c == '\n') 155 break; 156 } 157 *p = '\0'; 158 return line; 159} 160#endif 161 162 163/* 164 * Read a character from the script, returning PEOF on end of file. 165 * Nul characters in the input are silently discarded. 166 */ 167 168int 169pgetc(void) 170{ 171 int c; 172 173 c = pgetc_macro(); 174 if (c == PFAKE) 175 c = pgetc_macro(); 176 return c; 177} 178 179 180static int 181preadfd(void) 182{ 183 int nr; 184 char *buf = parsefile->buf; 185 parsenextc = buf; 186 187 retry: 188#ifndef SMALL 189 if (parsefile->fd == 0 && el) { 190 static const char *rl_cp; 191 static int el_len; 192 193 if (rl_cp == NULL) 194 rl_cp = el_gets(el, &el_len); 195 if (rl_cp == NULL) 196 nr = el_len == 0 ? 0 : -1; 197 else { 198 nr = el_len; 199 if (nr > BUFSIZ - 8) 200 nr = BUFSIZ - 8; 201 memcpy(buf, rl_cp, nr); 202 if (nr != el_len) { 203 el_len -= nr; 204 rl_cp += nr; 205 } else 206 rl_cp = 0; 207 } 208 209 } else 210#endif 211 nr = read(parsefile->fd, buf, BUFSIZ - 8); 212 213 214 if (nr <= 0) { 215 if (nr < 0) { 216 if (errno == EINTR) 217 goto retry; 218 if (parsefile->fd == 0 && errno == EWOULDBLOCK) { 219 int flags = fcntl(0, F_GETFL, 0); 220 221 if (flags >= 0 && flags & O_NONBLOCK) { 222 flags &=~ O_NONBLOCK; 223 if (fcntl(0, F_SETFL, flags) >= 0) { 224 out2str("sh: turning off NDELAY mode\n"); 225 goto retry; 226 } 227 } 228 } 229 } 230 nr = -1; 231 } 232 return nr; 233} 234 235/* 236 * Refill the input buffer and return the next input character: 237 * 238 * 1) If a string was pushed back on the input, pop it; 239 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading 240 * from a string so we can't refill the buffer, return EOF. 241 * 3) If the is more stuff in this buffer, use it else call read to fill it. 242 * 4) Process input up to the next newline, deleting nul characters. 243 */ 244 245int 246preadbuffer(void) 247{ 248 char *p, *q; 249 int more; 250#ifndef SMALL 251 int something; 252#endif 253 char savec; 254 255 while (parsefile->strpush) { 256 if (parsenleft == -1 && parsefile->strpush->ap != NULL) 257 return PFAKE; 258 popstring(); 259 if (--parsenleft >= 0) 260 return (*parsenextc++); 261 } 262 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) 263 return PEOF; 264 flushout(&output); 265 flushout(&errout); 266 267 again: 268 if (parselleft <= 0) { 269 if ((parselleft = preadfd()) == -1) { 270 parselleft = parsenleft = EOF_NLEFT; 271 return PEOF; 272 } 273 } 274 275 /* p = (not const char *)parsenextc; */ 276 p = parsefile->buf + (parsenextc - parsefile->buf); 277 q = p; 278 279 /* delete nul characters */ 280#ifndef SMALL 281 something = 0; 282#endif 283 for (more = 1; more;) { 284 switch (*p) { 285 case '\0': 286 p++; /* Skip nul */ 287 goto check; 288 289 case '\t': 290 case ' ': 291 break; 292 293 case '\n': 294 parsenleft = q - parsenextc; 295 more = 0; /* Stop processing here */ 296 break; 297 298 default: 299#ifndef SMALL 300 something = 1; 301#endif 302 break; 303 } 304 305 *q++ = *p++; 306 check: 307 if (--parselleft <= 0) { 308 parsenleft = q - parsenextc - 1; 309 if (parsenleft < 0) 310 goto again; 311 *q = '\0'; 312 more = 0; 313 } 314 } 315 316 savec = *q; 317 *q = '\0'; 318 319#ifndef SMALL 320 if (parsefile->fd == 0 && hist && (something || whichprompt == 2)) { 321 HistEvent he; 322 323 INTOFF; 324 history(hist, &he, whichprompt != 2 ? H_ENTER : H_APPEND, 325 parsenextc); 326 INTON; 327 } 328#endif 329 330 if (vflag) { 331 out2str(parsenextc); 332 flushout(out2); 333 } 334 335 *q = savec; 336 337 return *parsenextc++; 338} 339 340/* 341 * Test whether we have reached EOF on input stream. 342 * Return true only if certain (without attempting a read). 343 * 344 * Note the similarity to the opening section of preadbuffer() 345 */ 346int 347at_eof(void) 348{ 349 struct strpush *sp = parsefile->strpush; 350 351 if (parsenleft > 0) /* more chars are in the buffer */ 352 return 0; 353 354 while (sp != NULL) { 355 /* 356 * If any pushed string has any remaining data, 357 * then we are not at EOF (simulating popstring()) 358 */ 359 if (sp->prevnleft > 0) 360 return 0; 361 sp = sp->prev; 362 } 363 364 /* 365 * If we reached real EOF and pushed it back, 366 * or if we are just processing a string (not reading a file) 367 * then there is no more. Note that if a file pushes a 368 * string, the file's ->buf remains present. 369 */ 370 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) 371 return 1; 372 373 /* 374 * In other cases, there might be more 375 */ 376 return 0; 377} 378 379/* 380 * Undo the last call to pgetc. Only one character may be pushed back. 381 * PEOF may be pushed back. 382 */ 383 384void 385pungetc(void) 386{ 387 parsenleft++; 388 parsenextc--; 389} 390 391/* 392 * Push a string back onto the input at this current parsefile level. 393 * We handle aliases this way. 394 */ 395void 396pushstring(const char *s, int len, struct alias *ap) 397{ 398 struct strpush *sp; 399 400 VTRACE(DBG_INPUT, 401 ("pushstring(\"%.*s\", %d)%s%s%s had: nl=%d ll=%d \"%.*s\"\n", 402 len, s, len, ap ? " for alias:'" : "", 403 ap ? ap->name : "", ap ? "'" : "", 404 parsenleft, parselleft, parsenleft, parsenextc)); 405 406 INTOFF; 407 if (parsefile->strpush) { 408 sp = ckmalloc(sizeof (struct strpush)); 409 sp->prev = parsefile->strpush; 410 parsefile->strpush = sp; 411 } else 412 sp = parsefile->strpush = &(parsefile->basestrpush); 413 414 sp->prevstring = parsenextc; 415 sp->prevnleft = parsenleft; 416 sp->prevlleft = parselleft; 417 sp->ap = ap; 418 if (ap) 419 ap->flag |= ALIASINUSE; 420 parsenextc = s; 421 parsenleft = len; 422 INTON; 423} 424 425void 426popstring(void) 427{ 428 struct strpush *sp = parsefile->strpush; 429 430 INTOFF; 431 if (sp->ap) { 432 if (parsenextc != sp->ap->val && 433 (parsenextc[-1] == ' ' || parsenextc[-1] == '\t')) 434 checkkwd |= CHKALIAS; 435 sp->ap->flag &= ~ALIASINUSE; 436 } 437 parsenextc = sp->prevstring; 438 parsenleft = sp->prevnleft; 439 parselleft = sp->prevlleft; 440 441 VTRACE(DBG_INPUT, ("popstring()%s%s%s nl=%d ll=%d \"%.*s\"\n", 442 sp->ap ? " from alias:'" : "", sp->ap ? sp->ap->name : "", 443 sp->ap ? "'" : "", parsenleft, parselleft, parsenleft, parsenextc)); 444 445 parsefile->strpush = sp->prev; 446 if (sp != &(parsefile->basestrpush)) 447 ckfree(sp); 448 INTON; 449} 450 451/* 452 * Set the input to take input from a file. If push is set, push the 453 * old input onto the stack first. 454 */ 455 456void 457setinputfile(const char *fname, int push) 458{ 459 unsigned char magic[4]; 460 int fd; 461 int fd2; 462 struct stat sb; 463 464 CTRACE(DBG_INPUT,("setinputfile(\"%s\", %spush)\n",fname,push?"":"no")); 465 466 INTOFF; 467 if ((fd = open(fname, O_RDONLY)) < 0) 468 error("Can't open %s", fname); 469 470 /* Since the message "Syntax error: "(" unexpected" is not very 471 * helpful, we check if the file starts with the ELF magic to 472 * avoid that message. The first lseek tries to make sure that 473 * we can later rewind the file. 474 */ 475 if (fstat(fd, &sb) == 0 && S_ISREG(sb.st_mode) && 476 lseek(fd, 0, SEEK_SET) == 0) { 477 if (read(fd, magic, 4) == 4) { 478 if (memcmp(magic, "\177ELF", 4) == 0) { 479 (void)close(fd); 480 error("Cannot execute ELF binary %s", fname); 481 } 482 } 483 if (lseek(fd, 0, SEEK_SET) != 0) { 484 (void)close(fd); 485 error("Cannot rewind the file %s", fname); 486 } 487 } 488 489 fd2 = to_upper_fd(fd); /* closes fd, returns higher equiv */ 490 if (fd2 == fd) { 491 (void) close(fd); 492 error("Out of file descriptors"); 493 } 494 495 setinputfd(fd2, push); 496 INTON; 497} 498 499/* 500 * When a shell fd needs to be altered (when the user wants to use 501 * the same fd - rare, but happens - we need to locate the ref to 502 * the fd, and update it. This happens via a callback. 503 * This is the callback func for fd's used for shell input 504 */ 505static void 506input_fd_swap(int from, int to) 507{ 508 struct parsefile *pf; 509 510 pf = parsefile; 511 while (pf != NULL) { /* don't need to stop at basepf */ 512 if (pf->fd == from) 513 pf->fd = to; 514 pf = pf->prev; 515 } 516} 517 518/* 519 * Like setinputfile, but takes an open file descriptor. Call this with 520 * interrupts off. 521 */ 522 523void 524setinputfd(int fd, int push) 525{ 526 VTRACE(DBG_INPUT, ("setinputfd(%d, %spush)\n", fd, push?"":"no")); 527 528 register_sh_fd(fd, input_fd_swap); 529 (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 530 if (push) 531 pushfile(); 532 if (parsefile->fd > 0) 533 sh_close(parsefile->fd); 534 parsefile->fd = fd; 535 if (parsefile->buf == NULL) 536 parsefile->buf = ckmalloc(BUFSIZ); 537 parselleft = parsenleft = 0; 538 plinno = 1; 539 540 CTRACE(DBG_INPUT, ("setinputfd(%d, %spush) done; plinno=1\n", fd, 541 push ? "" : "no")); 542} 543 544 545/* 546 * Like setinputfile, but takes input from a string. 547 */ 548 549void 550setinputstring(char *string, int push, int line1) 551{ 552 553 INTOFF; 554 if (push) /* XXX: always, as it happens */ 555 pushfile(); 556 parsenextc = string; 557 parselleft = parsenleft = strlen(string); 558 plinno = line1; 559 560 CTRACE(DBG_INPUT, 561 ("setinputstring(\"%.20s%s\" (%d), %spush, @ %d)\n", string, 562 (parsenleft > 20 ? "..." : ""), parsenleft, push?"":"no", line1)); 563 INTON; 564} 565 566 567 568/* 569 * To handle the "." command, a stack of input files is used. Pushfile 570 * adds a new entry to the stack and popfile restores the previous level. 571 */ 572 573STATIC void 574pushfile(void) 575{ 576 struct parsefile *pf; 577 578 VTRACE(DBG_INPUT, 579 ("pushfile(): fd=%d buf=%p nl=%d ll=%d \"%.*s\" plinno=%d\n", 580 parsefile->fd, parsefile->buf, parsenleft, parselleft, 581 parsenleft, parsenextc, plinno)); 582 583 parsefile->nleft = parsenleft; 584 parsefile->lleft = parselleft; 585 parsefile->nextc = parsenextc; 586 parsefile->linno = plinno; 587 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); 588 pf->prev = parsefile; 589 pf->fd = -1; 590 pf->strpush = NULL; 591 pf->basestrpush.prev = NULL; 592 pf->buf = NULL; 593 parsefile = pf; 594} 595 596 597void 598popfile(void) 599{ 600 struct parsefile *pf = parsefile; 601 602 INTOFF; 603 if (pf->fd >= 0) 604 sh_close(pf->fd); 605 if (pf->buf) 606 ckfree(pf->buf); 607 while (pf->strpush) 608 popstring(); 609 parsefile = pf->prev; 610 ckfree(pf); 611 parsenleft = parsefile->nleft; 612 parselleft = parsefile->lleft; 613 parsenextc = parsefile->nextc; 614 615 VTRACE(DBG_INPUT, 616 ("popfile(): fd=%d buf=%p nl=%d ll=%d \"%.*s\" plinno:%d->%d\n", 617 parsefile->fd, parsefile->buf, parsenleft, parselleft, 618 parsenleft, parsenextc, plinno, parsefile->linno)); 619 620 plinno = parsefile->linno; 621 INTON; 622} 623 624/* 625 * Return current file (to go back to it later using popfilesupto()). 626 */ 627 628struct parsefile * 629getcurrentfile(void) 630{ 631 return parsefile; 632} 633 634 635/* 636 * Pop files until the given file is on top again. Useful for regular 637 * builtins that read shell commands from files or strings. 638 * If the given file is not an active file, an error is raised. 639 */ 640 641void 642popfilesupto(struct parsefile *file) 643{ 644 while (parsefile != file && parsefile != &basepf) 645 popfile(); 646 if (parsefile != file) 647 error("popfilesupto() misused"); 648} 649 650 651/* 652 * Return to top level. 653 */ 654 655void 656popallfiles(void) 657{ 658 while (parsefile != &basepf) 659 popfile(); 660} 661 662 663 664/* 665 * Close the file(s) that the shell is reading commands from. Called 666 * after a fork is done. 667 * 668 * Takes one arg, vfork, which tells it to not modify its global vars 669 * as it is still running in the parent. 670 * 671 * This code is (probably) unnecessary as the 'close on exec' flag is 672 * set and should be enough. In the vfork case it is definitely wrong 673 * to close the fds as another fork() may be done later to feed data 674 * from a 'here' document into a pipe and we don't want to close the 675 * pipe! 676 */ 677 678void 679closescript(int vforked) 680{ 681 if (vforked) 682 return; 683 popallfiles(); 684 if (parsefile->fd > 0) { 685 sh_close(parsefile->fd); 686 parsefile->fd = 0; 687 } 688} 689