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 <errno.h>
36#include <fcntl.h>
37#include <stdio.h> /* defines BUFSIZ */
38#include <stdlib.h>
39#include <string.h>
40#include <unistd.h>
41
42/*
43 * This file implements the input routines used by the parser.
44 */
45
46#include "alias.h"
47#include "error.h"
48#include "input.h"
49#include "memalloc.h"
50#include "options.h"
51#include "output.h"
52#include "parser.h"
53#include "redir.h"
54#include "shell.h"
55#include "syntax.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
89int plinno = 1; /* input line number */
90int parsenleft; /* copy of parsefile->nleft */
91static int parselleft; /* copy of parsefile->lleft */
92const char *parsenextc; /* copy of parsefile->nextc */
93static char basebuf[BUFSIZ + 1]; /* buffer for top level input file */
94static struct parsefile basepf = {
95 /* 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 * Read a character from the script, returning PEOF on end of file.
116 * Nul characters in the input are silently discarded.
117 */
118
119int
120pgetc(void)
121{
122 return pgetc_macro();
123}
124
125static int
126preadfd(void)
127{
128 int nr;
129
130retry:
131#ifndef NO_HISTORY
132 if (parsefile->fd == 0 && sh_history_enabled) {
133 char *line;
134
135 line = redline(getprompt(NULL));
136 if (line != NULL) {
137 nr = strlen(line) + 1;
138 if (parsefile->bufsize < (size_t)nr + 1) {
139 size_t bufsize;
140
141 INTOFF;
142 if (parsefile->buf != basebuf) {
143 ckfree(parsefile->buf);
144 parsefile->buf = NULL;
145 parsefile->bufsize = 0;
146 }
147 bufsize = (size_t)nr + BUFSIZ + 1;
148 bufsize -= bufsize % BUFSIZ;
149 parsefile->buf = ckmalloc(bufsize);
150 parsefile->bufsize = bufsize;
151 INTON;
152 }
153 memcpy(parsefile->buf, line, nr - 1);
154 parsefile->buf[nr - 1] = '\n';
155 parsefile->buf[nr] = '\0';
156 free(line);
157 } else {
158 nr = 0;
159 }
160 } else
161#endif
162 nr = read(parsefile->fd, parsefile->buf, parsefile->bufsize - 1);
163
164 if (nr < 0)
165 switch (errno) {
166 int flags;
167
168 case EINTR:
169 goto retry;
170 case EWOULDBLOCK:
171 if (parsefile->fd != 0)
172 break;
173 if ((flags = fcntl(0, F_GETFL, 0)) < 0)
174 break;
175 if (!(flags & O_NONBLOCK))
176 break;
177 if (fcntl(0, F_SETFL, flags & ~O_NONBLOCK) < 0)
178 break;
179 out2fmt_flush("sh: turning off NDELAY mode\n");
180 goto retry;
181 }
182 else if (nr > 0)
183 parsefile->buf[nr] = '\0';
184 else
185 nr = -1;
186
187 parsenextc = parsefile->buf;
188 return nr;
189}
190
191/*
192 * Refill the input buffer and return the next input character:
193 *
194 * 1) If a string was pushed back on the input, pop it;
195 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
196 * from a string so we can't refill the buffer, return EOF.
197 * 3) If there is more in this buffer, use it else call read to fill it.
198 * 4) Process input up to the next newline, deleting nul characters.
199 */
200
201int
202preadbuffer(void)
203{
204 const char *end;
205 char *q, *r;
206 char savec;
207
208 while (parsefile->strpush) {
209 /*
210 * Add a space to the end of an alias to ensure that the
211 * alias remains in use while parsing its last word.
212 * This avoids alias recursions.
213 */
214 if (parsenleft == -1 && parsefile->strpush->ap != NULL)
215 return ' ';
216 popstring();
217 if (--parsenleft >= 0)
218 return (*parsenextc++);
219 }
220 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
221 return PEOF;
222
223again:
224 if (parselleft <= 0 && (parselleft = preadfd()) == -1) {
225 parselleft = parsenleft = EOF_NLEFT;
226 return (PEOF);
227 }
228 end = parsenextc + parselleft;
229 q = strchrnul(parsenextc, '\n');
230 if (*q == '\0' && q != end) {
231 /* delete nul characters */
232 for (r = q++; q != end; q++)
233 if (*q != '\0')
234 *r++ = *q;
235 *r = '\0';
236 parselleft = r - parsenextc;
237 goto again;
238 }
239 if (*q == '\0') {
240 parsenleft = parselleft;
241 parselleft = 0;
242 } else /* *q == '\n' */ {
243 q++;
244 parsenleft = q - parsenextc;
245 parselleft -= parsenleft;
246 }
247 parsenleft--;
248
249 savec = *q;
250 *q = '\0';
251
252#ifndef NO_HISTORY
253 if (parsefile->fd == 0 && sh_history_enabled && parsenextc[strspn(parsenextc, " \t\n")] != '\0') {
254 char *histline = strdup(parsenextc);
255 if (histline) {
256 char *nl = strchr(histline, '\n');
257 if (nl)
258 *nl = '\0';
259 INTOFF;
260 redlineHistoryAdd(histline);
261 INTON;
262 free(histline);
263 }
264 }
265#endif
266
267 if (vflag) {
268 out2str(parsenextc);
269 flushout(out2);
270 }
271
272 *q = savec;
273
274 return *parsenextc++;
275}
276
277/*
278 * Returns if we are certain we are at EOF. Does not cause any more input
279 * to be read from the outside world.
280 */
281
282int
283preadateof(void)
284{
285 if (parsenleft > 0)
286 return 0;
287 if (parsefile->strpush)
288 return 0;
289 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
290 return 1;
291 return 0;
292}
293
294/*
295 * Undo the last call to pgetc. Only one character may be pushed back.
296 * PEOF may be pushed back.
297 */
298
299void
300pungetc(void)
301{
302 parsenleft++;
303 parsenextc--;
304}
305
306/*
307 * Push a string back onto the input at this current parsefile level.
308 * We handle aliases this way.
309 */
310void
311pushstring(const char *s, int len, struct alias *ap)
312{
313 struct strpush *sp;
314
315 INTOFF;
316 /*out2fmt_flush("*** calling pushstring: %s, %d\n", s, len);*/
317 if (parsefile->strpush) {
318 sp = ckmalloc(sizeof(struct strpush));
319 sp->prev = parsefile->strpush;
320 parsefile->strpush = sp;
321 } else
322 sp = parsefile->strpush = &(parsefile->basestrpush);
323 sp->prevstring = parsenextc;
324 sp->prevnleft = parsenleft;
325 sp->prevlleft = parselleft;
326 sp->ap = ap;
327 if (ap)
328 ap->flag |= ALIASINUSE;
329 parsenextc = s;
330 parsenleft = len;
331 INTON;
332}
333
334static void
335popstring(void)
336{
337 struct strpush *sp = parsefile->strpush;
338
339 INTOFF;
340 if (sp->ap) {
341 if (parsenextc != sp->ap->val && (parsenextc[-1] == ' ' || parsenextc[-1] == '\t'))
342 forcealias();
343 sp->ap->flag &= ~ALIASINUSE;
344 }
345 parsenextc = sp->prevstring;
346 parsenleft = sp->prevnleft;
347 parselleft = sp->prevlleft;
348 /*out2fmt_flush("*** calling popstring: restoring to '%s'\n",
349 * parsenextc);*/
350 parsefile->strpush = sp->prev;
351 if (sp != &(parsefile->basestrpush))
352 ckfree(sp);
353 INTON;
354}
355
356/*
357 * Set the input to take input from a file. If push is set, push the
358 * old input onto the stack first.
359 * About verify:
360 * -1: Obey verifyflag
361 * 0: Do not verify
362 * 1: Do verify
363 */
364
365void
366setinputfile(const char *fname, int push, int verify)
367{
368 int e;
369 int fd;
370 int fd2;
371 int oflags = O_RDONLY | O_CLOEXEC;
372
373 if (verify == 1 || (verify == -1 && verifyflag))
374 oflags |= O_VERIFY;
375
376 INTOFF;
377 if ((fd = open(fname, oflags)) < 0) {
378 e = errno;
379 errorwithstatus(
380 e == ENOENT || e == ENOTDIR ? 127 : 126, "cannot open %s: %s", fname, strerror(e)
381 );
382 }
383 if (fd < 10) {
384 fd2 = fcntl(fd, F_DUPFD_CLOEXEC, 10);
385 close(fd);
386 if (fd2 < 0)
387 error("Out of file descriptors");
388 fd = fd2;
389 }
390 setinputfd(fd, push);
391 INTON;
392}
393
394/*
395 * Like setinputfile, but takes an open file descriptor (which should have
396 * its FD_CLOEXEC flag already set). Call this with interrupts off.
397 */
398
399void
400setinputfd(int fd, int push)
401{
402 if (push)
403 pushfile();
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 parsefile->bufsize = BUFSIZ + 1;
410 }
411 parselleft = parsenleft = 0;
412 plinno = 1;
413}
414
415/*
416 * Like setinputfile, but takes input from a string.
417 */
418
419void
420setinputstring(const char *string)
421{
422 INTOFF;
423 pushfile();
424 parsenextc = string;
425 parselleft = parsenleft = strlen(string);
426 plinno = 1;
427 INTON;
428}
429
430/*
431 * To handle the "." command, a stack of input files is used. Pushfile
432 * adds a new entry to the stack and popfile restores the previous level.
433 */
434
435static void
436pushfile(void)
437{
438 struct parsefile *pf;
439
440 pf = (struct parsefile *)ckmalloc(sizeof(struct parsefile));
441 *pf = (struct parsefile){.prev = parsefile, .fd = -1};
442 parsefile->nleft = parsenleft;
443 parsefile->lleft = parselleft;
444 parsefile->nextc = parsenextc;
445 parsefile->linno = plinno;
446 parsefile = pf;
447}
448
449void
450popfile(void)
451{
452 struct parsefile *pf = parsefile;
453
454 INTOFF;
455 if (pf->fd >= 0)
456 close(pf->fd);
457 if (pf->buf)
458 ckfree(pf->buf);
459 while (pf->strpush)
460 popstring();
461 parsefile = pf->prev;
462 ckfree(pf);
463 parsenleft = parsefile->nleft;
464 parselleft = parsefile->lleft;
465 parsenextc = parsefile->nextc;
466 plinno = parsefile->linno;
467 INTON;
468}
469
470/*
471 * Return current file (to go back to it later using popfilesupto()).
472 */
473
474struct parsefile *
475getcurrentfile(void)
476{
477 return parsefile;
478}
479
480/*
481 * Pop files until the given file is on top again. Useful for regular
482 * builtins that read shell commands from files or strings.
483 * If the given file is not an active file, an error is raised.
484 */
485
486void
487popfilesupto(struct parsefile *file)
488{
489 while (parsefile != file && parsefile != &basepf)
490 popfile();
491 if (parsefile != file)
492 error("popfilesupto() misused");
493}
494
495/*
496 * Return to top level.
497 */
498
499void
500popallfiles(void)
501{
502 while (parsefile != &basepf)
503 popfile();
504}
505
506/*
507 * Close the file(s) that the shell is reading commands from. Called
508 * after a fork is done.
509 */
510
511void
512closescript(void)
513{
514 popallfiles();
515 if (parsefile->fd > 0) {
516 close(parsefile->fd);
517 parsefile->fd = 0;
518 }
519}