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