xref: /freebsd/bin/sh/input.c (revision e67e85659c0de33e617e5fbf1028c6e8b49eee53)
1  /*-
2   * Copyright (c) 1991, 1993
3   *	The Regents of the University of California.  All rights reserved.
4   *
5   * This code is derived from software contributed to Berkeley by
6   * Kenneth Almquist.
7   *
8   * Redistribution and use in source and binary forms, with or without
9   * modification, are permitted provided that the following conditions
10   * are met:
11   * 1. Redistributions of source code must retain the above copyright
12   *    notice, this list of conditions and the following disclaimer.
13   * 2. Redistributions in binary form must reproduce the above copyright
14   *    notice, this list of conditions and the following disclaimer in the
15   *    documentation and/or other materials provided with the distribution.
16   * 3. Neither the name of the University nor the names of its contributors
17   *    may be used to endorse or promote products derived from this software
18   *    without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30   * SUCH DAMAGE.
31   */
32  
33  #ifndef lint
34  #if 0
35  static char sccsid[] = "@(#)input.c	8.3 (Berkeley) 6/9/95";
36  #endif
37  #endif /* not lint */
38  #include <sys/cdefs.h>
39  __FBSDID("$FreeBSD$");
40  
41  #include <stdio.h>	/* defines BUFSIZ */
42  #include <fcntl.h>
43  #include <errno.h>
44  #include <unistd.h>
45  #include <stdlib.h>
46  #include <string.h>
47  
48  /*
49   * This file implements the input routines used by the parser.
50   */
51  
52  #include "shell.h"
53  #include "redir.h"
54  #include "syntax.h"
55  #include "input.h"
56  #include "output.h"
57  #include "options.h"
58  #include "memalloc.h"
59  #include "error.h"
60  #include "alias.h"
61  #include "parser.h"
62  #ifndef NO_HISTORY
63  #include "myhistedit.h"
64  #endif
65  #include "trap.h"
66  
67  #define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
68  
69  struct strpush {
70  	struct strpush *prev;	/* preceding string on stack */
71  	const char *prevstring;
72  	int prevnleft;
73  	int prevlleft;
74  	struct alias *ap;	/* if push was associated with an alias */
75  };
76  
77  /*
78   * The parsefile structure pointed to by the global variable parsefile
79   * contains information about the current file being read.
80   */
81  
82  struct parsefile {
83  	struct parsefile *prev;	/* preceding file on stack */
84  	int linno;		/* current line */
85  	int fd;			/* file descriptor (or -1 if string) */
86  	int nleft;		/* number of chars left in this line */
87  	int lleft;		/* number of lines left in this buffer */
88  	const char *nextc;	/* next char in buffer */
89  	char *buf;		/* input buffer */
90  	struct strpush *strpush; /* for pushing strings at this level */
91  	struct strpush basestrpush; /* so pushing one is fast */
92  };
93  
94  
95  int plinno = 1;			/* input line number */
96  int parsenleft;			/* copy of parsefile->nleft */
97  static int parselleft;		/* copy of parsefile->lleft */
98  const char *parsenextc;		/* copy of parsefile->nextc */
99  static char basebuf[BUFSIZ + 1];/* buffer for top level input file */
100  static struct parsefile basepf = {	/* top level input file */
101  	.nextc = basebuf,
102  	.buf = basebuf
103  };
104  static struct parsefile *parsefile = &basepf;	/* current input file */
105  int whichprompt;		/* 1 == PS1, 2 == PS2 */
106  
107  static void pushfile(void);
108  static int preadfd(void);
109  static void popstring(void);
110  
111  void
112  resetinput(void)
113  {
114  	popallfiles();
115  	parselleft = parsenleft = 0;	/* clear input buffer */
116  }
117  
118  
119  
120  /*
121   * Read a character from the script, returning PEOF on end of file.
122   * Nul characters in the input are silently discarded.
123   */
124  
125  int
126  pgetc(void)
127  {
128  	return pgetc_macro();
129  }
130  
131  
132  static int
133  preadfd(void)
134  {
135  	int nr;
136  	parsenextc = parsefile->buf;
137  
138  retry:
139  #ifndef NO_HISTORY
140  	if (parsefile->fd == 0 && el) {
141  		static const char *rl_cp;
142  		static int el_len;
143  
144  		if (rl_cp == NULL) {
145  			el_resize(el);
146  			rl_cp = el_gets(el, &el_len);
147  		}
148  		if (rl_cp == NULL)
149  			nr = el_len == 0 ? 0 : -1;
150  		else {
151  			nr = el_len;
152  			if (nr > BUFSIZ)
153  				nr = BUFSIZ;
154  			memcpy(parsefile->buf, rl_cp, nr);
155  			if (nr != el_len) {
156  				el_len -= nr;
157  				rl_cp += nr;
158  			} else
159  				rl_cp = NULL;
160  		}
161  	} else
162  #endif
163  		nr = read(parsefile->fd, parsefile->buf, BUFSIZ);
164  
165  	if (nr <= 0) {
166                  if (nr < 0) {
167                          if (errno == EINTR)
168                                  goto retry;
169                          if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
170                                  int flags = fcntl(0, F_GETFL, 0);
171                                  if (flags >= 0 && flags & O_NONBLOCK) {
172                                          flags &=~ O_NONBLOCK;
173                                          if (fcntl(0, F_SETFL, flags) >= 0) {
174  						out2fmt_flush("sh: turning off NDELAY mode\n");
175                                                  goto retry;
176                                          }
177                                  }
178                          }
179                  }
180                  nr = -1;
181  	}
182  	return nr;
183  }
184  
185  /*
186   * Refill the input buffer and return the next input character:
187   *
188   * 1) If a string was pushed back on the input, pop it;
189   * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
190   *    from a string so we can't refill the buffer, return EOF.
191   * 3) If there is more in this buffer, use it else call read to fill it.
192   * 4) Process input up to the next newline, deleting nul characters.
193   */
194  
195  int
196  preadbuffer(void)
197  {
198  	char *p, *q, *r, *end;
199  	char savec;
200  
201  	while (parsefile->strpush) {
202  		/*
203  		 * Add a space to the end of an alias to ensure that the
204  		 * alias remains in use while parsing its last word.
205  		 * This avoids alias recursions.
206  		 */
207  		if (parsenleft == -1 && parsefile->strpush->ap != NULL)
208  			return ' ';
209  		popstring();
210  		if (--parsenleft >= 0)
211  			return (*parsenextc++);
212  	}
213  	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
214  		return PEOF;
215  
216  again:
217  	if (parselleft <= 0) {
218  		if ((parselleft = preadfd()) == -1) {
219  			parselleft = parsenleft = EOF_NLEFT;
220  			return PEOF;
221  		}
222  	}
223  
224  	p = parsefile->buf + (parsenextc - parsefile->buf);
225  	end = p + parselleft;
226  	*end = '\0';
227  	q = strchrnul(p, '\n');
228  	if (q != end && *q == '\0') {
229  		/* delete nul characters */
230  		for (r = q; q != end; q++) {
231  			if (*q != '\0')
232  				*r++ = *q;
233  		}
234  		parselleft -= end - r;
235  		if (parselleft == 0)
236  			goto again;
237  		end = p + parselleft;
238  		*end = '\0';
239  		q = strchrnul(p, '\n');
240  	}
241  	if (q == end) {
242  		parsenleft = parselleft;
243  		parselleft = 0;
244  	} else /* *q == '\n' */ {
245  		q++;
246  		parsenleft = q - parsenextc;
247  		parselleft -= parsenleft;
248  	}
249  	parsenleft--;
250  
251  	savec = *q;
252  	*q = '\0';
253  
254  #ifndef NO_HISTORY
255  	if (parsefile->fd == 0 && hist &&
256  	    parsenextc[strspn(parsenextc, " \t\n")] != '\0') {
257  		HistEvent he;
258  		INTOFF;
259  		history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD,
260  		    parsenextc);
261  		INTON;
262  	}
263  #endif
264  
265  	if (vflag) {
266  		out2str(parsenextc);
267  		flushout(out2);
268  	}
269  
270  	*q = savec;
271  
272  	return *parsenextc++;
273  }
274  
275  /*
276   * Returns if we are certain we are at EOF. Does not cause any more input
277   * to be read from the outside world.
278   */
279  
280  int
281  preadateof(void)
282  {
283  	if (parsenleft > 0)
284  		return 0;
285  	if (parsefile->strpush)
286  		return 0;
287  	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
288  		return 1;
289  	return 0;
290  }
291  
292  /*
293   * Undo the last call to pgetc.  Only one character may be pushed back.
294   * PEOF may be pushed back.
295   */
296  
297  void
298  pungetc(void)
299  {
300  	parsenleft++;
301  	parsenextc--;
302  }
303  
304  /*
305   * Push a string back onto the input at this current parsefile level.
306   * We handle aliases this way.
307   */
308  void
309  pushstring(const char *s, int len, struct alias *ap)
310  {
311  	struct strpush *sp;
312  
313  	INTOFF;
314  /*out2fmt_flush("*** calling pushstring: %s, %d\n", s, len);*/
315  	if (parsefile->strpush) {
316  		sp = ckmalloc(sizeof (struct strpush));
317  		sp->prev = parsefile->strpush;
318  		parsefile->strpush = sp;
319  	} else
320  		sp = parsefile->strpush = &(parsefile->basestrpush);
321  	sp->prevstring = parsenextc;
322  	sp->prevnleft = parsenleft;
323  	sp->prevlleft = parselleft;
324  	sp->ap = ap;
325  	if (ap)
326  		ap->flag |= ALIASINUSE;
327  	parsenextc = s;
328  	parsenleft = len;
329  	INTON;
330  }
331  
332  static void
333  popstring(void)
334  {
335  	struct strpush *sp = parsefile->strpush;
336  
337  	INTOFF;
338  	if (sp->ap) {
339  		if (parsenextc != sp->ap->val &&
340  		    (parsenextc[-1] == ' ' || parsenextc[-1] == '\t'))
341  			forcealias();
342  		sp->ap->flag &= ~ALIASINUSE;
343  	}
344  	parsenextc = sp->prevstring;
345  	parsenleft = sp->prevnleft;
346  	parselleft = sp->prevlleft;
347  /*out2fmt_flush("*** calling popstring: restoring to '%s'\n", parsenextc);*/
348  	parsefile->strpush = sp->prev;
349  	if (sp != &(parsefile->basestrpush))
350  		ckfree(sp);
351  	INTON;
352  }
353  
354  /*
355   * Set the input to take input from a file.  If push is set, push the
356   * old input onto the stack first.
357   * About verify:
358   *   -1: Obey verifyflag
359   *    0: Do not verify
360   *    1: Do verify
361   */
362  
363  void
364  setinputfile(const char *fname, int push, int verify)
365  {
366  	int e;
367  	int fd;
368  	int fd2;
369  	int oflags = O_RDONLY | O_CLOEXEC;
370  
371  	if (verify == 1 || (verify == -1 && verifyflag))
372  		oflags |= O_VERIFY;
373  
374  	INTOFF;
375  	if ((fd = open(fname, oflags)) < 0) {
376  		e = errno;
377  		errorwithstatus(e == ENOENT || e == ENOTDIR ? 127 : 126,
378  		    "cannot open %s: %s", fname, strerror(e));
379  	}
380  	if (fd < 10) {
381  		fd2 = fcntl(fd, F_DUPFD_CLOEXEC, 10);
382  		close(fd);
383  		if (fd2 < 0)
384  			error("Out of file descriptors");
385  		fd = fd2;
386  	}
387  	setinputfd(fd, push);
388  	INTON;
389  }
390  
391  
392  /*
393   * Like setinputfile, but takes an open file descriptor (which should have
394   * its FD_CLOEXEC flag already set).  Call this with interrupts off.
395   */
396  
397  void
398  setinputfd(int fd, int push)
399  {
400  	if (push) {
401  		pushfile();
402  		parsefile->buf = ckmalloc(BUFSIZ + 1);
403  	}
404  	if (parsefile->fd > 0)
405  		close(parsefile->fd);
406  	parsefile->fd = fd;
407  	if (parsefile->buf == NULL)
408  		parsefile->buf = ckmalloc(BUFSIZ + 1);
409  	parselleft = parsenleft = 0;
410  	plinno = 1;
411  }
412  
413  
414  /*
415   * Like setinputfile, but takes input from a string.
416   */
417  
418  void
419  setinputstring(const char *string, int push)
420  {
421  	INTOFF;
422  	if (push)
423  		pushfile();
424  	parsenextc = string;
425  	parselleft = parsenleft = strlen(string);
426  	parsefile->buf = NULL;
427  	plinno = 1;
428  	INTON;
429  }
430  
431  
432  
433  /*
434   * To handle the "." command, a stack of input files is used.  Pushfile
435   * adds a new entry to the stack and popfile restores the previous level.
436   */
437  
438  static void
439  pushfile(void)
440  {
441  	struct parsefile *pf;
442  
443  	parsefile->nleft = parsenleft;
444  	parsefile->lleft = parselleft;
445  	parsefile->nextc = parsenextc;
446  	parsefile->linno = plinno;
447  	pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
448  	pf->prev = parsefile;
449  	pf->fd = -1;
450  	pf->strpush = NULL;
451  	pf->basestrpush.prev = NULL;
452  	parsefile = pf;
453  }
454  
455  
456  void
457  popfile(void)
458  {
459  	struct parsefile *pf = parsefile;
460  
461  	INTOFF;
462  	if (pf->fd >= 0)
463  		close(pf->fd);
464  	if (pf->buf)
465  		ckfree(pf->buf);
466  	while (pf->strpush)
467  		popstring();
468  	parsefile = pf->prev;
469  	ckfree(pf);
470  	parsenleft = parsefile->nleft;
471  	parselleft = parsefile->lleft;
472  	parsenextc = parsefile->nextc;
473  	plinno = parsefile->linno;
474  	INTON;
475  }
476  
477  
478  /*
479   * Return current file (to go back to it later using popfilesupto()).
480   */
481  
482  struct parsefile *
483  getcurrentfile(void)
484  {
485  	return parsefile;
486  }
487  
488  
489  /*
490   * Pop files until the given file is on top again. Useful for regular
491   * builtins that read shell commands from files or strings.
492   * If the given file is not an active file, an error is raised.
493   */
494  
495  void
496  popfilesupto(struct parsefile *file)
497  {
498  	while (parsefile != file && parsefile != &basepf)
499  		popfile();
500  	if (parsefile != file)
501  		error("popfilesupto() misused");
502  }
503  
504  /*
505   * Return to top level.
506   */
507  
508  void
509  popallfiles(void)
510  {
511  	while (parsefile != &basepf)
512  		popfile();
513  }
514  
515  
516  
517  /*
518   * Close the file(s) that the shell is reading commands from.  Called
519   * after a fork is done.
520   */
521  
522  void
523  closescript(void)
524  {
525  	popallfiles();
526  	if (parsefile->fd > 0) {
527  		close(parsefile->fd);
528  		parsefile->fd = 0;
529  	}
530  }
531