14b88c807SRodney W. Grimes /*- 24b88c807SRodney W. Grimes * Copyright (c) 1991, 1993 34b88c807SRodney W. Grimes * The Regents of the University of California. All rights reserved. 44b88c807SRodney W. Grimes * 54b88c807SRodney W. Grimes * This code is derived from software contributed to Berkeley by 64b88c807SRodney W. Grimes * Kenneth Almquist. 74b88c807SRodney W. Grimes * 84b88c807SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 94b88c807SRodney W. Grimes * modification, are permitted provided that the following conditions 104b88c807SRodney W. Grimes * are met: 114b88c807SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 124b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 134b88c807SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 144b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 154b88c807SRodney W. Grimes * documentation and/or other materials provided with the distribution. 16fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 174b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software 184b88c807SRodney W. Grimes * without specific prior written permission. 194b88c807SRodney W. Grimes * 204b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 214b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 224b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 234b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 244b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 254b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 264b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 274b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 284b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 294b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 304b88c807SRodney W. Grimes * SUCH DAMAGE. 314b88c807SRodney W. Grimes */ 324b88c807SRodney W. Grimes 334b88c807SRodney W. Grimes #ifndef lint 343d7b5b93SPhilippe Charnier #if 0 353d7b5b93SPhilippe Charnier static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95"; 363d7b5b93SPhilippe Charnier #endif 374b88c807SRodney W. Grimes #endif /* not lint */ 382749b141SDavid E. O'Brien #include <sys/cdefs.h> 392749b141SDavid E. O'Brien __FBSDID("$FreeBSD$"); 404b88c807SRodney W. Grimes 41aa9caaf6SPeter Wemm #include <stdio.h> /* defines BUFSIZ */ 42aa9caaf6SPeter Wemm #include <fcntl.h> 43aa9caaf6SPeter Wemm #include <errno.h> 44aa9caaf6SPeter Wemm #include <unistd.h> 45aa9caaf6SPeter Wemm #include <stdlib.h> 46aa9caaf6SPeter Wemm #include <string.h> 47aa9caaf6SPeter Wemm 484b88c807SRodney W. Grimes /* 494b88c807SRodney W. Grimes * This file implements the input routines used by the parser. 504b88c807SRodney W. Grimes */ 514b88c807SRodney W. Grimes 524b88c807SRodney W. Grimes #include "shell.h" 53aa9caaf6SPeter Wemm #include "redir.h" 544b88c807SRodney W. Grimes #include "syntax.h" 554b88c807SRodney W. Grimes #include "input.h" 564b88c807SRodney W. Grimes #include "output.h" 574b88c807SRodney W. Grimes #include "options.h" 584b88c807SRodney W. Grimes #include "memalloc.h" 594b88c807SRodney W. Grimes #include "error.h" 604b88c807SRodney W. Grimes #include "alias.h" 614b88c807SRodney W. Grimes #include "parser.h" 624b88c807SRodney W. Grimes #include "myhistedit.h" 63be58cc48STim J. Robbins #include "trap.h" 644b88c807SRodney W. Grimes 654b88c807SRodney W. Grimes #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ 664b88c807SRodney W. Grimes 674b88c807SRodney W. Grimes struct strpush { 684b88c807SRodney W. Grimes struct strpush *prev; /* preceding string on stack */ 6946c6b52dSJilles Tjoelker const char *prevstring; 704b88c807SRodney W. Grimes int prevnleft; 718f08f33eSPeter Wemm int prevlleft; 724b88c807SRodney W. Grimes struct alias *ap; /* if push was associated with an alias */ 734b88c807SRodney W. Grimes }; 744b88c807SRodney W. Grimes 754b88c807SRodney W. Grimes /* 764b88c807SRodney W. Grimes * The parsefile structure pointed to by the global variable parsefile 774b88c807SRodney W. Grimes * contains information about the current file being read. 784b88c807SRodney W. Grimes */ 794b88c807SRodney W. Grimes 804b88c807SRodney W. Grimes struct parsefile { 814b88c807SRodney W. Grimes struct parsefile *prev; /* preceding file on stack */ 824b88c807SRodney W. Grimes int linno; /* current line */ 834b88c807SRodney W. Grimes int fd; /* file descriptor (or -1 if string) */ 84ab0a2172SSteve Price int nleft; /* number of chars left in this line */ 85ab0a2172SSteve Price int lleft; /* number of lines left in this buffer */ 8646c6b52dSJilles Tjoelker const char *nextc; /* next char in buffer */ 874b88c807SRodney W. Grimes char *buf; /* input buffer */ 884b88c807SRodney W. Grimes struct strpush *strpush; /* for pushing strings at this level */ 894b88c807SRodney W. Grimes struct strpush basestrpush; /* so pushing one is fast */ 904b88c807SRodney W. Grimes }; 914b88c807SRodney W. Grimes 924b88c807SRodney W. Grimes 934b88c807SRodney W. Grimes int plinno = 1; /* input line number */ 94384aedabSJilles Tjoelker int parsenleft; /* copy of parsefile->nleft */ 950bdd3871SJilles Tjoelker static int parselleft; /* copy of parsefile->lleft */ 9646c6b52dSJilles Tjoelker const char *parsenextc; /* copy of parsefile->nextc */ 9760a6bf2aSJilles Tjoelker static char basebuf[BUFSIZ + 1];/* buffer for top level input file */ 9860a6bf2aSJilles Tjoelker static struct parsefile basepf = { /* top level input file */ 9960a6bf2aSJilles Tjoelker .nextc = basebuf, 10060a6bf2aSJilles Tjoelker .buf = basebuf 10160a6bf2aSJilles Tjoelker }; 102aa7b6f82SDavid E. O'Brien static struct parsefile *parsefile = &basepf; /* current input file */ 1034b88c807SRodney W. Grimes int whichprompt; /* 1 == PS1, 2 == PS2 */ 1044b88c807SRodney W. Grimes 1054b88c807SRodney W. Grimes EditLine *el; /* cookie for editline package */ 1064b88c807SRodney W. Grimes 10788328642SDavid E. O'Brien static void pushfile(void); 10888328642SDavid E. O'Brien static int preadfd(void); 109260fc3f4SJilles Tjoelker static void popstring(void); 1104b88c807SRodney W. Grimes 111338b821bSJilles Tjoelker void 112338b821bSJilles Tjoelker resetinput(void) 113338b821bSJilles Tjoelker { 1143055b7c6SJilles Tjoelker popallfiles(); 1158f08f33eSPeter Wemm parselleft = parsenleft = 0; /* clear input buffer */ 1164b88c807SRodney W. Grimes } 1174b88c807SRodney W. Grimes 1184b88c807SRodney W. Grimes 1194b88c807SRodney W. Grimes 1204b88c807SRodney W. Grimes /* 1214b88c807SRodney W. Grimes * Read a character from the script, returning PEOF on end of file. 1224b88c807SRodney W. Grimes * Nul characters in the input are silently discarded. 1234b88c807SRodney W. Grimes */ 1244b88c807SRodney W. Grimes 1254b88c807SRodney W. Grimes int 1265134c3f7SWarner Losh pgetc(void) 127ab0a2172SSteve Price { 1284b88c807SRodney W. Grimes return pgetc_macro(); 1294b88c807SRodney W. Grimes } 1304b88c807SRodney W. Grimes 131ab0a2172SSteve Price 13288328642SDavid E. O'Brien static int 1335134c3f7SWarner Losh preadfd(void) 1348f08f33eSPeter Wemm { 1358f08f33eSPeter Wemm int nr; 1368f08f33eSPeter Wemm parsenextc = parsefile->buf; 137ab0a2172SSteve Price 1384b88c807SRodney W. Grimes retry: 1394ca7fe3bSSteve Price #ifndef NO_HISTORY 1404b88c807SRodney W. Grimes if (parsefile->fd == 0 && el) { 141896229d9SStefan Farfeleder static const char *rl_cp; 142896229d9SStefan Farfeleder static int el_len; 1434b88c807SRodney W. Grimes 144d78fdfdeSJilles Tjoelker if (rl_cp == NULL) { 145d78fdfdeSJilles Tjoelker el_resize(el); 146896229d9SStefan Farfeleder rl_cp = el_gets(el, &el_len); 147d78fdfdeSJilles Tjoelker } 1488f08f33eSPeter Wemm if (rl_cp == NULL) 14900c43e0cSPedro F. Giffuni nr = el_len == 0 ? 0 : -1; 1508f08f33eSPeter Wemm else { 151896229d9SStefan Farfeleder nr = el_len; 1527f40c1f8SJilles Tjoelker if (nr > BUFSIZ) 1537f40c1f8SJilles Tjoelker nr = BUFSIZ; 15446c6b52dSJilles Tjoelker memcpy(parsefile->buf, rl_cp, nr); 155896229d9SStefan Farfeleder if (nr != el_len) { 156896229d9SStefan Farfeleder el_len -= nr; 157896229d9SStefan Farfeleder rl_cp += nr; 158896229d9SStefan Farfeleder } else 159896229d9SStefan Farfeleder rl_cp = NULL; 1604b88c807SRodney W. Grimes } 1614ca7fe3bSSteve Price } else 1624ca7fe3bSSteve Price #endif 16346c6b52dSJilles Tjoelker nr = read(parsefile->fd, parsefile->buf, BUFSIZ); 1648f08f33eSPeter Wemm 1658f08f33eSPeter Wemm if (nr <= 0) { 1668f08f33eSPeter Wemm if (nr < 0) { 1674b88c807SRodney W. Grimes if (errno == EINTR) 1684b88c807SRodney W. Grimes goto retry; 1694b88c807SRodney W. Grimes if (parsefile->fd == 0 && errno == EWOULDBLOCK) { 1704b88c807SRodney W. Grimes int flags = fcntl(0, F_GETFL, 0); 1714b88c807SRodney W. Grimes if (flags >= 0 && flags & O_NONBLOCK) { 1724b88c807SRodney W. Grimes flags &=~ O_NONBLOCK; 1734b88c807SRodney W. Grimes if (fcntl(0, F_SETFL, flags) >= 0) { 174c6204d4aSJilles Tjoelker out2fmt_flush("sh: turning off NDELAY mode\n"); 1754b88c807SRodney W. Grimes goto retry; 1764b88c807SRodney W. Grimes } 1774b88c807SRodney W. Grimes } 1784b88c807SRodney W. Grimes } 1794b88c807SRodney W. Grimes } 1808f08f33eSPeter Wemm nr = -1; 1818f08f33eSPeter Wemm } 1828f08f33eSPeter Wemm return nr; 1838f08f33eSPeter Wemm } 1848f08f33eSPeter Wemm 1858f08f33eSPeter Wemm /* 1868f08f33eSPeter Wemm * Refill the input buffer and return the next input character: 1878f08f33eSPeter Wemm * 1888f08f33eSPeter Wemm * 1) If a string was pushed back on the input, pop it; 1898f08f33eSPeter Wemm * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading 1908f08f33eSPeter Wemm * from a string so we can't refill the buffer, return EOF. 191ab0a2172SSteve Price * 3) If there is more in this buffer, use it else call read to fill it. 192ab0a2172SSteve Price * 4) Process input up to the next newline, deleting nul characters. 1938f08f33eSPeter Wemm */ 1948f08f33eSPeter Wemm 1958f08f33eSPeter Wemm int 1965134c3f7SWarner Losh preadbuffer(void) 197ab0a2172SSteve Price { 198dcd95d8aSJilles Tjoelker char *p, *q, *r, *end; 1998f08f33eSPeter Wemm char savec; 2008f08f33eSPeter Wemm 2014b489a60SJilles Tjoelker while (parsefile->strpush) { 2024b489a60SJilles Tjoelker /* 2034b489a60SJilles Tjoelker * Add a space to the end of an alias to ensure that the 2044b489a60SJilles Tjoelker * alias remains in use while parsing its last word. 2054b489a60SJilles Tjoelker * This avoids alias recursions. 2064b489a60SJilles Tjoelker */ 2074b489a60SJilles Tjoelker if (parsenleft == -1 && parsefile->strpush->ap != NULL) 2084b489a60SJilles Tjoelker return ' '; 2098f08f33eSPeter Wemm popstring(); 2108f08f33eSPeter Wemm if (--parsenleft >= 0) 2118f08f33eSPeter Wemm return (*parsenextc++); 2128f08f33eSPeter Wemm } 2138f08f33eSPeter Wemm if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) 2148f08f33eSPeter Wemm return PEOF; 2158f08f33eSPeter Wemm 2168f08f33eSPeter Wemm again: 2178f08f33eSPeter Wemm if (parselleft <= 0) { 2184ca7fe3bSSteve Price if ((parselleft = preadfd()) == -1) { 2198f08f33eSPeter Wemm parselleft = parsenleft = EOF_NLEFT; 2204b88c807SRodney W. Grimes return PEOF; 2214b88c807SRodney W. Grimes } 2228f08f33eSPeter Wemm } 2238f08f33eSPeter Wemm 224dcd95d8aSJilles Tjoelker p = parsefile->buf + (parsenextc - parsefile->buf); 225dcd95d8aSJilles Tjoelker end = p + parselleft; 226dcd95d8aSJilles Tjoelker *end = '\0'; 227dcd95d8aSJilles Tjoelker q = strchrnul(p, '\n'); 228dcd95d8aSJilles Tjoelker if (q != end && *q == '\0') { 2294b88c807SRodney W. Grimes /* delete nul characters */ 230dcd95d8aSJilles Tjoelker for (r = q; q != end; q++) { 231dcd95d8aSJilles Tjoelker if (*q != '\0') 232dcd95d8aSJilles Tjoelker *r++ = *q; 2338f08f33eSPeter Wemm } 234dcd95d8aSJilles Tjoelker parselleft -= end - r; 235dcd95d8aSJilles Tjoelker if (parselleft == 0) 2368f08f33eSPeter Wemm goto again; 237dcd95d8aSJilles Tjoelker end = p + parselleft; 238dcd95d8aSJilles Tjoelker *end = '\0'; 239dcd95d8aSJilles Tjoelker q = strchrnul(p, '\n'); 2408f08f33eSPeter Wemm } 241dcd95d8aSJilles Tjoelker if (q == end) { 242dcd95d8aSJilles Tjoelker parsenleft = parselleft; 243dcd95d8aSJilles Tjoelker parselleft = 0; 244dcd95d8aSJilles Tjoelker } else /* *q == '\n' */ { 24584f18910SJilles Tjoelker q++; 24684f18910SJilles Tjoelker parsenleft = q - parsenextc; 247dcd95d8aSJilles Tjoelker parselleft -= parsenleft; 2488f08f33eSPeter Wemm } 249dcd95d8aSJilles Tjoelker parsenleft--; 2508f08f33eSPeter Wemm 2518f08f33eSPeter Wemm savec = *q; 2528f08f33eSPeter Wemm *q = '\0'; 2538f08f33eSPeter Wemm 2544417f629SPeter Wemm #ifndef NO_HISTORY 255cac001aaSJilles Tjoelker if (parsefile->fd == 0 && hist && 256cac001aaSJilles Tjoelker parsenextc[strspn(parsenextc, " \t\n")] != '\0') { 257757eeda0SDavid E. O'Brien HistEvent he; 2584b88c807SRodney W. Grimes INTOFF; 259757eeda0SDavid E. O'Brien history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD, 260757eeda0SDavid E. O'Brien parsenextc); 2614b88c807SRodney W. Grimes INTON; 2624b88c807SRodney W. Grimes } 2634417f629SPeter Wemm #endif 2648f08f33eSPeter Wemm 2654b88c807SRodney W. Grimes if (vflag) { 2668f08f33eSPeter Wemm out2str(parsenextc); 2674b88c807SRodney W. Grimes flushout(out2); 2684b88c807SRodney W. Grimes } 2698f08f33eSPeter Wemm 2708f08f33eSPeter Wemm *q = savec; 2718f08f33eSPeter Wemm 2724b88c807SRodney W. Grimes return *parsenextc++; 2734b88c807SRodney W. Grimes } 2744b88c807SRodney W. Grimes 2754b88c807SRodney W. Grimes /* 276960da934SJilles Tjoelker * Returns if we are certain we are at EOF. Does not cause any more input 277960da934SJilles Tjoelker * to be read from the outside world. 278960da934SJilles Tjoelker */ 279960da934SJilles Tjoelker 280960da934SJilles Tjoelker int 281960da934SJilles Tjoelker preadateof(void) 282960da934SJilles Tjoelker { 283960da934SJilles Tjoelker if (parsenleft > 0) 284960da934SJilles Tjoelker return 0; 285960da934SJilles Tjoelker if (parsefile->strpush) 286960da934SJilles Tjoelker return 0; 287960da934SJilles Tjoelker if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) 288960da934SJilles Tjoelker return 1; 289960da934SJilles Tjoelker return 0; 290960da934SJilles Tjoelker } 291960da934SJilles Tjoelker 292960da934SJilles Tjoelker /* 2934b88c807SRodney W. Grimes * Undo the last call to pgetc. Only one character may be pushed back. 2944b88c807SRodney W. Grimes * PEOF may be pushed back. 2954b88c807SRodney W. Grimes */ 2964b88c807SRodney W. Grimes 2974b88c807SRodney W. Grimes void 2985134c3f7SWarner Losh pungetc(void) 2995134c3f7SWarner Losh { 3004b88c807SRodney W. Grimes parsenleft++; 3014b88c807SRodney W. Grimes parsenextc--; 3024b88c807SRodney W. Grimes } 3034b88c807SRodney W. Grimes 3044b88c807SRodney W. Grimes /* 3054b88c807SRodney W. Grimes * Push a string back onto the input at this current parsefile level. 3064b88c807SRodney W. Grimes * We handle aliases this way. 3074b88c807SRodney W. Grimes */ 3084b88c807SRodney W. Grimes void 3095545faddSJilles Tjoelker pushstring(const char *s, int len, struct alias *ap) 3104b88c807SRodney W. Grimes { 3114b88c807SRodney W. Grimes struct strpush *sp; 3124b88c807SRodney W. Grimes 3134b88c807SRodney W. Grimes INTOFF; 314c6204d4aSJilles Tjoelker /*out2fmt_flush("*** calling pushstring: %s, %d\n", s, len);*/ 3154b88c807SRodney W. Grimes if (parsefile->strpush) { 3164b88c807SRodney W. Grimes sp = ckmalloc(sizeof (struct strpush)); 3174b88c807SRodney W. Grimes sp->prev = parsefile->strpush; 3184b88c807SRodney W. Grimes parsefile->strpush = sp; 3194b88c807SRodney W. Grimes } else 3204b88c807SRodney W. Grimes sp = parsefile->strpush = &(parsefile->basestrpush); 3214b88c807SRodney W. Grimes sp->prevstring = parsenextc; 3224b88c807SRodney W. Grimes sp->prevnleft = parsenleft; 3238f08f33eSPeter Wemm sp->prevlleft = parselleft; 32435dab859SJilles Tjoelker sp->ap = ap; 3254b88c807SRodney W. Grimes if (ap) 32635dab859SJilles Tjoelker ap->flag |= ALIASINUSE; 3274b88c807SRodney W. Grimes parsenextc = s; 3284b88c807SRodney W. Grimes parsenleft = len; 3294b88c807SRodney W. Grimes INTON; 3304b88c807SRodney W. Grimes } 3314b88c807SRodney W. Grimes 332260fc3f4SJilles Tjoelker static void 3335134c3f7SWarner Losh popstring(void) 3344b88c807SRodney W. Grimes { 3354b88c807SRodney W. Grimes struct strpush *sp = parsefile->strpush; 3364b88c807SRodney W. Grimes 3374b88c807SRodney W. Grimes INTOFF; 33848f49aacSJilles Tjoelker if (sp->ap) { 33948f49aacSJilles Tjoelker if (parsenextc != sp->ap->val && 34048f49aacSJilles Tjoelker (parsenextc[-1] == ' ' || parsenextc[-1] == '\t')) 34148f49aacSJilles Tjoelker forcealias(); 34248f49aacSJilles Tjoelker sp->ap->flag &= ~ALIASINUSE; 34348f49aacSJilles Tjoelker } 3444b88c807SRodney W. Grimes parsenextc = sp->prevstring; 3454b88c807SRodney W. Grimes parsenleft = sp->prevnleft; 3468f08f33eSPeter Wemm parselleft = sp->prevlleft; 347c6204d4aSJilles Tjoelker /*out2fmt_flush("*** calling popstring: restoring to '%s'\n", parsenextc);*/ 3484b88c807SRodney W. Grimes parsefile->strpush = sp->prev; 3494b88c807SRodney W. Grimes if (sp != &(parsefile->basestrpush)) 3504b88c807SRodney W. Grimes ckfree(sp); 3514b88c807SRodney W. Grimes INTON; 3524b88c807SRodney W. Grimes } 3534b88c807SRodney W. Grimes 3544b88c807SRodney W. Grimes /* 3554b88c807SRodney W. Grimes * Set the input to take input from a file. If push is set, push the 3564b88c807SRodney W. Grimes * old input onto the stack first. 3574b88c807SRodney W. Grimes */ 3584b88c807SRodney W. Grimes 3594b88c807SRodney W. Grimes void 3602cac6e36SJilles Tjoelker setinputfile(const char *fname, int push) 3614b88c807SRodney W. Grimes { 362*77da4a95SJilles Tjoelker int e; 3634b88c807SRodney W. Grimes int fd; 3644b88c807SRodney W. Grimes int fd2; 3654b88c807SRodney W. Grimes 3664b88c807SRodney W. Grimes INTOFF; 367*77da4a95SJilles Tjoelker if ((fd = open(fname, O_RDONLY | O_CLOEXEC)) < 0) { 368*77da4a95SJilles Tjoelker e = errno; 369*77da4a95SJilles Tjoelker errorwithstatus(e == ENOENT || e == ENOTDIR ? 127 : 126, 370*77da4a95SJilles Tjoelker "cannot open %s: %s", fname, strerror(e)); 371*77da4a95SJilles Tjoelker } 3724b88c807SRodney W. Grimes if (fd < 10) { 3735aa6dfdaSJilles Tjoelker fd2 = fcntl(fd, F_DUPFD_CLOEXEC, 10); 3744b88c807SRodney W. Grimes close(fd); 3754b88c807SRodney W. Grimes if (fd2 < 0) 3764b88c807SRodney W. Grimes error("Out of file descriptors"); 3774b88c807SRodney W. Grimes fd = fd2; 3784b88c807SRodney W. Grimes } 3794b88c807SRodney W. Grimes setinputfd(fd, push); 3804b88c807SRodney W. Grimes INTON; 3814b88c807SRodney W. Grimes } 3824b88c807SRodney W. Grimes 3834b88c807SRodney W. Grimes 3844b88c807SRodney W. Grimes /* 3855aa6dfdaSJilles Tjoelker * Like setinputfile, but takes an open file descriptor (which should have 3865aa6dfdaSJilles Tjoelker * its FD_CLOEXEC flag already set). Call this with interrupts off. 3874b88c807SRodney W. Grimes */ 3884b88c807SRodney W. Grimes 3894b88c807SRodney W. Grimes void 3905134c3f7SWarner Losh setinputfd(int fd, int push) 391aa9caaf6SPeter Wemm { 3924b88c807SRodney W. Grimes if (push) { 3934b88c807SRodney W. Grimes pushfile(); 3947f40c1f8SJilles Tjoelker parsefile->buf = ckmalloc(BUFSIZ + 1); 3954b88c807SRodney W. Grimes } 3964b88c807SRodney W. Grimes if (parsefile->fd > 0) 3974b88c807SRodney W. Grimes close(parsefile->fd); 3984b88c807SRodney W. Grimes parsefile->fd = fd; 3994b88c807SRodney W. Grimes if (parsefile->buf == NULL) 4007f40c1f8SJilles Tjoelker parsefile->buf = ckmalloc(BUFSIZ + 1); 4018f08f33eSPeter Wemm parselleft = parsenleft = 0; 4024b88c807SRodney W. Grimes plinno = 1; 4034b88c807SRodney W. Grimes } 4044b88c807SRodney W. Grimes 4054b88c807SRodney W. Grimes 4064b88c807SRodney W. Grimes /* 4074b88c807SRodney W. Grimes * Like setinputfile, but takes input from a string. 4084b88c807SRodney W. Grimes */ 4094b88c807SRodney W. Grimes 4104b88c807SRodney W. Grimes void 41146c6b52dSJilles Tjoelker setinputstring(const char *string, int push) 4124b88c807SRodney W. Grimes { 4134b88c807SRodney W. Grimes INTOFF; 4144b88c807SRodney W. Grimes if (push) 4154b88c807SRodney W. Grimes pushfile(); 4164b88c807SRodney W. Grimes parsenextc = string; 4178f08f33eSPeter Wemm parselleft = parsenleft = strlen(string); 4184b88c807SRodney W. Grimes parsefile->buf = NULL; 4194b88c807SRodney W. Grimes plinno = 1; 4204b88c807SRodney W. Grimes INTON; 4214b88c807SRodney W. Grimes } 4224b88c807SRodney W. Grimes 4234b88c807SRodney W. Grimes 4244b88c807SRodney W. Grimes 4254b88c807SRodney W. Grimes /* 4264b88c807SRodney W. Grimes * To handle the "." command, a stack of input files is used. Pushfile 4274b88c807SRodney W. Grimes * adds a new entry to the stack and popfile restores the previous level. 4284b88c807SRodney W. Grimes */ 4294b88c807SRodney W. Grimes 43088328642SDavid E. O'Brien static void 4315134c3f7SWarner Losh pushfile(void) 4325134c3f7SWarner Losh { 4334b88c807SRodney W. Grimes struct parsefile *pf; 4344b88c807SRodney W. Grimes 4354b88c807SRodney W. Grimes parsefile->nleft = parsenleft; 4368f08f33eSPeter Wemm parsefile->lleft = parselleft; 4374b88c807SRodney W. Grimes parsefile->nextc = parsenextc; 4384b88c807SRodney W. Grimes parsefile->linno = plinno; 4394b88c807SRodney W. Grimes pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); 4404b88c807SRodney W. Grimes pf->prev = parsefile; 4414b88c807SRodney W. Grimes pf->fd = -1; 4424b88c807SRodney W. Grimes pf->strpush = NULL; 4434b88c807SRodney W. Grimes pf->basestrpush.prev = NULL; 4444b88c807SRodney W. Grimes parsefile = pf; 4454b88c807SRodney W. Grimes } 4464b88c807SRodney W. Grimes 4474b88c807SRodney W. Grimes 4484b88c807SRodney W. Grimes void 4495134c3f7SWarner Losh popfile(void) 4505134c3f7SWarner Losh { 4514b88c807SRodney W. Grimes struct parsefile *pf = parsefile; 4524b88c807SRodney W. Grimes 4534b88c807SRodney W. Grimes INTOFF; 4544b88c807SRodney W. Grimes if (pf->fd >= 0) 4554b88c807SRodney W. Grimes close(pf->fd); 4564b88c807SRodney W. Grimes if (pf->buf) 4574b88c807SRodney W. Grimes ckfree(pf->buf); 4584b88c807SRodney W. Grimes while (pf->strpush) 4594b88c807SRodney W. Grimes popstring(); 4604b88c807SRodney W. Grimes parsefile = pf->prev; 4614b88c807SRodney W. Grimes ckfree(pf); 4624b88c807SRodney W. Grimes parsenleft = parsefile->nleft; 4638f08f33eSPeter Wemm parselleft = parsefile->lleft; 4644b88c807SRodney W. Grimes parsenextc = parsefile->nextc; 4654b88c807SRodney W. Grimes plinno = parsefile->linno; 4664b88c807SRodney W. Grimes INTON; 4674b88c807SRodney W. Grimes } 4684b88c807SRodney W. Grimes 4694b88c807SRodney W. Grimes 4704b88c807SRodney W. Grimes /* 471eaa34893SJilles Tjoelker * Return current file (to go back to it later using popfilesupto()). 472eaa34893SJilles Tjoelker */ 473eaa34893SJilles Tjoelker 474eaa34893SJilles Tjoelker struct parsefile * 475eaa34893SJilles Tjoelker getcurrentfile(void) 476eaa34893SJilles Tjoelker { 477eaa34893SJilles Tjoelker return parsefile; 478eaa34893SJilles Tjoelker } 479eaa34893SJilles Tjoelker 480eaa34893SJilles Tjoelker 481eaa34893SJilles Tjoelker /* 482eaa34893SJilles Tjoelker * Pop files until the given file is on top again. Useful for regular 483eaa34893SJilles Tjoelker * builtins that read shell commands from files or strings. 484eaa34893SJilles Tjoelker * If the given file is not an active file, an error is raised. 485eaa34893SJilles Tjoelker */ 486eaa34893SJilles Tjoelker 487eaa34893SJilles Tjoelker void 488eaa34893SJilles Tjoelker popfilesupto(struct parsefile *file) 489eaa34893SJilles Tjoelker { 490eaa34893SJilles Tjoelker while (parsefile != file && parsefile != &basepf) 491eaa34893SJilles Tjoelker popfile(); 492eaa34893SJilles Tjoelker if (parsefile != file) 493eaa34893SJilles Tjoelker error("popfilesupto() misused"); 494eaa34893SJilles Tjoelker } 495eaa34893SJilles Tjoelker 496eaa34893SJilles Tjoelker /* 4974b88c807SRodney W. Grimes * Return to top level. 4984b88c807SRodney W. Grimes */ 4994b88c807SRodney W. Grimes 5004b88c807SRodney W. Grimes void 5015134c3f7SWarner Losh popallfiles(void) 5025134c3f7SWarner Losh { 5034b88c807SRodney W. Grimes while (parsefile != &basepf) 5044b88c807SRodney W. Grimes popfile(); 5054b88c807SRodney W. Grimes } 5064b88c807SRodney W. Grimes 5074b88c807SRodney W. Grimes 5084b88c807SRodney W. Grimes 5094b88c807SRodney W. Grimes /* 5104b88c807SRodney W. Grimes * Close the file(s) that the shell is reading commands from. Called 5114b88c807SRodney W. Grimes * after a fork is done. 5124b88c807SRodney W. Grimes */ 5134b88c807SRodney W. Grimes 5144b88c807SRodney W. Grimes void 5155134c3f7SWarner Losh closescript(void) 5165134c3f7SWarner Losh { 5174b88c807SRodney W. Grimes popallfiles(); 5184b88c807SRodney W. Grimes if (parsefile->fd > 0) { 5194b88c807SRodney W. Grimes close(parsefile->fd); 5204b88c807SRodney W. Grimes parsefile->fd = 0; 5214b88c807SRodney W. Grimes } 5224b88c807SRodney W. Grimes } 523