input.c revision 199629
11558Srgrimes/*- 21558Srgrimes * Copyright (c) 1991, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * This code is derived from software contributed to Berkeley by 61558Srgrimes * Kenneth Almquist. 71558Srgrimes * 81558Srgrimes * Redistribution and use in source and binary forms, with or without 91558Srgrimes * modification, are permitted provided that the following conditions 101558Srgrimes * are met: 111558Srgrimes * 1. Redistributions of source code must retain the above copyright 121558Srgrimes * notice, this list of conditions and the following disclaimer. 131558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141558Srgrimes * notice, this list of conditions and the following disclaimer in the 151558Srgrimes * documentation and/or other materials provided with the distribution. 161558Srgrimes * 4. Neither the name of the University nor the names of its contributors 171558Srgrimes * may be used to endorse or promote products derived from this software 181558Srgrimes * without specific prior written permission. 191558Srgrimes * 201558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301558Srgrimes * SUCH DAMAGE. 311558Srgrimes */ 3226737Scharnier 3326737Scharnier#ifndef lint 341558Srgrimes#if 0 351558Srgrimesstatic char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95"; 361558Srgrimes#endif 371558Srgrimes#endif /* not lint */ 381558Srgrimes#include <sys/cdefs.h> 391558Srgrimes__FBSDID("$FreeBSD: head/bin/sh/input.c 199629 2009-11-21 14:28:32Z jilles $"); 401558Srgrimes 411558Srgrimes#include <stdio.h> /* defines BUFSIZ */ 421558Srgrimes#include <fcntl.h> 431558Srgrimes#include <errno.h> 441558Srgrimes#include <unistd.h> 451558Srgrimes#include <stdlib.h> 461558Srgrimes#include <string.h> 471558Srgrimes 481558Srgrimes/* 491558Srgrimes * This file implements the input routines used by the parser. 501558Srgrimes */ 511558Srgrimes 521558Srgrimes#include "shell.h" 531558Srgrimes#include "redir.h" 541558Srgrimes#include "syntax.h" 551558Srgrimes#include "input.h" 561558Srgrimes#include "output.h" 571558Srgrimes#include "options.h" 581558Srgrimes#include "memalloc.h" 591558Srgrimes#include "error.h" 6026737Scharnier#include "alias.h" 611558Srgrimes#include "parser.h" 621558Srgrimes#include "myhistedit.h" 631558Srgrimes#include "trap.h" 641558Srgrimes 651558Srgrimes#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ 661558Srgrimes 671558SrgrimesMKINIT 681558Srgrimesstruct strpush { 691558Srgrimes struct strpush *prev; /* preceding string on stack */ 701558Srgrimes char *prevstring; 711558Srgrimes int prevnleft; 721558Srgrimes int prevlleft; 731558Srgrimes struct alias *ap; /* if push was associated with an alias */ 741558Srgrimes}; 751558Srgrimes 761558Srgrimes/* 771558Srgrimes * The parsefile structure pointed to by the global variable parsefile 781558Srgrimes * contains information about the current file being read. 791558Srgrimes */ 801558Srgrimes 811558SrgrimesMKINIT 821558Srgrimesstruct parsefile { 831558Srgrimes struct parsefile *prev; /* preceding file on stack */ 841558Srgrimes int linno; /* current line */ 851558Srgrimes int fd; /* file descriptor (or -1 if string) */ 866443Sdg int nleft; /* number of chars left in this line */ 871558Srgrimes int lleft; /* number of lines left in this buffer */ 881558Srgrimes char *nextc; /* next char in buffer */ 891558Srgrimes char *buf; /* input buffer */ 901558Srgrimes struct strpush *strpush; /* for pushing strings at this level */ 911558Srgrimes struct strpush basestrpush; /* so pushing one is fast */ 921558Srgrimes}; 931558Srgrimes 941558Srgrimes 951558Srgrimesint plinno = 1; /* input line number */ 961558SrgrimesMKINIT int parsenleft; /* copy of parsefile->nleft */ 971558SrgrimesMKINIT int parselleft; /* copy of parsefile->lleft */ 981558Srgrimeschar *parsenextc; /* copy of parsefile->nextc */ 991558SrgrimesMKINIT struct parsefile basepf; /* top level input file */ 1001558Srgrimeschar basebuf[BUFSIZ]; /* buffer for top level input file */ 1011558SrgrimesSTATIC struct parsefile *parsefile = &basepf; /* current input file */ 1021558Srgrimesint init_editline = 0; /* editline library initialized? */ 1031558Srgrimesint whichprompt; /* 1 == PS1, 2 == PS2 */ 1041558Srgrimes 1051558SrgrimesEditLine *el; /* cookie for editline package */ 1061558Srgrimes 1071558SrgrimesSTATIC void pushfile(void); 1081558Srgrimesstatic int preadfd(void); 1091558Srgrimes 11026737Scharnier#ifdef mkinit 11126737ScharnierINCLUDE "input.h" 1121558SrgrimesINCLUDE "error.h" 1131558Srgrimes 1141558SrgrimesINIT { 11524359Simp extern char basebuf[]; 1161558Srgrimes 1171558Srgrimes basepf.nextc = basepf.buf = basebuf; 1181558Srgrimes} 1191558Srgrimes 1201558SrgrimesRESET { 1211558Srgrimes popallfiles(); 1221558Srgrimes if (exception != EXSHELLPROC) 1231558Srgrimes parselleft = parsenleft = 0; /* clear input buffer */ 1241558Srgrimes} 1251558Srgrimes 1261558SrgrimesSHELLPROC { 1271558Srgrimes popallfiles(); 1281558Srgrimes} 1291558Srgrimes#endif 1301558Srgrimes 1311558Srgrimes 1321558Srgrimes/* 1331558Srgrimes * Read a line from the script. 1341558Srgrimes */ 1351558Srgrimes 1361558Srgrimeschar * 1371558Srgrimespfgets(char *line, int len) 1381558Srgrimes{ 1391558Srgrimes char *p = line; 1401558Srgrimes int nleft = len; 1411558Srgrimes int c; 1421558Srgrimes 14326737Scharnier while (--nleft > 0) { 1441558Srgrimes c = pgetc_macro(); 1451558Srgrimes if (c == PEOF) { 1461558Srgrimes if (p == line) 1471558Srgrimes return NULL; 1481558Srgrimes break; 1491558Srgrimes } 1501558Srgrimes *p++ = c; 1511558Srgrimes if (c == '\n') 1521558Srgrimes break; 1531558Srgrimes } 1541558Srgrimes *p = '\0'; 1551558Srgrimes return line; 1561558Srgrimes} 1571558Srgrimes 1581558Srgrimes 1591558Srgrimes 1601558Srgrimes/* 1611558Srgrimes * Read a character from the script, returning PEOF on end of file. 1621558Srgrimes * Nul characters in the input are silently discarded. 1631558Srgrimes */ 1641558Srgrimes 1651558Srgrimesint 1661558Srgrimespgetc(void) 1671558Srgrimes{ 1681558Srgrimes return pgetc_macro(); 1691558Srgrimes} 1701558Srgrimes 1711558Srgrimes 1721558Srgrimesstatic int 1731558Srgrimespreadfd(void) 1741558Srgrimes{ 1751558Srgrimes int nr; 1761558Srgrimes parsenextc = parsefile->buf; 1771558Srgrimes 1781558Srgrimes#ifndef NO_HISTORY 1791558Srgrimes if (el != NULL && gotwinch) { 1801558Srgrimes gotwinch = 0; 1811558Srgrimes el_resize(el); 1821558Srgrimes } 1831558Srgrimes#endif 1841558Srgrimesretry: 1851558Srgrimes#ifndef NO_HISTORY 1861558Srgrimes if (parsefile->fd == 0 && el) { 1871558Srgrimes static const char *rl_cp; 1881558Srgrimes static int el_len; 1891558Srgrimes 1901558Srgrimes if (rl_cp == NULL) 1911558Srgrimes rl_cp = el_gets(el, &el_len); 1921558Srgrimes if (rl_cp == NULL) 1931558Srgrimes nr = 0; 19426737Scharnier else { 19526737Scharnier nr = el_len; 19626737Scharnier if (nr > BUFSIZ - 1) 19726737Scharnier nr = BUFSIZ - 1; 1981558Srgrimes memcpy(parsenextc, rl_cp, nr); 1991558Srgrimes if (nr != el_len) { 2001558Srgrimes el_len -= nr; 2011558Srgrimes rl_cp += nr; 2021558Srgrimes } else 2031558Srgrimes rl_cp = NULL; 2041558Srgrimes } 2051558Srgrimes } else 2061558Srgrimes#endif 2071558Srgrimes nr = read(parsefile->fd, parsenextc, BUFSIZ - 1); 2081558Srgrimes 2091558Srgrimes if (nr <= 0) { 2101558Srgrimes if (nr < 0) { 2111558Srgrimes if (errno == EINTR) 2121558Srgrimes goto retry; 2131558Srgrimes if (parsefile->fd == 0 && errno == EWOULDBLOCK) { 2141558Srgrimes int flags = fcntl(0, F_GETFL, 0); 2151558Srgrimes if (flags >= 0 && flags & O_NONBLOCK) { 2161558Srgrimes flags &=~ O_NONBLOCK; 2171558Srgrimes if (fcntl(0, F_SETFL, flags) >= 0) { 2181558Srgrimes out2fmt_flush("sh: turning off NDELAY mode\n"); 2191558Srgrimes goto retry; 2201558Srgrimes } 2211558Srgrimes } 2221558Srgrimes } 2231558Srgrimes } 2241558Srgrimes nr = -1; 2251558Srgrimes } 2261558Srgrimes return nr; 2271558Srgrimes} 2281558Srgrimes 2291558Srgrimes/* 2301558Srgrimes * Refill the input buffer and return the next input character: 2311558Srgrimes * 2321558Srgrimes * 1) If a string was pushed back on the input, pop it; 2331558Srgrimes * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading 2341558Srgrimes * from a string so we can't refill the buffer, return EOF. 2351558Srgrimes * 3) If there is more in this buffer, use it else call read to fill it. 2361558Srgrimes * 4) Process input up to the next newline, deleting nul characters. 2371558Srgrimes */ 2381558Srgrimes 2391558Srgrimesint 2401558Srgrimespreadbuffer(void) 2411558Srgrimes{ 2421558Srgrimes char *p, *q; 2431558Srgrimes int more; 2441558Srgrimes int something; 2451558Srgrimes char savec; 2461558Srgrimes 2471558Srgrimes if (parsefile->strpush) { 2481558Srgrimes popstring(); 2491558Srgrimes if (--parsenleft >= 0) 2501558Srgrimes return (*parsenextc++); 2511558Srgrimes } 2521558Srgrimes if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) 2531558Srgrimes return PEOF; 2541558Srgrimes flushout(&output); 2551558Srgrimes flushout(&errout); 2561558Srgrimes 2571558Srgrimesagain: 2581558Srgrimes if (parselleft <= 0) { 2591558Srgrimes if ((parselleft = preadfd()) == -1) { 2601558Srgrimes parselleft = parsenleft = EOF_NLEFT; 2611558Srgrimes return PEOF; 2621558Srgrimes } 2631558Srgrimes } 2641558Srgrimes 2651558Srgrimes q = p = parsenextc; 2661558Srgrimes 2671558Srgrimes /* delete nul characters */ 2681558Srgrimes something = 0; 2691558Srgrimes for (more = 1; more;) { 2701558Srgrimes switch (*p) { 2711558Srgrimes case '\0': 2721558Srgrimes p++; /* Skip nul */ 2731558Srgrimes goto check; 2741558Srgrimes 2751558Srgrimes case '\t': 2761558Srgrimes case ' ': 2771558Srgrimes break; 2781558Srgrimes 2791558Srgrimes case '\n': 2801558Srgrimes parsenleft = q - parsenextc; 2811558Srgrimes more = 0; /* Stop processing here */ 2821558Srgrimes break; 2831558Srgrimes 2841558Srgrimes default: 2851558Srgrimes something = 1; 2861558Srgrimes break; 2871558Srgrimes } 2881558Srgrimes 2891558Srgrimes *q++ = *p++; 2901558Srgrimescheck: 2911558Srgrimes if (--parselleft <= 0) { 2921558Srgrimes parsenleft = q - parsenextc - 1; 2931558Srgrimes if (parsenleft < 0) 2941558Srgrimes goto again; 2951558Srgrimes *q = '\0'; 2961558Srgrimes more = 0; 2971558Srgrimes } 2981558Srgrimes } 2991558Srgrimes 3001558Srgrimes savec = *q; 3011558Srgrimes *q = '\0'; 3021558Srgrimes 3031558Srgrimes#ifndef NO_HISTORY 3041558Srgrimes if (parsefile->fd == 0 && hist && something) { 3051558Srgrimes HistEvent he; 3061558Srgrimes INTOFF; 3071558Srgrimes history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD, 3081558Srgrimes parsenextc); 3091558Srgrimes INTON; 3101558Srgrimes } 3111558Srgrimes#endif 3121558Srgrimes 3131558Srgrimes if (vflag) { 3141558Srgrimes out2str(parsenextc); 3151558Srgrimes flushout(out2); 3161558Srgrimes } 3174844Sats 3181558Srgrimes *q = savec; 3191558Srgrimes 3201558Srgrimes return *parsenextc++; 3211558Srgrimes} 3221558Srgrimes 3231558Srgrimes/* 3241558Srgrimes * Returns if we are certain we are at EOF. Does not cause any more input 3251558Srgrimes * to be read from the outside world. 3261558Srgrimes */ 3271558Srgrimes 3281558Srgrimesint 3291558Srgrimespreadateof(void) 3301558Srgrimes{ 3311558Srgrimes if (parsenleft > 0) 3321558Srgrimes return 0; 3331558Srgrimes if (parsefile->strpush) 3341558Srgrimes return 0; 3351558Srgrimes if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) 3361558Srgrimes return 1; 3371558Srgrimes return 0; 3381558Srgrimes} 3391558Srgrimes 3401558Srgrimes/* 3411558Srgrimes * Undo the last call to pgetc. Only one character may be pushed back. 3421558Srgrimes * PEOF may be pushed back. 3431558Srgrimes */ 3441558Srgrimes 3451558Srgrimesvoid 3461558Srgrimespungetc(void) 3471558Srgrimes{ 3481558Srgrimes parsenleft++; 3491558Srgrimes parsenextc--; 3501558Srgrimes} 3511558Srgrimes 3521558Srgrimes/* 3531558Srgrimes * Push a string back onto the input at this current parsefile level. 3541558Srgrimes * We handle aliases this way. 3551558Srgrimes */ 3561558Srgrimesvoid 3571558Srgrimespushstring(char *s, int len, void *ap) 3581558Srgrimes{ 3591558Srgrimes struct strpush *sp; 3601558Srgrimes 3611558Srgrimes INTOFF; 3621558Srgrimes/*out2fmt_flush("*** calling pushstring: %s, %d\n", s, len);*/ 3631558Srgrimes if (parsefile->strpush) { 3641558Srgrimes sp = ckmalloc(sizeof (struct strpush)); 3651558Srgrimes sp->prev = parsefile->strpush; 3661558Srgrimes parsefile->strpush = sp; 3671558Srgrimes } else 3681558Srgrimes sp = parsefile->strpush = &(parsefile->basestrpush); 3691558Srgrimes sp->prevstring = parsenextc; 3701558Srgrimes sp->prevnleft = parsenleft; 3711558Srgrimes sp->prevlleft = parselleft; 3721558Srgrimes sp->ap = (struct alias *)ap; 3731558Srgrimes if (ap) 3741558Srgrimes ((struct alias *)ap)->flag |= ALIASINUSE; 3751558Srgrimes parsenextc = s; 3761558Srgrimes parsenleft = len; 3771558Srgrimes INTON; 3781558Srgrimes} 3791558Srgrimes 3801558Srgrimesvoid 3811558Srgrimespopstring(void) 3821558Srgrimes{ 3831558Srgrimes struct strpush *sp = parsefile->strpush; 3841558Srgrimes 3851558Srgrimes INTOFF; 3861558Srgrimes parsenextc = sp->prevstring; 3871558Srgrimes parsenleft = sp->prevnleft; 3881558Srgrimes parselleft = sp->prevlleft; 3891558Srgrimes/*out2fmt_flush("*** calling popstring: restoring to '%s'\n", parsenextc);*/ 3901558Srgrimes if (sp->ap) 3911558Srgrimes sp->ap->flag &= ~ALIASINUSE; 3921558Srgrimes parsefile->strpush = sp->prev; 3931558Srgrimes if (sp != &(parsefile->basestrpush)) 3941558Srgrimes ckfree(sp); 3951558Srgrimes INTON; 3961558Srgrimes} 3971558Srgrimes 3981558Srgrimes/* 3991558Srgrimes * Set the input to take input from a file. If push is set, push the 4001558Srgrimes * old input onto the stack first. 4011558Srgrimes */ 4021558Srgrimes 4031558Srgrimesvoid 4041558Srgrimessetinputfile(char *fname, int push) 40526737Scharnier{ 40626737Scharnier int fd; 4071558Srgrimes int fd2; 4081558Srgrimes 4091558Srgrimes INTOFF; 4101558Srgrimes if ((fd = open(fname, O_RDONLY)) < 0) 4111558Srgrimes error("Can't open %s: %s", fname, strerror(errno)); 4121558Srgrimes if (fd < 10) { 4131558Srgrimes fd2 = fcntl(fd, F_DUPFD, 10); 4141558Srgrimes close(fd); 4151558Srgrimes if (fd2 < 0) 4161558Srgrimes error("Out of file descriptors"); 4171558Srgrimes fd = fd2; 4181558Srgrimes } 4191558Srgrimes setinputfd(fd, push); 4201558Srgrimes INTON; 4211558Srgrimes} 4221558Srgrimes 4231558Srgrimes 4241558Srgrimes/* 4251558Srgrimes * Like setinputfile, but takes an open file descriptor. Call this with 4261558Srgrimes * interrupts off. 4271558Srgrimes */ 4281558Srgrimes 4291558Srgrimesvoid 4301558Srgrimessetinputfd(int fd, int push) 4311558Srgrimes{ 4321558Srgrimes (void)fcntl(fd, F_SETFD, FD_CLOEXEC); 4331558Srgrimes if (push) { 4341558Srgrimes pushfile(); 4351558Srgrimes parsefile->buf = ckmalloc(BUFSIZ); 4361558Srgrimes } 4371558Srgrimes if (parsefile->fd > 0) 4381558Srgrimes close(parsefile->fd); 4391558Srgrimes parsefile->fd = fd; 4401558Srgrimes if (parsefile->buf == NULL) 4411558Srgrimes parsefile->buf = ckmalloc(BUFSIZ); 4421558Srgrimes parselleft = parsenleft = 0; 4431558Srgrimes plinno = 1; 4441558Srgrimes} 4451558Srgrimes 4461558Srgrimes 44726737Scharnier/* 4481558Srgrimes * Like setinputfile, but takes input from a string. 4491558Srgrimes */ 4501558Srgrimes 4511558Srgrimesvoid 4521558Srgrimessetinputstring(char *string, int push) 4536443Sdg{ 4541558Srgrimes INTOFF; 4551558Srgrimes if (push) 456 pushfile(); 457 parsenextc = string; 458 parselleft = parsenleft = strlen(string); 459 parsefile->buf = NULL; 460 plinno = 1; 461 INTON; 462} 463 464 465 466/* 467 * To handle the "." command, a stack of input files is used. Pushfile 468 * adds a new entry to the stack and popfile restores the previous level. 469 */ 470 471STATIC void 472pushfile(void) 473{ 474 struct parsefile *pf; 475 476 parsefile->nleft = parsenleft; 477 parsefile->lleft = parselleft; 478 parsefile->nextc = parsenextc; 479 parsefile->linno = plinno; 480 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); 481 pf->prev = parsefile; 482 pf->fd = -1; 483 pf->strpush = NULL; 484 pf->basestrpush.prev = NULL; 485 parsefile = pf; 486} 487 488 489void 490popfile(void) 491{ 492 struct parsefile *pf = parsefile; 493 494 INTOFF; 495 if (pf->fd >= 0) 496 close(pf->fd); 497 if (pf->buf) 498 ckfree(pf->buf); 499 while (pf->strpush) 500 popstring(); 501 parsefile = pf->prev; 502 ckfree(pf); 503 parsenleft = parsefile->nleft; 504 parselleft = parsefile->lleft; 505 parsenextc = parsefile->nextc; 506 plinno = parsefile->linno; 507 INTON; 508} 509 510 511/* 512 * Return to top level. 513 */ 514 515void 516popallfiles(void) 517{ 518 while (parsefile != &basepf) 519 popfile(); 520} 521 522 523 524/* 525 * Close the file(s) that the shell is reading commands from. Called 526 * after a fork is done. 527 */ 528 529void 530closescript(void) 531{ 532 popallfiles(); 533 if (parsefile->fd > 0) { 534 close(parsefile->fd); 535 parsefile->fd = 0; 536 } 537} 538