input.c revision 200956
11556Srgrimes/*- 21556Srgrimes * Copyright (c) 1991, 1993 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * 51556Srgrimes * This code is derived from software contributed to Berkeley by 61556Srgrimes * Kenneth Almquist. 71556Srgrimes * 81556Srgrimes * Redistribution and use in source and binary forms, with or without 91556Srgrimes * modification, are permitted provided that the following conditions 101556Srgrimes * are met: 111556Srgrimes * 1. Redistributions of source code must retain the above copyright 121556Srgrimes * notice, this list of conditions and the following disclaimer. 131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141556Srgrimes * notice, this list of conditions and the following disclaimer in the 151556Srgrimes * documentation and/or other materials provided with the distribution. 161556Srgrimes * 4. Neither the name of the University nor the names of its contributors 171556Srgrimes * may be used to endorse or promote products derived from this software 181556Srgrimes * without specific prior written permission. 191556Srgrimes * 201556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301556Srgrimes * SUCH DAMAGE. 311556Srgrimes */ 321556Srgrimes 331556Srgrimes#ifndef lint 3436150Scharnier#if 0 3536150Scharnierstatic char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95"; 3636150Scharnier#endif 371556Srgrimes#endif /* not lint */ 3899110Sobrien#include <sys/cdefs.h> 3999110Sobrien__FBSDID("$FreeBSD: head/bin/sh/input.c 200956 2009-12-24 18:41:14Z jilles $"); 401556Srgrimes 4117987Speter#include <stdio.h> /* defines BUFSIZ */ 4217987Speter#include <fcntl.h> 4317987Speter#include <errno.h> 4417987Speter#include <unistd.h> 4517987Speter#include <stdlib.h> 4617987Speter#include <string.h> 4717987Speter 481556Srgrimes/* 491556Srgrimes * This file implements the input routines used by the parser. 501556Srgrimes */ 511556Srgrimes 521556Srgrimes#include "shell.h" 5317987Speter#include "redir.h" 541556Srgrimes#include "syntax.h" 551556Srgrimes#include "input.h" 561556Srgrimes#include "output.h" 571556Srgrimes#include "options.h" 581556Srgrimes#include "memalloc.h" 591556Srgrimes#include "error.h" 601556Srgrimes#include "alias.h" 611556Srgrimes#include "parser.h" 621556Srgrimes#include "myhistedit.h" 63100588Stjr#include "trap.h" 641556Srgrimes 651556Srgrimes#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ 661556Srgrimes 671556SrgrimesMKINIT 681556Srgrimesstruct strpush { 691556Srgrimes struct strpush *prev; /* preceding string on stack */ 701556Srgrimes char *prevstring; 711556Srgrimes int prevnleft; 7212043Speter int prevlleft; 731556Srgrimes struct alias *ap; /* if push was associated with an alias */ 741556Srgrimes}; 751556Srgrimes 761556Srgrimes/* 771556Srgrimes * The parsefile structure pointed to by the global variable parsefile 781556Srgrimes * contains information about the current file being read. 791556Srgrimes */ 801556Srgrimes 811556SrgrimesMKINIT 821556Srgrimesstruct parsefile { 831556Srgrimes struct parsefile *prev; /* preceding file on stack */ 841556Srgrimes int linno; /* current line */ 851556Srgrimes int fd; /* file descriptor (or -1 if string) */ 8620425Ssteve int nleft; /* number of chars left in this line */ 8720425Ssteve int lleft; /* number of lines left in this buffer */ 881556Srgrimes char *nextc; /* next char in buffer */ 891556Srgrimes char *buf; /* input buffer */ 901556Srgrimes struct strpush *strpush; /* for pushing strings at this level */ 911556Srgrimes struct strpush basestrpush; /* so pushing one is fast */ 921556Srgrimes}; 931556Srgrimes 941556Srgrimes 951556Srgrimesint plinno = 1; /* input line number */ 961556SrgrimesMKINIT int parsenleft; /* copy of parsefile->nleft */ 9712043SpeterMKINIT int parselleft; /* copy of parsefile->lleft */ 981556Srgrimeschar *parsenextc; /* copy of parsefile->nextc */ 991556SrgrimesMKINIT struct parsefile basepf; /* top level input file */ 1001556Srgrimeschar basebuf[BUFSIZ]; /* buffer for top level input file */ 101117261SddsSTATIC struct parsefile *parsefile = &basepf; /* current input file */ 1021556Srgrimesint init_editline = 0; /* editline library initialized? */ 1031556Srgrimesint whichprompt; /* 1 == PS1, 2 == PS2 */ 1041556Srgrimes 1051556SrgrimesEditLine *el; /* cookie for editline package */ 1061556Srgrimes 10790111SimpSTATIC void pushfile(void); 10890111Simpstatic int preadfd(void); 1091556Srgrimes 1101556Srgrimes#ifdef mkinit 1111556SrgrimesINCLUDE "input.h" 1121556SrgrimesINCLUDE "error.h" 1131556Srgrimes 1141556SrgrimesINIT { 1151556Srgrimes extern char basebuf[]; 1161556Srgrimes 1171556Srgrimes basepf.nextc = basepf.buf = basebuf; 1181556Srgrimes} 1191556Srgrimes 1201556SrgrimesRESET { 121194406Sjilles popallfiles(); 1221556Srgrimes if (exception != EXSHELLPROC) 12312043Speter parselleft = parsenleft = 0; /* clear input buffer */ 1241556Srgrimes} 1251556Srgrimes 1261556SrgrimesSHELLPROC { 1271556Srgrimes popallfiles(); 1281556Srgrimes} 1291556Srgrimes#endif 1301556Srgrimes 1311556Srgrimes 1321556Srgrimes/* 1331556Srgrimes * Read a line from the script. 1341556Srgrimes */ 1351556Srgrimes 1361556Srgrimeschar * 13790111Simppfgets(char *line, int len) 13817987Speter{ 13925225Ssteve char *p = line; 1401556Srgrimes int nleft = len; 1411556Srgrimes int c; 1421556Srgrimes 1431556Srgrimes while (--nleft > 0) { 1441556Srgrimes c = pgetc_macro(); 1451556Srgrimes if (c == PEOF) { 1461556Srgrimes if (p == line) 1471556Srgrimes return NULL; 1481556Srgrimes break; 1491556Srgrimes } 1501556Srgrimes *p++ = c; 1511556Srgrimes if (c == '\n') 1521556Srgrimes break; 1531556Srgrimes } 1541556Srgrimes *p = '\0'; 1551556Srgrimes return line; 1561556Srgrimes} 1571556Srgrimes 1581556Srgrimes 1591556Srgrimes 1601556Srgrimes/* 1611556Srgrimes * Read a character from the script, returning PEOF on end of file. 1621556Srgrimes * Nul characters in the input are silently discarded. 1631556Srgrimes */ 1641556Srgrimes 1651556Srgrimesint 16690111Simppgetc(void) 16720425Ssteve{ 1681556Srgrimes return pgetc_macro(); 1691556Srgrimes} 1701556Srgrimes 17120425Ssteve 17212043Speterstatic int 17390111Simppreadfd(void) 17412043Speter{ 17512043Speter int nr; 17620425Ssteve parsenextc = parsefile->buf; 1771556Srgrimes 178100588Stjr#ifndef NO_HISTORY 179100588Stjr if (el != NULL && gotwinch) { 180100588Stjr gotwinch = 0; 181100588Stjr el_resize(el); 182100588Stjr } 183100588Stjr#endif 18412043Speterretry: 18525225Ssteve#ifndef NO_HISTORY 18612043Speter if (parsefile->fd == 0 && el) { 187158143Sstefanf static const char *rl_cp; 188158143Sstefanf static int el_len; 18912043Speter 19012043Speter if (rl_cp == NULL) 191158143Sstefanf rl_cp = el_gets(el, &el_len); 192158143Sstefanf if (rl_cp == NULL) 19312043Speter nr = 0; 19412043Speter else { 195158143Sstefanf nr = el_len; 196158143Sstefanf if (nr > BUFSIZ - 1) 197158143Sstefanf nr = BUFSIZ - 1; 198158143Sstefanf memcpy(parsenextc, rl_cp, nr); 199158143Sstefanf if (nr != el_len) { 200158143Sstefanf el_len -= nr; 201158143Sstefanf rl_cp += nr; 202158143Sstefanf } else 203158143Sstefanf rl_cp = NULL; 20412043Speter } 20525225Ssteve } else 20625225Ssteve#endif 20712043Speter nr = read(parsefile->fd, parsenextc, BUFSIZ - 1); 20812043Speter 20912043Speter if (nr <= 0) { 21012043Speter if (nr < 0) { 21112043Speter if (errno == EINTR) 21212043Speter goto retry; 21312043Speter if (parsefile->fd == 0 && errno == EWOULDBLOCK) { 21412043Speter int flags = fcntl(0, F_GETFL, 0); 21512043Speter if (flags >= 0 && flags & O_NONBLOCK) { 21612043Speter flags &=~ O_NONBLOCK; 21712043Speter if (fcntl(0, F_SETFL, flags) >= 0) { 218199629Sjilles out2fmt_flush("sh: turning off NDELAY mode\n"); 21912043Speter goto retry; 22012043Speter } 22112043Speter } 22212043Speter } 22312043Speter } 22420425Ssteve nr = -1; 22512043Speter } 22612043Speter return nr; 22712043Speter} 22812043Speter 2291556Srgrimes/* 2301556Srgrimes * Refill the input buffer and return the next input character: 2311556Srgrimes * 2321556Srgrimes * 1) If a string was pushed back on the input, pop it; 2331556Srgrimes * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading 2341556Srgrimes * from a string so we can't refill the buffer, return EOF. 23520425Ssteve * 3) If there is more in this buffer, use it else call read to fill it. 23620425Ssteve * 4) Process input up to the next newline, deleting nul characters. 2371556Srgrimes */ 2381556Srgrimes 2391556Srgrimesint 24090111Simppreadbuffer(void) 24120425Ssteve{ 24212043Speter char *p, *q; 24312043Speter int more; 24412043Speter int something; 24512043Speter char savec; 2461556Srgrimes 2471556Srgrimes if (parsefile->strpush) { 2481556Srgrimes popstring(); 2491556Srgrimes if (--parsenleft >= 0) 2501556Srgrimes return (*parsenextc++); 2511556Srgrimes } 2521556Srgrimes if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) 2531556Srgrimes return PEOF; 2541556Srgrimes flushout(&output); 2551556Srgrimes flushout(&errout); 2561556Srgrimes 25712043Speteragain: 25812043Speter if (parselleft <= 0) { 25925225Ssteve if ((parselleft = preadfd()) == -1) { 26012043Speter parselleft = parsenleft = EOF_NLEFT; 26112043Speter return PEOF; 2621556Srgrimes } 2631556Srgrimes } 2641556Srgrimes 26512043Speter q = p = parsenextc; 26612043Speter 2671556Srgrimes /* delete nul characters */ 2681556Srgrimes something = 0; 26912043Speter for (more = 1; more;) { 27012043Speter switch (*p) { 27112043Speter case '\0': 27212043Speter p++; /* Skip nul */ 27312043Speter goto check; 27412043Speter 27512043Speter case '\t': 27612043Speter case ' ': 2771556Srgrimes break; 27812043Speter 27912043Speter case '\n': 28012043Speter parsenleft = q - parsenextc; 28112043Speter more = 0; /* Stop processing here */ 28212043Speter break; 28312043Speter 28412043Speter default: 2851556Srgrimes something = 1; 28612043Speter break; 2871556Srgrimes } 28812043Speter 28912043Speter *q++ = *p++; 29012043Spetercheck: 29112043Speter if (--parselleft <= 0) { 29212043Speter parsenleft = q - parsenextc - 1; 29312043Speter if (parsenleft < 0) 29412043Speter goto again; 29512043Speter *q = '\0'; 29612043Speter more = 0; 29712043Speter } 2981556Srgrimes } 29912043Speter 30012043Speter savec = *q; 3011556Srgrimes *q = '\0'; 3021556Srgrimes 30318018Speter#ifndef NO_HISTORY 3041556Srgrimes if (parsefile->fd == 0 && hist && something) { 30584261Sobrien HistEvent he; 3061556Srgrimes INTOFF; 30784261Sobrien history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD, 30884261Sobrien parsenextc); 3091556Srgrimes INTON; 3101556Srgrimes } 31118018Speter#endif 31212043Speter 3131556Srgrimes if (vflag) { 31412043Speter out2str(parsenextc); 3151556Srgrimes flushout(out2); 3161556Srgrimes } 31712043Speter 31812043Speter *q = savec; 31912043Speter 3201556Srgrimes return *parsenextc++; 3211556Srgrimes} 3221556Srgrimes 3231556Srgrimes/* 324194128Sjilles * Returns if we are certain we are at EOF. Does not cause any more input 325194128Sjilles * to be read from the outside world. 326194128Sjilles */ 327194128Sjilles 328194128Sjillesint 329194128Sjillespreadateof(void) 330194128Sjilles{ 331194128Sjilles if (parsenleft > 0) 332194128Sjilles return 0; 333194128Sjilles if (parsefile->strpush) 334194128Sjilles return 0; 335194128Sjilles if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) 336194128Sjilles return 1; 337194128Sjilles return 0; 338194128Sjilles} 339194128Sjilles 340194128Sjilles/* 3411556Srgrimes * Undo the last call to pgetc. Only one character may be pushed back. 3421556Srgrimes * PEOF may be pushed back. 3431556Srgrimes */ 3441556Srgrimes 3451556Srgrimesvoid 34690111Simppungetc(void) 34790111Simp{ 3481556Srgrimes parsenleft++; 3491556Srgrimes parsenextc--; 3501556Srgrimes} 3511556Srgrimes 3521556Srgrimes/* 3531556Srgrimes * Push a string back onto the input at this current parsefile level. 3541556Srgrimes * We handle aliases this way. 3551556Srgrimes */ 3561556Srgrimesvoid 35790111Simppushstring(char *s, int len, void *ap) 35890111Simp{ 3591556Srgrimes struct strpush *sp; 3601556Srgrimes 3611556Srgrimes INTOFF; 362199629Sjilles/*out2fmt_flush("*** calling pushstring: %s, %d\n", s, len);*/ 3631556Srgrimes if (parsefile->strpush) { 3641556Srgrimes sp = ckmalloc(sizeof (struct strpush)); 3651556Srgrimes sp->prev = parsefile->strpush; 3661556Srgrimes parsefile->strpush = sp; 3671556Srgrimes } else 3681556Srgrimes sp = parsefile->strpush = &(parsefile->basestrpush); 3691556Srgrimes sp->prevstring = parsenextc; 3701556Srgrimes sp->prevnleft = parsenleft; 37112043Speter sp->prevlleft = parselleft; 3721556Srgrimes sp->ap = (struct alias *)ap; 3731556Srgrimes if (ap) 3741556Srgrimes ((struct alias *)ap)->flag |= ALIASINUSE; 3751556Srgrimes parsenextc = s; 3761556Srgrimes parsenleft = len; 3771556Srgrimes INTON; 3781556Srgrimes} 3791556Srgrimes 38017987Spetervoid 38190111Simppopstring(void) 3821556Srgrimes{ 3831556Srgrimes struct strpush *sp = parsefile->strpush; 3841556Srgrimes 3851556Srgrimes INTOFF; 3861556Srgrimes parsenextc = sp->prevstring; 3871556Srgrimes parsenleft = sp->prevnleft; 38812043Speter parselleft = sp->prevlleft; 389199629Sjilles/*out2fmt_flush("*** calling popstring: restoring to '%s'\n", parsenextc);*/ 3901556Srgrimes if (sp->ap) 3911556Srgrimes sp->ap->flag &= ~ALIASINUSE; 3921556Srgrimes parsefile->strpush = sp->prev; 3931556Srgrimes if (sp != &(parsefile->basestrpush)) 3941556Srgrimes ckfree(sp); 3951556Srgrimes INTON; 3961556Srgrimes} 3971556Srgrimes 3981556Srgrimes/* 3991556Srgrimes * Set the input to take input from a file. If push is set, push the 4001556Srgrimes * old input onto the stack first. 4011556Srgrimes */ 4021556Srgrimes 4031556Srgrimesvoid 404200956Sjillessetinputfile(const char *fname, int push) 40517987Speter{ 4061556Srgrimes int fd; 4071556Srgrimes int fd2; 4081556Srgrimes 4091556Srgrimes INTOFF; 4101556Srgrimes if ((fd = open(fname, O_RDONLY)) < 0) 41153891Scracauer error("Can't open %s: %s", fname, strerror(errno)); 4121556Srgrimes if (fd < 10) { 413124780Sdes fd2 = fcntl(fd, F_DUPFD, 10); 4141556Srgrimes close(fd); 4151556Srgrimes if (fd2 < 0) 4161556Srgrimes error("Out of file descriptors"); 4171556Srgrimes fd = fd2; 4181556Srgrimes } 4191556Srgrimes setinputfd(fd, push); 4201556Srgrimes INTON; 4211556Srgrimes} 4221556Srgrimes 4231556Srgrimes 4241556Srgrimes/* 4251556Srgrimes * Like setinputfile, but takes an open file descriptor. Call this with 4261556Srgrimes * interrupts off. 4271556Srgrimes */ 4281556Srgrimes 4291556Srgrimesvoid 43090111Simpsetinputfd(int fd, int push) 43117987Speter{ 43225225Ssteve (void)fcntl(fd, F_SETFD, FD_CLOEXEC); 4331556Srgrimes if (push) { 4341556Srgrimes pushfile(); 4351556Srgrimes parsefile->buf = ckmalloc(BUFSIZ); 4361556Srgrimes } 4371556Srgrimes if (parsefile->fd > 0) 4381556Srgrimes close(parsefile->fd); 4391556Srgrimes parsefile->fd = fd; 4401556Srgrimes if (parsefile->buf == NULL) 4411556Srgrimes parsefile->buf = ckmalloc(BUFSIZ); 44212043Speter parselleft = parsenleft = 0; 4431556Srgrimes plinno = 1; 4441556Srgrimes} 4451556Srgrimes 4461556Srgrimes 4471556Srgrimes/* 4481556Srgrimes * Like setinputfile, but takes input from a string. 4491556Srgrimes */ 4501556Srgrimes 4511556Srgrimesvoid 45290111Simpsetinputstring(char *string, int push) 45390111Simp{ 4541556Srgrimes INTOFF; 4551556Srgrimes if (push) 4561556Srgrimes pushfile(); 4571556Srgrimes parsenextc = string; 45812043Speter parselleft = parsenleft = strlen(string); 4591556Srgrimes parsefile->buf = NULL; 4601556Srgrimes plinno = 1; 4611556Srgrimes INTON; 4621556Srgrimes} 4631556Srgrimes 4641556Srgrimes 4651556Srgrimes 4661556Srgrimes/* 4671556Srgrimes * To handle the "." command, a stack of input files is used. Pushfile 4681556Srgrimes * adds a new entry to the stack and popfile restores the previous level. 4691556Srgrimes */ 4701556Srgrimes 4711556SrgrimesSTATIC void 47290111Simppushfile(void) 47390111Simp{ 4741556Srgrimes struct parsefile *pf; 4751556Srgrimes 4761556Srgrimes parsefile->nleft = parsenleft; 47712043Speter parsefile->lleft = parselleft; 4781556Srgrimes parsefile->nextc = parsenextc; 4791556Srgrimes parsefile->linno = plinno; 4801556Srgrimes pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); 4811556Srgrimes pf->prev = parsefile; 4821556Srgrimes pf->fd = -1; 4831556Srgrimes pf->strpush = NULL; 4841556Srgrimes pf->basestrpush.prev = NULL; 4851556Srgrimes parsefile = pf; 4861556Srgrimes} 4871556Srgrimes 4881556Srgrimes 4891556Srgrimesvoid 49090111Simppopfile(void) 49190111Simp{ 4921556Srgrimes struct parsefile *pf = parsefile; 4931556Srgrimes 4941556Srgrimes INTOFF; 4951556Srgrimes if (pf->fd >= 0) 4961556Srgrimes close(pf->fd); 4971556Srgrimes if (pf->buf) 4981556Srgrimes ckfree(pf->buf); 4991556Srgrimes while (pf->strpush) 5001556Srgrimes popstring(); 5011556Srgrimes parsefile = pf->prev; 5021556Srgrimes ckfree(pf); 5031556Srgrimes parsenleft = parsefile->nleft; 50412043Speter parselleft = parsefile->lleft; 5051556Srgrimes parsenextc = parsefile->nextc; 5061556Srgrimes plinno = parsefile->linno; 5071556Srgrimes INTON; 5081556Srgrimes} 5091556Srgrimes 5101556Srgrimes 5111556Srgrimes/* 512199647Sjilles * Return current file (to go back to it later using popfilesupto()). 513199647Sjilles */ 514199647Sjilles 515199647Sjillesstruct parsefile * 516199647Sjillesgetcurrentfile(void) 517199647Sjilles{ 518199647Sjilles return parsefile; 519199647Sjilles} 520199647Sjilles 521199647Sjilles 522199647Sjilles/* 523199647Sjilles * Pop files until the given file is on top again. Useful for regular 524199647Sjilles * builtins that read shell commands from files or strings. 525199647Sjilles * If the given file is not an active file, an error is raised. 526199647Sjilles */ 527199647Sjilles 528199647Sjillesvoid 529199647Sjillespopfilesupto(struct parsefile *file) 530199647Sjilles{ 531199647Sjilles while (parsefile != file && parsefile != &basepf) 532199647Sjilles popfile(); 533199647Sjilles if (parsefile != file) 534199647Sjilles error("popfilesupto() misused"); 535199647Sjilles} 536199647Sjilles 537199647Sjilles/* 5381556Srgrimes * Return to top level. 5391556Srgrimes */ 5401556Srgrimes 5411556Srgrimesvoid 54290111Simppopallfiles(void) 54390111Simp{ 5441556Srgrimes while (parsefile != &basepf) 5451556Srgrimes popfile(); 5461556Srgrimes} 5471556Srgrimes 5481556Srgrimes 5491556Srgrimes 5501556Srgrimes/* 5511556Srgrimes * Close the file(s) that the shell is reading commands from. Called 5521556Srgrimes * after a fork is done. 5531556Srgrimes */ 5541556Srgrimes 5551556Srgrimesvoid 55690111Simpclosescript(void) 55790111Simp{ 5581556Srgrimes popallfiles(); 5591556Srgrimes if (parsefile->fd > 0) { 5601556Srgrimes close(parsefile->fd); 5611556Srgrimes parsefile->fd = 0; 5621556Srgrimes } 5631556Srgrimes} 564