1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 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 <stdio.h> /* defines BUFSIZ */ 36 #include <fcntl.h> 37 #include <errno.h> 38 #include <unistd.h> 39 #include <stdlib.h> 40 #include <string.h> 41 42 /* 43 * This file implements the input routines used by the parser. 44 */ 45 46 #include "shell.h" 47 #include "redir.h" 48 #include "syntax.h" 49 #include "input.h" 50 #include "output.h" 51 #include "options.h" 52 #include "memalloc.h" 53 #include "error.h" 54 #include "alias.h" 55 #include "parser.h" 56 #ifndef NO_HISTORY 57 #include "myhistedit.h" 58 #endif 59 #include "trap.h" 60 61 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ 62 63 struct strpush { 64 struct strpush *prev; /* preceding string on stack */ 65 const char *prevstring; 66 int prevnleft; 67 int prevlleft; 68 struct alias *ap; /* if push was associated with an alias */ 69 }; 70 71 /* 72 * The parsefile structure pointed to by the global variable parsefile 73 * contains information about the current file being read. 74 */ 75 76 struct parsefile { 77 struct parsefile *prev; /* preceding file on stack */ 78 int linno; /* current line */ 79 int fd; /* file descriptor (or -1 if string) */ 80 int nleft; /* number of chars left in this line */ 81 int lleft; /* number of lines left in this buffer */ 82 const char *nextc; /* next char in buffer */ 83 char *buf; /* input buffer */ 84 size_t bufsize; /* input buffer size */ 85 struct strpush *strpush; /* for pushing strings at this level */ 86 struct strpush basestrpush; /* so pushing one is fast */ 87 }; 88 89 90 int plinno = 1; /* input line number */ 91 int parsenleft; /* copy of parsefile->nleft */ 92 static int parselleft; /* copy of parsefile->lleft */ 93 const char *parsenextc; /* copy of parsefile->nextc */ 94 static char basebuf[BUFSIZ + 1];/* buffer for top level input file */ 95 static struct parsefile basepf = { /* top level input file */ 96 .nextc = basebuf, 97 .buf = basebuf, 98 .bufsize = sizeof(basebuf), 99 }; 100 static struct parsefile *parsefile = &basepf; /* current input file */ 101 int whichprompt; /* 1 == PS1, 2 == PS2 */ 102 103 static void pushfile(void); 104 static int preadfd(void); 105 static void popstring(void); 106 107 void 108 resetinput(void) 109 { 110 popallfiles(); 111 parselleft = parsenleft = 0; /* clear input buffer */ 112 } 113 114 115 116 /* 117 * Read a character from the script, returning PEOF on end of file. 118 * Nul characters in the input are silently discarded. 119 */ 120 121 int 122 pgetc(void) 123 { 124 return pgetc_macro(); 125 } 126 127 128 static int 129 preadfd(void) 130 { 131 int nr; 132 133 retry: 134 #ifndef NO_HISTORY 135 if (parsefile->fd == 0 && el) { 136 const char *line; 137 138 el_resize(el); 139 line = el_gets(el, &nr); 140 if (nr > 0 && parsefile->bufsize < (size_t)nr + 1) { 141 size_t bufsize; 142 143 INTOFF; 144 if (parsefile->buf != basebuf) { 145 ckfree(parsefile->buf); 146 parsefile->buf = NULL; 147 parsefile->bufsize = 0; 148 } 149 bufsize = (size_t)nr + BUFSIZ + 1; 150 bufsize -= bufsize % BUFSIZ; 151 parsefile->buf = ckmalloc(bufsize); 152 parsefile->bufsize = bufsize; 153 INTON; 154 } 155 if (nr > 0 && line != NULL) 156 memcpy(parsefile->buf, line, nr); 157 else 158 nr = nr ? -1 : 0; 159 } else 160 #endif 161 nr = read(parsefile->fd, parsefile->buf, parsefile->bufsize - 1); 162 163 if (nr < 0) 164 switch (errno) { 165 int flags; 166 167 case EINTR: 168 goto retry; 169 case EWOULDBLOCK: 170 if (parsefile->fd != 0) 171 break; 172 if ((flags = fcntl(0, F_GETFL, 0)) < 0) 173 break; 174 if (!(flags & O_NONBLOCK)) 175 break; 176 if (fcntl(0, F_SETFL, flags & ~O_NONBLOCK) < 0) 177 break; 178 out2fmt_flush("sh: turning off NDELAY mode\n"); 179 goto retry; 180 } 181 else if (nr > 0) 182 parsefile->buf[nr] = '\0'; 183 else 184 nr = -1; 185 186 parsenextc = parsefile->buf; 187 return nr; 188 } 189 190 /* 191 * Refill the input buffer and return the next input character: 192 * 193 * 1) If a string was pushed back on the input, pop it; 194 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading 195 * from a string so we can't refill the buffer, return EOF. 196 * 3) If there is more in this buffer, use it else call read to fill it. 197 * 4) Process input up to the next newline, deleting nul characters. 198 */ 199 200 int 201 preadbuffer(void) 202 { 203 const char *end; 204 char *q, *r; 205 char savec; 206 207 while (parsefile->strpush) { 208 /* 209 * Add a space to the end of an alias to ensure that the 210 * alias remains in use while parsing its last word. 211 * This avoids alias recursions. 212 */ 213 if (parsenleft == -1 && parsefile->strpush->ap != NULL) 214 return ' '; 215 popstring(); 216 if (--parsenleft >= 0) 217 return (*parsenextc++); 218 } 219 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) 220 return PEOF; 221 222 again: 223 if (parselleft <= 0 && (parselleft = preadfd()) == -1) { 224 parselleft = parsenleft = EOF_NLEFT; 225 return (PEOF); 226 } 227 end = parsenextc + parselleft; 228 q = strchrnul(parsenextc, '\n'); 229 if (*q == '\0' && q != end) { 230 /* delete nul characters */ 231 for (r = q++; q != end; q++) 232 if (*q != '\0') 233 *r++ = *q; 234 *r = '\0'; 235 parselleft = r - parsenextc; 236 goto again; 237 } 238 if (*q == '\0') { 239 parsenleft = parselleft; 240 parselleft = 0; 241 } else /* *q == '\n' */ { 242 q++; 243 parsenleft = q - parsenextc; 244 parselleft -= parsenleft; 245 } 246 parsenleft--; 247 248 savec = *q; 249 *q = '\0'; 250 251 #ifndef NO_HISTORY 252 if (parsefile->fd == 0 && hist && 253 parsenextc[strspn(parsenextc, " \t\n")] != '\0') { 254 HistEvent he; 255 INTOFF; 256 history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD, 257 parsenextc); 258 INTON; 259 } 260 #endif 261 262 if (vflag) { 263 out2str(parsenextc); 264 flushout(out2); 265 } 266 267 *q = savec; 268 269 return *parsenextc++; 270 } 271 272 /* 273 * Returns if we are certain we are at EOF. Does not cause any more input 274 * to be read from the outside world. 275 */ 276 277 int 278 preadateof(void) 279 { 280 if (parsenleft > 0) 281 return 0; 282 if (parsefile->strpush) 283 return 0; 284 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) 285 return 1; 286 return 0; 287 } 288 289 /* 290 * Undo the last call to pgetc. Only one character may be pushed back. 291 * PEOF may be pushed back. 292 */ 293 294 void 295 pungetc(void) 296 { 297 parsenleft++; 298 parsenextc--; 299 } 300 301 /* 302 * Push a string back onto the input at this current parsefile level. 303 * We handle aliases this way. 304 */ 305 void 306 pushstring(const char *s, int len, struct alias *ap) 307 { 308 struct strpush *sp; 309 310 INTOFF; 311 /*out2fmt_flush("*** calling pushstring: %s, %d\n", s, len);*/ 312 if (parsefile->strpush) { 313 sp = ckmalloc(sizeof(struct strpush)); 314 sp->prev = parsefile->strpush; 315 parsefile->strpush = sp; 316 } else 317 sp = parsefile->strpush = &(parsefile->basestrpush); 318 sp->prevstring = parsenextc; 319 sp->prevnleft = parsenleft; 320 sp->prevlleft = parselleft; 321 sp->ap = ap; 322 if (ap) 323 ap->flag |= ALIASINUSE; 324 parsenextc = s; 325 parsenleft = len; 326 INTON; 327 } 328 329 static void 330 popstring(void) 331 { 332 struct strpush *sp = parsefile->strpush; 333 334 INTOFF; 335 if (sp->ap) { 336 if (parsenextc != sp->ap->val && 337 (parsenextc[-1] == ' ' || parsenextc[-1] == '\t')) 338 forcealias(); 339 sp->ap->flag &= ~ALIASINUSE; 340 } 341 parsenextc = sp->prevstring; 342 parsenleft = sp->prevnleft; 343 parselleft = sp->prevlleft; 344 /*out2fmt_flush("*** calling popstring: restoring to '%s'\n", parsenextc);*/ 345 parsefile->strpush = sp->prev; 346 if (sp != &(parsefile->basestrpush)) 347 ckfree(sp); 348 INTON; 349 } 350 351 /* 352 * Set the input to take input from a file. If push is set, push the 353 * old input onto the stack first. 354 * About verify: 355 * -1: Obey verifyflag 356 * 0: Do not verify 357 * 1: Do verify 358 */ 359 360 void 361 setinputfile(const char *fname, int push, int verify) 362 { 363 int e; 364 int fd; 365 int fd2; 366 int oflags = O_RDONLY | O_CLOEXEC; 367 368 if (verify == 1 || (verify == -1 && verifyflag)) 369 oflags |= O_VERIFY; 370 371 INTOFF; 372 if ((fd = open(fname, oflags)) < 0) { 373 e = errno; 374 errorwithstatus(e == ENOENT || e == ENOTDIR ? 127 : 126, 375 "cannot open %s: %s", fname, strerror(e)); 376 } 377 if (fd < 10) { 378 fd2 = fcntl(fd, F_DUPFD_CLOEXEC, 10); 379 close(fd); 380 if (fd2 < 0) 381 error("Out of file descriptors"); 382 fd = fd2; 383 } 384 setinputfd(fd, push); 385 INTON; 386 } 387 388 389 /* 390 * Like setinputfile, but takes an open file descriptor (which should have 391 * its FD_CLOEXEC flag already set). Call this with interrupts off. 392 */ 393 394 void 395 setinputfd(int fd, int push) 396 { 397 if (push) 398 pushfile(); 399 if (parsefile->fd > 0) 400 close(parsefile->fd); 401 parsefile->fd = fd; 402 if (parsefile->buf == NULL) { 403 parsefile->buf = ckmalloc(BUFSIZ + 1); 404 parsefile->bufsize = BUFSIZ + 1; 405 } 406 parselleft = parsenleft = 0; 407 plinno = 1; 408 } 409 410 411 /* 412 * Like setinputfile, but takes input from a string. 413 */ 414 415 void 416 setinputstring(const char *string) 417 { 418 INTOFF; 419 pushfile(); 420 parsenextc = string; 421 parselleft = parsenleft = strlen(string); 422 plinno = 1; 423 INTON; 424 } 425 426 427 428 /* 429 * To handle the "." command, a stack of input files is used. Pushfile 430 * adds a new entry to the stack and popfile restores the previous level. 431 */ 432 433 static void 434 pushfile(void) 435 { 436 struct parsefile *pf; 437 438 pf = (struct parsefile *)ckmalloc(sizeof(struct parsefile)); 439 *pf = (struct parsefile){ .prev = parsefile, .fd = -1 }; 440 parsefile->nleft = parsenleft; 441 parsefile->lleft = parselleft; 442 parsefile->nextc = parsenextc; 443 parsefile->linno = plinno; 444 parsefile = pf; 445 } 446 447 448 void 449 popfile(void) 450 { 451 struct parsefile *pf = parsefile; 452 453 INTOFF; 454 if (pf->fd >= 0) 455 close(pf->fd); 456 if (pf->buf) 457 ckfree(pf->buf); 458 while (pf->strpush) 459 popstring(); 460 parsefile = pf->prev; 461 ckfree(pf); 462 parsenleft = parsefile->nleft; 463 parselleft = parsefile->lleft; 464 parsenextc = parsefile->nextc; 465 plinno = parsefile->linno; 466 INTON; 467 } 468 469 470 /* 471 * Return current file (to go back to it later using popfilesupto()). 472 */ 473 474 struct parsefile * 475 getcurrentfile(void) 476 { 477 return parsefile; 478 } 479 480 481 /* 482 * Pop files until the given file is on top again. Useful for regular 483 * builtins that read shell commands from files or strings. 484 * If the given file is not an active file, an error is raised. 485 */ 486 487 void 488 popfilesupto(struct parsefile *file) 489 { 490 while (parsefile != file && parsefile != &basepf) 491 popfile(); 492 if (parsefile != file) 493 error("popfilesupto() misused"); 494 } 495 496 /* 497 * Return to top level. 498 */ 499 500 void 501 popallfiles(void) 502 { 503 while (parsefile != &basepf) 504 popfile(); 505 } 506 507 508 509 /* 510 * Close the file(s) that the shell is reading commands from. Called 511 * after a fork is done. 512 */ 513 514 void 515 closescript(void) 516 { 517 popallfiles(); 518 if (parsefile->fd > 0) { 519 close(parsefile->fd); 520 parsefile->fd = 0; 521 } 522 } 523