1 /*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1997-2005
5 * Herbert Xu <herbert@gondor.apana.org.au>. 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 <unistd.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #ifdef USE_LINENOISE
42 #include <linenoise/linenoise.h>
43 #endif
44
45 /*
46 * This file implements the input routines used by the parser.
47 */
48
49 #include "eval.h"
50 #include "shell.h"
51 #include "redir.h"
52 #include "syntax.h"
53 #include "input.h"
54 #include "output.h"
55 #include "options.h"
56 #include "memalloc.h"
57 #include "error.h"
58 #include "alias.h"
59 #include "parser.h"
60 #include "main.h"
61
62 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
63 #define IBUFSIZ (BUFSIZ + 1)
64
65
66 MKINIT struct parsefile basepf; /* top level input file */
67 MKINIT char basebuf[IBUFSIZ]; /* buffer for top level input file */
68 struct parsefile *parsefile = &basepf; /* current input file */
69 int whichprompt; /* 1 == PS1, 2 == PS2 */
70
71 #ifdef USE_LINENOISE
72 static char *pending_line;
73 static size_t pending_line_index;
74 static size_t pending_line_length;
75 #endif
76
77 STATIC void pushfile(void);
78 static int preadfd(void);
79 static void setinputfd(int fd, int push);
80 static int preadbuffer(void);
81
82 #ifdef mkinit
83 INCLUDE <stdio.h>
84 INCLUDE "input.h"
85 INCLUDE "error.h"
86
87 INIT {
88 basepf.nextc = basepf.buf = basebuf;
89 basepf.linno = 1;
90 }
91
92 RESET {
93 /* clear input buffer */
94 basepf.lleft = basepf.nleft = 0;
95 popallfiles();
96 }
97 #endif
98
99
100 /*
101 * Read a character from the script, returning PEOF on end of file.
102 * Nul characters in the input are silently discarded.
103 */
104
105 int
pgetc(void)106 pgetc(void)
107 {
108 int c;
109
110 if (parsefile->unget)
111 return parsefile->lastc[--parsefile->unget];
112
113 if (--parsefile->nleft >= 0)
114 c = (signed char)*parsefile->nextc++;
115 else
116 c = preadbuffer();
117
118 parsefile->lastc[1] = parsefile->lastc[0];
119 parsefile->lastc[0] = c;
120
121 return c;
122 }
123
124
125 /*
126 * Same as pgetc(), but ignores PEOA.
127 */
128
129 int
pgetc2()130 pgetc2()
131 {
132 int c;
133 do {
134 c = pgetc();
135 } while (c == PEOA);
136 return c;
137 }
138
139
140 static int
preadfd(void)141 preadfd(void)
142 {
143 int nr;
144 char *buf = parsefile->buf;
145 parsefile->nextc = buf;
146 const char* prompt = NULL;
147
148 retry:
149 #ifdef USE_LINENOISE
150 if (parsefile->fd == 0 && iflag) {
151 if (pending_line == NULL) {
152 // linenoise stashs the prompt buffer away for
153 // the duration of its edit cycle. Because
154 // some edit functionality (in particular, tab
155 // completion allocates the parts of PATH from
156 // dash's stack-based allocator), we need to
157 // properly save the string and then free it,
158 // or it will be clobbered.
159 prompt = savestr(getprompt(NULL));
160 pending_line = linenoise(prompt);
161 if (pending_line) {
162 pending_line_index = 0u;
163 pending_line_length = strlen(pending_line);
164 pending_line[pending_line_length] = '\n';
165 pending_line_length += 1;
166 }
167 }
168 if (pending_line == NULL)
169 nr = 0;
170 else {
171 nr = pending_line_length - pending_line_index;
172 if (nr > IBUFSIZ - 1)
173 nr = IBUFSIZ - 1;
174 memcpy(buf, pending_line + pending_line_index, nr);
175 pending_line_index += nr;
176 if (pending_line_index == pending_line_length) {
177 linenoiseFree(pending_line);
178 free(prompt);
179 pending_line = NULL;
180 pending_line_index = 0u;
181 pending_line_length = 0u;
182 }
183 }
184 } else
185 #endif
186 nr = read(parsefile->fd, buf, IBUFSIZ - 1);
187
188
189 if (nr < 0) {
190 if (errno == EINTR)
191 goto retry;
192 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
193 int flags = fcntl(0, F_GETFL, 0);
194 if (flags >= 0 && flags & O_NONBLOCK) {
195 flags &=~ O_NONBLOCK;
196 if (fcntl(0, F_SETFL, flags) >= 0) {
197 out2str("sh: turning off NDELAY mode\n");
198 goto retry;
199 }
200 }
201 }
202 }
203 return nr;
204 }
205
addtohistory(const char * entry,size_t length)206 static void addtohistory(const char* entry, size_t length) {
207 // TODO(abarth): If whichprompt != 1, we should append this value to an
208 // existing history entry. However, linenoise doesn't support editing the
209 // history entries, so we'll probably need to refactor the input system to
210 // get this behavior right.
211 #ifdef USE_LINENOISE
212 linenoiseHistoryAdd(entry);
213 #endif
214 }
215
216 /*
217 * Refill the input buffer and return the next input character:
218 *
219 * 1) If a string was pushed back on the input, pop it;
220 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
221 * from a string so we can't refill the buffer, return EOF.
222 * 3) If the is more stuff in this buffer, use it else call read to fill it.
223 * 4) Process input up to the next newline, deleting nul characters.
224 */
225
preadbuffer(void)226 static int preadbuffer(void)
227 {
228 char *q;
229 int more;
230 #ifdef USE_LINENOISE
231 int something;
232 #endif
233 char savec;
234
235 if (unlikely(parsefile->strpush)) {
236 if (
237 parsefile->nleft == -1 &&
238 parsefile->strpush->ap &&
239 parsefile->nextc[-1] != ' ' &&
240 parsefile->nextc[-1] != '\t'
241 ) {
242 return PEOA;
243 }
244 popstring();
245 return pgetc();
246 }
247 if (unlikely(parsefile->nleft == EOF_NLEFT ||
248 parsefile->buf == NULL))
249 return PEOF;
250 flushall();
251
252 more = parsefile->lleft;
253 if (more <= 0) {
254 again:
255 if ((more = preadfd()) <= 0) {
256 parsefile->lleft = parsefile->nleft = EOF_NLEFT;
257 return PEOF;
258 }
259 }
260
261 q = parsefile->nextc;
262
263 /* delete nul characters */
264 #ifdef USE_LINENOISE
265 something = 0;
266 #endif
267 for (;;) {
268 int c;
269
270 more--;
271 c = *q;
272
273 if (!c)
274 memmove(q, q + 1, more);
275 else {
276 q++;
277
278 if (c == '\n') {
279 parsefile->nleft = q - parsefile->nextc - 1;
280 break;
281 }
282
283 #ifdef USE_LINENOISE
284 switch (c) {
285 default:
286 something = 1;
287 /* fall through */
288 case '\t':
289 case ' ':
290 break;
291 }
292 #endif
293 }
294
295 if (more <= 0) {
296 parsefile->nleft = q - parsefile->nextc - 1;
297 if (parsefile->nleft < 0)
298 goto again;
299 break;
300 }
301 }
302 parsefile->lleft = more;
303
304 savec = *q;
305 *q = '\0';
306
307 #ifdef USE_LINENOISE
308 if (parsefile->fd == 0 && iflag && something) {
309 // linenoise doesn't expect the command terminator at the end of the history
310 // entry.
311 char command_terminator = q[-1];
312 q[-1] = '\0';
313
314 addtohistory(parsefile->nextc, strlen(parsefile->nextc));
315
316 // Restore the command terminator.
317 q[-1] = command_terminator;
318 }
319 #endif
320
321 if (vflag) {
322 out2str(parsefile->nextc);
323 #ifdef FLUSHERR
324 flushout(out2);
325 #endif
326 }
327
328 *q = savec;
329
330 return (signed char)*parsefile->nextc++;
331 }
332
333 /*
334 * Undo a call to pgetc. Only two characters may be pushed back.
335 * PEOF may be pushed back.
336 */
337
338 void
pungetc(void)339 pungetc(void)
340 {
341 parsefile->unget++;
342 }
343
344 /*
345 * Push a string back onto the input at this current parsefile level.
346 * We handle aliases this way.
347 */
348 void
pushstring(char * s,void * ap)349 pushstring(char *s, void *ap)
350 {
351 struct strpush *sp;
352 size_t len;
353
354 len = strlen(s);
355 INTOFF;
356 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
357 if (parsefile->strpush) {
358 sp = ckmalloc(sizeof (struct strpush));
359 sp->prev = parsefile->strpush;
360 parsefile->strpush = sp;
361 } else
362 sp = parsefile->strpush = &(parsefile->basestrpush);
363 sp->prevstring = parsefile->nextc;
364 sp->prevnleft = parsefile->nleft;
365 sp->unget = parsefile->unget;
366 memcpy(sp->lastc, parsefile->lastc, sizeof(sp->lastc));
367 sp->ap = (struct alias *)ap;
368 if (ap) {
369 ((struct alias *)ap)->flag |= ALIASINUSE;
370 sp->string = s;
371 }
372 parsefile->nextc = s;
373 parsefile->nleft = len;
374 parsefile->unget = 0;
375 INTON;
376 }
377
378 void
popstring(void)379 popstring(void)
380 {
381 struct strpush *sp = parsefile->strpush;
382
383 INTOFF;
384 if (sp->ap) {
385 if (parsefile->nextc[-1] == ' ' ||
386 parsefile->nextc[-1] == '\t') {
387 checkkwd |= CHKALIAS;
388 }
389 if (sp->string != sp->ap->val) {
390 ckfree(sp->string);
391 }
392 sp->ap->flag &= ~ALIASINUSE;
393 if (sp->ap->flag & ALIASDEAD) {
394 unalias(sp->ap->name);
395 }
396 }
397 parsefile->nextc = sp->prevstring;
398 parsefile->nleft = sp->prevnleft;
399 parsefile->unget = sp->unget;
400 memcpy(parsefile->lastc, sp->lastc, sizeof(sp->lastc));
401 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
402 parsefile->strpush = sp->prev;
403 if (sp != &(parsefile->basestrpush))
404 ckfree(sp);
405 INTON;
406 }
407
408 /*
409 * Set the input to take input from a file. If push is set, push the
410 * old input onto the stack first.
411 */
412
413 int
setinputfile(const char * fname,int flags)414 setinputfile(const char *fname, int flags)
415 {
416 int fd;
417
418 INTOFF;
419 if ((fd = open(fname, O_RDONLY)) < 0) {
420 if (flags & INPUT_NOFILE_OK)
421 goto out;
422 exitstatus = 127;
423 exerror(EXERROR, "Can't open %s", fname);
424 }
425 if (fd < 10)
426 fd = savefd(fd, fd);
427 setinputfd(fd, flags & INPUT_PUSH_FILE);
428 out:
429 INTON;
430 return fd;
431 }
432
433
434 /*
435 * Like setinputfile, but takes an open file descriptor. Call this with
436 * interrupts off.
437 */
438
439 static void
setinputfd(int fd,int push)440 setinputfd(int fd, int push)
441 {
442 if (push) {
443 pushfile();
444 parsefile->buf = 0;
445 }
446 parsefile->fd = fd;
447 if (parsefile->buf == NULL)
448 parsefile->buf = ckmalloc(IBUFSIZ);
449 parsefile->lleft = parsefile->nleft = 0;
450 plinno = 1;
451 }
452
453
454 /*
455 * Like setinputfile, but takes input from a string.
456 */
457
458 void
setinputstring(char * string)459 setinputstring(char *string)
460 {
461 INTOFF;
462 pushfile();
463 parsefile->nextc = string;
464 parsefile->nleft = strlen(string);
465 parsefile->buf = NULL;
466 plinno = 1;
467 INTON;
468 }
469
470
471
472 /*
473 * To handle the "." command, a stack of input files is used. Pushfile
474 * adds a new entry to the stack and popfile restores the previous level.
475 */
476
477 STATIC void
pushfile(void)478 pushfile(void)
479 {
480 struct parsefile *pf;
481
482 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
483 pf->prev = parsefile;
484 pf->fd = -1;
485 pf->strpush = NULL;
486 pf->basestrpush.prev = NULL;
487 pf->unget = 0;
488 parsefile = pf;
489 }
490
491
492 void
popfile(void)493 popfile(void)
494 {
495 struct parsefile *pf = parsefile;
496
497 INTOFF;
498 if (pf->fd >= 0)
499 close(pf->fd);
500 if (pf->buf)
501 ckfree(pf->buf);
502 while (pf->strpush)
503 popstring();
504 parsefile = pf->prev;
505 ckfree(pf);
506 INTON;
507 }
508
509
510 /*
511 * Return to top level.
512 */
513
514 void
popallfiles(void)515 popallfiles(void)
516 {
517 while (parsefile != &basepf)
518 popfile();
519 }
520
521
522
523 /*
524 * Close the file(s) that the shell is reading commands from. Called
525 * after a fork is done.
526 */
527
528 void
closescript(void)529 closescript(void)
530 {
531 popallfiles();
532 if (parsefile->fd > 0) {
533 close(parsefile->fd);
534 parsefile->fd = 0;
535 }
536 }
537