footer.kmk: KBUILD_NO_TESTING_PASS_ALIASES.
[kbuild-mirror.git] / src / ash / input.c
bloba231f4d6547005a04dea7ace41bd2a290917898f
1 /* $NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc 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 #ifdef HAVE_SYS_CDEFS_H
36 #include <sys/cdefs.h>
37 #endif
38 #ifndef lint
39 #if 0
40 static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95";
41 #else
42 __RCSID("$NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc Exp $");
43 #endif
44 #endif /* not lint */
46 #include <stdio.h> /* defines BUFSIZ */
47 #include <fcntl.h>
48 #include <errno.h>
49 #include <unistd.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #ifdef __sun__
53 #include <iso/limits_iso.h>
54 #endif
57 * This file implements the input routines used by the parser.
60 #include "shell.h"
61 #include "redir.h"
62 #include "syntax.h"
63 #include "input.h"
64 #include "output.h"
65 #include "options.h"
66 #include "memalloc.h"
67 #include "error.h"
68 #include "alias.h"
69 #include "parser.h"
70 #include "myhistedit.h"
72 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
74 MKINIT
75 struct strpush {
76 struct strpush *prev; /* preceding string on stack */
77 char *prevstring;
78 int prevnleft;
79 int prevlleft;
80 struct alias *ap; /* if push was associated with an alias */
84 * The parsefile structure pointed to by the global variable parsefile
85 * contains information about the current file being read.
88 MKINIT
89 struct parsefile {
90 struct parsefile *prev; /* preceding file on stack */
91 int linno; /* current line */
92 int fd; /* file descriptor (or -1 if string) */
93 int nleft; /* number of chars left in this line */
94 int lleft; /* number of chars left in this buffer */
95 char *nextc; /* next char in buffer */
96 char *buf; /* input buffer */
97 struct strpush *strpush; /* for pushing strings at this level */
98 struct strpush basestrpush; /* so pushing one is fast */
102 int plinno = 1; /* input line number */
103 int parsenleft; /* copy of parsefile->nleft */
104 MKINIT int parselleft; /* copy of parsefile->lleft */
105 char *parsenextc; /* copy of parsefile->nextc */
106 MKINIT struct parsefile basepf; /* top level input file */
107 MKINIT char basebuf[BUFSIZ]; /* buffer for top level input file */
108 struct parsefile *parsefile = &basepf; /* current input file */
109 int init_editline = 0; /* editline library initialized? */
110 int whichprompt; /* 1 == PS1, 2 == PS2 */
112 #ifndef SMALL
113 EditLine *el; /* cookie for editline package */
114 #endif
116 STATIC void pushfile(void);
117 static int preadfd(void);
119 #ifdef mkinit
120 INCLUDE <stdio.h>
121 INCLUDE "input.h"
122 INCLUDE "error.h"
124 INIT {
125 basepf.nextc = basepf.buf = basebuf;
128 RESET {
129 if (exception != EXSHELLPROC)
130 parselleft = parsenleft = 0; /* clear input buffer */
131 popallfiles();
134 SHELLPROC {
135 popallfiles();
137 #endif
141 * Read a line from the script.
144 char *
145 pfgets(char *line, int len)
147 char *p = line;
148 int nleft = len;
149 int c;
151 while (--nleft > 0) {
152 c = pgetc_macro();
153 if (c == PEOF) {
154 if (p == line)
155 return NULL;
156 break;
158 *p++ = c;
159 if (c == '\n')
160 break;
162 *p = '\0';
163 return line;
169 * Read a character from the script, returning PEOF on end of file.
170 * Nul characters in the input are silently discarded.
174 pgetc(void)
176 return pgetc_macro();
180 static int
181 preadfd(void)
183 int nr;
184 char *buf = parsefile->buf;
185 parsenextc = buf;
187 retry:
188 #ifndef SMALL
189 if (parsefile->fd == 0 && el) {
190 static const char *rl_cp;
191 static int el_len;
193 if (rl_cp == NULL)
194 rl_cp = el_gets(el, &el_len);
195 if (rl_cp == NULL)
196 nr = 0;
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;
209 } else
210 #endif
211 nr = read(parsefile->fd, buf, BUFSIZ - 8);
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 if (flags >= 0 && flags & O_NONBLOCK) {
221 flags &=~ O_NONBLOCK;
222 if (fcntl(0, F_SETFL, flags) >= 0) {
223 out2str("sh: turning off NDELAY mode\n");
224 goto retry;
229 nr = -1;
231 return nr;
235 * Refill the input buffer and return the next input character:
237 * 1) If a string was pushed back on the input, pop it;
238 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
239 * from a string so we can't refill the buffer, return EOF.
240 * 3) If the is more stuff in this buffer, use it else call read to fill it.
241 * 4) Process input up to the next newline, deleting nul characters.
245 preadbuffer(void)
247 char *p, *q;
248 int more;
249 int something;
250 char savec;
252 if (parsefile->strpush) {
253 popstring();
254 if (--parsenleft >= 0)
255 return (*parsenextc++);
257 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
258 return PEOF;
259 flushout(&output);
260 flushout(&errout);
262 again:
263 if (parselleft <= 0) {
264 if ((parselleft = preadfd()) == -1) {
265 parselleft = parsenleft = EOF_NLEFT;
266 return PEOF;
270 q = p = parsenextc;
272 /* delete nul characters */
273 something = 0;
274 for (more = 1; more;) {
275 switch (*p) {
276 case '\0':
277 p++; /* Skip nul */
278 goto check;
280 case '\t':
281 case ' ':
282 break;
284 case '\n':
285 parsenleft = q - parsenextc;
286 more = 0; /* Stop processing here */
287 break;
289 default:
290 something = 1;
291 break;
294 *q++ = *p++;
295 check:
296 if (--parselleft <= 0) {
297 parsenleft = q - parsenextc - 1;
298 if (parsenleft < 0)
299 goto again;
300 *q = '\0';
301 more = 0;
305 savec = *q;
306 *q = '\0';
308 #ifndef SMALL
309 if (parsefile->fd == 0 && hist && something) {
310 HistEvent he;
311 INTOFF;
312 history(hist, &he, whichprompt == 1? H_ENTER : H_APPEND,
313 parsenextc);
314 INTON;
316 #endif
318 if (vflag) {
319 out2str(parsenextc);
320 flushout(out2);
323 *q = savec;
325 return *parsenextc++;
329 * Undo the last call to pgetc. Only one character may be pushed back.
330 * PEOF may be pushed back.
333 void
334 pungetc(void)
336 parsenleft++;
337 parsenextc--;
341 * Push a string back onto the input at this current parsefile level.
342 * We handle aliases this way.
344 void
345 pushstring(char *s, int len, void *ap)
347 struct strpush *sp;
349 INTOFF;
350 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
351 if (parsefile->strpush) {
352 sp = ckmalloc(sizeof (struct strpush));
353 sp->prev = parsefile->strpush;
354 parsefile->strpush = sp;
355 } else
356 sp = parsefile->strpush = &(parsefile->basestrpush);
357 sp->prevstring = parsenextc;
358 sp->prevnleft = parsenleft;
359 sp->prevlleft = parselleft;
360 sp->ap = (struct alias *)ap;
361 if (ap)
362 ((struct alias *)ap)->flag |= ALIASINUSE;
363 parsenextc = s;
364 parsenleft = len;
365 INTON;
368 void
369 popstring(void)
371 struct strpush *sp = parsefile->strpush;
373 INTOFF;
374 parsenextc = sp->prevstring;
375 parsenleft = sp->prevnleft;
376 parselleft = sp->prevlleft;
377 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
378 if (sp->ap)
379 sp->ap->flag &= ~ALIASINUSE;
380 parsefile->strpush = sp->prev;
381 if (sp != &(parsefile->basestrpush))
382 ckfree(sp);
383 INTON;
387 * Set the input to take input from a file. If push is set, push the
388 * old input onto the stack first.
391 void
392 setinputfile(const char *fname, int push)
394 int fd;
395 int fd2;
397 INTOFF;
398 if ((fd = open(fname, O_RDONLY)) < 0)
399 error("Can't open %s", fname);
400 if (fd < 10) {
401 fd2 = copyfd(fd, 10);
402 close(fd);
403 if (fd2 < 0)
404 error("Out of file descriptors");
405 fd = fd2;
407 setinputfd(fd, push);
408 INTON;
413 * Like setinputfile, but takes an open file descriptor. Call this with
414 * interrupts off.
417 void
418 setinputfd(int fd, int push)
420 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
421 if (push) {
422 pushfile();
423 parsefile->buf = ckmalloc(BUFSIZ);
425 if (parsefile->fd > 0)
426 close(parsefile->fd);
427 parsefile->fd = fd;
428 if (parsefile->buf == NULL)
429 parsefile->buf = ckmalloc(BUFSIZ);
430 parselleft = parsenleft = 0;
431 plinno = 1;
436 * Like setinputfile, but takes input from a string.
439 void
440 setinputstring(char *string, int push)
442 INTOFF;
443 if (push)
444 pushfile();
445 parsenextc = string;
446 parselleft = parsenleft = strlen(string);
447 parsefile->buf = NULL;
448 plinno = 1;
449 INTON;
455 * To handle the "." command, a stack of input files is used. Pushfile
456 * adds a new entry to the stack and popfile restores the previous level.
459 STATIC void
460 pushfile(void)
462 struct parsefile *pf;
464 parsefile->nleft = parsenleft;
465 parsefile->lleft = parselleft;
466 parsefile->nextc = parsenextc;
467 parsefile->linno = plinno;
468 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
469 pf->prev = parsefile;
470 pf->fd = -1;
471 pf->strpush = NULL;
472 pf->basestrpush.prev = NULL;
473 parsefile = pf;
477 void
478 popfile(void)
480 struct parsefile *pf = parsefile;
482 INTOFF;
483 if (pf->fd >= 0)
484 close(pf->fd);
485 if (pf->buf)
486 ckfree(pf->buf);
487 while (pf->strpush)
488 popstring();
489 parsefile = pf->prev;
490 ckfree(pf);
491 parsenleft = parsefile->nleft;
492 parselleft = parsefile->lleft;
493 parsenextc = parsefile->nextc;
494 plinno = parsefile->linno;
495 INTON;
500 * Return to top level.
503 void
504 popallfiles(void)
506 while (parsefile != &basepf)
507 popfile();
513 * Close the file(s) that the shell is reading commands from. Called
514 * after a fork is done.
516 * Takes one arg, vfork, which tells it to not modify its global vars
517 * as it is still running in the parent.
519 * This code is (probably) unnecessary as the 'close on exec' flag is
520 * set and should be enough. In the vfork case it is definitely wrong
521 * to close the fds as another fork() may be done later to feed data
522 * from a 'here' document into a pipe and we don't want to close the
523 * pipe!
526 void
527 closescript(int vforked)
529 if (vforked)
530 return;
531 popallfiles();
532 if (parsefile->fd > 0) {
533 close(parsefile->fd);
534 parsefile->fd = 0;