| 1 | /*      $NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc Exp $   */
 | 
|---|
| 2 | 
 | 
|---|
| 3 | /*-
 | 
|---|
| 4 |  * Copyright (c) 1991, 1993
 | 
|---|
| 5 |  *      The Regents of the University of California.  All rights reserved.
 | 
|---|
| 6 |  *
 | 
|---|
| 7 |  * This code is derived from software contributed to Berkeley by
 | 
|---|
| 8 |  * Kenneth Almquist.
 | 
|---|
| 9 |  *
 | 
|---|
| 10 |  * Redistribution and use in source and binary forms, with or without
 | 
|---|
| 11 |  * modification, are permitted provided that the following conditions
 | 
|---|
| 12 |  * are met:
 | 
|---|
| 13 |  * 1. Redistributions of source code must retain the above copyright
 | 
|---|
| 14 |  *    notice, this list of conditions and the following disclaimer.
 | 
|---|
| 15 |  * 2. Redistributions in binary form must reproduce the above copyright
 | 
|---|
| 16 |  *    notice, this list of conditions and the following disclaimer in the
 | 
|---|
| 17 |  *    documentation and/or other materials provided with the distribution.
 | 
|---|
| 18 |  * 3. Neither the name of the University nor the names of its contributors
 | 
|---|
| 19 |  *    may be used to endorse or promote products derived from this software
 | 
|---|
| 20 |  *    without specific prior written permission.
 | 
|---|
| 21 |  *
 | 
|---|
| 22 |  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 | 
|---|
| 23 |  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
|---|
| 24 |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
|---|
| 25 |  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 | 
|---|
| 26 |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
|---|
| 27 |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | 
|---|
| 28 |  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
|---|
| 29 |  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
|---|
| 30 |  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
|---|
| 31 |  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
|---|
| 32 |  * SUCH DAMAGE.
 | 
|---|
| 33 |  */
 | 
|---|
| 34 | 
 | 
|---|
| 35 | #include <sys/cdefs.h>
 | 
|---|
| 36 | #ifndef lint
 | 
|---|
| 37 | #if 0
 | 
|---|
| 38 | static char sccsid[] = "@(#)input.c     8.3 (Berkeley) 6/9/95";
 | 
|---|
| 39 | #else
 | 
|---|
| 40 | __RCSID("$NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc Exp $");
 | 
|---|
| 41 | #endif
 | 
|---|
| 42 | #endif /* not lint */
 | 
|---|
| 43 | 
 | 
|---|
| 44 | #include <stdio.h>      /* defines BUFSIZ */
 | 
|---|
| 45 | #include <fcntl.h>
 | 
|---|
| 46 | #include <errno.h>
 | 
|---|
| 47 | #include <unistd.h>
 | 
|---|
| 48 | #include <stdlib.h>
 | 
|---|
| 49 | #include <string.h>
 | 
|---|
| 50 | 
 | 
|---|
| 51 | /*
 | 
|---|
| 52 |  * This file implements the input routines used by the parser.
 | 
|---|
| 53 |  */
 | 
|---|
| 54 | 
 | 
|---|
| 55 | #include "shell.h"
 | 
|---|
| 56 | #include "redir.h"
 | 
|---|
| 57 | #include "syntax.h"
 | 
|---|
| 58 | #include "input.h"
 | 
|---|
| 59 | #include "output.h"
 | 
|---|
| 60 | #include "options.h"
 | 
|---|
| 61 | #include "memalloc.h"
 | 
|---|
| 62 | #include "error.h"
 | 
|---|
| 63 | #include "alias.h"
 | 
|---|
| 64 | #include "parser.h"
 | 
|---|
| 65 | #include "myhistedit.h"
 | 
|---|
| 66 | 
 | 
|---|
| 67 | #define EOF_NLEFT -99           /* value of parsenleft when EOF pushed back */
 | 
|---|
| 68 | 
 | 
|---|
| 69 | MKINIT
 | 
|---|
| 70 | struct strpush {
 | 
|---|
| 71 |         struct strpush *prev;   /* preceding string on stack */
 | 
|---|
| 72 |         char *prevstring;
 | 
|---|
| 73 |         int prevnleft;
 | 
|---|
| 74 |         int prevlleft;
 | 
|---|
| 75 |         struct alias *ap;       /* if push was associated with an alias */
 | 
|---|
| 76 | };
 | 
