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