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