|---|
| 77 | 
 | 
|---|
| 78 | /*
 | 
|---|
| 79 |  * The parsefile structure pointed to by the global variable parsefile
 | 
|---|
| 80 |  * contains information about the current file being read.
 | 
|---|
| 81 |  */
 | 
|---|
| 82 | 
 | 
|---|
| 83 | MKINIT
 | 
|---|
| 84 | struct parsefile {
 | 
|---|
| 85 |         struct parsefile *prev; /* preceding file on stack */
 | 
|---|
| 86 |         int linno;              /* current line */
 | 
|---|
| 87 |         int fd;                 /* file descriptor (or -1 if string) */
 | 
|---|
| 88 |         int nleft;              /* number of chars left in this line */
 | 
|---|
| 89 |         int lleft;              /* number of chars left in this buffer */
 | 
|---|
| 90 |         char *nextc;            /* next char in buffer */
 | 
|---|
| 91 |         char *buf;              /* input buffer */
 | 
|---|
| 92 |         struct strpush *strpush; /* for pushing strings at this level */
 | 
|---|
| 93 |         struct strpush basestrpush; /* so pushing one is fast */
 | 
|---|
| 94 | };
 | 
|---|
| 95 | 
 | 
|---|
| 96 | 
 | 
|---|
| 97 | int plinno = 1;                 /* input line number */
 | 
|---|
| 98 | int parsenleft;                 /* copy of parsefile->nleft */
 | 
|---|
| 99 | MKINIT int parselleft;          /* copy of parsefile->lleft */
 | 
|---|
| 100 | char *parsenextc;               /* copy of parsefile->nextc */
 | 
|---|
| 101 | MKINIT struct parsefile basepf; /* top level input file */
 | 
|---|
| 102 | MKINIT char basebuf[BUFSIZ];    /* buffer for top level input file */
 | 
|---|
| 103 | struct parsefile *parsefile = &basepf;  /* current input file */
 | 
|---|
| 104 | int init_editline = 0;          /* editline library initialized? */
 | 
|---|
| 105 | int whichprompt;                /* 1 == PS1, 2 == PS2 */
 | 
|---|
| 106 | 
 | 
|---|
| 107 | #ifndef SMALL
 | 
|---|
| 108 | EditLine *el;                   /* cookie for editline package */
 | 
|---|
| 109 | #endif
 | 
|---|
| 110 | 
 | 
|---|
| 111 | STATIC void pushfile(void);
 | 
|---|
| 112 | static int preadfd(void);
 | 
|---|
| 113 | 
 | 
|---|
| 114 | #ifdef mkinit
 | 
|---|
| 115 | INCLUDE <stdio.h>
 | 
|---|
| 116 | INCLUDE "input.h"
 | 
|---|
| 117 | INCLUDE "error.h"
 | 
|---|
| 118 | 
 | 
|---|
| 119 | INIT {
 | 
|---|
| 120 |         basepf.nextc = basepf.buf = basebuf;
 | 
|---|
| 121 | }
 | 
|---|
| 122 | 
 | 
|---|
| 123 | RESET {
 | 
|---|
| 124 |         if (exception != EXSHELLPROC)
 | 
|---|
| 125 |                 parselleft = parsenleft = 0;    /* clear input buffer */
 | 
|---|
| 126 |         popallfiles();
 | 
|---|
| 127 | }
 | 
|---|
| 128 | 
 | 
|---|
| 129 | SHELLPROC {
 | 
|---|
| 130 |         popallfiles();
 | 
|---|
| 131 | }
 | 
|---|
| 132 | #endif
 | 
|---|
| 133 | 
 | 
|---|
| 134 | 
 | 
|---|
| 135 | /*
 | 
|---|
| 136 |  * Read a line from the script.
 | 
|---|
| 137 |  */
 | 
|---|
| 138 | 
 | 
|---|
| 139 | char *
 | 
|---|
| 140 | pfgets(char *line, int len)
 | 
