input.c revision 1.64 1 /* $NetBSD: input.c,v 1.64 2018/12/03 06:40:26 kre Exp $ */
2
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 <sys/cdefs.h>
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95";
39 #else
40 __RCSID("$NetBSD: input.c,v 1.64 2018/12/03 06:40:26 kre Exp $");
41 #endif
42 #endif /* not lint */
43
44 #include <stdio.h> /* defines BUFSIZ */
45 #include <fcntl.h>
46 #include <errno.h>
47 #include <unistd.h>
48 #include <limits.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <sys/stat.h>
52
53 /*
54 * This file implements the input routines used by the parser.
55 */
56
57 #include "shell.h"
58 #include "redir.h"
59 #include "syntax.h"
60 #include "input.h"
61 #include "output.h"
62 #include "options.h"
63 #include "memalloc.h"
64 #include "error.h"
65 #include "alias.h"
66 #include "parser.h"
67 #include "myhistedit.h"
68 #include "show.h"
69
70 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
71
72 MKINIT
73 struct strpush {
74 struct strpush *prev; /* preceding string on stack */
75 const char *prevstring;
76 int prevnleft;
77 int prevlleft;
78 struct alias *ap; /* if push was associated with an alias */
79 };
80
81 /*
82 * The parsefile structure pointed to by the global variable parsefile
83 * contains information about the current file being read.
84 */
85
86 MKINIT
87 struct parsefile {
88 struct parsefile *prev; /* preceding file on stack */
89 int linno; /* current line */
90 int fd; /* file descriptor (or -1 if string) */
91 int nleft; /* number of chars left in this line */
92 int lleft; /* number of chars left in this buffer */
93 const char *nextc; /* next char in buffer */
94 char *buf; /* input buffer */
95 struct strpush *strpush; /* for pushing strings at this level */
96 struct strpush basestrpush; /* so pushing one is fast */
97 };
98
99
100 int plinno = 1; /* input line number */
101 int parsenleft; /* copy of parsefile->nleft */
102 MKINIT int parselleft; /* copy of parsefile->lleft */
103 const char *parsenextc; /* copy of parsefile->nextc */
104 MKINIT struct parsefile basepf; /* top level input file */
105 MKINIT char basebuf[BUFSIZ]; /* buffer for top level input file */
106 struct parsefile *parsefile = &basepf; /* current input file */
107 int init_editline = 0; /* editline library initialized? */
108 int whichprompt; /* 1 == PS1, 2 == PS2 */
109
110 STATIC void pushfile(void);
111 static int preadfd(void);
112
113 #ifdef mkinit
114 INCLUDE <stdio.h>
115 INCLUDE "input.h"
116 INCLUDE "error.h"
117
118 INIT {
119 basepf.nextc = basepf.buf = basebuf;
120 }
121
122 RESET {
123 if (exception != EXSHELLPROC)
124 parselleft = parsenleft = 0; /* clear input buffer */
125 popallfiles();
126 }
127
128 SHELLPROC {
129 popallfiles();
130 }
131 #endif
132
133
134 #if 0 /* this is unused */
135 /*
136 * Read a line from the script.
137 */
138
139 char *
140 pfgets(char *line, int len)
141 {
142 char *p = line;
143 int nleft = len;
144 int c;
145
146 while (--nleft > 0) {
147 c = pgetc_macro();
148 if (c == PEOF) {
149 if (p == line)
150 return NULL;
151 break;
152 }
153 *p++ = c;
154 if (c == '\n')
155 break;
156 }
157 *p = '\0';
158 return line;
159 }
160 #endif
161
162
163 /*
164 * Read a character from the script, returning PEOF on end of file.
165 * Nul characters in the input are silently discarded.
166 */
167
168 int
169 pgetc(void)
170 {
171 int c;
172
173 c = pgetc_macro();
174 if (c == PFAKE)
175 c = pgetc_macro();
176 return c;
177 }
178
179
180 static int
181 preadfd(void)
182 {
183 int nr;
184 char *buf = parsefile->buf;
185 parsenextc = buf;
186
187 retry:
188 #ifndef SMALL
189 if (parsefile->fd == 0 && el) {
190 static const char *rl_cp;
191 static int el_len;
192
193 if (rl_cp == NULL)
194 rl_cp = el_gets(el, &el_len);
195 if (rl_cp == NULL)
196 nr = el_len == 0 ? 0 : -1;
197 else {
198 nr = el_len;
199 if (nr > BUFSIZ - 8)
200 nr = BUFSIZ - 8;
201 memcpy(buf, rl_cp, nr);
202 if (nr != el_len) {
203 el_len -= nr;
204 rl_cp += nr;
205 } else
206 rl_cp = 0;
207 }
208
209 } else
210 #endif
211 nr = read(parsefile->fd, buf, BUFSIZ - 8);
212
213
214 if (nr <= 0) {
215 if (nr < 0) {
216 if (errno == EINTR)
217 goto retry;
218 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
219 int flags = fcntl(0, F_GETFL, 0);
220
221 if (flags >= 0 && flags & O_NONBLOCK) {
222 flags &=~ O_NONBLOCK;
223 if (fcntl(0, F_SETFL, flags) >= 0) {
224 out2str("sh: turning off NDELAY mode\n");
225 goto retry;
226 }
227 }
228 }
229 }
230 nr = -1;
231 }
232 return nr;
233 }
234
235 /*
236 * Refill the input buffer and return the next input character:
237 *
238 * 1) If a string was pushed back on the input, pop it;
239 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
240 * from a string so we can't refill the buffer, return EOF.
241 * 3) If the is more stuff in this buffer, use it else call read to fill it.
242 * 4) Process input up to the next newline, deleting nul characters.
243 */
244
245 int
246 preadbuffer(void)
247 {
248 char *p, *q;
249 int more;
250 #ifndef SMALL
251 int something;
252 #endif
253 char savec;
254
255 while (parsefile->strpush) {
256 if (parsenleft == -1 && parsefile->strpush->ap != NULL)
257 return PFAKE;
258 popstring();
259 if (--parsenleft >= 0)
260 return (*parsenextc++);
261 }
262 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
263 return PEOF;
264 flushout(&output);
265 flushout(&errout);
266
267 again:
268 if (parselleft <= 0) {
269 if ((parselleft = preadfd()) == -1) {
270 parselleft = parsenleft = EOF_NLEFT;
271 return PEOF;
272 }
273 }
274
275 /* p = (not const char *)parsenextc; */
276 p = parsefile->buf + (parsenextc - parsefile->buf);
277 q = p;
278
279 /* delete nul characters */
280 #ifndef SMALL
281 something = 0;
282 #endif
283 for (more = 1; more;) {
284 switch (*p) {
285 case '\0':
286 p++; /* Skip nul */
287 goto check;
288
289 case '\t':
290 case ' ':
291 break;
292
293 case '\n':
294 parsenleft = q - parsenextc;
295 more = 0; /* Stop processing here */
296 break;
297
298 default:
299 #ifndef SMALL
300 something = 1;
301 #endif
302 break;
303 }
304
305 *q++ = *p++;
306 check:
307 if (--parselleft <= 0) {
308 parsenleft = q - parsenextc - 1;
309 if (parsenleft < 0)
310 goto again;
311 *q = '\0';
312 more = 0;
313 }
314 }
315
316 savec = *q;
317 *q = '\0';
318
319 #ifndef SMALL
320 if (parsefile->fd == 0 && hist && (something || whichprompt == 2)) {
321 HistEvent he;
322
323 INTOFF;
324 history(hist, &he, whichprompt != 2 ? H_ENTER : H_APPEND,
325 parsenextc);
326 INTON;
327 }
328 #endif
329
330 if (vflag) {
331 out2str(parsenextc);
332 flushout(out2);
333 }
334
335 *q = savec;
336
337 return *parsenextc++;
338 }
339
340 /*
341 * Test whether we have reached EOF on input stream.
342 * Return true only if certain (without attempting a read).
343 *
344 * Note the similarity to the opening section of preadbuffer()
345 */
346 int
347 at_eof(void)
348 {
349 struct strpush *sp = parsefile->strpush;
350
351 if (parsenleft > 0) /* more chars are in the buffer */
352 return 0;
353
354 while (sp != NULL) {
355 /*
356 * If any pushed string has any remaining data,
357 * then we are not at EOF (simulating popstring())
358 */
359 if (sp->prevnleft > 0)
360 return 0;
361 sp = sp->prev;
362 }
363
364 /*
365 * If we reached real EOF and pushed it back,
366 * or if we are just processing a string (not reading a file)
367 * then there is no more. Note that if a file pushes a
368 * string, the file's ->buf remains present.
369 */
370 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
371 return 1;
372
373 /*
374 * In other cases, there might be more
375 */
376 return 0;
377 }
378
379 /*
380 * Undo the last call to pgetc. Only one character may be pushed back.
381 * PEOF may be pushed back.
382 */
383
384 void
385 pungetc(void)
386 {
387 parsenleft++;
388 parsenextc--;
389 }
390
391 /*
392 * Push a string back onto the input at this current parsefile level.
393 * We handle aliases this way.
394 */
395 void
396 pushstring(const char *s, int len, struct alias *ap)
397 {
398 struct strpush *sp;
399
400 VTRACE(DBG_INPUT,
401 ("pushstring(\"%.*s\", %d)%s%s%s had: nl=%d ll=%d \"%.*s\"\n",
402 len, s, len, ap ? " for alias:'" : "",
403 ap ? ap->name : "", ap ? "'" : "",
404 parsenleft, parselleft, parsenleft, parsenextc));
405
406 INTOFF;
407 if (parsefile->strpush) {
408 sp = ckmalloc(sizeof (struct strpush));
409 sp->prev = parsefile->strpush;
410 parsefile->strpush = sp;
411 } else
412 sp = parsefile->strpush = &(parsefile->basestrpush);
413
414 sp->prevstring = parsenextc;
415 sp->prevnleft = parsenleft;
416 sp->prevlleft = parselleft;
417 sp->ap = ap;
418 if (ap)
419 ap->flag |= ALIASINUSE;
420 parsenextc = s;
421 parsenleft = len;
422 INTON;
423 }
424
425 void
426 popstring(void)
427 {
428 struct strpush *sp = parsefile->strpush;
429
430 INTOFF;
431 if (sp->ap) {
432 if (parsenextc != sp->ap->val &&
433 (parsenextc[-1] == ' ' || parsenextc[-1] == '\t'))
434 checkkwd |= CHKALIAS;
435 sp->ap->flag &= ~ALIASINUSE;
436 }
437 parsenextc = sp->prevstring;
438 parsenleft = sp->prevnleft;
439 parselleft = sp->prevlleft;
440
441 VTRACE(DBG_INPUT, ("popstring()%s%s%s nl=%d ll=%d \"%.*s\"\n",
442 sp->ap ? " from alias:'" : "", sp->ap ? sp->ap->name : "",
443 sp->ap ? "'" : "", parsenleft, parselleft, parsenleft, parsenextc));
444
445 parsefile->strpush = sp->prev;
446 if (sp != &(parsefile->basestrpush))
447 ckfree(sp);
448 INTON;
449 }
450
451 /*
452 * Set the input to take input from a file. If push is set, push the
453 * old input onto the stack first.
454 */
455
456 void
457 setinputfile(const char *fname, int push)
458 {
459 unsigned char magic[4];
460 int fd;
461 int fd2;
462 struct stat sb;
463
464 CTRACE(DBG_INPUT,("setinputfile(\"%s\", %spush)\n",fname,push?"":"no"));
465
466 INTOFF;
467 if ((fd = open(fname, O_RDONLY)) < 0)
468 error("Can't open %s", fname);
469
470 /* Since the message "Syntax error: "(" unexpected" is not very
471 * helpful, we check if the file starts with the ELF magic to
472 * avoid that message. The first lseek tries to make sure that
473 * we can later rewind the file.
474 */
475 if (fstat(fd, &sb) == 0 && S_ISREG(sb.st_mode) &&
476 lseek(fd, 0, SEEK_SET) == 0) {
477 if (read(fd, magic, 4) == 4) {
478 if (memcmp(magic, "\177ELF", 4) == 0) {
479 (void)close(fd);
480 error("Cannot execute ELF binary %s", fname);
481 }
482 }
483 if (lseek(fd, 0, SEEK_SET) != 0) {
484 (void)close(fd);
485 error("Cannot rewind the file %s", fname);
486 }
487 }
488
489 fd2 = to_upper_fd(fd); /* closes fd, returns higher equiv */
490 if (fd2 == fd) {
491 (void) close(fd);
492 error("Out of file descriptors");
493 }
494
495 setinputfd(fd2, push);
496 INTON;
497 }
498
499 /*
500 * When a shell fd needs to be altered (when the user wants to use
501 * the same fd - rare, but happens - we need to locate the ref to
502 * the fd, and update it. This happens via a callback.
503 * This is the callback func for fd's used for shell input
504 */
505 static void
506 input_fd_swap(int from, int to)
507 {
508 struct parsefile *pf;
509
510 pf = parsefile;
511 while (pf != NULL) { /* don't need to stop at basepf */
512 if (pf->fd == from)
513 pf->fd = to;
514 pf = pf->prev;
515 }
516 }
517
518 /*
519 * Like setinputfile, but takes an open file descriptor. Call this with
520 * interrupts off.
521 */
522
523 void
524 setinputfd(int fd, int push)
525 {
526 VTRACE(DBG_INPUT, ("setinputfd(%d, %spush)\n", fd, push?"":"no"));
527
528 register_sh_fd(fd, input_fd_swap);
529 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
530 if (push)
531 pushfile();
532 if (parsefile->fd > 0)
533 sh_close(parsefile->fd);
534 parsefile->fd = fd;
535 if (parsefile->buf == NULL)
536 parsefile->buf = ckmalloc(BUFSIZ);
537 parselleft = parsenleft = 0;
538 plinno = 1;
539
540 CTRACE(DBG_INPUT, ("setinputfd(%d, %spush) done; plinno=1\n", fd,
541 push ? "" : "no"));
542 }
543
544
545 /*
546 * Like setinputfile, but takes input from a string.
547 */
548
549 void
550 setinputstring(char *string, int push, int line1)
551 {
552
553 INTOFF;
554 if (push) /* XXX: always, as it happens */
555 pushfile();
556 parsenextc = string;
557 parselleft = parsenleft = strlen(string);
558 plinno = line1;
559
560 CTRACE(DBG_INPUT,
561 ("setinputstring(\"%.20s%s\" (%d), %spush, @ %d)\n", string,
562 (parsenleft > 20 ? "..." : ""), parsenleft, push?"":"no", line1));
563 INTON;
564 }
565
566
567
568 /*
569 * To handle the "." command, a stack of input files is used. Pushfile
570 * adds a new entry to the stack and popfile restores the previous level.
571 */
572
573 STATIC void
574 pushfile(void)
575 {
576 struct parsefile *pf;
577
578 VTRACE(DBG_INPUT,
579 ("pushfile(): fd=%d buf=%p nl=%d ll=%d \"%.*s\" plinno=%d\n",
580 parsefile->fd, parsefile->buf, parsenleft, parselleft,
581 parsenleft, parsenextc, plinno));
582
583 parsefile->nleft = parsenleft;
584 parsefile->lleft = parselleft;
585 parsefile->nextc = parsenextc;
586 parsefile->linno = plinno;
587 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
588 pf->prev = parsefile;
589 pf->fd = -1;
590 pf->strpush = NULL;
591 pf->basestrpush.prev = NULL;
592 pf->buf = NULL;
593 parsefile = pf;
594 }
595
596
597 void
598 popfile(void)
599 {
600 struct parsefile *pf = parsefile;
601
602 INTOFF;
603 if (pf->fd >= 0)
604 sh_close(pf->fd);
605 if (pf->buf)
606 ckfree(pf->buf);
607 while (pf->strpush)
608 popstring();
609 parsefile = pf->prev;
610 ckfree(pf);
611 parsenleft = parsefile->nleft;
612 parselleft = parsefile->lleft;
613 parsenextc = parsefile->nextc;
614
615 VTRACE(DBG_INPUT,
616 ("popfile(): fd=%d buf=%p nl=%d ll=%d \"%.*s\" plinno:%d->%d\n",
617 parsefile->fd, parsefile->buf, parsenleft, parselleft,
618 parsenleft, parsenextc, plinno, parsefile->linno));
619
620 plinno = parsefile->linno;
621 INTON;
622 }
623
624 /*
625 * Return current file (to go back to it later using popfilesupto()).
626 */
627
628 struct parsefile *
629 getcurrentfile(void)
630 {
631 return parsefile;
632 }
633
634
635 /*
636 * Pop files until the given file is on top again. Useful for regular
637 * builtins that read shell commands from files or strings.
638 * If the given file is not an active file, an error is raised.
639 */
640
641 void
642 popfilesupto(struct parsefile *file)
643 {
644 while (parsefile != file && parsefile != &basepf)
645 popfile();
646 if (parsefile != file)
647 error("popfilesupto() misused");
648 }
649
650
651 /*
652 * Return to top level.
653 */
654
655 void
656 popallfiles(void)
657 {
658 while (parsefile != &basepf)
659 popfile();
660 }
661
662
663
664 /*
665 * Close the file(s) that the shell is reading commands from. Called
666 * after a fork is done.
667 *
668 * Takes one arg, vfork, which tells it to not modify its global vars
669 * as it is still running in the parent.
670 *
671 * This code is (probably) unnecessary as the 'close on exec' flag is
672 * set and should be enough. In the vfork case it is definitely wrong
673 * to close the fds as another fork() may be done later to feed data
674 * from a 'here' document into a pipe and we don't want to close the
675 * pipe!
676 */
677
678 void
679 closescript(int vforked)
680 {
681 if (vforked)
682 return;
683 popallfiles();
684 if (parsefile->fd > 0) {
685 sh_close(parsefile->fd);
686 parsefile->fd = 0;
687 }
688 }
689