Rev 2714 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2714 | Rev 3240 | ||
---|---|---|---|
1 | /* $NetBSD: input.c,v 1.34 2000/05/22 10:18:47 elric Exp $ */ |
1 | /* $NetBSD: input.c,v 1.34 2000/05/22 10:18:47 elric Exp $ */ |
2 | 2 | ||
3 | /*- |
3 | /*- |
4 | * Copyright (c) 1991, 1993 |
4 | * Copyright (c) 1991, 1993 |
5 | * The Regents of the University of California. All rights reserved. |
5 | * The Regents of the University of California. All rights reserved. |
6 | * |
6 | * |
7 | * This code is derived from software contributed to Berkeley by |
7 | * This code is derived from software contributed to Berkeley by |
8 | * Kenneth Almquist. |
8 | * Kenneth Almquist. |
9 | * |
9 | * |
10 | * Redistribution and use in source and binary forms, with or without |
10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions |
11 | * modification, are permitted provided that the following conditions |
12 | * are met: |
12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright |
13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. |
14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright |
15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the |
16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. |
17 | * documentation and/or other materials provided with the distribution. |
18 | * 3. All advertising materials mentioning features or use of this software |
18 | * 3. All advertising materials mentioning features or use of this software |
19 | * must display the following acknowledgement: |
19 | * must display the following acknowledgement: |
20 | * This product includes software developed by the University of |
20 | * This product includes software developed by the University of |
21 | * California, Berkeley and its contributors. |
21 | * California, Berkeley and its contributors. |
22 | * 4. Neither the name of the University nor the names of its contributors |
22 | * 4. Neither the name of the University nor the names of its contributors |
23 | * may be used to endorse or promote products derived from this software |
23 | * may be used to endorse or promote products derived from this software |
24 | * without specific prior written permission. |
24 | * without specific prior written permission. |
25 | * |
25 | * |
26 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
26 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
27 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
27 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
28 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
28 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
29 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
29 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
30 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
30 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
31 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
31 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
32 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
32 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
33 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
33 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
34 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
34 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
35 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
35 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
36 | * SUCH DAMAGE. |
36 | * SUCH DAMAGE. |
37 | */ |
37 | */ |
38 | 38 | ||
39 | #include <sys/cdefs.h> |
39 | #include <sys/cdefs.h> |
40 | #ifndef lint |
40 | #ifndef lint |
41 | #if 0 |
41 | #if 0 |
42 | static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95"; |
42 | static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95"; |
43 | #else |
43 | #else |
44 | __RCSID("$NetBSD: input.c,v 1.34 2000/05/22 10:18:47 elric Exp $"); |
44 | __RCSID("$NetBSD: input.c,v 1.34 2000/05/22 10:18:47 elric Exp $"); |
45 | #endif |
45 | #endif |
46 | #endif /* not lint */ |
46 | #endif /* not lint */ |
47 | 47 | ||
48 | #include <stdio.h> /* defines BUFSIZ */ |
48 | #include <stdio.h> /* defines BUFSIZ */ |
49 | #include <fcntl.h> |
49 | #include <fcntl.h> |
50 | #include <errno.h> |
50 | #include <errno.h> |
51 | #include <unistd.h> |
51 | #include <unistd.h> |
52 | #include <stdlib.h> |
52 | #include <stdlib.h> |
53 | #include <string.h> |
53 | #include <string.h> |
54 | 54 | ||
55 | /* |
55 | /* |
56 | * This file implements the input routines used by the parser. |
56 | * This file implements the input routines used by the parser. |
57 | */ |
57 | */ |
58 | 58 | ||
59 | #include "shell.h" |
59 | #include "shell.h" |
60 | #include "redir.h" |
60 | #include "redir.h" |
61 | #include "syntax.h" |
61 | #include "syntax.h" |
62 | #include "input.h" |
62 | #include "input.h" |
63 | #include "output.h" |
63 | #include "output.h" |
64 | #include "options.h" |
64 | #include "options.h" |
65 | #include "memalloc.h" |
65 | #include "memalloc.h" |
66 | #include "error.h" |
66 | #include "error.h" |
67 | #include "alias.h" |
67 | #include "alias.h" |
68 | #include "parser.h" |
68 | #include "parser.h" |
69 | #ifndef SMALL |
69 | #ifndef SMALL |
70 | #include "myhistedit.h" |
70 | #include "myhistedit.h" |
71 | #endif |
71 | #endif |
72 | 72 | ||
73 | #ifdef HETIO |
73 | #ifdef HETIO |
74 | #include "hetio.h" |
74 | #include "hetio.h" |
75 | #endif |
75 | #endif |
76 | 76 | ||
77 | #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ |
77 | #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ |
78 | 78 | ||
79 | MKINIT |
79 | MKINIT |
80 | struct strpush { |
80 | struct strpush { |
81 | struct strpush *prev; /* preceding string on stack */ |
81 | struct strpush *prev; /* preceding string on stack */ |
82 | char *prevstring; |
82 | char *prevstring; |
83 | int prevnleft; |
83 | int prevnleft; |
84 | int prevlleft; |
84 | int prevlleft; |
85 | struct alias *ap; /* if push was associated with an alias */ |
85 | struct alias *ap; /* if push was associated with an alias */ |
86 | }; |
86 | }; |
87 | 87 | ||
88 | /* |
88 | /* |
89 | * The parsefile structure pointed to by the global variable parsefile |
89 | * The parsefile structure pointed to by the global variable parsefile |
90 | * contains information about the current file being read. |
90 | * contains information about the current file being read. |
91 | */ |
91 | */ |
92 | 92 | ||
93 | MKINIT |
93 | MKINIT |
94 | struct parsefile { |
94 | struct parsefile { |
95 | struct parsefile *prev; /* preceding file on stack */ |
95 | struct parsefile *prev; /* preceding file on stack */ |
96 | int linno; /* current line */ |
96 | int linno; /* current line */ |
97 | int fd; /* file descriptor (or -1 if string) */ |
97 | int fd; /* file descriptor (or -1 if string) */ |
98 | int nleft; /* number of chars left in this line */ |
98 | int nleft; /* number of chars left in this line */ |
99 | int lleft; /* number of chars left in this buffer */ |
99 | int lleft; /* number of chars left in this buffer */ |
100 | char *nextc; /* next char in buffer */ |
100 | char *nextc; /* next char in buffer */ |
101 | char *buf; /* input buffer */ |
101 | char *buf; /* input buffer */ |
102 | struct strpush *strpush; /* for pushing strings at this level */ |
102 | struct strpush *strpush; /* for pushing strings at this level */ |
103 | struct strpush basestrpush; /* so pushing one is fast */ |
103 | struct strpush basestrpush; /* so pushing one is fast */ |
104 | }; |
104 | }; |
105 | 105 | ||
106 | 106 | ||
107 | int plinno = 1; /* input line number */ |
107 | int plinno = 1; /* input line number */ |
108 | MKINIT int parsenleft; /* copy of parsefile->nleft */ |
108 | MKINIT int parsenleft; /* copy of parsefile->nleft */ |
109 | MKINIT int parselleft; /* copy of parsefile->lleft */ |
109 | MKINIT int parselleft; /* copy of parsefile->lleft */ |
110 | char *parsenextc; /* copy of parsefile->nextc */ |
110 | char *parsenextc; /* copy of parsefile->nextc */ |
111 | MKINIT struct parsefile basepf; /* top level input file */ |
111 | MKINIT struct parsefile basepf; /* top level input file */ |
112 | char basebuf[BUFSIZ]; /* buffer for top level input file */ |
112 | char basebuf[BUFSIZ]; /* buffer for top level input file */ |
113 | struct parsefile *parsefile = &basepf; /* current input file */ |
113 | struct parsefile *parsefile = &basepf; /* current input file */ |
114 | int init_editline = 0; /* editline library initialized? */ |
114 | int init_editline = 0; /* editline library initialized? */ |
115 | int whichprompt; /* 1 == PS1, 2 == PS2 */ |
115 | int whichprompt; /* 1 == PS1, 2 == PS2 */ |
116 | 116 | ||
117 | #ifndef SMALL |
117 | #ifndef SMALL |
118 | EditLine *el; /* cookie for editline package */ |
118 | EditLine *el; /* cookie for editline package */ |
119 | #endif |
119 | #endif |
120 | 120 | ||
121 | STATIC void pushfile (void); |
121 | STATIC void pushfile (void); |
122 | static int preadfd (void); |
122 | static int preadfd (void); |
123 | 123 | ||
124 | #ifdef mkinit |
124 | #ifdef mkinit |
125 | INCLUDE "input.h" |
125 | INCLUDE "input.h" |
126 | INCLUDE "error.h" |
126 | INCLUDE "error.h" |
127 | 127 | ||
128 | INIT { |
128 | INIT { |
129 | extern char basebuf[]; |
129 | extern char basebuf[]; |
130 | 130 | ||
131 | basepf.nextc = basepf.buf = basebuf; |
131 | basepf.nextc = basepf.buf = basebuf; |
132 | } |
132 | } |
133 | 133 | ||
134 | RESET { |
134 | RESET { |
135 | if (exception != EXSHELLPROC) |
135 | if (exception != EXSHELLPROC) |
136 | parselleft = parsenleft = 0; /* clear input buffer */ |
136 | parselleft = parsenleft = 0; /* clear input buffer */ |
137 | popallfiles(); |
137 | popallfiles(); |
138 | } |
138 | } |
139 | 139 | ||
140 | SHELLPROC { |
140 | SHELLPROC { |
141 | popallfiles(); |
141 | popallfiles(); |
142 | } |
142 | } |
143 | #endif |
143 | #endif |
144 | 144 | ||
145 | 145 | ||
146 | /* |
146 | /* |
147 | * Read a line from the script. |
147 | * Read a line from the script. |
148 | */ |
148 | */ |
149 | 149 | ||
150 | char * |
150 | char * |
151 | pfgets(line, len) |
151 | pfgets(line, len) |
152 | char *line; |
152 | char *line; |
153 | int len; |
153 | int len; |
154 | { |
154 | { |
155 | char *p = line; |
155 | char *p = line; |
156 | int nleft = len; |
156 | int nleft = len; |
157 | int c; |
157 | int c; |
158 | 158 | ||
159 | while (--nleft > 0) { |
159 | while (--nleft > 0) { |
160 | c = pgetc_macro(); |
160 | c = pgetc_macro(); |
161 | if (c == PEOF) { |
161 | if (c == PEOF) { |
162 | if (p == line) |
162 | if (p == line) |
163 | return NULL; |
163 | return NULL; |
164 | break; |
164 | break; |
165 | } |
165 | } |
166 | *p++ = c; |
166 | *p++ = c; |
167 | if (c == '\n') |
167 | if (c == '\n') |
168 | break; |
168 | break; |
169 | } |
169 | } |
170 | *p = '\0'; |
170 | *p = '\0'; |
171 | return line; |
171 | return line; |
172 | } |
172 | } |
173 | 173 | ||
174 | 174 | ||
175 | 175 | ||
176 | /* |
176 | /* |
177 | * Read a character from the script, returning PEOF on end of file. |
177 | * Read a character from the script, returning PEOF on end of file. |
178 | * Nul characters in the input are silently discarded. |
178 | * Nul characters in the input are silently discarded. |
179 | */ |
179 | */ |
180 | 180 | ||
181 | int |
181 | int |
182 | pgetc() |
182 | pgetc() |
183 | { |
183 | { |
184 | return pgetc_macro(); |
184 | return pgetc_macro(); |
185 | } |
185 | } |
186 | 186 | ||
187 | 187 | ||
188 | static int |
188 | static int |
189 | preadfd() |
189 | preadfd() |
190 | { |
190 | { |
191 | int nr; |
191 | int nr; |
192 | char *buf = parsefile->buf; |
192 | char *buf = parsefile->buf; |
193 | parsenextc = buf; |
193 | parsenextc = buf; |
194 | 194 | ||
195 | retry: |
195 | retry: |
196 | #ifndef SMALL |
196 | #ifndef SMALL |
197 | if (parsefile->fd == 0 && el) { |
197 | if (parsefile->fd == 0 && el) { |
198 | const char *rl_cp; |
198 | const char *rl_cp; |
199 | 199 | ||
200 | rl_cp = el_gets(el, &nr); |
200 | rl_cp = el_gets(el, &nr); |
201 | if (rl_cp == NULL) |
201 | if (rl_cp == NULL) |
202 | nr = 0; |
202 | nr = 0; |
203 | else { |
203 | else { |
204 | /* XXX - BUFSIZE should redesign so not necessary */ |
204 | /* XXX - BUFSIZE should redesign so not necessary */ |
205 | (void) strcpy(buf, rl_cp); |
205 | (void) strcpy(buf, rl_cp); |
206 | } |
206 | } |
207 | } else |
207 | } else |
208 | #endif |
208 | #endif |
209 | 209 | ||
210 | #ifdef HETIO |
210 | #ifdef HETIO |
211 | nr = hetio_read_input(parsefile->fd); |
211 | nr = hetio_read_input(parsefile->fd); |
212 | if (nr == -255) |
212 | if (nr == -255) |
213 | #endif |
213 | #endif |
214 | nr = read(parsefile->fd, buf, BUFSIZ - 1); |
214 | nr = read(parsefile->fd, buf, BUFSIZ - 1); |
215 | 215 | ||
216 | 216 | ||
217 | if (nr <= 0) { |
217 | if (nr <= 0) { |
218 | if (nr < 0) { |
218 | if (nr < 0) { |
219 | if (errno == EINTR) |
219 | if (errno == EINTR) |
220 | goto retry; |
220 | goto retry; |
221 | if (parsefile->fd == 0 && errno == EWOULDBLOCK) { |
221 | if (parsefile->fd == 0 && errno == EWOULDBLOCK) { |
222 | int flags = fcntl(0, F_GETFL, 0); |
222 | int flags = fcntl(0, F_GETFL, 0); |
223 | if (flags >= 0 && flags & O_NONBLOCK) { |
223 | if (flags >= 0 && flags & O_NONBLOCK) { |
224 | flags &=~ O_NONBLOCK; |
224 | flags &=~ O_NONBLOCK; |
225 | if (fcntl(0, F_SETFL, flags) >= 0) { |
225 | if (fcntl(0, F_SETFL, flags) >= 0) { |
226 | out2str("sh: turning off NDELAY mode\n"); |
226 | out2str("sh: turning off NDELAY mode\n"); |
227 | goto retry; |
227 | goto retry; |
228 | } |
228 | } |
229 | } |
229 | } |
230 | } |
230 | } |
231 | } |
231 | } |
232 | nr = -1; |
232 | nr = -1; |
233 | } |
233 | } |
234 | return nr; |
234 | return nr; |
235 | } |
235 | } |
236 | 236 | ||
237 | /* |
237 | /* |
238 | * Refill the input buffer and return the next input character: |
238 | * Refill the input buffer and return the next input character: |
239 | * |
239 | * |
240 | * 1) If a string was pushed back on the input, pop it; |
240 | * 1) If a string was pushed back on the input, pop it; |
241 | * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading |
241 | * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading |
242 | * from a string so we can't refill the buffer, return EOF. |
242 | * from a string so we can't refill the buffer, return EOF. |
243 | * 3) If the is more stuff in this buffer, use it else call read to fill it. |
243 | * 3) If the is more stuff in this buffer, use it else call read to fill it. |
244 | * 4) Process input up to the next newline, deleting nul characters. |
244 | * 4) Process input up to the next newline, deleting nul characters. |
245 | */ |
245 | */ |
246 | 246 | ||
247 | int |
247 | int |
248 | preadbuffer() |
248 | preadbuffer() |
249 | { |
249 | { |
250 | char *p, *q; |
250 | char *p, *q; |
251 | int more; |
251 | int more; |
252 | int something; |
252 | int something; |
253 | char savec; |
253 | char savec; |
254 | 254 | ||
255 | if (parsefile->strpush) { |
255 | if (parsefile->strpush) { |
256 | popstring(); |
256 | popstring(); |
257 | if (--parsenleft >= 0) |
257 | if (--parsenleft >= 0) |
258 | return (*parsenextc++); |
258 | return (*parsenextc++); |
259 | } |
259 | } |
260 | if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) |
260 | if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) |
261 | return PEOF; |
261 | return PEOF; |
262 | flushout(&output); |
262 | flushout(&output); |
263 | flushout(&errout); |
263 | flushout(&errout); |
264 | 264 | ||
265 | again: |
265 | again: |
266 | if (parselleft <= 0) { |
266 | if (parselleft <= 0) { |
267 | if ((parselleft = preadfd()) == -1) { |
267 | if ((parselleft = preadfd()) == -1) { |
268 | parselleft = parsenleft = EOF_NLEFT; |
268 | parselleft = parsenleft = EOF_NLEFT; |
269 | return PEOF; |
269 | return PEOF; |
270 | } |
270 | } |
271 | } |
271 | } |
272 | 272 | ||
273 | q = p = parsenextc; |
273 | q = p = parsenextc; |
274 | 274 | ||
275 | /* delete nul characters */ |
275 | /* delete nul characters */ |
276 | something = 0; |
276 | something = 0; |
277 | for (more = 1; more;) { |
277 | for (more = 1; more;) { |
278 | switch (*p) { |
278 | switch (*p) { |
279 | case '\0': |
279 | case '\0': |
280 | p++; /* Skip nul */ |
280 | p++; /* Skip nul */ |
281 | goto check; |
281 | goto check; |
282 | 282 | ||
283 | case '\t': |
283 | case '\t': |
284 | case ' ': |
284 | case ' ': |
285 | break; |
285 | break; |
286 | 286 | ||
287 | case '\n': |
287 | case '\n': |
288 | parsenleft = q - parsenextc; |
288 | parsenleft = q - parsenextc; |
289 | more = 0; /* Stop processing here */ |
289 | more = 0; /* Stop processing here */ |
290 | break; |
290 | break; |
291 | 291 | ||
292 | default: |
292 | default: |
293 | something = 1; |
293 | something = 1; |
294 | break; |
294 | break; |
295 | } |
295 | } |
296 | 296 | ||
297 | *q++ = *p++; |
297 | *q++ = *p++; |
298 | check: |
298 | check: |
299 | if (--parselleft <= 0) { |
299 | if (--parselleft <= 0) { |
300 | parsenleft = q - parsenextc - 1; |
300 | parsenleft = q - parsenextc - 1; |
301 | if (parsenleft < 0) |
301 | if (parsenleft < 0) |
302 | goto again; |
302 | goto again; |
303 | *q = '\0'; |
303 | *q = '\0'; |
304 | more = 0; |
304 | more = 0; |
305 | } |
305 | } |
306 | } |
306 | } |
307 | 307 | ||
308 | savec = *q; |
308 | savec = *q; |
309 | *q = '\0'; |
309 | *q = '\0'; |
310 | 310 | ||
311 | #ifndef SMALL |
311 | #ifndef SMALL |
312 | if (parsefile->fd == 0 && hist && something) { |
312 | if (parsefile->fd == 0 && hist && something) { |
313 | HistEvent he; |
313 | HistEvent he; |
314 | INTOFF; |
314 | INTOFF; |
315 | history(hist, &he, whichprompt == 1? H_ENTER : H_APPEND, |
315 | history(hist, &he, whichprompt == 1? H_ENTER : H_APPEND, |
316 | parsenextc); |
316 | parsenextc); |
317 | INTON; |
317 | INTON; |
318 | } |
318 | } |
319 | #endif |
319 | #endif |
320 | 320 | ||
321 | if (vflag) { |
321 | if (vflag) { |
322 | out2str(parsenextc); |
322 | out2str(parsenextc); |
323 | flushout(out2); |
323 | flushout(out2); |
324 | } |
324 | } |
325 | 325 | ||
326 | *q = savec; |
326 | *q = savec; |
327 | 327 | ||
328 | return *parsenextc++; |
328 | return *parsenextc++; |
329 | } |
329 | } |
330 | 330 | ||
331 | /* |
331 | /* |
332 | * Undo the last call to pgetc. Only one character may be pushed back. |
332 | * Undo the last call to pgetc. Only one character may be pushed back. |
333 | * PEOF may be pushed back. |
333 | * PEOF may be pushed back. |
334 | */ |
334 | */ |
335 | 335 | ||
336 | void |
336 | void |
337 | pungetc() { |
337 | pungetc() { |
338 | parsenleft++; |
338 | parsenleft++; |
339 | parsenextc--; |
339 | parsenextc--; |
340 | } |
340 | } |
341 | 341 | ||
342 | /* |
342 | /* |
343 | * Push a string back onto the input at this current parsefile level. |
343 | * Push a string back onto the input at this current parsefile level. |
344 | * We handle aliases this way. |
344 | * We handle aliases this way. |
345 | */ |
345 | */ |
346 | void |
346 | void |
347 | pushstring(s, len, ap) |
347 | pushstring(s, len, ap) |
348 | char *s; |
348 | char *s; |
349 | int len; |
349 | int len; |
350 | void *ap; |
350 | void *ap; |
351 | { |
351 | { |
352 | struct strpush *sp; |
352 | struct strpush *sp; |
353 | 353 | ||
354 | INTOFF; |
354 | INTOFF; |
355 | /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/ |
355 | /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/ |
356 | if (parsefile->strpush) { |
356 | if (parsefile->strpush) { |
357 | sp = ckmalloc(sizeof (struct strpush)); |
357 | sp = ckmalloc(sizeof (struct strpush)); |
358 | sp->prev = parsefile->strpush; |
358 | sp->prev = parsefile->strpush; |
359 | parsefile->strpush = sp; |
359 | parsefile->strpush = sp; |
360 | } else |
360 | } else |
361 | sp = parsefile->strpush = &(parsefile->basestrpush); |
361 | sp = parsefile->strpush = &(parsefile->basestrpush); |
362 | sp->prevstring = parsenextc; |
362 | sp->prevstring = parsenextc; |
363 | sp->prevnleft = parsenleft; |
363 | sp->prevnleft = parsenleft; |
364 | sp->prevlleft = parselleft; |
364 | sp->prevlleft = parselleft; |
365 | sp->ap = (struct alias *)ap; |
365 | sp->ap = (struct alias *)ap; |
366 | if (ap) |
366 | if (ap) |
367 | ((struct alias *)ap)->flag |= ALIASINUSE; |
367 | ((struct alias *)ap)->flag |= ALIASINUSE; |
368 | parsenextc = s; |
368 | parsenextc = s; |
369 | parsenleft = len; |
369 | parsenleft = len; |
370 | INTON; |
370 | INTON; |
371 | } |
371 | } |
372 | 372 | ||
373 | void |
373 | void |
374 | popstring() |
374 | popstring() |
375 | { |
375 | { |
376 | struct strpush *sp = parsefile->strpush; |
376 | struct strpush *sp = parsefile->strpush; |
377 | 377 | ||
378 | INTOFF; |
378 | INTOFF; |
379 | parsenextc = sp->prevstring; |
379 | parsenextc = sp->prevstring; |
380 | parsenleft = sp->prevnleft; |
380 | parsenleft = sp->prevnleft; |
381 | parselleft = sp->prevlleft; |
381 | parselleft = sp->prevlleft; |
382 | /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/ |
382 | /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/ |
383 | if (sp->ap) |
383 | if (sp->ap) |
384 | sp->ap->flag &= ~ALIASINUSE; |
384 | sp->ap->flag &= ~ALIASINUSE; |
385 | parsefile->strpush = sp->prev; |
385 | parsefile->strpush = sp->prev; |
386 | if (sp != &(parsefile->basestrpush)) |
386 | if (sp != &(parsefile->basestrpush)) |
387 | ckfree(sp); |
387 | ckfree(sp); |
388 | INTON; |
388 | INTON; |
389 | } |
389 | } |
390 | 390 | ||
391 | /* |
391 | /* |
392 | * Set the input to take input from a file. If push is set, push the |
392 | * Set the input to take input from a file. If push is set, push the |
393 | * old input onto the stack first. |
393 | * old input onto the stack first. |
394 | */ |
394 | */ |
395 | 395 | ||
396 | void |
396 | void |
397 | setinputfile(fname, push) |
397 | setinputfile(fname, push) |
398 | const char *fname; |
398 | const char *fname; |
399 | int push; |
399 | int push; |
400 | { |
400 | { |
401 | int fd; |
401 | int fd; |
402 | int fd2; |
402 | int fd2; |
403 | 403 | ||
404 | INTOFF; |
404 | INTOFF; |
405 | if ((fd = open(fname, O_RDONLY)) < 0) |
405 | if ((fd = open(fname, O_RDONLY)) < 0) |
406 | error("Can't open %s", fname); |
406 | error("Can't open %s", fname); |
407 | if (fd < 10) { |
407 | if (fd < 10) { |
408 | fd2 = copyfd(fd, 10); |
408 | fd2 = copyfd(fd, 10); |
409 | close(fd); |
409 | close(fd); |
410 | if (fd2 < 0) |
410 | if (fd2 < 0) |
411 | error("Out of file descriptors"); |
411 | error("Out of file descriptors"); |
412 | fd = fd2; |
412 | fd = fd2; |
413 | } |
413 | } |
414 | setinputfd(fd, push); |
414 | setinputfd(fd, push); |
415 | INTON; |
415 | INTON; |
416 | } |
416 | } |
417 | 417 | ||
418 | 418 | ||
419 | /* |
419 | /* |
420 | * Like setinputfile, but takes an open file descriptor. Call this with |
420 | * Like setinputfile, but takes an open file descriptor. Call this with |
421 | * interrupts off. |
421 | * interrupts off. |
422 | */ |
422 | */ |
423 | 423 | ||
424 | void |
424 | void |
425 | setinputfd(fd, push) |
425 | setinputfd(fd, push) |
426 | int fd, push; |
426 | int fd, push; |
427 | { |
427 | { |
428 | (void) fcntl(fd, F_SETFD, FD_CLOEXEC); |
428 | (void) fcntl(fd, F_SETFD, FD_CLOEXEC); |
429 | if (push) { |
429 | if (push) { |
430 | pushfile(); |
430 | pushfile(); |
431 | parsefile->buf = ckmalloc(BUFSIZ); |
431 | parsefile->buf = ckmalloc(BUFSIZ); |
432 | } |
432 | } |
433 | if (parsefile->fd > 0) |
433 | if (parsefile->fd > 0) |
434 | close(parsefile->fd); |
434 | close(parsefile->fd); |
435 | parsefile->fd = fd; |
435 | parsefile->fd = fd; |
436 | if (parsefile->buf == NULL) |
436 | if (parsefile->buf == NULL) |
437 | parsefile->buf = ckmalloc(BUFSIZ); |
437 | parsefile->buf = ckmalloc(BUFSIZ); |
438 | parselleft = parsenleft = 0; |
438 | parselleft = parsenleft = 0; |
439 | plinno = 1; |
439 | plinno = 1; |
440 | } |
440 | } |
441 | 441 | ||
442 | 442 | ||
443 | /* |
443 | /* |
444 | * Like setinputfile, but takes input from a string. |
444 | * Like setinputfile, but takes input from a string. |
445 | */ |
445 | */ |
446 | 446 | ||
447 | void |
447 | void |
448 | setinputstring(string, push) |
448 | setinputstring(string, push) |
449 | char *string; |
449 | char *string; |
450 | int push; |
450 | int push; |
451 | { |
451 | { |
452 | INTOFF; |
452 | INTOFF; |
453 | if (push) |
453 | if (push) |
454 | pushfile(); |
454 | pushfile(); |
455 | parsenextc = string; |
455 | parsenextc = string; |
456 | parselleft = parsenleft = strlen(string); |
456 | parselleft = parsenleft = strlen(string); |
457 | parsefile->buf = NULL; |
457 | parsefile->buf = NULL; |
458 | plinno = 1; |
458 | plinno = 1; |
459 | INTON; |
459 | INTON; |
460 | } |
460 | } |
461 | 461 | ||
462 | 462 | ||
463 | 463 | ||
464 | /* |
464 | /* |
465 | * To handle the "." command, a stack of input files is used. Pushfile |
465 | * To handle the "." command, a stack of input files is used. Pushfile |
466 | * adds a new entry to the stack and popfile restores the previous level. |
466 | * adds a new entry to the stack and popfile restores the previous level. |
467 | */ |
467 | */ |
468 | 468 | ||
469 | STATIC void |
469 | STATIC void |
470 | pushfile() { |
470 | pushfile() { |
471 | struct parsefile *pf; |
471 | struct parsefile *pf; |
472 | 472 | ||
473 | parsefile->nleft = parsenleft; |
473 | parsefile->nleft = parsenleft; |
474 | parsefile->lleft = parselleft; |
474 | parsefile->lleft = parselleft; |
475 | parsefile->nextc = parsenextc; |
475 | parsefile->nextc = parsenextc; |
476 | parsefile->linno = plinno; |
476 | parsefile->linno = plinno; |
477 | pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); |
477 | pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); |
478 | pf->prev = parsefile; |
478 | pf->prev = parsefile; |
479 | pf->fd = -1; |
479 | pf->fd = -1; |
480 | pf->strpush = NULL; |
480 | pf->strpush = NULL; |
481 | pf->basestrpush.prev = NULL; |
481 | pf->basestrpush.prev = NULL; |
482 | parsefile = pf; |
482 | parsefile = pf; |
483 | } |
483 | } |
484 | 484 | ||
485 | 485 | ||
486 | void |
486 | void |
487 | popfile() { |
487 | popfile() { |
488 | struct parsefile *pf = parsefile; |
488 | struct parsefile *pf = parsefile; |
489 | 489 | ||
490 | INTOFF; |
490 | INTOFF; |
491 | if (pf->fd >= 0) |
491 | if (pf->fd >= 0) |
492 | close(pf->fd); |
492 | close(pf->fd); |
493 | if (pf->buf) |
493 | if (pf->buf) |
494 | ckfree(pf->buf); |
494 | ckfree(pf->buf); |
495 | while (pf->strpush) |
495 | while (pf->strpush) |
496 | popstring(); |
496 | popstring(); |
497 | parsefile = pf->prev; |
497 | parsefile = pf->prev; |
498 | ckfree(pf); |
498 | ckfree(pf); |
499 | parsenleft = parsefile->nleft; |
499 | parsenleft = parsefile->nleft; |
500 | parselleft = parsefile->lleft; |
500 | parselleft = parsefile->lleft; |
501 | parsenextc = parsefile->nextc; |
501 | parsenextc = parsefile->nextc; |
502 | plinno = parsefile->linno; |
502 | plinno = parsefile->linno; |
503 | INTON; |
503 | INTON; |
504 | } |
504 | } |
505 | 505 | ||
506 | 506 | ||
507 | /* |
507 | /* |
508 | * Return to top level. |
508 | * Return to top level. |
509 | */ |
509 | */ |
510 | 510 | ||
511 | void |
511 | void |
512 | popallfiles() { |
512 | popallfiles() { |
513 | while (parsefile != &basepf) |
513 | while (parsefile != &basepf) |
514 | popfile(); |
514 | popfile(); |
515 | } |
515 | } |
516 | 516 | ||
517 | 517 | ||
518 | 518 | ||
519 | /* |
519 | /* |
520 | * Close the file(s) that the shell is reading commands from. Called |
520 | * Close the file(s) that the shell is reading commands from. Called |
521 | * after a fork is done. |
521 | * after a fork is done. |
522 | */ |
522 | */ |
523 | 523 | ||
524 | void |
524 | void |
525 | closescript() { |
525 | closescript() { |
526 | popallfiles(); |
526 | popallfiles(); |
527 | if (parsefile->fd > 0) { |
527 | if (parsefile->fd > 0) { |
528 | close(parsefile->fd); |
528 | close(parsefile->fd); |
529 | parsefile->fd = 0; |
529 | parsefile->fd = 0; |
530 | } |
530 | } |
531 | } |
531 | } |
532 | 532 |