input.c revision 213760
1111314Snyan/*- 2111314Snyan * Copyright (c) 1991, 1993 3111314Snyan * The Regents of the University of California. All rights reserved. 4111314Snyan * 5111314Snyan * This code is derived from software contributed to Berkeley by 6111314Snyan * Kenneth Almquist. 7111314Snyan * 8111314Snyan * Redistribution and use in source and binary forms, with or without 9111314Snyan * modification, are permitted provided that the following conditions 10111314Snyan * are met: 11111314Snyan * 1. Redistributions of source code must retain the above copyright 12111314Snyan * notice, this list of conditions and the following disclaimer. 13111314Snyan * 2. Redistributions in binary form must reproduce the above copyright 14111314Snyan * notice, this list of conditions and the following disclaimer in the 15111314Snyan * documentation and/or other materials provided with the distribution. 16111314Snyan * 4. Neither the name of the University nor the names of its contributors 17111314Snyan * may be used to endorse or promote products derived from this software 18111314Snyan * without specific prior written permission. 19111314Snyan * 20111314Snyan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21111314Snyan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22111314Snyan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23111314Snyan * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24111314Snyan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25111314Snyan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26122755Snyan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27122755Snyan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28122755Snyan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29122755Snyan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30111314Snyan * SUCH DAMAGE. 31111314Snyan */ 32111314Snyan 33122755Snyan#ifndef lint 34111314Snyan#if 0 35122755Snyanstatic char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95"; 36122755Snyan#endif 37122755Snyan#endif /* not lint */ 38122755Snyan#include <sys/cdefs.h> 39122755Snyan__FBSDID("$FreeBSD: head/bin/sh/input.c 213760 2010-10-13 04:01:01Z obrien $"); 40122755Snyan 41122755Snyan#include <stdio.h> /* defines BUFSIZ */ 42111314Snyan#include <fcntl.h> 43111314Snyan#include <errno.h> 44111314Snyan#include <unistd.h> 45122056Snyan#include <stdlib.h> 46124795Snyan#include <string.h> 47124795Snyan 48122755Snyan/* 49111314Snyan * This file implements the input routines used by the parser. 50111314Snyan */ 51111314Snyan 52111314Snyan#include "shell.h" 53111314Snyan#include "redir.h" 54111314Snyan#include "syntax.h" 55111314Snyan#include "input.h" 56111314Snyan#include "output.h" 57111314Snyan#include "options.h" 58111314Snyan#include "memalloc.h" 59111314Snyan#include "error.h" 60111314Snyan#include "alias.h" 61111314Snyan#include "parser.h" 62111314Snyan#include "myhistedit.h" 63111314Snyan#include "trap.h" 64111314Snyan 65111314Snyan#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ 66111314Snyan 67111314SnyanMKINIT 68124795Snyanstruct strpush { 69124795Snyan struct strpush *prev; /* preceding string on stack */ 70124795Snyan char *prevstring; 71124795Snyan int prevnleft; 72111314Snyan int prevlleft; 73111314Snyan struct alias *ap; /* if push was associated with an alias */ 74111314Snyan}; 75111314Snyan 76111314Snyan/* 77111314Snyan * The parsefile structure pointed to by the global variable parsefile 78111314Snyan * contains information about the current file being read. 79111314Snyan */ 80111314Snyan 81111314SnyanMKINIT 82124795Snyanstruct parsefile { 83124795Snyan struct parsefile *prev; /* preceding file on stack */ 84124795Snyan int linno; /* current line */ 85111314Snyan int fd; /* file descriptor (or -1 if string) */ 86111314Snyan int nleft; /* number of chars left in this line */ 87111314Snyan int lleft; /* number of lines left in this buffer */ 88111314Snyan char *nextc; /* next char in buffer */ 89124795Snyan char *buf; /* input buffer */ 90124795Snyan struct strpush *strpush; /* for pushing strings at this level */ 91124795Snyan struct strpush basestrpush; /* so pushing one is fast */ 92124795Snyan}; 93124795Snyan 94124795Snyan 95124795Snyanint plinno = 1; /* input line number */ 96111314Snyanint parsenleft; /* copy of parsefile->nleft */ 97111314SnyanMKINIT int parselleft; /* copy of parsefile->lleft */ 98111314Snyanchar *parsenextc; /* copy of parsefile->nextc */ 99111314SnyanMKINIT struct parsefile basepf; /* top level input file */ 100111314Snyanchar basebuf[BUFSIZ]; /* buffer for top level input file */ 101111314Snyanstatic struct parsefile *parsefile = &basepf; /* current input file */ 102111314Snyanint init_editline = 0; /* editline library initialized? */ 103111314Snyanint whichprompt; /* 1 == PS1, 2 == PS2 */ 104111314Snyan 105111314SnyanEditLine *el; /* cookie for editline package */ 106111314Snyan 107111314SnyanSTATIC void pushfile(void); 108111314SnyanSTATIC int preadfd(void); 109111314Snyan 110111314Snyan#ifdef mkinit 111111314SnyanINCLUDE "input.h" 112111314SnyanINCLUDE "error.h" 113111314Snyan 114111314SnyanMKINIT char basebuf[]; 115111314Snyan 116111314SnyanINIT { 117111314Snyan basepf.nextc = basepf.buf = basebuf; 118111314Snyan} 119111314Snyan 120111314SnyanRESET { 121111314Snyan popallfiles(); 122111314Snyan if (exception != EXSHELLPROC) 123111314Snyan parselleft = parsenleft = 0; /* clear input buffer */ 124111314Snyan} 125111314Snyan 126111314SnyanSHELLPROC { 127111314Snyan popallfiles(); 128111314Snyan} 129111314Snyan#endif 130111314Snyan 131111314Snyan 132111314Snyan/* 133111314Snyan * Read a line from the script. 134111314Snyan */ 135111314Snyan 136111314Snyanchar * 137111314Snyanpfgets(char *line, int len) 138111314Snyan{ 139111314Snyan char *p = line; 140111314Snyan int nleft = len; 141111314Snyan int c; 142111314Snyan 143111314Snyan while (--nleft > 0) { 144111314Snyan c = pgetc_macro(); 145111314Snyan if (c == PEOF) { 146111314Snyan if (p == line) 147111314Snyan return NULL; 148111314Snyan break; 149111314Snyan } 150111314Snyan *p++ = c; 151111314Snyan if (c == '\n') 152111314Snyan break; 153111314Snyan } 154111314Snyan *p = '\0'; 155111314Snyan return line; 156111314Snyan} 157124795Snyan 158111314Snyan 159111314Snyan 160111314Snyan/* 161111314Snyan * Read a character from the script, returning PEOF on end of file. 162124795Snyan * Nul characters in the input are silently discarded. 163124795Snyan */ 164111314Snyan 165111314Snyanint 166111314Snyanpgetc(void) 167111314Snyan{ 168111314Snyan return pgetc_macro(); 169111314Snyan} 170111314Snyan 171111314Snyan 172111314SnyanSTATIC int 173111314Snyanpreadfd(void) 174111314Snyan{ 175111314Snyan int nr; 176111314Snyan parsenextc = parsefile->buf; 177111314Snyan 178111314Snyan#ifndef NO_HISTORY 179111314Snyan if (el != NULL && gotwinch) { 180124795Snyan gotwinch = 0; 181111314Snyan el_resize(el); 182111314Snyan } 183111314Snyan#endif 184111314Snyanretry: 185111314Snyan#ifndef NO_HISTORY 186111314Snyan if (parsefile->fd == 0 && el) { 187111314Snyan static const char *rl_cp; 188111314Snyan static int el_len; 189111314Snyan 190111314Snyan if (rl_cp == NULL) 191111314Snyan rl_cp = el_gets(el, &el_len); 192111314Snyan if (rl_cp == NULL) 193111314Snyan nr = 0; 194111314Snyan else { 195111314Snyan nr = el_len; 196111314Snyan if (nr > BUFSIZ - 1) 197124795Snyan nr = BUFSIZ - 1; 198111314Snyan memcpy(parsenextc, rl_cp, nr); 199111314Snyan if (nr != el_len) { 200111314Snyan el_len -= nr; 201111314Snyan rl_cp += nr; 202111314Snyan } else 203111314Snyan rl_cp = NULL; 204111314Snyan } 205111314Snyan } else 206124408Snyan#endif 207124408Snyan nr = read(parsefile->fd, parsenextc, BUFSIZ - 1); 208111314Snyan 209111314Snyan if (nr <= 0) { 210111314Snyan if (nr < 0) { 211111314Snyan if (errno == EINTR) 212111314Snyan goto retry; 213111314Snyan if (parsefile->fd == 0 && errno == EWOULDBLOCK) { 214111314Snyan int flags = fcntl(0, F_GETFL, 0); 215111314Snyan if (flags >= 0 && flags & O_NONBLOCK) { 216111314Snyan flags &=~ O_NONBLOCK; 217111314Snyan if (fcntl(0, F_SETFL, flags) >= 0) { 218123984Sbde out2fmt_flush("sh: turning off NDELAY mode\n"); 219123984Sbde goto retry; 220123984Sbde } 221123984Sbde } 222111314Snyan } 223111314Snyan } 224123984Sbde nr = -1; 225123984Sbde } 226111314Snyan return nr; 227111314Snyan} 228111314Snyan 229111314Snyan/* 230111314Snyan * Refill the input buffer and return the next input character: 231111314Snyan * 232111314Snyan * 1) If a string was pushed back on the input, pop it; 233111314Snyan * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading 234111314Snyan * from a string so we can't refill the buffer, return EOF. 235124795Snyan * 3) If there is more in this buffer, use it else call read to fill it. 236111314Snyan * 4) Process input up to the next newline, deleting nul characters. 237111314Snyan */ 238111314Snyan 239111314Snyanint 240111314Snyanpreadbuffer(void) 241111314Snyan{ 242111314Snyan char *p, *q; 243111314Snyan int more; 244111314Snyan int something; 245111314Snyan char savec; 246111314Snyan 247111314Snyan if (parsefile->strpush) { 248111314Snyan popstring(); 249111314Snyan if (--parsenleft >= 0) 250111314Snyan return (*parsenextc++); 251111314Snyan } 252111314Snyan if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) 253111314Snyan return PEOF; 254111314Snyan flushout(&output); 255111314Snyan flushout(&errout); 256111314Snyan 257111314Snyanagain: 258111314Snyan if (parselleft <= 0) { 259111314Snyan if ((parselleft = preadfd()) == -1) { 260111314Snyan parselleft = parsenleft = EOF_NLEFT; 261111314Snyan return PEOF; 262111314Snyan } 263111314Snyan } 264111314Snyan 265111314Snyan q = p = parsenextc; 266111314Snyan 267111314Snyan /* delete nul characters */ 268111314Snyan something = 0; 269111314Snyan for (more = 1; more;) { 270111314Snyan switch (*p) { 271111314Snyan case '\0': 272111314Snyan p++; /* Skip nul */ 273111314Snyan goto check; 274111314Snyan 275111314Snyan case '\t': 276111314Snyan case ' ': 277111314Snyan break; 278111314Snyan 279111314Snyan case '\n': 280111314Snyan parsenleft = q - parsenextc; 281111314Snyan more = 0; /* Stop processing here */ 282111314Snyan break; 283111314Snyan 284111314Snyan default: 285111314Snyan something = 1; 286111314Snyan break; 287111314Snyan } 288111314Snyan 289111314Snyan *q++ = *p++; 290111314Snyancheck: 291111314Snyan if (--parselleft <= 0) { 292111314Snyan parsenleft = q - parsenextc - 1; 293111314Snyan if (parsenleft < 0) 294111314Snyan goto again; 295111314Snyan *q = '\0'; 296111314Snyan more = 0; 297111314Snyan } 298111314Snyan } 299111314Snyan 300111314Snyan savec = *q; 301111314Snyan *q = '\0'; 302111314Snyan 303111314Snyan#ifndef NO_HISTORY 304111314Snyan if (parsefile->fd == 0 && hist && something) { 305111314Snyan HistEvent he; 306111314Snyan INTOFF; 307111314Snyan history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD, 308111314Snyan parsenextc); 309111314Snyan INTON; 310111314Snyan } 311111314Snyan#endif 312111314Snyan 313111314Snyan if (vflag) { 314111314Snyan out2str(parsenextc); 315111314Snyan flushout(out2); 316111314Snyan } 317111314Snyan 318111314Snyan *q = savec; 319111314Snyan 320111314Snyan return *parsenextc++; 321111314Snyan} 322111314Snyan 323111314Snyan/* 324111314Snyan * Returns if we are certain we are at EOF. Does not cause any more input 325111314Snyan * to be read from the outside world. 326111314Snyan */ 327111314Snyan 328111314Snyanint 329111314Snyanpreadateof(void) 330111314Snyan{ 331111314Snyan if (parsenleft > 0) 332111314Snyan return 0; 333111314Snyan if (parsefile->strpush) 334111314Snyan return 0; 335124795Snyan if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) 336124795Snyan return 1; 337124795Snyan return 0; 338111314Snyan} 339111314Snyan 340111314Snyan/* 341124795Snyan * Undo the last call to pgetc. Only one character may be pushed back. 342111314Snyan * PEOF may be pushed back. 343111314Snyan */ 344111314Snyan 345111314Snyanvoid 346111314Snyanpungetc(void) 347111314Snyan{ 348111314Snyan parsenleft++; 349112034Snyan parsenextc--; 350112034Snyan} 351119985Snyan 352119985Snyan/* 353112034Snyan * Push a string back onto the input at this current parsefile level. 354111314Snyan * We handle aliases this way. 355112034Snyan */ 356112034Snyanvoid 357111314Snyanpushstring(char *s, int len, void *ap) 358111314Snyan{ 359111314Snyan struct strpush *sp; 360111314Snyan 361119985Snyan INTOFF; 362111314Snyan/*out2fmt_flush("*** calling pushstring: %s, %d\n", s, len);*/ 363111314Snyan if (parsefile->strpush) { 364111314Snyan sp = ckmalloc(sizeof (struct strpush)); 365111314Snyan sp->prev = parsefile->strpush; 366111314Snyan parsefile->strpush = sp; 367111314Snyan } else 368111314Snyan sp = parsefile->strpush = &(parsefile->basestrpush); 369111314Snyan sp->prevstring = parsenextc; 370111314Snyan sp->prevnleft = parsenleft; 371111314Snyan sp->prevlleft = parselleft; 372111314Snyan sp->ap = (struct alias *)ap; 373111314Snyan if (ap) 374111314Snyan ((struct alias *)ap)->flag |= ALIASINUSE; 375111314Snyan parsenextc = s; 376111314Snyan parsenleft = len; 377111314Snyan INTON; 378111314Snyan} 379111314Snyan 380111314Snyanvoid 381111314Snyanpopstring(void) 382111314Snyan{ 383111314Snyan struct strpush *sp = parsefile->strpush; 384111314Snyan 385111314Snyan INTOFF; 386111314Snyan parsenextc = sp->prevstring; 387111314Snyan parsenleft = sp->prevnleft; 388111314Snyan parselleft = sp->prevlleft; 389111314Snyan/*out2fmt_flush("*** calling popstring: restoring to '%s'\n", parsenextc);*/ 390111314Snyan if (sp->ap) 391111314Snyan sp->ap->flag &= ~ALIASINUSE; 392111314Snyan parsefile->strpush = sp->prev; 393111314Snyan if (sp != &(parsefile->basestrpush)) 394111314Snyan ckfree(sp); 395111314Snyan INTON; 396111314Snyan} 397111314Snyan 398111314Snyan/* 399111314Snyan * Set the input to take input from a file. If push is set, push the 400111314Snyan * old input onto the stack first. 401111314Snyan */ 402111314Snyan 403111314Snyanvoid 404111314Snyansetinputfile(const char *fname, int push) 405111314Snyan{ 406111314Snyan int fd; 407111314Snyan int fd2; 408111314Snyan 409111314Snyan INTOFF; 410111314Snyan if ((fd = open(fname, O_RDONLY)) < 0) 411111314Snyan error("Can't open %s: %s", fname, strerror(errno)); 412111314Snyan if (fd < 10) { 413111314Snyan fd2 = fcntl(fd, F_DUPFD, 10); 414111314Snyan close(fd); 415111314Snyan if (fd2 < 0) 416112840Smdodd error("Out of file descriptors"); 417112840Smdodd fd = fd2; 418112840Smdodd } 419112840Smdodd setinputfd(fd, push); 420112840Smdodd INTON; 421111314Snyan} 422111314Snyan 423111314Snyan 424111314Snyan/* 425111314Snyan * Like setinputfile, but takes an open file descriptor. Call this with 426111314Snyan * interrupts off. 427111314Snyan */ 428111314Snyan 429111314Snyanvoid 430111314Snyansetinputfd(int fd, int push) 431111314Snyan{ 432111314Snyan (void)fcntl(fd, F_SETFD, FD_CLOEXEC); 433111314Snyan if (push) { 434111314Snyan pushfile(); 435111314Snyan parsefile->buf = ckmalloc(BUFSIZ); 436111314Snyan } 437111314Snyan if (parsefile->fd > 0) 438111314Snyan close(parsefile->fd); 439111314Snyan parsefile->fd = fd; 440111314Snyan if (parsefile->buf == NULL) 441111314Snyan parsefile->buf = ckmalloc(BUFSIZ); 442111314Snyan parselleft = parsenleft = 0; 443111314Snyan plinno = 1; 444111314Snyan} 445111314Snyan 446111314Snyan 447111314Snyan/* 448111314Snyan * Like setinputfile, but takes input from a string. 449111314Snyan */ 450111314Snyan 451111314Snyanvoid 452111314Snyansetinputstring(char *string, int push) 453111314Snyan{ 454111314Snyan INTOFF; 455111314Snyan if (push) 456111314Snyan pushfile(); 457111314Snyan parsenextc = string; 458111314Snyan parselleft = parsenleft = strlen(string); 459111314Snyan parsefile->buf = NULL; 460111314Snyan plinno = 1; 461111314Snyan INTON; 462111314Snyan} 463111314Snyan 464111314Snyan 465111314Snyan 466111314Snyan/* 467111314Snyan * To handle the "." command, a stack of input files is used. Pushfile 468111314Snyan * adds a new entry to the stack and popfile restores the previous level. 469111314Snyan */ 470111314Snyan 471111314SnyanSTATIC void 472111314Snyanpushfile(void) 473111314Snyan{ 474111314Snyan struct parsefile *pf; 475111314Snyan 476111314Snyan parsefile->nleft = parsenleft; 477117918Snyan parsefile->lleft = parselleft; 478117918Snyan parsefile->nextc = parsenextc; 479117918Snyan parsefile->linno = plinno; 480117918Snyan pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); 481117918Snyan pf->prev = parsefile; 482117918Snyan pf->fd = -1; 483117918Snyan pf->strpush = NULL; 484117918Snyan pf->basestrpush.prev = NULL; 485117918Snyan parsefile = pf; 486117918Snyan} 487111314Snyan 488111314Snyan 489111314Snyanvoid 490111314Snyanpopfile(void) 491111314Snyan{ 492111314Snyan struct parsefile *pf = parsefile; 493111314Snyan 494124795Snyan INTOFF; 495111314Snyan if (pf->fd >= 0) 496111314Snyan close(pf->fd); 497111314Snyan if (pf->buf) 498111314Snyan ckfree(pf->buf); 499111314Snyan while (pf->strpush) 500111314Snyan popstring(); 501111314Snyan parsefile = pf->prev; 502111314Snyan ckfree(pf); 503111314Snyan parsenleft = parsefile->nleft; 504111314Snyan parselleft = parsefile->lleft; 505111314Snyan parsenextc = parsefile->nextc; 506111314Snyan plinno = parsefile->linno; 507111314Snyan INTON; 508111314Snyan} 509111314Snyan 510111314Snyan 511111314Snyan/* 512111314Snyan * Return current file (to go back to it later using popfilesupto()). 513111314Snyan */ 514111314Snyan 515111314Snyanstruct parsefile * 516111314Snyangetcurrentfile(void) 517111314Snyan{ 518111314Snyan return parsefile; 519111314Snyan} 520111314Snyan 521111314Snyan 522111314Snyan/* 523124795Snyan * Pop files until the given file is on top again. Useful for regular 524111314Snyan * builtins that read shell commands from files or strings. 525111314Snyan * If the given file is not an active file, an error is raised. 526124795Snyan */ 527124795Snyan 528111314Snyanvoid 529124795Snyanpopfilesupto(struct parsefile *file) 530111314Snyan{ 531111314Snyan while (parsefile != file && parsefile != &basepf) 532111314Snyan popfile(); 533111314Snyan if (parsefile != file) 534111314Snyan error("popfilesupto() misused"); 535111314Snyan} 536111314Snyan 537111314Snyan/* 538111314Snyan * Return to top level. 539111314Snyan */ 540111314Snyan 541111314Snyanvoid 542111314Snyanpopallfiles(void) 543111314Snyan{ 544111314Snyan while (parsefile != &basepf) 545111314Snyan popfile(); 546111314Snyan} 547111314Snyan 548111314Snyan 549111314Snyan 550111314Snyan/* 551111314Snyan * Close the file(s) that the shell is reading commands from. Called 552111314Snyan * after a fork is done. 553115469Sphk */ 554111314Snyan 555111314Snyanvoid 556111314Snyanclosescript(void) 557111314Snyan{ 558111314Snyan popallfiles(); 559111314Snyan if (parsefile->fd > 0) { 560111314Snyan close(parsefile->fd); 561111314Snyan parsefile->fd = 0; 562111314Snyan } 563111314Snyan} 564111314Snyan