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