|---|
| 141 | {
 | 
|---|
| 142 |         char *p = line;
 | 
|---|
| 143 |         int nleft = len;
 | 
|---|
| 144 |         int c;
 | 
|---|
| 145 | 
 | 
|---|
| 146 |         while (--nleft > 0) {
 | 
|---|
| 147 |                 c = pgetc_macro();
 | 
|---|
| 148 |                 if (c == PEOF) {
 | 
|---|
| 149 |                         if (p == line)
 | 
|---|
| 150 |                                 return NULL;
 | 
|---|
| 151 |                         break;
 | 
|---|
| 152 |                 }
 | 
|---|
| 153 |                 *p++ = c;
 | 
|---|
| 154 |                 if (c == '\n')
 | 
|---|
| 155 |                         break;
 | 
|---|
| 156 |         }
 | 
|---|
| 157 |         *p = '\0';
 | 
|---|
| 158 |         return line;
 | 
|---|
| 159 | }
 | 
|---|
| 160 | 
 | 
|---|
| 161 | 
 | 
|---|
| 162 | 
 | 
|---|
| 163 | /*
 | 
|---|
| 164 |  * Read a character from the script, returning PEOF on end of file.
 | 
|---|
| 165 |  * Nul characters in the input are silently discarded.
 | 
|---|
| 166 |  */
 | 
|---|
| 167 | 
 | 
|---|
| 168 | int
 | 
|---|
| 169 | pgetc(void)
 | 
|---|
| 170 | {
 | 
|---|
| 171 |         return pgetc_macro();
 | 
|---|
| 172 | }
 | 
|---|
| 173 | 
 | 
|---|
| 174 | 
 | 
|---|
| 175 | static int
 | 
|---|
| 176 | preadfd(void)
 | 
|---|
| 177 | {
 | 
|---|
| 178 |         int nr;
 | 
|---|
| 179 |         char *buf =  parsefile->buf;
 | 
|---|
| 180 |         parsenextc = buf;
 | 
|---|
| 181 | 
 | 
|---|
| 182 | retry:
 | 
|---|
| 183 | #ifndef SMALL
 | 
|---|
| 184 |         if (parsefile->fd == 0 && el) {
 | 
|---|
| 185 |                 static const char *rl_cp;
 | 
|---|
| 186 |                 static int el_len;
 | 
|---|
| 187 | 
 | 
|---|
| 188 |                 if (rl_cp == NULL)
 | 
|---|
| 189 |                         rl_cp = el_gets(el, &el_len);
 | 
|---|
| 190 |                 if (rl_cp == NULL)
 | 
|---|
| 191 |                         nr = 0;
 | 
|---|
| 192 |                 else {
 | 
|---|
| 193 |                         nr = el_len;
 | 
|---|
| 194 |                         if (nr > BUFSIZ - 8)
 | 
|---|
| 195 |                                 nr = BUFSIZ - 8;
 | 
|---|
| 196 |                         memcpy(buf, rl_cp, nr);
 | 
|---|
| 197 |                         if (nr != el_len) {
 | 
|---|
| 198 |                                 el_len -= nr;
 | 
|---|
| 199 |                                 rl_cp += nr;
 | 
|---|
| 200 |                         } else
 | 
|---|
| 201 |                                 rl_cp = 0;
 | 
|---|
| 202 |                 }
 | 
|---|
| 203 | 
 | 
|---|
| 204 |         } else
 | 
|---|
| 205 | #endif
 | 
|---|
| 206 |                 nr = read(parsefile->fd, buf, BUFSIZ - 8);
 | 
|---|
| 207 | 
 | 
|---|
| 208 | 
 | 
|---|
| 209 |         if (nr <= 0) {
 | 
|---|
| 210 |                 if (nr < 0) {
 | 
|---|
| 211 |                         if (errno == EINTR)
 | 
|---|
| 212 |                                 goto retry;
 | 
|---|
| 213 |                         if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
 | 
|---|
| 214 |                                 int flags = fcntl(0, F_GETFL, 0);
 | 
|---|
| 215 |                                 if (flags >= 0 && flags & O_NONBLOCK) {
 | 
|---|
| 216 |                                         flags &=~ O_NONBLOCK;
 | 
|---|
| 217 |                                         if (fcntl(0, F_SETFL, flags) >= 0) {
 | 
|---|
| 218 |                                                 out2str("sh: turning off NDELAY mode\n");
 | 
|---|
| 219 |                                                 goto retry;
 | 
|---|
| 220 |                                         }
 | 
|---|
| 221 |                                 }
 | 
|---|
| 222 |                         }
 | 
|---|
| 223 |                 }
 | 
|---|
| 224 |                 nr = -1;
 | 
|---|
| 225 |         }
 | 
