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