147119Sbostic /*- 2*60698Sbostic * Copyright (c) 1991, 1993 3*60698Sbostic * 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*60698Sbostic static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 05/31/93"; 1347119Sbostic #endif /* not lint */ 1447119Sbostic 1547119Sbostic /* 1647119Sbostic * This file implements the input routines used by the parser. 1747119Sbostic */ 1847119Sbostic 1947119Sbostic #include <stdio.h> /* defines BUFSIZ */ 2047119Sbostic #include "shell.h" 2147119Sbostic #include <fcntl.h> 2247119Sbostic #include <errno.h> 2347119Sbostic #include "syntax.h" 2447119Sbostic #include "input.h" 2547119Sbostic #include "output.h" 2654313Smarc #include "options.h" 2747119Sbostic #include "memalloc.h" 2847119Sbostic #include "error.h" 2954313Smarc #include "alias.h" 3054313Smarc #include "parser.h" 3154330Smarc #include "myhistedit.h" 3247119Sbostic 3347119Sbostic #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ 3447119Sbostic 3554313Smarc MKINIT 3654313Smarc struct strpush { 3754313Smarc struct strpush *prev; /* preceding string on stack */ 3854313Smarc char *prevstring; 3954313Smarc int prevnleft; 4054313Smarc struct alias *ap; /* if push was associated with an alias */ 4154313Smarc }; 4247119Sbostic 4347119Sbostic /* 4447119Sbostic * The parsefile structure pointed to by the global variable parsefile 4547119Sbostic * contains information about the current file being read. 4647119Sbostic */ 4747119Sbostic 4847119Sbostic MKINIT 4947119Sbostic struct parsefile { 5054313Smarc struct parsefile *prev; /* preceding file on stack */ 5147119Sbostic int linno; /* current line */ 5247119Sbostic int fd; /* file descriptor (or -1 if string) */ 5347119Sbostic int nleft; /* number of chars left in buffer */ 5447119Sbostic char *nextc; /* next char in buffer */ 5547119Sbostic char *buf; /* input buffer */ 5654313Smarc struct strpush *strpush; /* for pushing strings at this level */ 5754313Smarc struct strpush basestrpush; /* so pushing one is fast */ 5847119Sbostic }; 5947119Sbostic 6047119Sbostic 6147119Sbostic int plinno = 1; /* input line number */ 6247119Sbostic MKINIT int parsenleft; /* copy of parsefile->nleft */ 6347119Sbostic char *parsenextc; /* copy of parsefile->nextc */ 6447119Sbostic MKINIT struct parsefile basepf; /* top level input file */ 6547119Sbostic char basebuf[BUFSIZ]; /* buffer for top level input file */ 6647119Sbostic struct parsefile *parsefile = &basepf; /* current input file */ 6747119Sbostic char *pushedstring; /* copy of parsenextc when text pushed back */ 6847119Sbostic int pushednleft; /* copy of parsenleft when text pushed back */ 6954313Smarc int init_editline = 0; /* editline library initialized? */ 7054313Smarc int whichprompt; /* 1 == PS1, 2 == PS2 */ 7147119Sbostic 7254313Smarc EditLine *el; /* cookie for editline package */ 7354313Smarc 7447119Sbostic #ifdef __STDC__ 7547119Sbostic STATIC void pushfile(void); 7647119Sbostic #else 7747119Sbostic STATIC void pushfile(); 7847119Sbostic #endif 7947119Sbostic 8047119Sbostic 8147119Sbostic 8247119Sbostic #ifdef mkinit 8347119Sbostic INCLUDE "input.h" 8447119Sbostic INCLUDE "error.h" 8547119Sbostic 8647119Sbostic INIT { 8747119Sbostic extern char basebuf[]; 8847119Sbostic 8947119Sbostic basepf.nextc = basepf.buf = basebuf; 9047119Sbostic } 9147119Sbostic 9247119Sbostic RESET { 9347119Sbostic if (exception != EXSHELLPROC) 9447119Sbostic parsenleft = 0; /* clear input buffer */ 9547119Sbostic popallfiles(); 9647119Sbostic } 9747119Sbostic 9847119Sbostic SHELLPROC { 9947119Sbostic popallfiles(); 10047119Sbostic } 10147119Sbostic #endif 10247119Sbostic 10347119Sbostic 10447119Sbostic /* 10547119Sbostic * Read a line from the script. 10647119Sbostic */ 10747119Sbostic 10847119Sbostic char * 10947119Sbostic pfgets(line, len) 11047119Sbostic char *line; 11147119Sbostic { 11247119Sbostic register char *p = line; 11347119Sbostic int nleft = len; 11447119Sbostic int c; 11547119Sbostic 11647119Sbostic while (--nleft > 0) { 11747119Sbostic c = pgetc_macro(); 11847119Sbostic if (c == PEOF) { 11947119Sbostic if (p == line) 12047119Sbostic return NULL; 12147119Sbostic break; 12247119Sbostic } 12347119Sbostic *p++ = c; 12447119Sbostic if (c == '\n') 12547119Sbostic break; 12647119Sbostic } 12747119Sbostic *p = '\0'; 12847119Sbostic return line; 12947119Sbostic } 13047119Sbostic 13147119Sbostic 13247119Sbostic 13347119Sbostic /* 13447119Sbostic * Read a character from the script, returning PEOF on end of file. 13547119Sbostic * Nul characters in the input are silently discarded. 13647119Sbostic */ 13747119Sbostic 13847119Sbostic int 13947119Sbostic pgetc() { 14047119Sbostic return pgetc_macro(); 14147119Sbostic } 14247119Sbostic 14347119Sbostic 14447119Sbostic /* 14547119Sbostic * Refill the input buffer and return the next input character: 14647119Sbostic * 14754313Smarc * 1) If a string was pushed back on the input, pop it; 14847119Sbostic * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading 14947119Sbostic * from a string so we can't refill the buffer, return EOF. 15047119Sbostic * 3) Call read to read in the characters. 15147119Sbostic * 4) Delete all nul characters from the buffer. 15247119Sbostic */ 15347119Sbostic 15447119Sbostic int 15547119Sbostic preadbuffer() { 15647119Sbostic register char *p, *q; 15747119Sbostic register int i; 15854313Smarc register int something; 15954313Smarc extern EditLine *el; 16047119Sbostic 16154313Smarc if (parsefile->strpush) { 16254313Smarc popstring(); 16347119Sbostic if (--parsenleft >= 0) 16454313Smarc return (*parsenextc++); 16547119Sbostic } 16647119Sbostic if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) 16747119Sbostic return PEOF; 16847119Sbostic flushout(&output); 16947119Sbostic flushout(&errout); 17047119Sbostic retry: 17147119Sbostic p = parsenextc = parsefile->buf; 17254313Smarc if (parsefile->fd == 0 && el) { 17355241Smarc const char *rl_cp; 17454313Smarc int len; 17554313Smarc 17654313Smarc rl_cp = el_gets(el, &len); 17754313Smarc if (rl_cp == NULL) { 17854313Smarc i = 0; 17954313Smarc goto eof; 18054313Smarc } 18154313Smarc strcpy(p, rl_cp); /* XXX - BUFSIZE should redesign so not necessary */ 18254313Smarc i = len; 18354313Smarc 18454313Smarc } else { 18554313Smarc regular_read: 18654313Smarc i = read(parsefile->fd, p, BUFSIZ - 1); 18754313Smarc } 18854313Smarc eof: 18947119Sbostic if (i <= 0) { 19047294Smarc if (i < 0) { 19147294Smarc if (errno == EINTR) 19247294Smarc goto retry; 19347294Smarc if (parsefile->fd == 0 && errno == EWOULDBLOCK) { 19447294Smarc int flags = fcntl(0, F_GETFL, 0); 19550345Sbostic if (flags >= 0 && flags & O_NONBLOCK) { 19650345Sbostic flags &=~ O_NONBLOCK; 19747294Smarc if (fcntl(0, F_SETFL, flags) >= 0) { 19847980Smarc out2str("sh: turning off NDELAY mode\n"); 19947294Smarc goto retry; 20047294Smarc } 20147294Smarc } 20247294Smarc } 20347294Smarc } 20447294Smarc parsenleft = EOF_NLEFT; 20547294Smarc return PEOF; 20647119Sbostic } 20754313Smarc parsenleft = i - 1; /* we're returning one char in this call */ 20847119Sbostic 20947119Sbostic /* delete nul characters */ 21054313Smarc something = 0; 21147119Sbostic for (;;) { 21254313Smarc if (*p == '\0') 21347119Sbostic break; 21454313Smarc if (*p != ' ' && *p != '\t' && *p != '\n') 21554313Smarc something = 1; 21654313Smarc p++; 21754313Smarc if (--i <= 0) { 21854313Smarc *p = '\0'; 21954313Smarc goto done; /* no nul characters */ 22054313Smarc } 22147119Sbostic } 22254313Smarc /* 22354313Smarc * remove nuls 22454313Smarc */ 22554313Smarc q = p++; 22647119Sbostic while (--i > 0) { 22747119Sbostic if (*p != '\0') 22847119Sbostic *q++ = *p; 22947119Sbostic p++; 23047119Sbostic } 23154313Smarc *q = '\0'; 23247119Sbostic if (q == parsefile->buf) 23347119Sbostic goto retry; /* buffer contained nothing but nuls */ 23447119Sbostic parsenleft = q - parsefile->buf - 1; 23554313Smarc 23654313Smarc done: 23754313Smarc if (parsefile->fd == 0 && hist && something) { 23854313Smarc INTOFF; 23954313Smarc history(hist, whichprompt == 1 ? H_ENTER : H_ADD, 24054313Smarc parsefile->buf); 24154313Smarc INTON; 24254313Smarc } 24354313Smarc if (vflag) { 24454313Smarc /* 24554313Smarc * This isn't right. Most shells coordinate it with 24654313Smarc * reading a line at a time. I honestly don't know if its 24754313Smarc * worth it. 24854313Smarc */ 24954313Smarc i = parsenleft + 1; 25054313Smarc p = parsefile->buf; 25154313Smarc for (; i--; p++) 25254313Smarc out2c(*p) 25354313Smarc flushout(out2); 25454313Smarc } 25547119Sbostic return *parsenextc++; 25647119Sbostic } 25747119Sbostic 25847119Sbostic /* 25947119Sbostic * Undo the last call to pgetc. Only one character may be pushed back. 26047119Sbostic * PEOF may be pushed back. 26147119Sbostic */ 26247119Sbostic 26347119Sbostic void 26447119Sbostic pungetc() { 26547119Sbostic parsenleft++; 26647119Sbostic parsenextc--; 26747119Sbostic } 26847119Sbostic 26947119Sbostic /* 27054313Smarc * Push a string back onto the input at this current parsefile level. 27154313Smarc * We handle aliases this way. 27247119Sbostic */ 27347119Sbostic void 27454313Smarc pushstring(s, len, ap) 27554313Smarc char *s; 27654313Smarc int len; 27754313Smarc void *ap; 27847119Sbostic { 27954313Smarc struct strpush *sp; 28054313Smarc 28154313Smarc INTOFF; 28254313Smarc /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/ 28354313Smarc if (parsefile->strpush) { 28454313Smarc sp = ckmalloc(sizeof (struct strpush)); 28554313Smarc sp->prev = parsefile->strpush; 28654313Smarc parsefile->strpush = sp; 28754313Smarc } else 28854313Smarc sp = parsefile->strpush = &(parsefile->basestrpush); 28954313Smarc sp->prevstring = parsenextc; 29054313Smarc sp->prevnleft = parsenleft; 29154313Smarc sp->ap = (struct alias *)ap; 29254313Smarc if (ap) 29354313Smarc ((struct alias *)ap)->flag |= ALIASINUSE; 29454313Smarc parsenextc = s; 29554313Smarc parsenleft = len; 29654313Smarc INTON; 29747119Sbostic } 29847119Sbostic 29954313Smarc popstring() 30054313Smarc { 30154313Smarc struct strpush *sp = parsefile->strpush; 30247119Sbostic 30354313Smarc INTOFF; 30454313Smarc parsenextc = sp->prevstring; 30554313Smarc parsenleft = sp->prevnleft; 30654313Smarc /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/ 30754313Smarc if (sp->ap) 30854313Smarc sp->ap->flag &= ~ALIASINUSE; 30954313Smarc parsefile->strpush = sp->prev; 31054313Smarc if (sp != &(parsefile->basestrpush)) 31154313Smarc ckfree(sp); 31254313Smarc INTON; 31354313Smarc } 31447119Sbostic 31547119Sbostic /* 31647119Sbostic * Set the input to take input from a file. If push is set, push the 31747119Sbostic * old input onto the stack first. 31847119Sbostic */ 31947119Sbostic 32047119Sbostic void 32147119Sbostic setinputfile(fname, push) 32247119Sbostic char *fname; 32347119Sbostic { 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 34847119Sbostic setinputfd(fd, push) { 34947119Sbostic if (push) { 35047119Sbostic pushfile(); 35147119Sbostic parsefile->buf = ckmalloc(BUFSIZ); 35247119Sbostic } 35347119Sbostic if (parsefile->fd > 0) 35447119Sbostic close(parsefile->fd); 35547119Sbostic parsefile->fd = fd; 35647119Sbostic if (parsefile->buf == NULL) 35747119Sbostic parsefile->buf = ckmalloc(BUFSIZ); 35847119Sbostic parsenleft = 0; 35947119Sbostic plinno = 1; 36047119Sbostic } 36147119Sbostic 36247119Sbostic 36347119Sbostic /* 36447119Sbostic * Like setinputfile, but takes input from a string. 36547119Sbostic */ 36647119Sbostic 36747119Sbostic void 36847119Sbostic setinputstring(string, push) 36947119Sbostic char *string; 37047119Sbostic { 37147119Sbostic INTOFF; 37247119Sbostic if (push) 37347119Sbostic pushfile(); 37447119Sbostic parsenextc = string; 37547119Sbostic parsenleft = strlen(string); 37647119Sbostic parsefile->buf = NULL; 37747119Sbostic plinno = 1; 37847119Sbostic INTON; 37947119Sbostic } 38047119Sbostic 38147119Sbostic 38247119Sbostic 38347119Sbostic /* 38447119Sbostic * To handle the "." command, a stack of input files is used. Pushfile 38547119Sbostic * adds a new entry to the stack and popfile restores the previous level. 38647119Sbostic */ 38747119Sbostic 38847119Sbostic STATIC void 38947119Sbostic pushfile() { 39047119Sbostic struct parsefile *pf; 39147119Sbostic 39247119Sbostic parsefile->nleft = parsenleft; 39347119Sbostic parsefile->nextc = parsenextc; 39447119Sbostic parsefile->linno = plinno; 39547119Sbostic pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); 39647119Sbostic pf->prev = parsefile; 39747119Sbostic pf->fd = -1; 39854313Smarc pf->strpush = NULL; 39954313Smarc pf->basestrpush.prev = NULL; 40047119Sbostic parsefile = pf; 40147119Sbostic } 40247119Sbostic 40347119Sbostic 40447119Sbostic void 40547119Sbostic popfile() { 40647119Sbostic struct parsefile *pf = parsefile; 40747119Sbostic 40847119Sbostic INTOFF; 40947119Sbostic if (pf->fd >= 0) 41047119Sbostic close(pf->fd); 41147119Sbostic if (pf->buf) 41247119Sbostic ckfree(pf->buf); 41354313Smarc while (pf->strpush) 41454313Smarc popstring(); 41547119Sbostic parsefile = pf->prev; 41647119Sbostic ckfree(pf); 41747119Sbostic parsenleft = parsefile->nleft; 41847119Sbostic parsenextc = parsefile->nextc; 41947119Sbostic plinno = parsefile->linno; 42047119Sbostic INTON; 42147119Sbostic } 42247119Sbostic 42347119Sbostic 42447119Sbostic /* 42547119Sbostic * Return to top level. 42647119Sbostic */ 42747119Sbostic 42847119Sbostic void 42947119Sbostic popallfiles() { 43047119Sbostic while (parsefile != &basepf) 43147119Sbostic popfile(); 43247119Sbostic } 43347119Sbostic 43447119Sbostic 43547119Sbostic 43647119Sbostic /* 43747119Sbostic * Close the file(s) that the shell is reading commands from. Called 43847119Sbostic * after a fork is done. 43947119Sbostic */ 44047119Sbostic 44147119Sbostic void 44247119Sbostic closescript() { 44347119Sbostic popallfiles(); 44447119Sbostic if (parsefile->fd > 0) { 44547119Sbostic close(parsefile->fd); 44647119Sbostic parsefile->fd = 0; 44747119Sbostic } 44847119Sbostic } 449