|---|
| 226 |         return nr;
 | 
|---|
| 227 | }
 | 
|---|
| 228 | 
 | 
|---|
| 229 | /*
 | 
|---|
| 230 |  * Refill the input buffer and return the next input character:
 | 
|---|
| 231 |  *
 | 
|---|
| 232 |  * 1) If a string was pushed back on the input, pop it;
 | 
|---|
| 233 |  * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
 | 
|---|
| 234 |  *    from a string so we can't refill the buffer, return EOF.
 | 
|---|
| 235 |  * 3) If the is more stuff in this buffer, use it else call read to fill it.
 | 
|---|
| 236 |  * 4) Process input up to the next newline, deleting nul characters.
 | 
|---|
| 237 |  */
 | 
|---|
| 238 | 
 | 
|---|
| 239 | int
 | 
|---|
| 240 | preadbuffer(void)
 | 
|---|
| 241 | {
 | 
|---|
| 242 |         char *p, *q;
 | 
|---|
| 243 |         int more;
 | 
|---|
| 244 |         int something;
 | 
|---|
| 245 |         char savec;
 | 
|---|
| 246 | 
 | 
|---|
| 247 |         if (parsefile->strpush) {
 | 
|---|
| 248 |                 popstring();
 | 
|---|
| 249 |                 if (--parsenleft >= 0)
 | 
|---|
| 250 |                         return (*parsenextc++);
 | 
|---|
| 251 |         }
 | 
|---|
| 252 |         if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
 | 
|---|
| 253 |                 return PEOF;
 | 
|---|
| 254 |         flushout(&output);
 | 
|---|
| 255 |         flushout(&errout);
 | 
|---|
| 256 | 
 | 
|---|
| 257 | again:
 | 
|---|
| 258 |         if (parselleft <= 0) {
 | 
|---|
| 259 |                 if ((parselleft = preadfd()) == -1) {
 | 
|---|
| 260 |                         parselleft = parsenleft = EOF_NLEFT;
 | 
|---|
| 261 |                         return PEOF;
 | 
|---|
| 262 |                 }
 | 
|---|
| 263 |         }
 | 
|---|
| 264 | 
 | 
|---|
| 265 |         q = p = parsenextc;
 | 
|---|
| 266 | 
 | 
|---|
| 267 |         /* delete nul characters */
 | 
|---|
| 268 |         something = 0;
 | 
|---|
| 269 |         for (more = 1; more;) {
 | 
|---|
| 270 |                 switch (*p) {
 | 
|---|
| 271 |                 case '\0':
 | 
|---|
| 272 |                         p++;    /* Skip nul */
 | 
|---|
| 273 |                         goto check;
 | 
|---|
| 274 | 
 | 
|---|
| 275 |                 case '\t':
 | 
|---|
| 276 |                 case ' ':
 | 
|---|
| 277 |                         break;
 | 
|---|
| 278 | 
 | 
|---|
| 279 |                 case '\n':
 | 
|---|
| 280 |                         parsenleft = q - parsenextc;
 | 
|---|
| 281 |                         more = 0; /* Stop processing here */
 | 
|---|
| 282 |                         break;
 | 
|---|
| 283 | 
 | 
|---|
| 284 |                 default:
 | 
|---|
| 285 |                         something = 1;
 | 
|---|
| 286 |                         break;
 | 
|---|
| 287 |                 }
 | 
|---|
| 288 | 
 | 
|---|
| 289 |                 *q++ = *p++;
 | 
|---|
| 290 | check:
 | 
|---|
| 291 |                 if (--parselleft <= 0) {
 | 
|---|
| 292 |                         parsenleft = q - parsenextc - 1;
 | 
|---|
| 293 |                         if (parsenleft < 0)
 | 
|---|
| 294 |                                 goto again;
 | 
|---|
| 295 |                         *q = '\0';
 | 
|---|
| 296 |                         more = 0;
 | 
|---|
| 297 |                 }
 | 
|---|
| 298 |         }
 | 
|---|
| 299 | 
 | 
|---|
| 300 |         savec = *q;
 | 
|---|
| 301 |         *q = '\0';
 | 
|---|
| 302 | 
 | 
|---|
| 303 | #ifndef SMALL
 | 
|---|
| 304 |         if (parsefile->fd == 0 && hist && something) {
 | 
|---|
| 305 |                 HistEvent he;
 | 
|---|
| 306 |                 INTOFF;
 | 
|---|
| 307 |                 history(hist, &he, whichprompt == 1? H_ENTER : H_APPEND,
 | 
|---|
| 308 |                     parsenextc);
 | 
|---|
| 309 |                 INTON;
 | 
|---|
| 310 |         }
 | 
|---|
| 311 | #endif
 | 
|---|
| 312 | 
 | 
|---|
| 313 |         if (vflag) {
 | 
|---|
| 314 |                 out2str(parsenextc);
 | 
|---|
| 315 |                 flushout(out2);
 | 
|---|
| 316 |         }
 | 
|---|
| 317 | 
 | 
|---|
| 318 |         *q = savec;
 | 
|---|
| 319 | 
 | 
|---|
| 320 |         return *parsenextc++;
 | 
|---|
| 321 | }
 | 
