147119Sbostic /*- 247119Sbostic * Copyright (c) 1991 The Regents of the University of California. 347119Sbostic * 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*54313Smarc static char sccsid[] = "@(#)input.c 5.5 (Berkeley) 06/23/92"; 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" 26*54313Smarc #include "options.h" 2747119Sbostic #include "memalloc.h" 2847119Sbostic #include "error.h" 29*54313Smarc #include "alias.h" 30*54313Smarc #include "parser.h" 31*54313Smarc #include "histedit.h" 3247119Sbostic 3347119Sbostic #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ 3447119Sbostic 35*54313Smarc MKINIT 36*54313Smarc struct strpush { 37*54313Smarc struct strpush *prev; /* preceding string on stack */ 38*54313Smarc char *prevstring; 39*54313Smarc int prevnleft; 40*54313Smarc struct alias *ap; /* if push was associated with an alias */ 41*54313Smarc }; 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 { 50*54313Smarc 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 */ 56*54313Smarc struct strpush *strpush; /* for pushing strings at this level */ 57*54313Smarc 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 */ 69*54313Smarc int init_editline = 0; /* editline library initialized? */ 70*54313Smarc int whichprompt; /* 1 == PS1, 2 == PS2 */ 7147119Sbostic 72*54313Smarc EditLine *el; /* cookie for editline package */ 73*54313Smarc 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 * 147*54313Smarc * 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; 158*54313Smarc register int something; 159*54313Smarc extern EditLine *el; 160*54313Smarc extern int is_interactive; 16147119Sbostic 162*54313Smarc if (parsefile->strpush) { 163*54313Smarc popstring(); 16447119Sbostic if (--parsenleft >= 0) 165*54313Smarc return (*parsenextc++); 16647119Sbostic } 16747119Sbostic if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) 16847119Sbostic return PEOF; 16947119Sbostic flushout(&output); 17047119Sbostic flushout(&errout); 17147119Sbostic retry: 17247119Sbostic p = parsenextc = parsefile->buf; 173*54313Smarc if (parsefile->fd == 0 && el) { 174*54313Smarc char *rl_cp; 175*54313Smarc int len; 176*54313Smarc 177*54313Smarc rl_cp = el_gets(el, &len); 178*54313Smarc if (rl_cp == NULL) { 179*54313Smarc i = 0; 180*54313Smarc goto eof; 181*54313Smarc } 182*54313Smarc strcpy(p, rl_cp); /* XXX - BUFSIZE should redesign so not necessary */ 183*54313Smarc i = len; 184*54313Smarc 185*54313Smarc } else { 186*54313Smarc regular_read: 187*54313Smarc i = read(parsefile->fd, p, BUFSIZ - 1); 188*54313Smarc } 189*54313Smarc eof: 19047119Sbostic if (i <= 0) { 19147294Smarc if (i < 0) { 19247294Smarc if (errno == EINTR) 19347294Smarc goto retry; 19447294Smarc if (parsefile->fd == 0 && errno == EWOULDBLOCK) { 19547294Smarc int flags = fcntl(0, F_GETFL, 0); 19650345Sbostic if (flags >= 0 && flags & O_NONBLOCK) { 19750345Sbostic flags &=~ O_NONBLOCK; 19847294Smarc if (fcntl(0, F_SETFL, flags) >= 0) { 19947980Smarc out2str("sh: turning off NDELAY mode\n"); 20047294Smarc goto retry; 20147294Smarc } 20247294Smarc } 20347294Smarc } 20447294Smarc } 20547294Smarc parsenleft = EOF_NLEFT; 20647294Smarc return PEOF; 20747119Sbostic } 208*54313Smarc parsenleft = i - 1; /* we're returning one char in this call */ 20947119Sbostic 21047119Sbostic /* delete nul characters */ 211*54313Smarc something = 0; 21247119Sbostic for (;;) { 213*54313Smarc if (*p == '\0') 21447119Sbostic break; 215*54313Smarc if (*p != ' ' && *p != '\t' && *p != '\n') 216*54313Smarc something = 1; 217*54313Smarc p++; 218*54313Smarc if (--i <= 0) { 219*54313Smarc *p = '\0'; 220*54313Smarc goto done; /* no nul characters */ 221*54313Smarc } 22247119Sbostic } 223*54313Smarc /* 224*54313Smarc * remove nuls 225*54313Smarc */ 226*54313Smarc q = p++; 22747119Sbostic while (--i > 0) { 22847119Sbostic if (*p != '\0') 22947119Sbostic *q++ = *p; 23047119Sbostic p++; 23147119Sbostic } 232*54313Smarc *q = '\0'; 23347119Sbostic if (q == parsefile->buf) 23447119Sbostic goto retry; /* buffer contained nothing but nuls */ 23547119Sbostic parsenleft = q - parsefile->buf - 1; 236*54313Smarc 237*54313Smarc done: 238*54313Smarc if (parsefile->fd == 0 && hist && something) { 239*54313Smarc INTOFF; 240*54313Smarc history(hist, whichprompt == 1 ? H_ENTER : H_ADD, 241*54313Smarc parsefile->buf); 242*54313Smarc INTON; 243*54313Smarc } 244*54313Smarc if (vflag) { 245*54313Smarc /* 246*54313Smarc * This isn't right. Most shells coordinate it with 247*54313Smarc * reading a line at a time. I honestly don't know if its 248*54313Smarc * worth it. 249*54313Smarc */ 250*54313Smarc i = parsenleft + 1; 251*54313Smarc p = parsefile->buf; 252*54313Smarc for (; i--; p++) 253*54313Smarc out2c(*p) 254*54313Smarc flushout(out2); 255*54313Smarc } 25647119Sbostic return *parsenextc++; 25747119Sbostic } 25847119Sbostic 25947119Sbostic /* 26047119Sbostic * Undo the last call to pgetc. Only one character may be pushed back. 26147119Sbostic * PEOF may be pushed back. 26247119Sbostic */ 26347119Sbostic 26447119Sbostic void 26547119Sbostic pungetc() { 26647119Sbostic parsenleft++; 26747119Sbostic parsenextc--; 26847119Sbostic } 26947119Sbostic 27047119Sbostic /* 271*54313Smarc * Push a string back onto the input at this current parsefile level. 272*54313Smarc * We handle aliases this way. 27347119Sbostic */ 27447119Sbostic void 275*54313Smarc pushstring(s, len, ap) 276*54313Smarc char *s; 277*54313Smarc int len; 278*54313Smarc void *ap; 27947119Sbostic { 280*54313Smarc struct strpush *sp; 281*54313Smarc 282*54313Smarc INTOFF; 283*54313Smarc /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/ 284*54313Smarc if (parsefile->strpush) { 285*54313Smarc sp = ckmalloc(sizeof (struct strpush)); 286*54313Smarc sp->prev = parsefile->strpush; 287*54313Smarc parsefile->strpush = sp; 288*54313Smarc } else 289*54313Smarc sp = parsefile->strpush = &(parsefile->basestrpush); 290*54313Smarc sp->prevstring = parsenextc; 291*54313Smarc sp->prevnleft = parsenleft; 292*54313Smarc sp->ap = (struct alias *)ap; 293*54313Smarc if (ap) 294*54313Smarc ((struct alias *)ap)->flag |= ALIASINUSE; 295*54313Smarc parsenextc = s; 296*54313Smarc parsenleft = len; 297*54313Smarc INTON; 29847119Sbostic } 29947119Sbostic 300*54313Smarc popstring() 301*54313Smarc { 302*54313Smarc struct strpush *sp = parsefile->strpush; 30347119Sbostic 304*54313Smarc INTOFF; 305*54313Smarc parsenextc = sp->prevstring; 306*54313Smarc parsenleft = sp->prevnleft; 307*54313Smarc /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/ 308*54313Smarc if (sp->ap) 309*54313Smarc sp->ap->flag &= ~ALIASINUSE; 310*54313Smarc parsefile->strpush = sp->prev; 311*54313Smarc if (sp != &(parsefile->basestrpush)) 312*54313Smarc ckfree(sp); 313*54313Smarc INTON; 314*54313Smarc } 31547119Sbostic 31647119Sbostic /* 31747119Sbostic * Set the input to take input from a file. If push is set, push the 31847119Sbostic * old input onto the stack first. 31947119Sbostic */ 32047119Sbostic 32147119Sbostic void 32247119Sbostic setinputfile(fname, push) 32347119Sbostic char *fname; 32447119Sbostic { 32547119Sbostic int fd; 32647119Sbostic int fd2; 32747119Sbostic 32847119Sbostic INTOFF; 32947119Sbostic if ((fd = open(fname, O_RDONLY)) < 0) 33047119Sbostic error("Can't open %s", fname); 33147119Sbostic if (fd < 10) { 33247119Sbostic fd2 = copyfd(fd, 10); 33347119Sbostic close(fd); 33447119Sbostic if (fd2 < 0) 33547119Sbostic error("Out of file descriptors"); 33647119Sbostic fd = fd2; 33747119Sbostic } 33847119Sbostic setinputfd(fd, push); 33947119Sbostic INTON; 34047119Sbostic } 34147119Sbostic 34247119Sbostic 34347119Sbostic /* 34447119Sbostic * Like setinputfile, but takes an open file descriptor. Call this with 34547119Sbostic * interrupts off. 34647119Sbostic */ 34747119Sbostic 34847119Sbostic void 34947119Sbostic setinputfd(fd, push) { 35047119Sbostic if (push) { 35147119Sbostic pushfile(); 35247119Sbostic parsefile->buf = ckmalloc(BUFSIZ); 35347119Sbostic } 35447119Sbostic if (parsefile->fd > 0) 35547119Sbostic close(parsefile->fd); 35647119Sbostic parsefile->fd = fd; 35747119Sbostic if (parsefile->buf == NULL) 35847119Sbostic parsefile->buf = ckmalloc(BUFSIZ); 35947119Sbostic parsenleft = 0; 36047119Sbostic plinno = 1; 36147119Sbostic } 36247119Sbostic 36347119Sbostic 36447119Sbostic /* 36547119Sbostic * Like setinputfile, but takes input from a string. 36647119Sbostic */ 36747119Sbostic 36847119Sbostic void 36947119Sbostic setinputstring(string, push) 37047119Sbostic char *string; 37147119Sbostic { 37247119Sbostic INTOFF; 37347119Sbostic if (push) 37447119Sbostic pushfile(); 37547119Sbostic parsenextc = string; 37647119Sbostic parsenleft = strlen(string); 37747119Sbostic parsefile->buf = NULL; 37847119Sbostic plinno = 1; 37947119Sbostic INTON; 38047119Sbostic } 38147119Sbostic 38247119Sbostic 38347119Sbostic 38447119Sbostic /* 38547119Sbostic * To handle the "." command, a stack of input files is used. Pushfile 38647119Sbostic * adds a new entry to the stack and popfile restores the previous level. 38747119Sbostic */ 38847119Sbostic 38947119Sbostic STATIC void 39047119Sbostic pushfile() { 39147119Sbostic struct parsefile *pf; 39247119Sbostic 39347119Sbostic parsefile->nleft = parsenleft; 39447119Sbostic parsefile->nextc = parsenextc; 39547119Sbostic parsefile->linno = plinno; 39647119Sbostic pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); 39747119Sbostic pf->prev = parsefile; 39847119Sbostic pf->fd = -1; 399*54313Smarc pf->strpush = NULL; 400*54313Smarc pf->basestrpush.prev = NULL; 40147119Sbostic parsefile = pf; 40247119Sbostic } 40347119Sbostic 40447119Sbostic 40547119Sbostic void 40647119Sbostic popfile() { 40747119Sbostic struct parsefile *pf = parsefile; 40847119Sbostic 40947119Sbostic INTOFF; 41047119Sbostic if (pf->fd >= 0) 41147119Sbostic close(pf->fd); 41247119Sbostic if (pf->buf) 41347119Sbostic ckfree(pf->buf); 414*54313Smarc while (pf->strpush) 415*54313Smarc popstring(); 41647119Sbostic parsefile = pf->prev; 41747119Sbostic ckfree(pf); 41847119Sbostic parsenleft = parsefile->nleft; 41947119Sbostic parsenextc = parsefile->nextc; 42047119Sbostic plinno = parsefile->linno; 42147119Sbostic INTON; 42247119Sbostic } 42347119Sbostic 42447119Sbostic 42547119Sbostic /* 42647119Sbostic * Return to top level. 42747119Sbostic */ 42847119Sbostic 42947119Sbostic void 43047119Sbostic popallfiles() { 43147119Sbostic while (parsefile != &basepf) 43247119Sbostic popfile(); 43347119Sbostic } 43447119Sbostic 43547119Sbostic 43647119Sbostic 43747119Sbostic /* 43847119Sbostic * Close the file(s) that the shell is reading commands from. Called 43947119Sbostic * after a fork is done. 44047119Sbostic */ 44147119Sbostic 44247119Sbostic void 44347119Sbostic closescript() { 44447119Sbostic popallfiles(); 44547119Sbostic if (parsefile->fd > 0) { 44647119Sbostic close(parsefile->fd); 44747119Sbostic parsefile->fd = 0; 44847119Sbostic } 44947119Sbostic } 450