No empty .Rs/.Re
[netbsd-mini2440.git] / bin / sh / input.c
blob138c84cfddba9c040c82e022033027b5df3a32b8
1 /* $NetBSD: input.c,v 1.41 2008/10/16 14:36:40 dholland Exp $ */
3 /*-
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
8 * Kenneth Almquist.
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.
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.
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.41 2008/10/16 14:36:40 dholland Exp $");
41 #endif
42 #endif /* not lint */
44 #include <stdio.h> /* defines BUFSIZ */
45 #include <fcntl.h>
46 #include <errno.h>
47 #include <unistd.h>
48 #include <stdlib.h>
49 #include <string.h>
52 * This file implements the input routines used by the parser.
55 #include "shell.h"
56 #include "redir.h"
57 #include "syntax.h"
58 #include "input.h"
59 #include "output.h"
60 #include "options.h"
61 #include "memalloc.h"
62 #include "error.h"
63 #include "alias.h"
64 #include "parser.h"
65 #include "myhistedit.h"
67 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
69 MKINIT
70 struct strpush {
71 struct strpush *prev; /* preceding string on stack */
72 char *prevstring;
73 int prevnleft;
74 int prevlleft;
75 struct alias *ap; /* if push was associated with an alias */
79 * The parsefile structure pointed to by the global variable parsefile
80 * contains information about the current file being read.
83 MKINIT
84 struct parsefile {
85 struct parsefile *prev; /* preceding file on stack */
86 int linno; /* current line */
87 int fd; /* file descriptor (or -1 if string) */
88 int nleft; /* number of chars left in this line */
89 int lleft; /* number of chars left in this buffer */
90 char *nextc; /* next char in buffer */
91 char *buf; /* input buffer */
92 struct strpush *strpush; /* for pushing strings at this level */
93 struct strpush basestrpush; /* so pushing one is fast */
97 int plinno = 1; /* input line number */
98 int parsenleft; /* copy of parsefile->nleft */
99 MKINIT int parselleft; /* copy of parsefile->lleft */
100 char *parsenextc; /* copy of parsefile->nextc */
101 MKINIT struct parsefile basepf; /* top level input file */
102 MKINIT char basebuf[BUFSIZ]; /* buffer for top level input file */
103 struct parsefile *parsefile = &basepf; /* current input file */
104 int init_editline = 0; /* editline library initialized? */
105 int whichprompt; /* 1 == PS1, 2 == PS2 */
107 STATIC void pushfile(void);
108 static int preadfd(void);
110 #ifdef mkinit
111 INCLUDE <stdio.h>
112 INCLUDE "input.h"
113 INCLUDE "error.h"
115 INIT {
116 basepf.nextc = basepf.buf = basebuf;
119 RESET {
120 if (exception != EXSHELLPROC)
121 parselleft = parsenleft = 0; /* clear input buffer */
122 popallfiles();
125 SHELLPROC {
126 popallfiles();
128 #endif
132 * Read a line from the script.
135 char *
136 pfgets(char *line, int len)
138 char *p = line;
139 int nleft = len;
140 int c;
142 while (--nleft > 0) {
143 c = pgetc_macro();
144 if (c == PEOF) {
145 if (p == line)
146 return NULL;
147 break;
149 *p++ = c;
150 if (c == '\n')
151 break;
153 *p = '\0';
154 return line;
160 * Read a character from the script, returning PEOF on end of file.
161 * Nul characters in the input are silently discarded.
165 pgetc(void)
167 return pgetc_macro();
171 static int
172 preadfd(void)
174 int nr;
175 char *buf = parsefile->buf;
176 parsenextc = buf;
178 retry:
179 #ifndef SMALL
180 if (parsefile->fd == 0 && el) {
181 static const char *rl_cp;
182 static int el_len;
184 if (rl_cp == NULL)
185 rl_cp = el_gets(el, &el_len);
186 if (rl_cp == NULL)
187 nr = el_len == 0 ? 0 : -1;
188 else {
189 nr = el_len;
190 if (nr > BUFSIZ - 8)
191 nr = BUFSIZ - 8;
192 memcpy(buf, rl_cp, nr);
193 if (nr != el_len) {
194 el_len -= nr;
195 rl_cp += nr;
196 } else
197 rl_cp = 0;
200 } else
201 #endif
202 nr = read(parsefile->fd, buf, BUFSIZ - 8);
205 if (nr <= 0) {
206 if (nr < 0) {
207 if (errno == EINTR)
208 goto retry;
209 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
210 int flags = fcntl(0, F_GETFL, 0);
211 if (flags >= 0 && flags & O_NONBLOCK) {
212 flags &=~ O_NONBLOCK;
213 if (fcntl(0, F_SETFL, flags) >= 0) {
214 out2str("sh: turning off NDELAY mode\n");
215 goto retry;
220 nr = -1;
222 return nr;
226 * Refill the input buffer and return the next input character:
228 * 1) If a string was pushed back on the input, pop it;
229 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
230 * from a string so we can't refill the buffer, return EOF.
231 * 3) If the is more stuff in this buffer, use it else call read to fill it.
232 * 4) Process input up to the next newline, deleting nul characters.
236 preadbuffer(void)
238 char *p, *q;
239 int more;
240 int something;
241 char savec;
243 if (parsefile->strpush) {
244 popstring();
245 if (--parsenleft >= 0)
246 return (*parsenextc++);
248 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
249 return PEOF;
250 flushout(&output);
251 flushout(&errout);
253 again:
254 if (parselleft <= 0) {
255 if ((parselleft = preadfd()) == -1) {
256 parselleft = parsenleft = EOF_NLEFT;
257 return PEOF;
261 q = p = parsenextc;
263 /* delete nul characters */
264 something = 0;
265 for (more = 1; more;) {
266 switch (*p) {
267 case '\0':
268 p++; /* Skip nul */
269 goto check;
271 case '\t':
272 case ' ':
273 break;
275 case '\n':
276 parsenleft = q - parsenextc;
277 more = 0; /* Stop processing here */
278 break;
280 default:
281 something = 1;
282 break;
285 *q++ = *p++;
286 check:
287 if (--parselleft <= 0) {
288 parsenleft = q - parsenextc - 1;
289 if (parsenleft < 0)
290 goto again;
291 *q = '\0';
292 more = 0;
296 savec = *q;
297 *q = '\0';
299 #ifndef SMALL
300 if (parsefile->fd == 0 && hist && something) {
301 HistEvent he;
302 INTOFF;
303 history(hist, &he, whichprompt == 1? H_ENTER : H_APPEND,
304 parsenextc);
305 INTON;
307 #endif
309 if (vflag) {
310 out2str(parsenextc);
311 flushout(out2);
314 *q = savec;
316 return *parsenextc++;
320 * Undo the last call to pgetc. Only one character may be pushed back.
321 * PEOF may be pushed back.
324 void
325 pungetc(void)
327 parsenleft++;
328 parsenextc--;
332 * Push a string back onto the input at this current parsefile level.
333 * We handle aliases this way.
335 void
336 pushstring(char *s, int len, void *ap)
338 struct strpush *sp;
340 INTOFF;
341 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
342 if (parsefile->strpush) {
343 sp = ckmalloc(sizeof (struct strpush));
344 sp->prev = parsefile->strpush;
345 parsefile->strpush = sp;
346 } else
347 sp = parsefile->strpush = &(parsefile->basestrpush);
348 sp->prevstring = parsenextc;
349 sp->prevnleft = parsenleft;
350 sp->prevlleft = parselleft;
351 sp->ap = (struct alias *)ap;
352 if (ap)
353 ((struct alias *)ap)->flag |= ALIASINUSE;
354 parsenextc = s;
355 parsenleft = len;
356 INTON;
359 void
360 popstring(void)
362 struct strpush *sp = parsefile->strpush;
364 INTOFF;
365 parsenextc = sp->prevstring;
366 parsenleft = sp->prevnleft;
367 parselleft = sp->prevlleft;
368 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
369 if (sp->ap)
370 sp->ap->flag &= ~ALIASINUSE;
371 parsefile->strpush = sp->prev;
372 if (sp != &(parsefile->basestrpush))
373 ckfree(sp);
374 INTON;
378 * Set the input to take input from a file. If push is set, push the
379 * old input onto the stack first.
382 void
383 setinputfile(const char *fname, int push)
385 unsigned char magic[4];
386 int fd;
387 int fd2;
389 INTOFF;
390 if ((fd = open(fname, O_RDONLY)) < 0)
391 error("Can't open %s", fname);
393 /* Since the message "Syntax error: "(" unexpected" is not very
394 * helpful, we check if the file starts with the ELF magic to
395 * avoid that message. The first lseek tries to make sure that
396 * we can later rewind the file.
398 if (lseek(fd, 0, SEEK_SET) == 0) {
399 if (read(fd, magic, 4) == 4) {
400 if (memcmp(magic, "\177ELF", 4) == 0)
401 error("Cannot execute ELF binary %s", fname);
403 if (lseek(fd, 0, SEEK_SET) != 0)
404 error("Cannot rewind the file %s", fname);
407 if (fd < 10) {
408 fd2 = copyfd(fd, 10);
409 close(fd);
410 if (fd2 < 0)
411 error("Out of file descriptors");
412 fd = fd2;
414 setinputfd(fd, push);
415 INTON;
420 * Like setinputfile, but takes an open file descriptor. Call this with
421 * interrupts off.
424 void
425 setinputfd(int fd, int push)
427 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
428 if (push) {
429 pushfile();
430 parsefile->buf = ckmalloc(BUFSIZ);
432 if (parsefile->fd > 0)
433 close(parsefile->fd);
434 parsefile->fd = fd;
435 if (parsefile->buf == NULL)
436 parsefile->buf = ckmalloc(BUFSIZ);
437 parselleft = parsenleft = 0;
438 plinno = 1;
443 * Like setinputfile, but takes input from a string.
446 void
447 setinputstring(char *string, int push)
449 INTOFF;
450 if (push)
451 pushfile();
452 parsenextc = string;
453 parselleft = parsenleft = strlen(string);
454 parsefile->buf = NULL;
455 plinno = 1;
456 INTON;
462 * To handle the "." command, a stack of input files is used. Pushfile
463 * adds a new entry to the stack and popfile restores the previous level.
466 STATIC void
467 pushfile(void)
469 struct parsefile *pf;
471 parsefile->nleft = parsenleft;
472 parsefile->lleft = parselleft;
473 parsefile->nextc = parsenextc;
474 parsefile->linno = plinno;
475 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
476 pf->prev = parsefile;
477 pf->fd = -1;
478 pf->strpush = NULL;
479 pf->basestrpush.prev = NULL;
480 parsefile = pf;
484 void
485 popfile(void)
487 struct parsefile *pf = parsefile;
489 INTOFF;
490 if (pf->fd >= 0)
491 close(pf->fd);
492 if (pf->buf)
493 ckfree(pf->buf);
494 while (pf->strpush)
495 popstring();
496 parsefile = pf->prev;
497 ckfree(pf);
498 parsenleft = parsefile->nleft;
499 parselleft = parsefile->lleft;
500 parsenextc = parsefile->nextc;
501 plinno = parsefile->linno;
502 INTON;
507 * Return to top level.
510 void
511 popallfiles(void)
513 while (parsefile != &basepf)
514 popfile();
520 * Close the file(s) that the shell is reading commands from. Called
521 * after a fork is done.
523 * Takes one arg, vfork, which tells it to not modify its global vars
524 * as it is still running in the parent.
526 * This code is (probably) unnecessary as the 'close on exec' flag is
527 * set and should be enough. In the vfork case it is definitely wrong
528 * to close the fds as another fork() may be done later to feed data
529 * from a 'here' document into a pipe and we don't want to close the
530 * pipe!
533 void
534 closescript(int vforked)
536 if (vforked)
537 return;
538 popallfiles();
539 if (parsefile->fd > 0) {
540 close(parsefile->fd);
541 parsefile->fd = 0;