|---|
| 322 | 
 | 
|---|
| 323 | /*
 | 
|---|
| 324 |  * Undo the last call to pgetc.  Only one character may be pushed back.
 | 
|---|
| 325 |  * PEOF may be pushed back.
 | 
|---|
| 326 |  */
 | 
|---|
| 327 | 
 | 
|---|
| 328 | void
 | 
|---|
| 329 | pungetc(void)
 | 
|---|
| 330 | {
 | 
|---|
| 331 |         parsenleft++;
 | 
|---|
| 332 |         parsenextc--;
 | 
|---|
| 333 | }
 | 
|---|
| 334 | 
 | 
|---|
| 335 | /*
 | 
|---|
| 336 |  * Push a string back onto the input at this current parsefile level.
 | 
|---|
| 337 |  * We handle aliases this way.
 | 
|---|
| 338 |  */
 | 
|---|
| 339 | void
 | 
|---|
| 340 | pushstring(char *s, int len, void *ap)
 | 
|---|
| 341 | {
 | 
|---|
| 342 |         struct strpush *sp;
 | 
|---|
| 343 | 
 | 
|---|
| 344 |         INTOFF;
 | 
|---|
| 345 | /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
 | 
|---|
| 346 |         if (parsefile->strpush) {
 | 
|---|
| 347 |                 sp = ckmalloc(sizeof (struct strpush));
 | 
|---|
| 348 |                 sp->prev = parsefile->strpush;
 | 
|---|
| 349 |                 parsefile->strpush = sp;
 | 
|---|
| 350 |         } else
 | 
|---|
| 351 |                 sp = parsefile->strpush = &(parsefile->basestrpush);
 | 
|---|
| 352 |         sp->prevstring = parsenextc;
 | 
|---|
| 353 |         sp->prevnleft = parsenleft;
 | 
|---|
| 354 |         sp->prevlleft = parselleft;
 | 
|---|
| 355 |         sp->ap = (struct alias *)ap;
 | 
|---|
| 356 |         if (ap)
 | 
|---|
| 357 |                 ((struct alias *)ap)->flag |= ALIASINUSE;
 | 
|---|
| 358 |         parsenextc = s;
 | 
|---|
| 359 |         parsenleft = len;
 | 
|---|
| 360 |         INTON;
 | 
|---|
| 361 | }
 | 
|---|
| 362 | 
 | 
|---|
| 363 | void
 | 
|---|
| 364 | popstring(void)
 | 
|---|
| 365 | {
 | 
|---|
| 366 |         struct strpush *sp = parsefile->strpush;
 | 
|---|
| 367 | 
 | 
|---|
| 368 |         INTOFF;
 | 
|---|
| 369 |         parsenextc = sp->prevstring;
 | 
|---|
| 370 |         parsenleft = sp->prevnleft;
 | 
|---|
| 371 |         parselleft = sp->prevlleft;
 | 
|---|
| 372 | /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
 | 
|---|
| 373 |         if (sp->ap)
 | 
|---|
| 374 |                 sp->ap->flag &= ~ALIASINUSE;
 | 
|---|
| 375 |         parsefile->strpush = sp->prev;
 | 
|---|
| 376 |         if (sp != &(parsefile->basestrpush))
 | 
|---|
| 377 |                 ckfree(sp);
 | 
|---|
| 378 |         INTON;
 | 
|---|
| 379 | }
 | 
