1/*- 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1997-2005 5 * Herbert Xu <herbert@gondor.apana.org.au>. 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 <unistd.h> 38#include <stdlib.h> 39#include <string.h> 40 41#ifdef USE_LINENOISE 42#include <linenoise/linenoise.h> 43#endif 44 45/* 46 * This file implements the input routines used by the parser. 47 */ 48 49#include "eval.h" 50#include "shell.h" 51#include "redir.h" 52#include "syntax.h" 53#include "input.h" 54#include "output.h" 55#include "options.h" 56#include "memalloc.h" 57#include "error.h" 58#include "alias.h" 59#include "parser.h" 60#include "main.h" 61 62#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ 63#define IBUFSIZ (BUFSIZ + 1) 64 65 66MKINIT struct parsefile basepf; /* top level input file */ 67MKINIT char basebuf[IBUFSIZ]; /* buffer for top level input file */ 68struct parsefile *parsefile = &basepf; /* current input file */ 69int whichprompt; /* 1 == PS1, 2 == PS2 */ 70 71#ifdef USE_LINENOISE 72static char *pending_line; 73static size_t pending_line_index; 74static size_t pending_line_length; 75#endif 76 77STATIC void pushfile(void); 78static int preadfd(void); 79static void setinputfd(int fd, int push); 80static int preadbuffer(void); 81 82#ifdef mkinit 83INCLUDE <stdio.h> 84INCLUDE "input.h" 85INCLUDE "error.h" 86 87INIT { 88 basepf.nextc = basepf.buf = basebuf; 89 basepf.linno = 1; 90} 91 92RESET { 93 /* clear input buffer */ 94 basepf.lleft = basepf.nleft = 0; 95 popallfiles(); 96} 97#endif 98 99 100/* 101 * Read a character from the script, returning PEOF on end of file. 102 * Nul characters in the input are silently discarded. 103 */ 104 105int 106pgetc(void) 107{ 108 int c; 109 110 if (parsefile->unget) 111 return parsefile->lastc[--parsefile->unget]; 112 113 if (--parsefile->nleft >= 0) 114 c = (signed char)*parsefile->nextc++; 115 else 116 c = preadbuffer(); 117 118 parsefile->lastc[1] = parsefile->lastc[0]; 119 parsefile->lastc[0] = c; 120 121 return c; 122} 123 124 125/* 126 * Same as pgetc(), but ignores PEOA. 127 */ 128 129int 130pgetc2() 131{ 132 int c; 133 do { 134 c = pgetc(); 135 } while (c == PEOA); 136 return c; 137} 138 139 140static int 141preadfd(void) 142{ 143 int nr; 144 char *buf = parsefile->buf; 145 parsefile->nextc = buf; 146 const char* prompt = NULL; 147 148retry: 149#ifdef USE_LINENOISE 150 if (parsefile->fd == 0 && iflag) { 151 if (pending_line == NULL) { 152 // linenoise stashs the prompt buffer away for 153 // the duration of its edit cycle. Because 154 // some edit functionality (in particular, tab 155 // completion allocates the parts of PATH from 156 // dash's stack-based allocator), we need to 157 // properly save the string and then free it, 158 // or it will be clobbered. 159 prompt = savestr(getprompt(NULL)); 160 pending_line = linenoise(prompt); 161 if (pending_line) { 162 pending_line_index = 0u; 163 pending_line_length = strlen(pending_line); 164 pending_line[pending_line_length] = '\n'; 165 pending_line_length += 1; 166 } 167 } 168 if (pending_line == NULL) 169 nr = 0; 170 else { 171 nr = pending_line_length - pending_line_index; 172 if (nr > IBUFSIZ - 1) 173 nr = IBUFSIZ - 1; 174 memcpy(buf, pending_line + pending_line_index, nr); 175 pending_line_index += nr; 176 if (pending_line_index == pending_line_length) { 177 linenoiseFree(pending_line); 178 free(prompt); 179 pending_line = NULL; 180 pending_line_index = 0u; 181 pending_line_length = 0u; 182 } 183 } 184 } else 185#endif 186 nr = read(parsefile->fd, buf, IBUFSIZ - 1); 187 188 189 if (nr < 0) { 190 if (errno == EINTR) 191 goto retry; 192 if (parsefile->fd == 0 && errno == EWOULDBLOCK) { 193 int flags = fcntl(0, F_GETFL, 0); 194 if (flags >= 0 && flags & O_NONBLOCK) { 195 flags &=~ O_NONBLOCK; 196 if (fcntl(0, F_SETFL, flags) >= 0) { 197 out2str("sh: turning off NDELAY mode\n"); 198 goto retry; 199 } 200 } 201 } 202 } 203 return nr; 204} 205 206static void addtohistory(const char* entry, size_t length) { 207 // TODO(abarth): If whichprompt != 1, we should append this value to an 208 // existing history entry. However, linenoise doesn't support editing the 209 // history entries, so we'll probably need to refactor the input system to 210 // get this behavior right. 211#ifdef USE_LINENOISE 212 linenoiseHistoryAdd(entry); 213#endif 214} 215 216/* 217 * Refill the input buffer and return the next input character: 218 * 219 * 1) If a string was pushed back on the input, pop it; 220 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading 221 * from a string so we can't refill the buffer, return EOF. 222 * 3) If the is more stuff in this buffer, use it else call read to fill it. 223 * 4) Process input up to the next newline, deleting nul characters. 224 */ 225 226static int preadbuffer(void) 227{ 228 char *q; 229 int more; 230#ifdef USE_LINENOISE 231 int something; 232#endif 233 char savec; 234 235 if (unlikely(parsefile->strpush)) { 236 if ( 237 parsefile->nleft == -1 && 238 parsefile->strpush->ap && 239 parsefile->nextc[-1] != ' ' && 240 parsefile->nextc[-1] != '\t' 241 ) { 242 return PEOA; 243 } 244 popstring(); 245 return pgetc(); 246 } 247 if (unlikely(parsefile->nleft == EOF_NLEFT || 248 parsefile->buf == NULL)) 249 return PEOF; 250 flushall(); 251 252 more = parsefile->lleft; 253 if (more <= 0) { 254again: 255 if ((more = preadfd()) <= 0) { 256 parsefile->lleft = parsefile->nleft = EOF_NLEFT; 257 return PEOF; 258 } 259 } 260 261 q = parsefile->nextc; 262 263 /* delete nul characters */ 264#ifdef USE_LINENOISE 265 something = 0; 266#endif 267 for (;;) { 268 int c; 269 270 more--; 271 c = *q; 272 273 if (!c) 274 memmove(q, q + 1, more); 275 else { 276 q++; 277 278 if (c == '\n') { 279 parsefile->nleft = q - parsefile->nextc - 1; 280 break; 281 } 282 283#ifdef USE_LINENOISE 284 switch (c) { 285 default: 286 something = 1; 287 /* fall through */ 288 case '\t': 289 case ' ': 290 break; 291 } 292#endif 293 } 294 295 if (more <= 0) { 296 parsefile->nleft = q - parsefile->nextc - 1; 297 if (parsefile->nleft < 0) 298 goto again; 299 break; 300 } 301 } 302 parsefile->lleft = more; 303 304 savec = *q; 305 *q = '\0'; 306 307#ifdef USE_LINENOISE 308 if (parsefile->fd == 0 && iflag && something) { 309 // linenoise doesn't expect the command terminator at the end of the history 310 // entry. 311 char command_terminator = q[-1]; 312 q[-1] = '\0'; 313 314 addtohistory(parsefile->nextc, strlen(parsefile->nextc)); 315 316 // Restore the command terminator. 317 q[-1] = command_terminator; 318 } 319#endif 320 321 if (vflag) { 322 out2str(parsefile->nextc); 323#ifdef FLUSHERR 324 flushout(out2); 325#endif 326 } 327 328 *q = savec; 329 330 return (signed char)*parsefile->nextc++; 331} 332 333/* 334 * Undo a call to pgetc. Only two characters may be pushed back. 335 * PEOF may be pushed back. 336 */ 337 338void 339pungetc(void) 340{ 341 parsefile->unget++; 342} 343 344/* 345 * Push a string back onto the input at this current parsefile level. 346 * We handle aliases this way. 347 */ 348void 349pushstring(char *s, void *ap) 350{ 351 struct strpush *sp; 352 size_t len; 353 354 len = strlen(s); 355 INTOFF; 356/*dprintf("*** 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 = parsefile->nextc; 364 sp->prevnleft = parsefile->nleft; 365 sp->unget = parsefile->unget; 366 memcpy(sp->lastc, parsefile->lastc, sizeof(sp->lastc)); 367 sp->ap = (struct alias *)ap; 368 if (ap) { 369 ((struct alias *)ap)->flag |= ALIASINUSE; 370 sp->string = s; 371 } 372 parsefile->nextc = s; 373 parsefile->nleft = len; 374 parsefile->unget = 0; 375 INTON; 376} 377 378void 379popstring(void) 380{ 381 struct strpush *sp = parsefile->strpush; 382 383 INTOFF; 384 if (sp->ap) { 385 if (parsefile->nextc[-1] == ' ' || 386 parsefile->nextc[-1] == '\t') { 387 checkkwd |= CHKALIAS; 388 } 389 if (sp->string != sp->ap->val) { 390 ckfree(sp->string); 391 } 392 sp->ap->flag &= ~ALIASINUSE; 393 if (sp->ap->flag & ALIASDEAD) { 394 unalias(sp->ap->name); 395 } 396 } 397 parsefile->nextc = sp->prevstring; 398 parsefile->nleft = sp->prevnleft; 399 parsefile->unget = sp->unget; 400 memcpy(parsefile->lastc, sp->lastc, sizeof(sp->lastc)); 401/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/ 402 parsefile->strpush = sp->prev; 403 if (sp != &(parsefile->basestrpush)) 404 ckfree(sp); 405 INTON; 406} 407 408/* 409 * Set the input to take input from a file. If push is set, push the 410 * old input onto the stack first. 411 */ 412 413int 414setinputfile(const char *fname, int flags) 415{ 416 int fd; 417 418 INTOFF; 419 if ((fd = open(fname, O_RDONLY)) < 0) { 420 if (flags & INPUT_NOFILE_OK) 421 goto out; 422 exitstatus = 127; 423 exerror(EXERROR, "Can't open %s", fname); 424 } 425 if (fd < 10) 426 fd = savefd(fd, fd); 427 setinputfd(fd, flags & INPUT_PUSH_FILE); 428out: 429 INTON; 430 return fd; 431} 432 433 434/* 435 * Like setinputfile, but takes an open file descriptor. Call this with 436 * interrupts off. 437 */ 438 439static void 440setinputfd(int fd, int push) 441{ 442 if (push) { 443 pushfile(); 444 parsefile->buf = 0; 445 } 446 parsefile->fd = fd; 447 if (parsefile->buf == NULL) 448 parsefile->buf = ckmalloc(IBUFSIZ); 449 parsefile->lleft = parsefile->nleft = 0; 450 plinno = 1; 451} 452 453 454/* 455 * Like setinputfile, but takes input from a string. 456 */ 457 458void 459setinputstring(char *string) 460{ 461 INTOFF; 462 pushfile(); 463 parsefile->nextc = string; 464 parsefile->nleft = strlen(string); 465 parsefile->buf = NULL; 466 plinno = 1; 467 INTON; 468} 469 470 471 472/* 473 * To handle the "." command, a stack of input files is used. Pushfile 474 * adds a new entry to the stack and popfile restores the previous level. 475 */ 476 477STATIC void 478pushfile(void) 479{ 480 struct parsefile *pf; 481 482 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); 483 pf->prev = parsefile; 484 pf->fd = -1; 485 pf->strpush = NULL; 486 pf->basestrpush.prev = NULL; 487 pf->unget = 0; 488 parsefile = pf; 489} 490 491 492void 493popfile(void) 494{ 495 struct parsefile *pf = parsefile; 496 497 INTOFF; 498 if (pf->fd >= 0) 499 close(pf->fd); 500 if (pf->buf) 501 ckfree(pf->buf); 502 while (pf->strpush) 503 popstring(); 504 parsefile = pf->prev; 505 ckfree(pf); 506 INTON; 507} 508 509 510/* 511 * Return to top level. 512 */ 513 514void 515popallfiles(void) 516{ 517 while (parsefile != &basepf) 518 popfile(); 519} 520 521 522 523/* 524 * Close the file(s) that the shell is reading commands from. Called 525 * after a fork is done. 526 */ 527 528void 529closescript(void) 530{ 531 popallfiles(); 532 if (parsefile->fd > 0) { 533 close(parsefile->fd); 534 parsefile->fd = 0; 535 } 536} 537