1 /* $NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc Exp $ */
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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
37 static char sccsid
[] = "@(#)input.c 8.3 (Berkeley) 6/9/95";
39 __RCSID("$NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc Exp $");
43 #include <stdio.h> /* defines BUFSIZ */
49 * This file implements the input routines used by the parser.
62 #include "myhistedit.h"
63 #include "shinstance.h"
65 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
69 // struct strpush *prev; /* preceding string on stack */
73 // struct alias *ap; /* if push was associated with an alias */
77 // * The parsefile structure pointed to by the global variable parsefile
78 // * contains information about the current file being read.
83 // struct parsefile *prev; /* preceding file on stack */
84 // int linno; /* current line */
85 // int fd; /* file descriptor (or -1 if string) */
86 // int nleft; /* number of chars left in this line */
87 // int lleft; /* number of chars left in this buffer */
88 // char *nextc; /* next char in buffer */
89 // char *buf; /* input buffer */
90 // struct strpush *strpush; /* for pushing strings at this level */
91 // struct strpush basestrpush; /* so pushing one is fast */
95 //int plinno = 1; /* input line number */
96 //int parsenleft; /* copy of parsefile->nleft */
97 //MKINIT int parselleft; /* copy of parsefile->lleft */
98 //char *parsenextc; /* copy of parsefile->nextc */
99 //MKINIT struct parsefile basepf; /* top level input file */
100 //MKINIT char basebuf[BUFSIZ]; /* buffer for top level input file */
101 //struct parsefile *parsefile = &basepf; /* current input file */
102 //int init_editline = 0; /* editline library initialized? */
103 //int whichprompt; /* 1 == PS1, 2 == PS2 */
106 //EditLine *el; /* cookie for editline package */
109 STATIC
void pushfile(shinstance
*psh
);
110 static int preadfd(shinstance
*psh
);
118 psh
->basepf
.nextc
= psh
->basepf
.buf
= psh
->basebuf
;
122 if (psh
->exception
!= EXSHELLPROC
)
123 psh
->parselleft
= psh
->parsenleft
= 0; /* clear input buffer */
134 * Read a line from the script.
138 pfgets(shinstance
*psh
, char *line
, int len
)
144 while (--nleft
> 0) {
145 c
= pgetc_macro(psh
);
162 * Read a character from the script, returning PEOF on end of file.
163 * Nul characters in the input are silently discarded.
167 pgetc(shinstance
*psh
)
169 return pgetc_macro(psh
);
174 preadfd(shinstance
*psh
)
177 char *buf
= psh
->parsefile
->buf
;
178 psh
->parsenextc
= buf
;
182 if (psh
->parsefile
->fd
== 0 && psh
->el
) {
183 static const char *rl_cp
;
187 rl_cp
= el_gets(psh
->el
, &el_len
);
194 memcpy(buf
, rl_cp
, nr
);
204 nr
= shfile_read(&psh
->fdtab
, psh
->parsefile
->fd
, buf
, BUFSIZ
- 8);
211 if (psh
->parsefile
->fd
== 0 && errno
== EWOULDBLOCK
) {
212 int flags
= shfile_fcntl(&psh
->fdtab
, 0, F_GETFL
, 0);
213 if (flags
>= 0 && flags
& O_NONBLOCK
) {
214 flags
&=~ O_NONBLOCK
;
215 if (shfile_fcntl(&psh
->fdtab
, 0, F_SETFL
, flags
) >= 0) {
216 out2str(psh
, "sh: turning off NDELAY mode\n");
228 * Refill the input buffer and return the next input character:
230 * 1) If a string was pushed back on the input, pop it;
231 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
232 * from a string so we can't refill the buffer, return EOF.
233 * 3) If the is more stuff in this buffer, use it else call read to fill it.
234 * 4) Process input up to the next newline, deleting nul characters.
238 preadbuffer(shinstance
*psh
)
245 if (psh
->parsefile
->strpush
) {
247 if (--psh
->parsenleft
>= 0)
248 return (*psh
->parsenextc
++);
250 if (psh
->parsenleft
== EOF_NLEFT
|| psh
->parsefile
->buf
== NULL
)
252 flushout(&psh
->output
);
253 flushout(&psh
->errout
);
256 if (psh
->parselleft
<= 0) {
257 if ((psh
->parselleft
= preadfd(psh
)) == -1) {
258 psh
->parselleft
= psh
->parsenleft
= EOF_NLEFT
;
263 q
= p
= psh
->parsenextc
;
265 /* delete nul characters */
267 for (more
= 1; more
;) {
278 psh
->parsenleft
= (int)(q
- psh
->parsenextc
);
279 more
= 0; /* Stop processing here */
289 if (--psh
->parselleft
<= 0) {
290 psh
->parsenleft
= (int)(q
- psh
->parsenextc
- 1);
291 if (psh
->parsenleft
< 0)
302 if (psh
->parsefile
->fd
== 0 && hist
&& something
) {
305 history(hist
, &he
, psh
->whichprompt
== 1? H_ENTER
: H_APPEND
,
312 out2str(psh
, psh
->parsenextc
);
318 return *psh
->parsenextc
++;
322 * Undo the last call to pgetc. Only one character may be pushed back.
323 * PEOF may be pushed back.
327 pungetc(shinstance
*psh
)
334 * Push a string back onto the input at this current parsefile level.
335 * We handle aliases this way.
338 pushstring(shinstance
*psh
, char *s
, size_t len
, void *ap
)
343 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
344 if (psh
->parsefile
->strpush
) {
345 sp
= ckmalloc(sizeof (struct strpush
));
346 sp
->prev
= psh
->parsefile
->strpush
;
347 psh
->parsefile
->strpush
= sp
;
349 sp
= psh
->parsefile
->strpush
= &(psh
->parsefile
->basestrpush
);
350 sp
->prevstring
= psh
->parsenextc
;
351 sp
->prevnleft
= psh
->parsenleft
;
352 sp
->prevlleft
= psh
->parselleft
;
353 sp
->ap
= (struct alias
*)ap
;
355 ((struct alias
*)ap
)->flag
|= ALIASINUSE
;
357 psh
->parsenleft
= (int)len
;
362 popstring(shinstance
*psh
)
364 struct strpush
*sp
= psh
->parsefile
->strpush
;
367 psh
->parsenextc
= sp
->prevstring
;
368 psh
->parsenleft
= sp
->prevnleft
;
369 psh
->parselleft
= sp
->prevlleft
;
370 /*dprintf("*** calling popstring: restoring to '%s'\n", psh->parsenextc);*/
372 sp
->ap
->flag
&= ~ALIASINUSE
;
373 psh
->parsefile
->strpush
= sp
->prev
;
374 if (sp
!= &(psh
->parsefile
->basestrpush
))
380 * Set the input to take input from a file. If push is set, push the
381 * old input onto the stack first.
385 setinputfile(shinstance
*psh
, const char *fname
, int push
)
391 /** @todo shfile fixme */
392 if ((fd
= shfile_open(&psh
->fdtab
, fname
, O_RDONLY
, 0)) < 0)
393 error(psh
, "Can't open %s", fname
);
395 fd2
= copyfd(psh
, fd
, 10);
396 shfile_close(&psh
->fdtab
, fd
);
398 error(psh
, "Out of file descriptors");
401 setinputfd(psh
, fd
, push
);
407 * Like setinputfile, but takes an open file descriptor. Call this with
412 setinputfd(shinstance
*psh
, int fd
, int push
)
414 (void) shfile_fcntl(&psh
->fdtab
, fd
, F_SETFD
, FD_CLOEXEC
);
417 psh
->parsefile
->buf
= ckmalloc(BUFSIZ
);
419 if (psh
->parsefile
->fd
> 0)
420 shfile_close(&psh
->fdtab
, psh
->parsefile
->fd
);
421 psh
->parsefile
->fd
= fd
;
422 if (psh
->parsefile
->buf
== NULL
)
423 psh
->parsefile
->buf
= ckmalloc(BUFSIZ
);
424 psh
->parselleft
= psh
->parsenleft
= 0;
430 * Like setinputfile, but takes input from a string.
434 setinputstring(shinstance
*psh
, char *string
, int push
)
439 psh
->parsenextc
= string
;
440 psh
->parselleft
= psh
->parsenleft
= (int)strlen(string
);
441 psh
->parsefile
->buf
= NULL
;
449 * To handle the "." command, a stack of input files is used. Pushfile
450 * adds a new entry to the stack and popfile restores the previous level.
454 pushfile(shinstance
*psh
)
456 struct parsefile
*pf
;
458 psh
->parsefile
->nleft
= psh
->parsenleft
;
459 psh
->parsefile
->lleft
= psh
->parselleft
;
460 psh
->parsefile
->nextc
= psh
->parsenextc
;
461 psh
->parsefile
->linno
= psh
->plinno
;
462 pf
= (struct parsefile
*)ckmalloc(sizeof (struct parsefile
));
463 pf
->prev
= psh
->parsefile
;
466 pf
->basestrpush
.prev
= NULL
;
472 popfile(shinstance
*psh
)
474 struct parsefile
*pf
= psh
->parsefile
;
478 shfile_close(&psh
->fdtab
, pf
->fd
);
483 psh
->parsefile
= pf
->prev
;
485 psh
->parsenleft
= psh
->parsefile
->nleft
;
486 psh
->parselleft
= psh
->parsefile
->lleft
;
487 psh
->parsenextc
= psh
->parsefile
->nextc
;
488 psh
->plinno
= psh
->parsefile
->linno
;
494 * Return to top level.
498 popallfiles(shinstance
*psh
)
500 while (psh
->parsefile
!= &psh
->basepf
)
507 * Close the file(s) that the shell is reading commands from. Called
508 * after a fork is done.
510 * Takes one arg, vfork, which tells it to not modify its global vars
511 * as it is still running in the parent.
513 * This code is (probably) unnecessary as the 'close on exec' flag is
514 * set and should be enough. In the vfork case it is definitely wrong
515 * to close the fds as another fork() may be done later to feed data
516 * from a 'here' document into a pipe and we don't want to close the
521 closescript(shinstance
*psh
, int vforked
)
526 if (psh
->parsefile
->fd
> 0) {
527 shfile_close(&psh
->fdtab
, psh
->parsefile
->fd
);
528 psh
->parsefile
->fd
= 0;