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. 164b88c807SRodney W. Grimes * 4. 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 MKINIT 684b88c807SRodney W. Grimes struct strpush { 694b88c807SRodney W. Grimes struct strpush *prev; /* preceding string on stack */ 704b88c807SRodney W. Grimes char *prevstring; 714b88c807SRodney W. Grimes int prevnleft; 728f08f33eSPeter Wemm int prevlleft; 734b88c807SRodney W. Grimes struct alias *ap; /* if push was associated with an alias */ 744b88c807SRodney W. Grimes }; 754b88c807SRodney W. Grimes 764b88c807SRodney W. Grimes /* 774b88c807SRodney W. Grimes * The parsefile structure pointed to by the global variable parsefile 784b88c807SRodney W. Grimes * contains information about the current file being read. 794b88c807SRodney W. Grimes */ 804b88c807SRodney W. Grimes 814b88c807SRodney W. Grimes MKINIT 824b88c807SRodney W. Grimes struct parsefile { 834b88c807SRodney W. Grimes struct parsefile *prev; /* preceding file on stack */ 844b88c807SRodney W. Grimes int linno; /* current line */ 854b88c807SRodney W. Grimes int fd; /* file descriptor (or -1 if string) */ 86ab0a2172SSteve Price int nleft; /* number of chars left in this line */ 87ab0a2172SSteve Price int lleft; /* number of lines left in this buffer */ 884b88c807SRodney W. Grimes char *nextc; /* next char in buffer */ 894b88c807SRodney W. Grimes char *buf; /* input buffer */ 904b88c807SRodney W. Grimes struct strpush *strpush; /* for pushing strings at this level */ 914b88c807SRodney W. Grimes struct strpush basestrpush; /* so pushing one is fast */ 924b88c807SRodney W. Grimes }; 934b88c807SRodney W. Grimes 944b88c807SRodney W. Grimes 954b88c807SRodney W. Grimes int plinno = 1; /* input line number */ 964b88c807SRodney W. Grimes MKINIT int parsenleft; /* copy of parsefile->nleft */ 978f08f33eSPeter Wemm MKINIT int parselleft; /* copy of parsefile->lleft */ 984b88c807SRodney W. Grimes char *parsenextc; /* copy of parsefile->nextc */ 994b88c807SRodney W. Grimes MKINIT struct parsefile basepf; /* top level input file */ 1004b88c807SRodney W. Grimes char basebuf[BUFSIZ]; /* buffer for top level input file */ 1012ba1b30bSDiomidis Spinellis STATIC struct parsefile *parsefile = &basepf; /* current input file */ 1024b88c807SRodney W. Grimes int init_editline = 0; /* editline library initialized? */ 1034b88c807SRodney W. Grimes int whichprompt; /* 1 == PS1, 2 == PS2 */ 1044b88c807SRodney W. Grimes 1054b88c807SRodney W. Grimes EditLine *el; /* cookie for editline package */ 1064b88c807SRodney W. Grimes 1075134c3f7SWarner Losh STATIC void pushfile(void); 1085134c3f7SWarner Losh static int preadfd(void); 1094b88c807SRodney W. Grimes 1104b88c807SRodney W. Grimes #ifdef mkinit 1114b88c807SRodney W. Grimes INCLUDE "input.h" 1124b88c807SRodney W. Grimes INCLUDE "error.h" 1134b88c807SRodney W. Grimes 1144b88c807SRodney W. Grimes INIT { 1154b88c807SRodney W. Grimes extern char basebuf[]; 1164b88c807SRodney W. Grimes 1174b88c807SRodney W. Grimes basepf.nextc = basepf.buf = basebuf; 1184b88c807SRodney W. Grimes } 1194b88c807SRodney W. Grimes 1204b88c807SRodney W. Grimes RESET { 1213055b7c6SJilles Tjoelker popallfiles(); 1224b88c807SRodney W. Grimes if (exception != EXSHELLPROC) 1238f08f33eSPeter Wemm parselleft = parsenleft = 0; /* clear input buffer */ 1244b88c807SRodney W. Grimes } 1254b88c807SRodney W. Grimes 1264b88c807SRodney W. Grimes SHELLPROC { 1274b88c807SRodney W. Grimes popallfiles(); 1284b88c807SRodney W. Grimes } 1294b88c807SRodney W. Grimes #endif 1304b88c807SRodney W. Grimes 1314b88c807SRodney W. Grimes 1324b88c807SRodney W. Grimes /* 1334b88c807SRodney W. Grimes * Read a line from the script. 1344b88c807SRodney W. Grimes */ 1354b88c807SRodney W. Grimes 1364b88c807SRodney W. Grimes char * 1375134c3f7SWarner Losh pfgets(char *line, int len) 1384b88c807SRodney W. Grimes { 1394ca7fe3bSSteve Price char *p = line; 1404b88c807SRodney W. Grimes int nleft = len; 1414b88c807SRodney W. Grimes int c; 1424b88c807SRodney W. Grimes 1434b88c807SRodney W. Grimes while (--nleft > 0) { 1444b88c807SRodney W. Grimes c = pgetc_macro(); 1454b88c807SRodney W. Grimes if (c == PEOF) { 1464b88c807SRodney W. Grimes if (p == line) 1474b88c807SRodney W. Grimes return NULL; 1484b88c807SRodney W. Grimes break; 1494b88c807SRodney W. Grimes } 1504b88c807SRodney W. Grimes *p++ = c; 1514b88c807SRodney W. Grimes if (c == '\n') 1524b88c807SRodney W. Grimes break; 1534b88c807SRodney W. Grimes } 1544b88c807SRodney W. Grimes *p = '\0'; 1554b88c807SRodney W. Grimes return line; 1564b88c807SRodney W. Grimes } 1574b88c807SRodney W. Grimes 1584b88c807SRodney W. Grimes 1594b88c807SRodney W. Grimes 1604b88c807SRodney W. Grimes /* 1614b88c807SRodney W. Grimes * Read a character from the script, returning PEOF on end of file. 1624b88c807SRodney W. Grimes * Nul characters in the input are silently discarded. 1634b88c807SRodney W. Grimes */ 1644b88c807SRodney W. Grimes 1654b88c807SRodney W. Grimes int 1665134c3f7SWarner Losh pgetc(void) 167ab0a2172SSteve Price { 1684b88c807SRodney W. Grimes return pgetc_macro(); 1694b88c807SRodney W. Grimes } 1704b88c807SRodney W. Grimes 171ab0a2172SSteve Price 1728f08f33eSPeter Wemm static int 1735134c3f7SWarner Losh preadfd(void) 1748f08f33eSPeter Wemm { 1758f08f33eSPeter Wemm int nr; 1768f08f33eSPeter Wemm parsenextc = parsefile->buf; 177ab0a2172SSteve Price 178be58cc48STim J. Robbins #ifndef NO_HISTORY 179be58cc48STim J. Robbins if (el != NULL && gotwinch) { 180be58cc48STim J. Robbins gotwinch = 0; 181be58cc48STim J. Robbins el_resize(el); 182be58cc48STim J. Robbins } 183be58cc48STim J. Robbins #endif 1844b88c807SRodney W. Grimes retry: 1854ca7fe3bSSteve Price #ifndef NO_HISTORY 1864b88c807SRodney W. Grimes if (parsefile->fd == 0 && el) { 187896229d9SStefan Farfeleder static const char *rl_cp; 188896229d9SStefan Farfeleder static int el_len; 1894b88c807SRodney W. Grimes 190896229d9SStefan Farfeleder if (rl_cp == NULL) 191896229d9SStefan Farfeleder rl_cp = el_gets(el, &el_len); 1928f08f33eSPeter Wemm if (rl_cp == NULL) 1938f08f33eSPeter Wemm nr = 0; 1948f08f33eSPeter Wemm else { 195896229d9SStefan Farfeleder nr = el_len; 196896229d9SStefan Farfeleder if (nr > BUFSIZ - 1) 197896229d9SStefan Farfeleder nr = BUFSIZ - 1; 198896229d9SStefan Farfeleder memcpy(parsenextc, rl_cp, nr); 199896229d9SStefan Farfeleder if (nr != el_len) { 200896229d9SStefan Farfeleder el_len -= nr; 201896229d9SStefan Farfeleder rl_cp += nr; 202896229d9SStefan Farfeleder } else 203896229d9SStefan Farfeleder rl_cp = NULL; 2044b88c807SRodney W. Grimes } 2054ca7fe3bSSteve Price } else 2064ca7fe3bSSteve Price #endif 2078f08f33eSPeter Wemm nr = read(parsefile->fd, parsenextc, BUFSIZ - 1); 2088f08f33eSPeter Wemm 2098f08f33eSPeter Wemm if (nr <= 0) { 2108f08f33eSPeter Wemm if (nr < 0) { 2114b88c807SRodney W. Grimes if (errno == EINTR) 2124b88c807SRodney W. Grimes goto retry; 2134b88c807SRodney W. Grimes if (parsefile->fd == 0 && errno == EWOULDBLOCK) { 2144b88c807SRodney W. Grimes int flags = fcntl(0, F_GETFL, 0); 2154b88c807SRodney W. Grimes if (flags >= 0 && flags & O_NONBLOCK) { 2164b88c807SRodney W. Grimes flags &=~ O_NONBLOCK; 2174b88c807SRodney W. Grimes if (fcntl(0, F_SETFL, flags) >= 0) { 2184b88c807SRodney W. Grimes out2str("sh: turning off NDELAY mode\n"); 2194b88c807SRodney W. Grimes goto retry; 2204b88c807SRodney W. Grimes } 2214b88c807SRodney W. Grimes } 2224b88c807SRodney W. Grimes } 2234b88c807SRodney W. Grimes } 2248f08f33eSPeter Wemm nr = -1; 2258f08f33eSPeter Wemm } 2268f08f33eSPeter Wemm return nr; 2278f08f33eSPeter Wemm } 2288f08f33eSPeter Wemm 2298f08f33eSPeter Wemm /* 2308f08f33eSPeter Wemm * Refill the input buffer and return the next input character: 2318f08f33eSPeter Wemm * 2328f08f33eSPeter Wemm * 1) If a string was pushed back on the input, pop it; 2338f08f33eSPeter Wemm * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading 2348f08f33eSPeter Wemm * from a string so we can't refill the buffer, return EOF. 235ab0a2172SSteve Price * 3) If there is more in this buffer, use it else call read to fill it. 236ab0a2172SSteve Price * 4) Process input up to the next newline, deleting nul characters. 2378f08f33eSPeter Wemm */ 2388f08f33eSPeter Wemm 2398f08f33eSPeter Wemm int 2405134c3f7SWarner Losh preadbuffer(void) 241ab0a2172SSteve Price { 2428f08f33eSPeter Wemm char *p, *q; 2438f08f33eSPeter Wemm int more; 2448f08f33eSPeter Wemm int something; 2458f08f33eSPeter Wemm char savec; 2468f08f33eSPeter Wemm 2478f08f33eSPeter Wemm if (parsefile->strpush) { 2488f08f33eSPeter Wemm popstring(); 2498f08f33eSPeter Wemm if (--parsenleft >= 0) 2508f08f33eSPeter Wemm return (*parsenextc++); 2518f08f33eSPeter Wemm } 2528f08f33eSPeter Wemm if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) 2538f08f33eSPeter Wemm return PEOF; 2548f08f33eSPeter Wemm flushout(&output); 2558f08f33eSPeter Wemm flushout(&errout); 2568f08f33eSPeter Wemm 2578f08f33eSPeter Wemm again: 2588f08f33eSPeter Wemm if (parselleft <= 0) { 2594ca7fe3bSSteve Price if ((parselleft = preadfd()) == -1) { 2608f08f33eSPeter Wemm parselleft = parsenleft = EOF_NLEFT; 2614b88c807SRodney W. Grimes return PEOF; 2624b88c807SRodney W. Grimes } 2638f08f33eSPeter Wemm } 2648f08f33eSPeter Wemm 2658f08f33eSPeter Wemm q = p = parsenextc; 2664b88c807SRodney W. Grimes 2674b88c807SRodney W. Grimes /* delete nul characters */ 2684b88c807SRodney W. Grimes something = 0; 2698f08f33eSPeter Wemm for (more = 1; more;) { 2708f08f33eSPeter Wemm switch (*p) { 2718f08f33eSPeter Wemm case '\0': 2728f08f33eSPeter Wemm p++; /* Skip nul */ 2738f08f33eSPeter Wemm goto check; 2744b88c807SRodney W. Grimes 2758f08f33eSPeter Wemm case '\t': 2768f08f33eSPeter Wemm case ' ': 2778f08f33eSPeter Wemm break; 2788f08f33eSPeter Wemm 2798f08f33eSPeter Wemm case '\n': 2808f08f33eSPeter Wemm parsenleft = q - parsenextc; 2818f08f33eSPeter Wemm more = 0; /* Stop processing here */ 2828f08f33eSPeter Wemm break; 2838f08f33eSPeter Wemm 2848f08f33eSPeter Wemm default: 2858f08f33eSPeter Wemm something = 1; 2868f08f33eSPeter Wemm break; 2878f08f33eSPeter Wemm } 2888f08f33eSPeter Wemm 2898f08f33eSPeter Wemm *q++ = *p++; 2908f08f33eSPeter Wemm check: 2918f08f33eSPeter Wemm if (--parselleft <= 0) { 2928f08f33eSPeter Wemm parsenleft = q - parsenextc - 1; 2938f08f33eSPeter Wemm if (parsenleft < 0) 2948f08f33eSPeter Wemm goto again; 2958f08f33eSPeter Wemm *q = '\0'; 2968f08f33eSPeter Wemm more = 0; 2978f08f33eSPeter Wemm } 2988f08f33eSPeter Wemm } 2998f08f33eSPeter Wemm 3008f08f33eSPeter Wemm savec = *q; 3018f08f33eSPeter Wemm *q = '\0'; 3028f08f33eSPeter Wemm 3034417f629SPeter Wemm #ifndef NO_HISTORY 3044b88c807SRodney W. Grimes if (parsefile->fd == 0 && hist && something) { 305757eeda0SDavid E. O'Brien HistEvent he; 3064b88c807SRodney W. Grimes INTOFF; 307757eeda0SDavid E. O'Brien history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD, 308757eeda0SDavid E. O'Brien parsenextc); 3094b88c807SRodney W. Grimes INTON; 3104b88c807SRodney W. Grimes } 3114417f629SPeter Wemm #endif 3128f08f33eSPeter Wemm 3134b88c807SRodney W. Grimes if (vflag) { 3148f08f33eSPeter Wemm out2str(parsenextc); 3154b88c807SRodney W. Grimes flushout(out2); 3164b88c807SRodney W. Grimes } 3178f08f33eSPeter Wemm 3188f08f33eSPeter Wemm *q = savec; 3198f08f33eSPeter Wemm 3204b88c807SRodney W. Grimes return *parsenextc++; 3214b88c807SRodney W. Grimes } 3224b88c807SRodney W. Grimes 3234b88c807SRodney W. Grimes /* 324960da934SJilles Tjoelker * Returns if we are certain we are at EOF. Does not cause any more input 325960da934SJilles Tjoelker * to be read from the outside world. 326960da934SJilles Tjoelker */ 327960da934SJilles Tjoelker 328960da934SJilles Tjoelker int 329960da934SJilles Tjoelker preadateof(void) 330960da934SJilles Tjoelker { 331960da934SJilles Tjoelker if (parsenleft > 0) 332960da934SJilles Tjoelker return 0; 333960da934SJilles Tjoelker if (parsefile->strpush) 334960da934SJilles Tjoelker return 0; 335960da934SJilles Tjoelker if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) 336960da934SJilles Tjoelker return 1; 337960da934SJilles Tjoelker return 0; 338960da934SJilles Tjoelker } 339960da934SJilles Tjoelker 340960da934SJilles Tjoelker /* 3414b88c807SRodney W. Grimes * Undo the last call to pgetc. Only one character may be pushed back. 3424b88c807SRodney W. Grimes * PEOF may be pushed back. 3434b88c807SRodney W. Grimes */ 3444b88c807SRodney W. Grimes 3454b88c807SRodney W. Grimes void 3465134c3f7SWarner Losh pungetc(void) 3475134c3f7SWarner Losh { 3484b88c807SRodney W. Grimes parsenleft++; 3494b88c807SRodney W. Grimes parsenextc--; 3504b88c807SRodney W. Grimes } 3514b88c807SRodney W. Grimes 3524b88c807SRodney W. Grimes /* 3534b88c807SRodney W. Grimes * Push a string back onto the input at this current parsefile level. 3544b88c807SRodney W. Grimes * We handle aliases this way. 3554b88c807SRodney W. Grimes */ 3564b88c807SRodney W. Grimes void 3575134c3f7SWarner Losh pushstring(char *s, int len, void *ap) 3584b88c807SRodney W. Grimes { 3594b88c807SRodney W. Grimes struct strpush *sp; 3604b88c807SRodney W. Grimes 3614b88c807SRodney W. Grimes INTOFF; 3624b88c807SRodney W. Grimes /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/ 3634b88c807SRodney W. Grimes if (parsefile->strpush) { 3644b88c807SRodney W. Grimes sp = ckmalloc(sizeof (struct strpush)); 3654b88c807SRodney W. Grimes sp->prev = parsefile->strpush; 3664b88c807SRodney W. Grimes parsefile->strpush = sp; 3674b88c807SRodney W. Grimes } else 3684b88c807SRodney W. Grimes sp = parsefile->strpush = &(parsefile->basestrpush); 3694b88c807SRodney W. Grimes sp->prevstring = parsenextc; 3704b88c807SRodney W. Grimes sp->prevnleft = parsenleft; 3718f08f33eSPeter Wemm sp->prevlleft = parselleft; 3724b88c807SRodney W. Grimes sp->ap = (struct alias *)ap; 3734b88c807SRodney W. Grimes if (ap) 3744b88c807SRodney W. Grimes ((struct alias *)ap)->flag |= ALIASINUSE; 3754b88c807SRodney W. Grimes parsenextc = s; 3764b88c807SRodney W. Grimes parsenleft = len; 3774b88c807SRodney W. Grimes INTON; 3784b88c807SRodney W. Grimes } 3794b88c807SRodney W. Grimes 380aa9caaf6SPeter Wemm void 3815134c3f7SWarner Losh popstring(void) 3824b88c807SRodney W. Grimes { 3834b88c807SRodney W. Grimes struct strpush *sp = parsefile->strpush; 3844b88c807SRodney W. Grimes 3854b88c807SRodney W. Grimes INTOFF; 3864b88c807SRodney W. Grimes parsenextc = sp->prevstring; 3874b88c807SRodney W. Grimes parsenleft = sp->prevnleft; 3888f08f33eSPeter Wemm parselleft = sp->prevlleft; 3894b88c807SRodney W. Grimes /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/ 3904b88c807SRodney W. Grimes if (sp->ap) 3914b88c807SRodney W. Grimes sp->ap->flag &= ~ALIASINUSE; 3924b88c807SRodney W. Grimes parsefile->strpush = sp->prev; 3934b88c807SRodney W. Grimes if (sp != &(parsefile->basestrpush)) 3944b88c807SRodney W. Grimes ckfree(sp); 3954b88c807SRodney W. Grimes INTON; 3964b88c807SRodney W. Grimes } 3974b88c807SRodney W. Grimes 3984b88c807SRodney W. Grimes /* 3994b88c807SRodney W. Grimes * Set the input to take input from a file. If push is set, push the 4004b88c807SRodney W. Grimes * old input onto the stack first. 4014b88c807SRodney W. Grimes */ 4024b88c807SRodney W. Grimes 4034b88c807SRodney W. Grimes void 4045134c3f7SWarner Losh setinputfile(char *fname, int push) 4054b88c807SRodney W. Grimes { 4064b88c807SRodney W. Grimes int fd; 4074b88c807SRodney W. Grimes int fd2; 4084b88c807SRodney W. Grimes 4094b88c807SRodney W. Grimes INTOFF; 4104b88c807SRodney W. Grimes if ((fd = open(fname, O_RDONLY)) < 0) 4116c48b6cfSMartin Cracauer error("Can't open %s: %s", fname, strerror(errno)); 4124b88c807SRodney W. Grimes if (fd < 10) { 4137e1c7266SDag-Erling Smørgrav fd2 = fcntl(fd, F_DUPFD, 10); 4144b88c807SRodney W. Grimes close(fd); 4154b88c807SRodney W. Grimes if (fd2 < 0) 4164b88c807SRodney W. Grimes error("Out of file descriptors"); 4174b88c807SRodney W. Grimes fd = fd2; 4184b88c807SRodney W. Grimes } 4194b88c807SRodney W. Grimes setinputfd(fd, push); 4204b88c807SRodney W. Grimes INTON; 4214b88c807SRodney W. Grimes } 4224b88c807SRodney W. Grimes 4234b88c807SRodney W. Grimes 4244b88c807SRodney W. Grimes /* 4254b88c807SRodney W. Grimes * Like setinputfile, but takes an open file descriptor. Call this with 4264b88c807SRodney W. Grimes * interrupts off. 4274b88c807SRodney W. Grimes */ 4284b88c807SRodney W. Grimes 4294b88c807SRodney W. Grimes void 4305134c3f7SWarner Losh setinputfd(int fd, int push) 431aa9caaf6SPeter Wemm { 4324ca7fe3bSSteve Price (void)fcntl(fd, F_SETFD, FD_CLOEXEC); 4334b88c807SRodney W. Grimes if (push) { 4344b88c807SRodney W. Grimes pushfile(); 4354b88c807SRodney W. Grimes parsefile->buf = ckmalloc(BUFSIZ); 4364b88c807SRodney W. Grimes } 4374b88c807SRodney W. Grimes if (parsefile->fd > 0) 4384b88c807SRodney W. Grimes close(parsefile->fd); 4394b88c807SRodney W. Grimes parsefile->fd = fd; 4404b88c807SRodney W. Grimes if (parsefile->buf == NULL) 4414b88c807SRodney W. Grimes parsefile->buf = ckmalloc(BUFSIZ); 4428f08f33eSPeter Wemm parselleft = parsenleft = 0; 4434b88c807SRodney W. Grimes plinno = 1; 4444b88c807SRodney W. Grimes } 4454b88c807SRodney W. Grimes 4464b88c807SRodney W. Grimes 4474b88c807SRodney W. Grimes /* 4484b88c807SRodney W. Grimes * Like setinputfile, but takes input from a string. 4494b88c807SRodney W. Grimes */ 4504b88c807SRodney W. Grimes 4514b88c807SRodney W. Grimes void 4525134c3f7SWarner Losh setinputstring(char *string, int push) 4534b88c807SRodney W. Grimes { 4544b88c807SRodney W. Grimes INTOFF; 4554b88c807SRodney W. Grimes if (push) 4564b88c807SRodney W. Grimes pushfile(); 4574b88c807SRodney W. Grimes parsenextc = string; 4588f08f33eSPeter Wemm parselleft = parsenleft = strlen(string); 4594b88c807SRodney W. Grimes parsefile->buf = NULL; 4604b88c807SRodney W. Grimes plinno = 1; 4614b88c807SRodney W. Grimes INTON; 4624b88c807SRodney W. Grimes } 4634b88c807SRodney W. Grimes 4644b88c807SRodney W. Grimes 4654b88c807SRodney W. Grimes 4664b88c807SRodney W. Grimes /* 4674b88c807SRodney W. Grimes * To handle the "." command, a stack of input files is used. Pushfile 4684b88c807SRodney W. Grimes * adds a new entry to the stack and popfile restores the previous level. 4694b88c807SRodney W. Grimes */ 4704b88c807SRodney W. Grimes 4714b88c807SRodney W. Grimes STATIC void 4725134c3f7SWarner Losh pushfile(void) 4735134c3f7SWarner Losh { 4744b88c807SRodney W. Grimes struct parsefile *pf; 4754b88c807SRodney W. Grimes 4764b88c807SRodney W. Grimes parsefile->nleft = parsenleft; 4778f08f33eSPeter Wemm parsefile->lleft = parselleft; 4784b88c807SRodney W. Grimes parsefile->nextc = parsenextc; 4794b88c807SRodney W. Grimes parsefile->linno = plinno; 4804b88c807SRodney W. Grimes pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); 4814b88c807SRodney W. Grimes pf->prev = parsefile; 4824b88c807SRodney W. Grimes pf->fd = -1; 4834b88c807SRodney W. Grimes pf->strpush = NULL; 4844b88c807SRodney W. Grimes pf->basestrpush.prev = NULL; 4854b88c807SRodney W. Grimes parsefile = pf; 4864b88c807SRodney W. Grimes } 4874b88c807SRodney W. Grimes 4884b88c807SRodney W. Grimes 4894b88c807SRodney W. Grimes void 4905134c3f7SWarner Losh popfile(void) 4915134c3f7SWarner Losh { 4924b88c807SRodney W. Grimes struct parsefile *pf = parsefile; 4934b88c807SRodney W. Grimes 4944b88c807SRodney W. Grimes INTOFF; 4954b88c807SRodney W. Grimes if (pf->fd >= 0) 4964b88c807SRodney W. Grimes close(pf->fd); 4974b88c807SRodney W. Grimes if (pf->buf) 4984b88c807SRodney W. Grimes ckfree(pf->buf); 4994b88c807SRodney W. Grimes while (pf->strpush) 5004b88c807SRodney W. Grimes popstring(); 5014b88c807SRodney W. Grimes parsefile = pf->prev; 5024b88c807SRodney W. Grimes ckfree(pf); 5034b88c807SRodney W. Grimes parsenleft = parsefile->nleft; 5048f08f33eSPeter Wemm parselleft = parsefile->lleft; 5054b88c807SRodney W. Grimes parsenextc = parsefile->nextc; 5064b88c807SRodney W. Grimes plinno = parsefile->linno; 5074b88c807SRodney W. Grimes INTON; 5084b88c807SRodney W. Grimes } 5094b88c807SRodney W. Grimes 5104b88c807SRodney W. Grimes 5114b88c807SRodney W. Grimes /* 5124b88c807SRodney W. Grimes * Return to top level. 5134b88c807SRodney W. Grimes */ 5144b88c807SRodney W. Grimes 5154b88c807SRodney W. Grimes void 5165134c3f7SWarner Losh popallfiles(void) 5175134c3f7SWarner Losh { 5184b88c807SRodney W. Grimes while (parsefile != &basepf) 5194b88c807SRodney W. Grimes popfile(); 5204b88c807SRodney W. Grimes } 5214b88c807SRodney W. Grimes 5224b88c807SRodney W. Grimes 5234b88c807SRodney W. Grimes 5244b88c807SRodney W. Grimes /* 5254b88c807SRodney W. Grimes * Close the file(s) that the shell is reading commands from. Called 5264b88c807SRodney W. Grimes * after a fork is done. 5274b88c807SRodney W. Grimes */ 5284b88c807SRodney W. Grimes 5294b88c807SRodney W. Grimes void 5305134c3f7SWarner Losh closescript(void) 5315134c3f7SWarner Losh { 5324b88c807SRodney W. Grimes popallfiles(); 5334b88c807SRodney W. Grimes if (parsefile->fd > 0) { 5344b88c807SRodney W. Grimes close(parsefile->fd); 5354b88c807SRodney W. Grimes parsefile->fd = 0; 5364b88c807SRodney W. Grimes } 5374b88c807SRodney W. Grimes } 538