1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23 /*
24 * Copyright 2000 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30
31 /*
32 * UNIX shell
33 */
34
35 #include "defs.h"
36 #include "sym.h"
37 #include <errno.h>
38 #include <fcntl.h>
39
40 static int readb(struct fileblk *, int, int);
41
42 /* ======== character handling for command lines ======== */
43
44 int
word(void)45 word(void)
46 {
47 unsigned int c, d, cc;
48 struct argnod *arg = (struct argnod *)locstak();
49 unsigned char *argp = arg->argval;
50 unsigned char *oldargp;
51 int alpha = 1;
52 unsigned char *pc;
53
54 wdnum = 0;
55 wdset = 0;
56
57 while (1)
58 {
59 while (c = nextwc(), space(c)) /* skipc() */
60 ;
61
62 if (c == COMCHAR)
63 {
64 while ((c = readwc()) != NL && c != EOF);
65 peekc = c;
66 }
67 else
68 {
69 break; /* out of comment - white space loop */
70 }
71 }
72 if (!eofmeta(c))
73 {
74 do
75 {
76 if (c == LITERAL)
77 {
78 oldargp = argp;
79 while ((c = readwc()) && c != LITERAL){
80 /*
81 * quote each character within
82 * single quotes
83 */
84 pc = readw(c);
85 if (argp >= brkend)
86 growstak(argp);
87 *argp++='\\';
88 /* Pick up rest of multibyte character */
89 if (c == NL)
90 chkpr();
91 while (c = *pc++) {
92 if (argp >= brkend)
93 growstak(argp);
94 *argp++ = (unsigned char)c;
95 }
96 }
97 if (argp == oldargp) { /* null argument - '' */
98 /*
99 * Word will be represented by quoted null
100 * in macro.c if necessary
101 */
102 if (argp >= brkend)
103 growstak(argp);
104 *argp++ = '"';
105 if (argp >= brkend)
106 growstak(argp);
107 *argp++ = '"';
108 }
109 }
110 else
111 {
112 if (c == 0) {
113 if (argp >= brkend)
114 growstak(argp);
115 *argp++ = 0;
116 } else {
117 pc = readw(c);
118 while (*pc) {
119 if (argp >= brkend)
120 growstak(argp);
121 *argp++ = *pc++;
122 }
123 }
124 if (c == '\\') {
125 if ((cc = readwc()) == 0) {
126 if (argp >= brkend)
127 growstak(argp);
128 *argp++ = 0;
129 } else {
130 pc = readw(cc);
131 while (*pc) {
132 if (argp >= brkend)
133 growstak(argp);
134 *argp++ = *pc++;
135 }
136 }
137 }
138 if (c == '=')
139 wdset |= alpha;
140 if (!alphanum(c))
141 alpha = 0;
142 if (qotchar(c))
143 {
144 d = c;
145 for (;;)
146 {
147 if ((c = nextwc()) == 0) {
148 if (argp >= brkend)
149 growstak(argp);
150 *argp++ = 0;
151 } else {
152 pc = readw(c);
153 while (*pc) {
154 if (argp >= brkend)
155 growstak(argp);
156 *argp++ = *pc++;
157 }
158 }
159 if (c == 0 || c == d)
160 break;
161 if (c == NL)
162 chkpr();
163 /*
164 * don't interpret quoted
165 * characters
166 */
167 if (c == '\\') {
168 if ((cc = readwc()) == 0) {
169 if (argp >= brkend)
170 growstak(argp);
171 *argp++ = 0;
172 } else {
173 pc = readw(cc);
174 while (*pc) {
175 if (argp >= brkend)
176 growstak(argp);
177 *argp++ = *pc++;
178 }
179 }
180 }
181 }
182 }
183 }
184 } while ((c = nextwc(), !eofmeta(c)));
185 argp = endstak(argp);
186 if (!letter(arg->argval[0]))
187 wdset = 0;
188
189 peekn = c | MARK;
190 if (arg->argval[1] == 0 &&
191 (d = arg->argval[0], digit(d)) &&
192 (c == '>' || c == '<'))
193 {
194 word();
195 wdnum = d - '0';
196 }else{ /* check for reserved words */
197 if (reserv == FALSE ||
198 (wdval = syslook(arg->argval,
199 reserved, no_reserved)) == 0) {
200 wdval = 0;
201 }
202 /* set arg for reserved words too */
203 wdarg = arg;
204 }
205 }else if (dipchar(c)){
206 if ((d = nextwc()) == c)
207 {
208 wdval = c | SYMREP;
209 if (c == '<')
210 {
211 if ((d = nextwc()) == '-')
212 wdnum |= IOSTRIP;
213 else
214 peekn = d | MARK;
215 }
216 }
217 else
218 {
219 peekn = d | MARK;
220 wdval = c;
221 }
222 }
223 else
224 {
225 if ((wdval = c) == EOF)
226 wdval = EOFSYM;
227 if (iopend && eolchar(c))
228 {
229 struct ionod *tmp_iopend;
230 tmp_iopend = iopend;
231 iopend = 0;
232 copy(tmp_iopend);
233 }
234 }
235 reserv = FALSE;
236 return (wdval);
237 }
238
skipwc()239 unsigned int skipwc()
240 {
241 unsigned int c;
242
243 while (c = nextwc(), space(c))
244 ;
245 return (c);
246 }
247
nextwc()248 unsigned int nextwc()
249 {
250 unsigned int c, d;
251
252 retry:
253 if ((d = readwc()) == ESCAPE) {
254 if ((c = readwc()) == NL) {
255 chkpr();
256 goto retry;
257 }
258 peekc = c | MARK;
259 }
260 return (d);
261 }
262
readw(d)263 unsigned char *readw(d)
264 wchar_t d;
265 {
266 static unsigned char c[MULTI_BYTE_MAX + 1];
267 int length;
268 wchar_t l;
269 if (isascii(d)) {
270 c[0] = d;
271 c[1] = '\0';
272 return (c);
273 }
274
275 length = wctomb((char *)c, d);
276 if (length <= 0) {
277 c[0] = (unsigned char)d;
278 length = 1;
279 }
280 c[length] = '\0';
281 return (c);
282 }
283
284 unsigned int
readwc()285 readwc()
286 {
287 wchar_t c;
288 int len;
289 struct fileblk *f;
290 int mbmax = MB_CUR_MAX;
291 int i, mlen;
292
293 if (peekn) {
294 c = peekn & 0x7fffffff;
295 peekn = 0;
296 return (c);
297 }
298 if (peekc) {
299 c = peekc & 0x7fffffff;
300 peekc = 0;
301 return (c);
302 }
303 f = standin;
304
305 retry:
306 if (f->fend > f->fnxt) {
307 /*
308 * something in buffer
309 */
310 if (*f->fnxt == 0) {
311 f->fnxt++;
312 f->nxtoff++;
313 if (f->feval == 0)
314 goto retry; /* = c = readc(); */
315 if (estabf(*f->feval++))
316 c = EOF;
317 else
318 c = SPACE;
319 if (flags & readpr && standin->fstak == 0)
320 prc(c);
321 if (c == NL)
322 f->flin++;
323 return (c);
324 }
325
326 if (isascii(c = (unsigned char)*f->fnxt)) {
327 f->fnxt++;
328 f->nxtoff++;
329 if (flags & readpr && standin->fstak == 0)
330 prc(c);
331 if (c == NL)
332 f->flin++;
333 return (c);
334 }
335
336 for (i = 1; i <= mbmax; i++) {
337 int rest;
338 if ((rest = f->fend - f->fnxt) < i) {
339 /*
340 * not enough bytes available
341 * f->fsiz could be BUFFERSIZE or 1
342 * since mbmax is enough smaller than BUFFERSIZE,
343 * this loop won't overrun the f->fbuf buffer.
344 */
345 len = readb(f,
346 (f->fsiz == 1) ? 1 : (f->fsiz - rest),
347 rest);
348 if (len == 0)
349 break;
350 }
351 mlen = mbtowc(&c, (char *)f->fnxt, i);
352 if (mlen > 0)
353 break;
354 }
355
356 if (i > mbmax) {
357 /*
358 * enough bytes available but cannot be converted to
359 * a valid wchar.
360 */
361 c = (unsigned char)*f->fnxt;
362 mlen = 1;
363 }
364
365 f->fnxt += mlen;
366 f->nxtoff += mlen;
367 if (flags & readpr && standin->fstak == 0)
368 prwc(c);
369 if (c == NL)
370 f->flin++;
371 return (c);
372 }
373
374 if (f->feof || f->fdes < 0){
375 c = EOF;
376 f->feof++;
377 return (c);
378 }
379
380 if (readb(f, f->fsiz, 0) <= 0){
381 if (f->fdes != input || !isatty(input)) {
382 close(f->fdes);
383 f->fdes = -1;
384 }
385 f->feof++;
386 c = EOF;
387 return (c);
388 }
389 goto retry;
390 }
391
392 static int
readb(struct fileblk * f,int toread,int rest)393 readb(struct fileblk *f, int toread, int rest)
394 {
395 int len;
396 int fflags;
397
398 if (rest) {
399 /*
400 * copies the remaining 'rest' bytes from f->fnxt
401 * to f->fbuf
402 */
403 (void) memcpy(f->fbuf, f->fnxt, rest);
404 f->fnxt = f->fbuf;
405 f->fend = f->fnxt + rest;
406 f->nxtoff = 0;
407 f->endoff = rest;
408 if (f->fbuf[rest - 1] == '\n') {
409 /*
410 * if '\n' found, it should be
411 * a bondary of multibyte char.
412 */
413 return (rest);
414 }
415 }
416
417 retry:
418 do {
419 if (trapnote & SIGSET) {
420 newline();
421 sigchk();
422 } else if ((trapnote & TRAPSET) && (rwait > 0)) {
423 newline();
424 chktrap();
425 clearup();
426 }
427 } while ((len = read(f->fdes, f->fbuf + rest, toread)) < 0 && trapnote);
428 /*
429 * if child sets O_NDELAY or O_NONBLOCK on stdin
430 * and exited then turn the modes off and retry
431 */
432 if (len == 0) {
433 if (((flags & intflg) ||
434 ((flags & oneflg) == 0 && isatty(input) &&
435 (flags & stdflg))) &&
436 ((fflags = fcntl(f->fdes, F_GETFL, 0)) & O_NDELAY)) {
437 fflags &= ~O_NDELAY;
438 fcntl(f->fdes, F_SETFL, fflags);
439 goto retry;
440 }
441 } else if (len < 0) {
442 if (errno == EAGAIN) {
443 fflags = fcntl(f->fdes, F_GETFL, 0);
444 fflags &= ~O_NONBLOCK;
445 fcntl(f->fdes, F_SETFL, fflags);
446 goto retry;
447 }
448 len = 0;
449 }
450 f->fnxt = f->fbuf;
451 f->fend = f->fnxt + (len + rest);
452 f->nxtoff = 0;
453 f->endoff = len + rest;
454 return (len + rest);
455 }
456