|---|
| 380 | 
 | 
|---|
| 381 | /*
 | 
|---|
| 382 |  * Set the input to take input from a file.  If push is set, push the
 | 
|---|
| 383 |  * old input onto the stack first.
 | 
|---|
| 384 |  */
 | 
|---|
| 385 | 
 | 
|---|
| 386 | void
 | 
|---|
| 387 | setinputfile(const char *fname, int push)
 | 
|---|
| 388 | {
 | 
|---|
| 389 |         int fd;
 | 
|---|
| 390 |         int fd2;
 | 
|---|
| 391 | 
 | 
|---|
| 392 |         INTOFF;
 | 
|---|
| 393 |         if ((fd = open(fname, O_RDONLY)) < 0)
 | 
|---|
| 394 |                 error("Can't open %s", fname);
 | 
|---|
| 395 |         if (fd < 10) {
 | 
|---|
| 396 |                 fd2 = copyfd(fd, 10);
 | 
|---|
| 397 |                 close(fd);
 | 
|---|
| 398 |                 if (fd2 < 0)
 | 
|---|
| 399 |                         error("Out of file descriptors");
 | 
|---|
| 400 |                 fd = fd2;
 | 
|---|
| 401 |         }
 | 
|---|
| 402 |         setinputfd(fd, push);
 | 
|---|
| 403 |         INTON;
 | 
|---|
| 404 | }
 | 
|---|
| 405 | 
 | 
|---|
| 406 | 
 | 
|---|
| 407 | /*
 | 
|---|
| 408 |  * Like setinputfile, but takes an open file descriptor.  Call this with
 | 
|---|
| 409 |  * interrupts off.
 | 
|---|
| 410 |  */
 | 
|---|
| 411 | 
 | 
|---|
| 412 | void
 | 
|---|
| 413 | setinputfd(int fd, int push)
 | 
