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