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