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 * 3. All advertising materials mentioning features or use of this software 174b88c807SRodney W. Grimes * must display the following acknowledgement: 184b88c807SRodney W. Grimes * This product includes software developed by the University of 194b88c807SRodney W. Grimes * California, Berkeley and its contributors. 204b88c807SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 214b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software 224b88c807SRodney W. Grimes * without specific prior written permission. 234b88c807SRodney W. Grimes * 244b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 254b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 264b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 274b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 284b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 294b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 304b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 314b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 324b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 334b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 344b88c807SRodney W. Grimes * SUCH DAMAGE. 354b88c807SRodney W. Grimes */ 364b88c807SRodney W. Grimes 374b88c807SRodney W. Grimes #ifndef lint 384b88c807SRodney W. Grimes static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 5/31/93"; 394b88c807SRodney W. Grimes #endif /* not lint */ 404b88c807SRodney W. Grimes 414b88c807SRodney W. Grimes /* 424b88c807SRodney W. Grimes * This file implements the input routines used by the parser. 434b88c807SRodney W. Grimes */ 444b88c807SRodney W. Grimes 454b88c807SRodney W. Grimes #include <stdio.h> /* defines BUFSIZ */ 464b88c807SRodney W. Grimes #include "shell.h" 474b88c807SRodney W. Grimes #include <fcntl.h> 484b88c807SRodney W. Grimes #include <errno.h> 494b88c807SRodney W. Grimes #include "syntax.h" 504b88c807SRodney W. Grimes #include "input.h" 514b88c807SRodney W. Grimes #include "output.h" 524b88c807SRodney W. Grimes #include "options.h" 534b88c807SRodney W. Grimes #include "memalloc.h" 544b88c807SRodney W. Grimes #include "error.h" 554b88c807SRodney W. Grimes #include "alias.h" 564b88c807SRodney W. Grimes #include "parser.h" 574b88c807SRodney W. Grimes #include "myhistedit.h" 584b88c807SRodney W. Grimes 594b88c807SRodney W. Grimes #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ 604b88c807SRodney W. Grimes 614b88c807SRodney W. Grimes MKINIT 624b88c807SRodney W. Grimes struct strpush { 634b88c807SRodney W. Grimes struct strpush *prev; /* preceding string on stack */ 644b88c807SRodney W. Grimes char *prevstring; 654b88c807SRodney W. Grimes int prevnleft; 664b88c807SRodney W. Grimes struct alias *ap; /* if push was associated with an alias */ 674b88c807SRodney W. Grimes }; 684b88c807SRodney W. Grimes 694b88c807SRodney W. Grimes /* 704b88c807SRodney W. Grimes * The parsefile structure pointed to by the global variable parsefile 714b88c807SRodney W. Grimes * contains information about the current file being read. 724b88c807SRodney W. Grimes */ 734b88c807SRodney W. Grimes 744b88c807SRodney W. Grimes MKINIT 754b88c807SRodney W. Grimes struct parsefile { 764b88c807SRodney W. Grimes struct parsefile *prev; /* preceding file on stack */ 774b88c807SRodney W. Grimes int linno; /* current line */ 784b88c807SRodney W. Grimes int fd; /* file descriptor (or -1 if string) */ 794b88c807SRodney W. Grimes int nleft; /* number of chars left in buffer */ 804b88c807SRodney W. Grimes char *nextc; /* next char in buffer */ 814b88c807SRodney W. Grimes char *buf; /* input buffer */ 824b88c807SRodney W. Grimes struct strpush *strpush; /* for pushing strings at this level */ 834b88c807SRodney W. Grimes struct strpush basestrpush; /* so pushing one is fast */ 844b88c807SRodney W. Grimes }; 854b88c807SRodney W. Grimes 864b88c807SRodney W. Grimes 874b88c807SRodney W. Grimes int plinno = 1; /* input line number */ 884b88c807SRodney W. Grimes MKINIT int parsenleft; /* copy of parsefile->nleft */ 894b88c807SRodney W. Grimes char *parsenextc; /* copy of parsefile->nextc */ 904b88c807SRodney W. Grimes MKINIT struct parsefile basepf; /* top level input file */ 914b88c807SRodney W. Grimes char basebuf[BUFSIZ]; /* buffer for top level input file */ 924b88c807SRodney W. Grimes struct parsefile *parsefile = &basepf; /* current input file */ 934b88c807SRodney W. Grimes char *pushedstring; /* copy of parsenextc when text pushed back */ 944b88c807SRodney W. Grimes int pushednleft; /* copy of parsenleft when text pushed back */ 954b88c807SRodney W. Grimes int init_editline = 0; /* editline library initialized? */ 964b88c807SRodney W. Grimes int whichprompt; /* 1 == PS1, 2 == PS2 */ 974b88c807SRodney W. Grimes 984b88c807SRodney W. Grimes EditLine *el; /* cookie for editline package */ 994b88c807SRodney W. Grimes 1004b88c807SRodney W. Grimes #ifdef __STDC__ 1014b88c807SRodney W. Grimes STATIC void pushfile(void); 1024b88c807SRodney W. Grimes #else 1034b88c807SRodney W. Grimes STATIC void pushfile(); 1044b88c807SRodney W. Grimes #endif 1054b88c807SRodney W. Grimes 1064b88c807SRodney W. Grimes 1074b88c807SRodney W. Grimes 1084b88c807SRodney W. Grimes #ifdef mkinit 1094b88c807SRodney W. Grimes INCLUDE "input.h" 1104b88c807SRodney W. Grimes INCLUDE "error.h" 1114b88c807SRodney W. Grimes 1124b88c807SRodney W. Grimes INIT { 1134b88c807SRodney W. Grimes extern char basebuf[]; 1144b88c807SRodney W. Grimes 1154b88c807SRodney W. Grimes basepf.nextc = basepf.buf = basebuf; 1164b88c807SRodney W. Grimes } 1174b88c807SRodney W. Grimes 1184b88c807SRodney W. Grimes RESET { 1194b88c807SRodney W. Grimes if (exception != EXSHELLPROC) 1204b88c807SRodney W. Grimes parsenleft = 0; /* clear input buffer */ 1214b88c807SRodney W. Grimes popallfiles(); 1224b88c807SRodney W. Grimes } 1234b88c807SRodney W. Grimes 1244b88c807SRodney W. Grimes SHELLPROC { 1254b88c807SRodney W. Grimes popallfiles(); 1264b88c807SRodney W. Grimes } 1274b88c807SRodney W. Grimes #endif 1284b88c807SRodney W. Grimes 1294b88c807SRodney W. Grimes 1304b88c807SRodney W. Grimes /* 1314b88c807SRodney W. Grimes * Read a line from the script. 1324b88c807SRodney W. Grimes */ 1334b88c807SRodney W. Grimes 1344b88c807SRodney W. Grimes char * 1354b88c807SRodney W. Grimes pfgets(line, len) 1364b88c807SRodney W. Grimes char *line; 1374b88c807SRodney W. Grimes { 1384b88c807SRodney W. Grimes register char *p = line; 1394b88c807SRodney W. Grimes int nleft = len; 1404b88c807SRodney W. Grimes int c; 1414b88c807SRodney W. Grimes 1424b88c807SRodney W. Grimes while (--nleft > 0) { 1434b88c807SRodney W. Grimes c = pgetc_macro(); 1444b88c807SRodney W. Grimes if (c == PEOF) { 1454b88c807SRodney W. Grimes if (p == line) 1464b88c807SRodney W. Grimes return NULL; 1474b88c807SRodney W. Grimes break; 1484b88c807SRodney W. Grimes } 1494b88c807SRodney W. Grimes *p++ = c; 1504b88c807SRodney W. Grimes if (c == '\n') 1514b88c807SRodney W. Grimes break; 1524b88c807SRodney W. Grimes } 1534b88c807SRodney W. Grimes *p = '\0'; 1544b88c807SRodney W. Grimes return line; 1554b88c807SRodney W. Grimes } 1564b88c807SRodney W. Grimes 1574b88c807SRodney W. Grimes 1584b88c807SRodney W. Grimes 1594b88c807SRodney W. Grimes /* 1604b88c807SRodney W. Grimes * Read a character from the script, returning PEOF on end of file. 1614b88c807SRodney W. Grimes * Nul characters in the input are silently discarded. 1624b88c807SRodney W. Grimes */ 1634b88c807SRodney W. Grimes 1644b88c807SRodney W. Grimes int 1654b88c807SRodney W. Grimes pgetc() { 1664b88c807SRodney W. Grimes return pgetc_macro(); 1674b88c807SRodney W. Grimes } 1684b88c807SRodney W. Grimes 1694b88c807SRodney W. Grimes 1704b88c807SRodney W. Grimes /* 1714b88c807SRodney W. Grimes * Refill the input buffer and return the next input character: 1724b88c807SRodney W. Grimes * 1734b88c807SRodney W. Grimes * 1) If a string was pushed back on the input, pop it; 1744b88c807SRodney W. Grimes * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading 1754b88c807SRodney W. Grimes * from a string so we can't refill the buffer, return EOF. 1764b88c807SRodney W. Grimes * 3) Call read to read in the characters. 1774b88c807SRodney W. Grimes * 4) Delete all nul characters from the buffer. 1784b88c807SRodney W. Grimes */ 1794b88c807SRodney W. Grimes 1804b88c807SRodney W. Grimes int 1814b88c807SRodney W. Grimes preadbuffer() { 1824b88c807SRodney W. Grimes register char *p, *q; 1834b88c807SRodney W. Grimes register int i; 1844b88c807SRodney W. Grimes register int something; 1854b88c807SRodney W. Grimes extern EditLine *el; 1864b88c807SRodney W. Grimes 1874b88c807SRodney W. Grimes if (parsefile->strpush) { 1884b88c807SRodney W. Grimes popstring(); 1894b88c807SRodney W. Grimes if (--parsenleft >= 0) 1904b88c807SRodney W. Grimes return (*parsenextc++); 1914b88c807SRodney W. Grimes } 1924b88c807SRodney W. Grimes if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) 1934b88c807SRodney W. Grimes return PEOF; 1944b88c807SRodney W. Grimes flushout(&output); 1954b88c807SRodney W. Grimes flushout(&errout); 1964b88c807SRodney W. Grimes retry: 1974b88c807SRodney W. Grimes p = parsenextc = parsefile->buf; 1984b88c807SRodney W. Grimes if (parsefile->fd == 0 && el) { 1994b88c807SRodney W. Grimes const char *rl_cp; 2004b88c807SRodney W. Grimes int len; 2014b88c807SRodney W. Grimes 2024b88c807SRodney W. Grimes rl_cp = el_gets(el, &len); 2034b88c807SRodney W. Grimes if (rl_cp == NULL) { 2044b88c807SRodney W. Grimes i = 0; 2054b88c807SRodney W. Grimes goto eof; 2064b88c807SRodney W. Grimes } 2074b88c807SRodney W. Grimes strcpy(p, rl_cp); /* XXX - BUFSIZE should redesign so not necessary */ 2084b88c807SRodney W. Grimes i = len; 2094b88c807SRodney W. Grimes 2104b88c807SRodney W. Grimes } else { 2114b88c807SRodney W. Grimes regular_read: 2124b88c807SRodney W. Grimes i = read(parsefile->fd, p, BUFSIZ - 1); 2134b88c807SRodney W. Grimes } 2144b88c807SRodney W. Grimes eof: 2154b88c807SRodney W. Grimes if (i <= 0) { 2164b88c807SRodney W. Grimes if (i < 0) { 2174b88c807SRodney W. Grimes if (errno == EINTR) 2184b88c807SRodney W. Grimes goto retry; 2194b88c807SRodney W. Grimes if (parsefile->fd == 0 && errno == EWOULDBLOCK) { 2204b88c807SRodney W. Grimes int flags = fcntl(0, F_GETFL, 0); 2214b88c807SRodney W. Grimes if (flags >= 0 && flags & O_NONBLOCK) { 2224b88c807SRodney W. Grimes flags &=~ O_NONBLOCK; 2234b88c807SRodney W. Grimes if (fcntl(0, F_SETFL, flags) >= 0) { 2244b88c807SRodney W. Grimes out2str("sh: turning off NDELAY mode\n"); 2254b88c807SRodney W. Grimes goto retry; 2264b88c807SRodney W. Grimes } 2274b88c807SRodney W. Grimes } 2284b88c807SRodney W. Grimes } 2294b88c807SRodney W. Grimes } 2304b88c807SRodney W. Grimes parsenleft = EOF_NLEFT; 2314b88c807SRodney W. Grimes return PEOF; 2324b88c807SRodney W. Grimes } 2334b88c807SRodney W. Grimes parsenleft = i - 1; /* we're returning one char in this call */ 2344b88c807SRodney W. Grimes 2354b88c807SRodney W. Grimes /* delete nul characters */ 2364b88c807SRodney W. Grimes something = 0; 2374b88c807SRodney W. Grimes for (;;) { 2384b88c807SRodney W. Grimes if (*p == '\0') 2394b88c807SRodney W. Grimes break; 2404b88c807SRodney W. Grimes if (*p != ' ' && *p != '\t' && *p != '\n') 2414b88c807SRodney W. Grimes something = 1; 2424b88c807SRodney W. Grimes p++; 2434b88c807SRodney W. Grimes if (--i <= 0) { 2444b88c807SRodney W. Grimes *p = '\0'; 2454b88c807SRodney W. Grimes goto done; /* no nul characters */ 2464b88c807SRodney W. Grimes } 2474b88c807SRodney W. Grimes } 2484b88c807SRodney W. Grimes /* 2494b88c807SRodney W. Grimes * remove nuls 2504b88c807SRodney W. Grimes */ 2514b88c807SRodney W. Grimes q = p++; 2524b88c807SRodney W. Grimes while (--i > 0) { 2534b88c807SRodney W. Grimes if (*p != '\0') 2544b88c807SRodney W. Grimes *q++ = *p; 2554b88c807SRodney W. Grimes p++; 2564b88c807SRodney W. Grimes } 2574b88c807SRodney W. Grimes *q = '\0'; 2584b88c807SRodney W. Grimes if (q == parsefile->buf) 2594b88c807SRodney W. Grimes goto retry; /* buffer contained nothing but nuls */ 2604b88c807SRodney W. Grimes parsenleft = q - parsefile->buf - 1; 2614b88c807SRodney W. Grimes 2624b88c807SRodney W. Grimes done: 2634b88c807SRodney W. Grimes if (parsefile->fd == 0 && hist && something) { 2644b88c807SRodney W. Grimes INTOFF; 2654b88c807SRodney W. Grimes history(hist, whichprompt == 1 ? H_ENTER : H_ADD, 2664b88c807SRodney W. Grimes parsefile->buf); 2674b88c807SRodney W. Grimes INTON; 2684b88c807SRodney W. Grimes } 2694b88c807SRodney W. Grimes if (vflag) { 2704b88c807SRodney W. Grimes /* 2714b88c807SRodney W. Grimes * This isn't right. Most shells coordinate it with 2724b88c807SRodney W. Grimes * reading a line at a time. I honestly don't know if its 2734b88c807SRodney W. Grimes * worth it. 2744b88c807SRodney W. Grimes */ 2754b88c807SRodney W. Grimes i = parsenleft + 1; 2764b88c807SRodney W. Grimes p = parsefile->buf; 2774b88c807SRodney W. Grimes for (; i--; p++) 2784b88c807SRodney W. Grimes out2c(*p) 2794b88c807SRodney W. Grimes flushout(out2); 2804b88c807SRodney W. Grimes } 2814b88c807SRodney W. Grimes return *parsenextc++; 2824b88c807SRodney W. Grimes } 2834b88c807SRodney W. Grimes 2844b88c807SRodney W. Grimes /* 2854b88c807SRodney W. Grimes * Undo the last call to pgetc. Only one character may be pushed back. 2864b88c807SRodney W. Grimes * PEOF may be pushed back. 2874b88c807SRodney W. Grimes */ 2884b88c807SRodney W. Grimes 2894b88c807SRodney W. Grimes void 2904b88c807SRodney W. Grimes pungetc() { 2914b88c807SRodney W. Grimes parsenleft++; 2924b88c807SRodney W. Grimes parsenextc--; 2934b88c807SRodney W. Grimes } 2944b88c807SRodney W. Grimes 2954b88c807SRodney W. Grimes /* 2964b88c807SRodney W. Grimes * Push a string back onto the input at this current parsefile level. 2974b88c807SRodney W. Grimes * We handle aliases this way. 2984b88c807SRodney W. Grimes */ 2994b88c807SRodney W. Grimes void 3004b88c807SRodney W. Grimes pushstring(s, len, ap) 3014b88c807SRodney W. Grimes char *s; 3024b88c807SRodney W. Grimes int len; 3034b88c807SRodney W. Grimes void *ap; 3044b88c807SRodney W. Grimes { 3054b88c807SRodney W. Grimes struct strpush *sp; 3064b88c807SRodney W. Grimes 3074b88c807SRodney W. Grimes INTOFF; 3084b88c807SRodney W. Grimes /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/ 3094b88c807SRodney W. Grimes if (parsefile->strpush) { 3104b88c807SRodney W. Grimes sp = ckmalloc(sizeof (struct strpush)); 3114b88c807SRodney W. Grimes sp->prev = parsefile->strpush; 3124b88c807SRodney W. Grimes parsefile->strpush = sp; 3134b88c807SRodney W. Grimes } else 3144b88c807SRodney W. Grimes sp = parsefile->strpush = &(parsefile->basestrpush); 3154b88c807SRodney W. Grimes sp->prevstring = parsenextc; 3164b88c807SRodney W. Grimes sp->prevnleft = parsenleft; 3174b88c807SRodney W. Grimes sp->ap = (struct alias *)ap; 3184b88c807SRodney W. Grimes if (ap) 3194b88c807SRodney W. Grimes ((struct alias *)ap)->flag |= ALIASINUSE; 3204b88c807SRodney W. Grimes parsenextc = s; 3214b88c807SRodney W. Grimes parsenleft = len; 3224b88c807SRodney W. Grimes INTON; 3234b88c807SRodney W. Grimes } 3244b88c807SRodney W. Grimes 3254b88c807SRodney W. Grimes popstring() 3264b88c807SRodney W. Grimes { 3274b88c807SRodney W. Grimes struct strpush *sp = parsefile->strpush; 3284b88c807SRodney W. Grimes 3294b88c807SRodney W. Grimes INTOFF; 3304b88c807SRodney W. Grimes parsenextc = sp->prevstring; 3314b88c807SRodney W. Grimes parsenleft = sp->prevnleft; 3324b88c807SRodney W. Grimes /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/ 3334b88c807SRodney W. Grimes if (sp->ap) 3344b88c807SRodney W. Grimes sp->ap->flag &= ~ALIASINUSE; 3354b88c807SRodney W. Grimes parsefile->strpush = sp->prev; 3364b88c807SRodney W. Grimes if (sp != &(parsefile->basestrpush)) 3374b88c807SRodney W. Grimes ckfree(sp); 3384b88c807SRodney W. Grimes INTON; 3394b88c807SRodney W. Grimes } 3404b88c807SRodney W. Grimes 3414b88c807SRodney W. Grimes /* 3424b88c807SRodney W. Grimes * Set the input to take input from a file. If push is set, push the 3434b88c807SRodney W. Grimes * old input onto the stack first. 3444b88c807SRodney W. Grimes */ 3454b88c807SRodney W. Grimes 3464b88c807SRodney W. Grimes void 3474b88c807SRodney W. Grimes setinputfile(fname, push) 3484b88c807SRodney W. Grimes char *fname; 3494b88c807SRodney W. Grimes { 3504b88c807SRodney W. Grimes int fd; 3514b88c807SRodney W. Grimes int fd2; 3524b88c807SRodney W. Grimes 3534b88c807SRodney W. Grimes INTOFF; 3544b88c807SRodney W. Grimes if ((fd = open(fname, O_RDONLY)) < 0) 3554b88c807SRodney W. Grimes error("Can't open %s", fname); 3564b88c807SRodney W. Grimes if (fd < 10) { 3574b88c807SRodney W. Grimes fd2 = copyfd(fd, 10); 3584b88c807SRodney W. Grimes close(fd); 3594b88c807SRodney W. Grimes if (fd2 < 0) 3604b88c807SRodney W. Grimes error("Out of file descriptors"); 3614b88c807SRodney W. Grimes fd = fd2; 3624b88c807SRodney W. Grimes } 3634b88c807SRodney W. Grimes setinputfd(fd, push); 3644b88c807SRodney W. Grimes INTON; 3654b88c807SRodney W. Grimes } 3664b88c807SRodney W. Grimes 3674b88c807SRodney W. Grimes 3684b88c807SRodney W. Grimes /* 3694b88c807SRodney W. Grimes * Like setinputfile, but takes an open file descriptor. Call this with 3704b88c807SRodney W. Grimes * interrupts off. 3714b88c807SRodney W. Grimes */ 3724b88c807SRodney W. Grimes 3734b88c807SRodney W. Grimes void 3744b88c807SRodney W. Grimes setinputfd(fd, push) { 3754b88c807SRodney W. Grimes if (push) { 3764b88c807SRodney W. Grimes pushfile(); 3774b88c807SRodney W. Grimes parsefile->buf = ckmalloc(BUFSIZ); 3784b88c807SRodney W. Grimes } 3794b88c807SRodney W. Grimes if (parsefile->fd > 0) 3804b88c807SRodney W. Grimes close(parsefile->fd); 3814b88c807SRodney W. Grimes parsefile->fd = fd; 3824b88c807SRodney W. Grimes if (parsefile->buf == NULL) 3834b88c807SRodney W. Grimes parsefile->buf = ckmalloc(BUFSIZ); 3844b88c807SRodney W. Grimes parsenleft = 0; 3854b88c807SRodney W. Grimes plinno = 1; 3864b88c807SRodney W. Grimes } 3874b88c807SRodney W. Grimes 3884b88c807SRodney W. Grimes 3894b88c807SRodney W. Grimes /* 3904b88c807SRodney W. Grimes * Like setinputfile, but takes input from a string. 3914b88c807SRodney W. Grimes */ 3924b88c807SRodney W. Grimes 3934b88c807SRodney W. Grimes void 3944b88c807SRodney W. Grimes setinputstring(string, push) 3954b88c807SRodney W. Grimes char *string; 3964b88c807SRodney W. Grimes { 3974b88c807SRodney W. Grimes INTOFF; 3984b88c807SRodney W. Grimes if (push) 3994b88c807SRodney W. Grimes pushfile(); 4004b88c807SRodney W. Grimes parsenextc = string; 4014b88c807SRodney W. Grimes parsenleft = strlen(string); 4024b88c807SRodney W. Grimes parsefile->buf = NULL; 4034b88c807SRodney W. Grimes plinno = 1; 4044b88c807SRodney W. Grimes INTON; 4054b88c807SRodney W. Grimes } 4064b88c807SRodney W. Grimes 4074b88c807SRodney W. Grimes 4084b88c807SRodney W. Grimes 4094b88c807SRodney W. Grimes /* 4104b88c807SRodney W. Grimes * To handle the "." command, a stack of input files is used. Pushfile 4114b88c807SRodney W. Grimes * adds a new entry to the stack and popfile restores the previous level. 4124b88c807SRodney W. Grimes */ 4134b88c807SRodney W. Grimes 4144b88c807SRodney W. Grimes STATIC void 4154b88c807SRodney W. Grimes pushfile() { 4164b88c807SRodney W. Grimes struct parsefile *pf; 4174b88c807SRodney W. Grimes 4184b88c807SRodney W. Grimes parsefile->nleft = parsenleft; 4194b88c807SRodney W. Grimes parsefile->nextc = parsenextc; 4204b88c807SRodney W. Grimes parsefile->linno = plinno; 4214b88c807SRodney W. Grimes pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); 4224b88c807SRodney W. Grimes pf->prev = parsefile; 4234b88c807SRodney W. Grimes pf->fd = -1; 4244b88c807SRodney W. Grimes pf->strpush = NULL; 4254b88c807SRodney W. Grimes pf->basestrpush.prev = NULL; 4264b88c807SRodney W. Grimes parsefile = pf; 4274b88c807SRodney W. Grimes } 4284b88c807SRodney W. Grimes 4294b88c807SRodney W. Grimes 4304b88c807SRodney W. Grimes void 4314b88c807SRodney W. Grimes popfile() { 4324b88c807SRodney W. Grimes struct parsefile *pf = parsefile; 4334b88c807SRodney W. Grimes 4344b88c807SRodney W. Grimes INTOFF; 4354b88c807SRodney W. Grimes if (pf->fd >= 0) 4364b88c807SRodney W. Grimes close(pf->fd); 4374b88c807SRodney W. Grimes if (pf->buf) 4384b88c807SRodney W. Grimes ckfree(pf->buf); 4394b88c807SRodney W. Grimes while (pf->strpush) 4404b88c807SRodney W. Grimes popstring(); 4414b88c807SRodney W. Grimes parsefile = pf->prev; 4424b88c807SRodney W. Grimes ckfree(pf); 4434b88c807SRodney W. Grimes parsenleft = parsefile->nleft; 4444b88c807SRodney W. Grimes parsenextc = parsefile->nextc; 4454b88c807SRodney W. Grimes plinno = parsefile->linno; 4464b88c807SRodney W. Grimes INTON; 4474b88c807SRodney W. Grimes } 4484b88c807SRodney W. Grimes 4494b88c807SRodney W. Grimes 4504b88c807SRodney W. Grimes /* 4514b88c807SRodney W. Grimes * Return to top level. 4524b88c807SRodney W. Grimes */ 4534b88c807SRodney W. Grimes 4544b88c807SRodney W. Grimes void 4554b88c807SRodney W. Grimes popallfiles() { 4564b88c807SRodney W. Grimes while (parsefile != &basepf) 4574b88c807SRodney W. Grimes popfile(); 4584b88c807SRodney W. Grimes } 4594b88c807SRodney W. Grimes 4604b88c807SRodney W. Grimes 4614b88c807SRodney W. Grimes 4624b88c807SRodney W. Grimes /* 4634b88c807SRodney W. Grimes * Close the file(s) that the shell is reading commands from. Called 4644b88c807SRodney W. Grimes * after a fork is done. 4654b88c807SRodney W. Grimes */ 4664b88c807SRodney W. Grimes 4674b88c807SRodney W. Grimes void 4684b88c807SRodney W. Grimes closescript() { 4694b88c807SRodney W. Grimes popallfiles(); 4704b88c807SRodney W. Grimes if (parsefile->fd > 0) { 4714b88c807SRodney W. Grimes close(parsefile->fd); 4724b88c807SRodney W. Grimes parsefile->fd = 0; 4734b88c807SRodney W. Grimes } 4744b88c807SRodney W. Grimes } 475