|---|
| 414 | {
 | 
|---|
| 415 |         (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
 | 
|---|
| 416 |         if (push) {
 | 
|---|
| 417 |                 pushfile();
 | 
|---|
| 418 |                 parsefile->buf = ckmalloc(BUFSIZ);
 | 
|---|
| 419 |         }
 | 
|---|
| 420 |         if (parsefile->fd > 0)
 | 
|---|
| 421 |                 close(parsefile->fd);
 | 
|---|
| 422 |         parsefile->fd = fd;
 | 
|---|
| 423 |         if (parsefile->buf == NULL)
 | 
|---|
| 424 |                 parsefile->buf = ckmalloc(BUFSIZ);
 | 
|---|
| 425 |         parselleft = parsenleft = 0;
 | 
|---|
| 426 |         plinno = 1;
 | 
|---|
| 427 | }
 | 
|---|
| 428 | 
 | 
|---|
| 429 | 
 | 
|---|
| 430 | /*
 | 
|---|
| 431 |  * Like setinputfile, but takes input from a string.
 | 
|---|
| 432 |  */
 | 
|---|
| 433 | 
 | 
|---|
| 434 | void
 | 
|---|
| 435 | setinputstring(char *string, int push)
 | 
|---|
| 436 | {
 | 
|---|
| 437 |         INTOFF;
 | 
|---|
| 438 |         if (push)
 | 
|---|
| 439 |                 pushfile();
 | 
|---|
| 440 |         parsenextc = string;
 | 
|---|
| 441 |         parselleft = parsenleft = strlen(string);
 | 
|---|
| 442 |         parsefile->buf = NULL;
 | 
|---|
| 443 |         plinno = 1;
 | 
|---|
| 444 |         INTON;
 | 
|---|
| 445 | }
 | 
|---|
| 446 | 
 | 
|---|
| 447 | 
 | 
|---|
| 448 | 
 | 
|---|
| 449 | /*
 | 
|---|
| 450 |  * To handle the "." command, a stack of input files is used.  Pushfile
 | 
|---|
| 451 |  * adds a new entry to the stack and popfile restores the previous level.
 | 
|---|
| 452 |  */
 | 
|---|
| 453 | 
 | 
|---|
| 454 | STATIC void
 | 
|---|
| 455 | pushfile(void)
 | 
|---|
| 456 | {
 | 
|---|
| 457 |         struct parsefile *pf;
 | 
|---|
| 458 | 
 | 
|---|
| 459 |         parsefile->nleft = parsenleft;
 | 
|---|
| 460 |         parsefile->lleft = parselleft;
 | 
|---|
| 461 |         parsefile->nextc = parsenextc;
 | 
|---|
| 462 |         parsefile->linno = plinno;
 | 
|---|
| 463 |         pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
 | 
|---|
| 464 |         pf->prev = parsefile;
 | 
|---|
| 465 |         pf->fd = -1;
 | 
|---|
| 466 |         pf->strpush = NULL;
 | 
|---|
| 467 |         pf->basestrpush.prev = NULL;
 | 
|---|
| 468 |         parsefile = pf;
 | 
|---|
| 469 | }
 | 
|---|
| 470 | 
 | 
|---|
| 471 | 
 | 
|---|
| 472 | void
 | 
|---|
| 473 | popfile(void)
 | 
|---|
| 474 | {
 | 
|---|
| 475 |         struct parsefile *pf = parsefile;
 | 
|---|
| 476 | 
 | 
|---|
| 477 |         INTOFF;
 | 
|---|
| 478 |         if (pf->fd >= 0)
 | 
|---|
| 479 |                 close(pf->fd);
 | 
|---|
| 480 |         if (pf->buf)
 | 
|---|
| 481 |                 ckfree(pf->buf);
 | 
|---|
| 482 |         while (pf->strpush)
 | 
|---|
| 483 |                 popstring();
 | 
|---|
| 484 |         parsefile = pf->prev;
 | 
|---|
| 485 |         ckfree(pf);
 | 
|---|
| 486 |         parsenleft = parsefile->nleft;
 | 
|---|
| 487 |         parselleft = parsefile->lleft;
 | 
|---|
| 488 |         parsenextc = parsefile->nextc;
 | 
|---|
| 489 |         plinno = parsefile->linno;
 | 
|---|
| 490 |         INTON;
 | 
|---|
| 491 | }
 | 
|---|
| 492 | 
 | 
|---|
| 493 | 
 | 
|---|
| 494 | /*
 | 
|---|
| 495 |  * Return to top level.
 | 
|---|
| 496 |  */
 | 
|---|
| 497 | 
 | 
|---|
| 498 | void
 | 
|---|
| 499 | popallfiles(void)
 | 
|---|
| 500 | {
 | 
|---|
| 501 |         while (parsefile != &basepf)
 | 
|---|
| 502 |                 popfile();
 | 
|---|
| 503 | }
 | 
|---|
| 504 | 
 | 
|---|
| 505 | 
 | 
|---|
| 506 | 
 | 
|---|
| 507 | /*
 | 
|---|
| 508 |  * Close the file(s) that the shell is reading commands from.  Called
 | 
|---|
| 509 |  * after a fork is done.
 | 
|---|
| 510 |  *
 | 
|---|
| 511 |  * Takes one arg, vfork, which tells it to not modify its global vars
 | 
|---|
| 512 |  * as it is still running in the parent.
 | 
|---|
| 513 |  *
 | 
|---|
| 514 |  * This code is (probably) unnecessary as the 'close on exec' flag is
 | 
|---|
| 515 |  * set and should be enough.  In the vfork case it is definitely wrong
 | 
|---|
| 516 |  * to close the fds as another fork() may be done later to feed data
 | 
|---|
| 517 |  * from a 'here' document into a pipe and we don't want to close the
 | 
|---|
| 518 |  * pipe!
 | 
|---|
| 519 |  */
 | 
|---|
| 520 | 
 | 
|---|
| 521 | void
 | 
|---|
| 522 | closescript(int vforked)
 | 
|---|
| 523 | {
 | 
|---|
| 524 |         if (vforked)
 | 
|---|
| 525 |                 return;
 | 
|---|
| 526 |         popallfiles();
 | 
|---|
| 527 |         if (parsefile->fd > 0) {
 | 
|---|
| 528 |                 close(parsefile->fd);
 | 
|---|
| 529 |                 parsefile->fd = 0;
 | 
|---|
| 530 |         }
 | 
|---|
| 531 | }
 | 
|---|