147119Sbostic /*- 260698Sbostic * Copyright (c) 1991, 1993 360698Sbostic * The Regents of the University of California. All rights reserved. 447119Sbostic * 547119Sbostic * This code is derived from software contributed to Berkeley by 647119Sbostic * Kenneth Almquist. 747119Sbostic * 847119Sbostic * %sccs.include.redist.c% 947119Sbostic */ 1047119Sbostic 1147119Sbostic #ifndef lint 12*69272Schristos static char sccsid[] = "@(#)input.c 8.2 (Berkeley) 05/04/95"; 1347119Sbostic #endif /* not lint */ 1447119Sbostic 15*69272Schristos #include <stdio.h> /* defines BUFSIZ */ 16*69272Schristos #include <fcntl.h> 17*69272Schristos #include <errno.h> 18*69272Schristos #include <unistd.h> 19*69272Schristos #include <stdlib.h> 20*69272Schristos 2147119Sbostic /* 2247119Sbostic * This file implements the input routines used by the parser. 2347119Sbostic */ 2447119Sbostic 2547119Sbostic #include "shell.h" 26*69272Schristos #include "redir.h" 2747119Sbostic #include "syntax.h" 2847119Sbostic #include "input.h" 2947119Sbostic #include "output.h" 3054313Smarc #include "options.h" 3147119Sbostic #include "memalloc.h" 3247119Sbostic #include "error.h" 3354313Smarc #include "alias.h" 3454313Smarc #include "parser.h" 3554330Smarc #include "myhistedit.h" 3647119Sbostic 3747119Sbostic #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ 3847119Sbostic 3954313Smarc MKINIT 4054313Smarc struct strpush { 4154313Smarc struct strpush *prev; /* preceding string on stack */ 4254313Smarc char *prevstring; 4354313Smarc int prevnleft; 4454313Smarc struct alias *ap; /* if push was associated with an alias */ 4554313Smarc }; 4647119Sbostic 4747119Sbostic /* 4847119Sbostic * The parsefile structure pointed to by the global variable parsefile 4947119Sbostic * contains information about the current file being read. 5047119Sbostic */ 5147119Sbostic 5247119Sbostic MKINIT 5347119Sbostic struct parsefile { 5454313Smarc struct parsefile *prev; /* preceding file on stack */ 5547119Sbostic int linno; /* current line */ 5647119Sbostic int fd; /* file descriptor (or -1 if string) */ 5747119Sbostic int nleft; /* number of chars left in buffer */ 5847119Sbostic char *nextc; /* next char in buffer */ 5947119Sbostic char *buf; /* input buffer */ 6054313Smarc struct strpush *strpush; /* for pushing strings at this level */ 6154313Smarc struct strpush basestrpush; /* so pushing one is fast */ 6247119Sbostic }; 6347119Sbostic 6447119Sbostic 6547119Sbostic int plinno = 1; /* input line number */ 6647119Sbostic MKINIT int parsenleft; /* copy of parsefile->nleft */ 6747119Sbostic char *parsenextc; /* copy of parsefile->nextc */ 6847119Sbostic MKINIT struct parsefile basepf; /* top level input file */ 6947119Sbostic char basebuf[BUFSIZ]; /* buffer for top level input file */ 7047119Sbostic struct parsefile *parsefile = &basepf; /* current input file */ 7147119Sbostic char *pushedstring; /* copy of parsenextc when text pushed back */ 7247119Sbostic int pushednleft; /* copy of parsenleft when text pushed back */ 7354313Smarc int init_editline = 0; /* editline library initialized? */ 7454313Smarc int whichprompt; /* 1 == PS1, 2 == PS2 */ 7547119Sbostic 7654313Smarc EditLine *el; /* cookie for editline package */ 7754313Smarc 78*69272Schristos STATIC void pushfile __P((void)); 7947119Sbostic 8047119Sbostic #ifdef mkinit 8147119Sbostic INCLUDE "input.h" 8247119Sbostic INCLUDE "error.h" 8347119Sbostic 8447119Sbostic INIT { 8547119Sbostic extern char basebuf[]; 8647119Sbostic 8747119Sbostic basepf.nextc = basepf.buf = basebuf; 8847119Sbostic } 8947119Sbostic 9047119Sbostic RESET { 9147119Sbostic if (exception != EXSHELLPROC) 9247119Sbostic parsenleft = 0; /* clear input buffer */ 9347119Sbostic popallfiles(); 9447119Sbostic } 9547119Sbostic 9647119Sbostic SHELLPROC { 9747119Sbostic popallfiles(); 9847119Sbostic } 9947119Sbostic #endif 10047119Sbostic 10147119Sbostic 10247119Sbostic /* 10347119Sbostic * Read a line from the script. 10447119Sbostic */ 10547119Sbostic 10647119Sbostic char * 10747119Sbostic pfgets(line, len) 10847119Sbostic char *line; 109*69272Schristos int len; 110*69272Schristos { 11147119Sbostic register char *p = line; 11247119Sbostic int nleft = len; 11347119Sbostic int c; 11447119Sbostic 11547119Sbostic while (--nleft > 0) { 11647119Sbostic c = pgetc_macro(); 11747119Sbostic if (c == PEOF) { 11847119Sbostic if (p == line) 11947119Sbostic return NULL; 12047119Sbostic break; 12147119Sbostic } 12247119Sbostic *p++ = c; 12347119Sbostic if (c == '\n') 12447119Sbostic break; 12547119Sbostic } 12647119Sbostic *p = '\0'; 12747119Sbostic return line; 12847119Sbostic } 12947119Sbostic 13047119Sbostic 13147119Sbostic 13247119Sbostic /* 13347119Sbostic * Read a character from the script, returning PEOF on end of file. 13447119Sbostic * Nul characters in the input are silently discarded. 13547119Sbostic */ 13647119Sbostic 13747119Sbostic int 13847119Sbostic pgetc() { 13947119Sbostic return pgetc_macro(); 14047119Sbostic } 14147119Sbostic 14247119Sbostic 14347119Sbostic /* 14447119Sbostic * Refill the input buffer and return the next input character: 14547119Sbostic * 14654313Smarc * 1) If a string was pushed back on the input, pop it; 14747119Sbostic * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading 14847119Sbostic * from a string so we can't refill the buffer, return EOF. 14947119Sbostic * 3) Call read to read in the characters. 15047119Sbostic * 4) Delete all nul characters from the buffer. 15147119Sbostic */ 15247119Sbostic 15347119Sbostic int 15447119Sbostic preadbuffer() { 15547119Sbostic register char *p, *q; 15647119Sbostic register int i; 15754313Smarc register int something; 15854313Smarc extern EditLine *el; 15947119Sbostic 16054313Smarc if (parsefile->strpush) { 16154313Smarc popstring(); 16247119Sbostic if (--parsenleft >= 0) 16354313Smarc return (*parsenextc++); 16447119Sbostic } 16547119Sbostic if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) 16647119Sbostic return PEOF; 16747119Sbostic flushout(&output); 16847119Sbostic flushout(&errout); 16947119Sbostic retry: 17047119Sbostic p = parsenextc = parsefile->buf; 17154313Smarc if (parsefile->fd == 0 && el) { 17255241Smarc const char *rl_cp; 17354313Smarc int len; 17454313Smarc 17554313Smarc rl_cp = el_gets(el, &len); 17654313Smarc if (rl_cp == NULL) { 17754313Smarc i = 0; 17854313Smarc goto eof; 17954313Smarc } 18054313Smarc strcpy(p, rl_cp); /* XXX - BUFSIZE should redesign so not necessary */ 18154313Smarc i = len; 18254313Smarc 18354313Smarc } else { 18454313Smarc i = read(parsefile->fd, p, BUFSIZ - 1); 18554313Smarc } 18654313Smarc eof: 18747119Sbostic if (i <= 0) { 18847294Smarc if (i < 0) { 18947294Smarc if (errno == EINTR) 19047294Smarc goto retry; 19147294Smarc if (parsefile->fd == 0 && errno == EWOULDBLOCK) { 19247294Smarc int flags = fcntl(0, F_GETFL, 0); 19350345Sbostic if (flags >= 0 && flags & O_NONBLOCK) { 19450345Sbostic flags &=~ O_NONBLOCK; 19547294Smarc if (fcntl(0, F_SETFL, flags) >= 0) { 19647980Smarc out2str("sh: turning off NDELAY mode\n"); 19747294Smarc goto retry; 19847294Smarc } 19947294Smarc } 20047294Smarc } 20147294Smarc } 20247294Smarc parsenleft = EOF_NLEFT; 20347294Smarc return PEOF; 20447119Sbostic } 20554313Smarc parsenleft = i - 1; /* we're returning one char in this call */ 20647119Sbostic 20747119Sbostic /* delete nul characters */ 20854313Smarc something = 0; 20947119Sbostic for (;;) { 21054313Smarc if (*p == '\0') 21147119Sbostic break; 21254313Smarc if (*p != ' ' && *p != '\t' && *p != '\n') 21354313Smarc something = 1; 21454313Smarc p++; 21554313Smarc if (--i <= 0) { 21654313Smarc *p = '\0'; 21754313Smarc goto done; /* no nul characters */ 21854313Smarc } 21947119Sbostic } 22054313Smarc /* 22154313Smarc * remove nuls 22254313Smarc */ 22354313Smarc q = p++; 22447119Sbostic while (--i > 0) { 22547119Sbostic if (*p != '\0') 22647119Sbostic *q++ = *p; 22747119Sbostic p++; 22847119Sbostic } 22954313Smarc *q = '\0'; 23047119Sbostic if (q == parsefile->buf) 23147119Sbostic goto retry; /* buffer contained nothing but nuls */ 23247119Sbostic parsenleft = q - parsefile->buf - 1; 23354313Smarc 23454313Smarc done: 23554313Smarc if (parsefile->fd == 0 && hist && something) { 23654313Smarc INTOFF; 23754313Smarc history(hist, whichprompt == 1 ? H_ENTER : H_ADD, 23854313Smarc parsefile->buf); 23954313Smarc INTON; 24054313Smarc } 24154313Smarc if (vflag) { 24254313Smarc /* 24354313Smarc * This isn't right. Most shells coordinate it with 24454313Smarc * reading a line at a time. I honestly don't know if its 24554313Smarc * worth it. 24654313Smarc */ 24754313Smarc i = parsenleft + 1; 24854313Smarc p = parsefile->buf; 24954313Smarc for (; i--; p++) 25054313Smarc out2c(*p) 25154313Smarc flushout(out2); 25254313Smarc } 25347119Sbostic return *parsenextc++; 25447119Sbostic } 25547119Sbostic 25647119Sbostic /* 25747119Sbostic * Undo the last call to pgetc. Only one character may be pushed back. 25847119Sbostic * PEOF may be pushed back. 25947119Sbostic */ 26047119Sbostic 26147119Sbostic void 26247119Sbostic pungetc() { 26347119Sbostic parsenleft++; 26447119Sbostic parsenextc--; 26547119Sbostic } 26647119Sbostic 26747119Sbostic /* 26854313Smarc * Push a string back onto the input at this current parsefile level. 26954313Smarc * We handle aliases this way. 27047119Sbostic */ 27147119Sbostic void 27254313Smarc pushstring(s, len, ap) 27354313Smarc char *s; 27454313Smarc int len; 27554313Smarc void *ap; 27647119Sbostic { 27754313Smarc struct strpush *sp; 27854313Smarc 27954313Smarc INTOFF; 28054313Smarc /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/ 28154313Smarc if (parsefile->strpush) { 28254313Smarc sp = ckmalloc(sizeof (struct strpush)); 28354313Smarc sp->prev = parsefile->strpush; 28454313Smarc parsefile->strpush = sp; 28554313Smarc } else 28654313Smarc sp = parsefile->strpush = &(parsefile->basestrpush); 28754313Smarc sp->prevstring = parsenextc; 28854313Smarc sp->prevnleft = parsenleft; 28954313Smarc sp->ap = (struct alias *)ap; 29054313Smarc if (ap) 29154313Smarc ((struct alias *)ap)->flag |= ALIASINUSE; 29254313Smarc parsenextc = s; 29354313Smarc parsenleft = len; 29454313Smarc INTON; 29547119Sbostic } 29647119Sbostic 297*69272Schristos void 29854313Smarc popstring() 29954313Smarc { 30054313Smarc struct strpush *sp = parsefile->strpush; 30147119Sbostic 30254313Smarc INTOFF; 30354313Smarc parsenextc = sp->prevstring; 30454313Smarc parsenleft = sp->prevnleft; 30554313Smarc /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/ 30654313Smarc if (sp->ap) 30754313Smarc sp->ap->flag &= ~ALIASINUSE; 30854313Smarc parsefile->strpush = sp->prev; 30954313Smarc if (sp != &(parsefile->basestrpush)) 31054313Smarc ckfree(sp); 31154313Smarc INTON; 31254313Smarc } 31347119Sbostic 31447119Sbostic /* 31547119Sbostic * Set the input to take input from a file. If push is set, push the 31647119Sbostic * old input onto the stack first. 31747119Sbostic */ 31847119Sbostic 31947119Sbostic void 32047119Sbostic setinputfile(fname, push) 32147119Sbostic char *fname; 322*69272Schristos int push; 323*69272Schristos { 32447119Sbostic int fd; 32547119Sbostic int fd2; 32647119Sbostic 32747119Sbostic INTOFF; 32847119Sbostic if ((fd = open(fname, O_RDONLY)) < 0) 32947119Sbostic error("Can't open %s", fname); 33047119Sbostic if (fd < 10) { 33147119Sbostic fd2 = copyfd(fd, 10); 33247119Sbostic close(fd); 33347119Sbostic if (fd2 < 0) 33447119Sbostic error("Out of file descriptors"); 33547119Sbostic fd = fd2; 33647119Sbostic } 33747119Sbostic setinputfd(fd, push); 33847119Sbostic INTON; 33947119Sbostic } 34047119Sbostic 34147119Sbostic 34247119Sbostic /* 34347119Sbostic * Like setinputfile, but takes an open file descriptor. Call this with 34447119Sbostic * interrupts off. 34547119Sbostic */ 34647119Sbostic 34747119Sbostic void 348*69272Schristos setinputfd(fd, push) 349*69272Schristos int fd, push; 350*69272Schristos { 35147119Sbostic if (push) { 35247119Sbostic pushfile(); 35347119Sbostic parsefile->buf = ckmalloc(BUFSIZ); 35447119Sbostic } 35547119Sbostic if (parsefile->fd > 0) 35647119Sbostic close(parsefile->fd); 35747119Sbostic parsefile->fd = fd; 35847119Sbostic if (parsefile->buf == NULL) 35947119Sbostic parsefile->buf = ckmalloc(BUFSIZ); 36047119Sbostic parsenleft = 0; 36147119Sbostic plinno = 1; 36247119Sbostic } 36347119Sbostic 36447119Sbostic 36547119Sbostic /* 36647119Sbostic * Like setinputfile, but takes input from a string. 36747119Sbostic */ 36847119Sbostic 36947119Sbostic void 37047119Sbostic setinputstring(string, push) 37147119Sbostic char *string; 372*69272Schristos int push; 37347119Sbostic { 37447119Sbostic INTOFF; 37547119Sbostic if (push) 37647119Sbostic pushfile(); 37747119Sbostic parsenextc = string; 37847119Sbostic parsenleft = strlen(string); 37947119Sbostic parsefile->buf = NULL; 38047119Sbostic plinno = 1; 38147119Sbostic INTON; 38247119Sbostic } 38347119Sbostic 38447119Sbostic 38547119Sbostic 38647119Sbostic /* 38747119Sbostic * To handle the "." command, a stack of input files is used. Pushfile 38847119Sbostic * adds a new entry to the stack and popfile restores the previous level. 38947119Sbostic */ 39047119Sbostic 39147119Sbostic STATIC void 39247119Sbostic pushfile() { 39347119Sbostic struct parsefile *pf; 39447119Sbostic 39547119Sbostic parsefile->nleft = parsenleft; 39647119Sbostic parsefile->nextc = parsenextc; 39747119Sbostic parsefile->linno = plinno; 39847119Sbostic pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); 39947119Sbostic pf->prev = parsefile; 40047119Sbostic pf->fd = -1; 40154313Smarc pf->strpush = NULL; 40254313Smarc pf->basestrpush.prev = NULL; 40347119Sbostic parsefile = pf; 40447119Sbostic } 40547119Sbostic 40647119Sbostic 40747119Sbostic void 40847119Sbostic popfile() { 40947119Sbostic struct parsefile *pf = parsefile; 41047119Sbostic 41147119Sbostic INTOFF; 41247119Sbostic if (pf->fd >= 0) 41347119Sbostic close(pf->fd); 41447119Sbostic if (pf->buf) 41547119Sbostic ckfree(pf->buf); 41654313Smarc while (pf->strpush) 41754313Smarc popstring(); 41847119Sbostic parsefile = pf->prev; 41947119Sbostic ckfree(pf); 42047119Sbostic parsenleft = parsefile->nleft; 42147119Sbostic parsenextc = parsefile->nextc; 42247119Sbostic plinno = parsefile->linno; 42347119Sbostic INTON; 42447119Sbostic } 42547119Sbostic 42647119Sbostic 42747119Sbostic /* 42847119Sbostic * Return to top level. 42947119Sbostic */ 43047119Sbostic 43147119Sbostic void 43247119Sbostic popallfiles() { 43347119Sbostic while (parsefile != &basepf) 43447119Sbostic popfile(); 43547119Sbostic } 43647119Sbostic 43747119Sbostic 43847119Sbostic 43947119Sbostic /* 44047119Sbostic * Close the file(s) that the shell is reading commands from. Called 44147119Sbostic * after a fork is done. 44247119Sbostic */ 44347119Sbostic 44447119Sbostic void 44547119Sbostic closescript() { 44647119Sbostic popallfiles(); 44747119Sbostic if (parsefile->fd > 0) { 44847119Sbostic close(parsefile->fd); 44947119Sbostic parsefile->fd = 0; 45047119Sbostic } 45147119Sbostic } 452