4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
29 #pragma ident "%Z%%M% %I% %E% SMI"
38 static unsigned char quote
; /* used locally */
39 static unsigned char quoted
; /* used locally */
41 static void comsubst(int);
42 static void flush(int);
45 copyto(unsigned char endch
, int trimflag
)
46 /* trimflag - flag to check if argument will be trimmed */
52 while ((c
= getch(endch
, trimflag
)) != endch
&& c
)
54 if(c
== '\\') { /* don't interpret next character */
55 if (staktop
>= brkend
)
59 if(!escchar(d
)) { /* both \ and following
60 character are quoted if next
61 character is not $, `, ", or \*/
62 if (staktop
>= brkend
)
65 if (staktop
>= brkend
)
69 /* push entire multibyte char */
71 if (staktop
>= brkend
)
78 /* Evenif d is NULL, we have to save it */
81 if (staktop
>= brkend
)
86 if (staktop
>= brkend
)
91 } else { /* push escapes onto stack to quote characters */
93 if (staktop
>= brkend
)
97 if (staktop
>= brkend
)
102 } else if(c
== '\\') {
103 c
= readwc(); /* get character to be escaped */
104 if (staktop
>= brkend
)
108 /* c might be NULL */
109 /* Evenif c is NULL, we have to save it */
112 if (staktop
>= brkend
)
117 if (staktop
>= brkend
)
124 if (staktop
>= brkend
)
129 if (staktop
>= brkend
)
137 skipto(unsigned char endch
)
144 while ((c
= readwc()) && c
!= endch
)
157 if (readwc() == BRACE
)
166 int getch(endch
, trimflag
)
168 int trimflag
; /* flag to check if an argument is going to be trimmed, here document
169 output is never trimmed
173 int atflag
; /* flag to check if $@ has already been seen within double
184 if ((c
= readwc(), dolchar(c
)))
186 struct namnod
*n
= (struct namnod
*)NIL
;
190 unsigned char *argp
, *v
;
191 unsigned char idb
[2];
192 unsigned char *id
= idb
;
194 if (bra
= (c
== BRACE
))
198 argp
= (unsigned char *)relstak();
201 if (staktop
>= brkend
)
206 if (staktop
>= brkend
)
209 n
= lookup(absstak(argp
));
211 if (n
->namflg
& N_FUNCTN
)
214 id
= (unsigned char *)n
->namid
;
223 if(c
== '@' && !atflag
&& quote
) {
231 v
= ((c
== 0) ? cmdadr
: ((int)c
<= dolc
) ? dolv
[c
] : (unsigned char *)(dolg
= 0));
254 if (c
== ':' && bra
) /* null and unset fix */
261 if (!defchar(c
) && bra
)
268 argp
= (unsigned char *)relstak();
269 if ((v
== 0 || (nulflg
&& *v
== 0)) ^ (setchar(c
)))
270 copyto('}', trimflag
);
273 argp
= absstak(argp
);
281 if (v
&& (!nulflg
|| *v
))
288 if (*v
== 0 && quote
) {
289 if (staktop
>= brkend
)
292 if (staktop
>= brkend
)
299 if ((length
= mbtowc(&wc
, (char *)v
, MB_LEN_MAX
)) <= 0)
302 if(quote
|| (c
== '\\' && trimflag
)) {
303 if (staktop
>= brkend
)
307 while(length
-- > 0) {
308 if (staktop
>= brkend
)
315 if (dolg
== 0 || (++dolg
> dolc
))
317 else /* $* and $@ expansion */
320 if(*id
== '*' && quote
) {
321 /* push quoted space so that " $* " will not be broken into separate arguments */
322 if (staktop
>= brkend
)
326 if (staktop
>= brkend
)
338 failed(id
, *argp
? (const char *)argp
:
345 int strlngth
= staktop
- stakbot
;
346 unsigned char *savptr
= fixstak();
347 unsigned char *newargp
;
349 * copy word onto stack, trim it, and then
357 if ((len
= mbtowc(&wc
, (char *)argp
, MB_LEN_MAX
)) <= 0)
360 if(c
== '\\' && trimflag
) {
366 if ((len
= mbtowc(&wc
, (char *)argp
, MB_LEN_MAX
)) <= 0)
370 if (staktop
>= brkend
)
378 (void) memcpystak(stakbot
, savptr
, strlngth
);
379 staktop
= stakbot
+ strlngth
;
385 else if (flags
& setflg
)
394 else if (d
== SQUOTE
)
399 else if (d
== DQUOTE
&& trimflag
)
416 * Strip "" and do $ substitution
417 * Leaves result on top of stack
420 unsigned char savq
= quote
;
430 if (quoted
&& (stakbot
== staktop
)) {
431 if (staktop
>= brkend
)
434 if (staktop
>= brkend
)
438 * above is the fix for *'.c' bug
445 /* Save file descriptor for command substitution */
449 comsubst(int trimflag
)
450 /* trimflag - used to determine if argument will later be trimmed */
457 int strlngth
= staktop
- stakbot
;
458 unsigned char *oldstaktop
;
459 unsigned char *savptr
= fixstak();
463 while ((d
= readwc()) != SQUOTE
&& d
) {
466 if(!escchar(d
) || (d
== '"' && !quote
)) {
467 /* trim quotes for `, \, or " if command substitution is within
469 if (staktop
>= brkend
)
475 /* d might be NULL */
478 if (staktop
>= brkend
)
483 if (staktop
>= brkend
)
493 estabf(argc
); /* read from string */
500 * this is done like this so that the pipe
501 * is open only when needed
503 t
= makefork(FPOU
, cmd(EOFSYM
, MTFLG
| NLFLG
));
505 savpipe
= pv
[OTPIPE
];
506 initf(pv
[INPIPE
]); /* read from pipe */
507 execute(t
, XEC_NOSTOP
, (int)(flags
& errflg
), 0, pv
);
512 (void) memcpystak(stakbot
, savptr
, strlngth
);
513 oldstaktop
= staktop
= stakbot
+ strlngth
;
514 while (d
= readwc()) {
515 if(quote
|| (d
== '\\' && trimflag
)) {
517 /* quote output from command subst. if within double
518 quotes or backslash part of output */
520 if (staktop
>= brkend
)
524 /* Pick up all of multibyte character */
525 if (staktop
>= brkend
)
533 if (staktop
>= brkend
)
545 while ((ret
= waitpid(parent
,&stat
,0)) != parent
) {
546 /* break out if waitpid(2) has failed */
551 rc
= WEXITSTATUS(stat
);
553 rc
= (WTERMSIG(stat
) | SIGFLG
);
554 if (rc
&& (flags
& errflg
))
560 while (oldstaktop
!= staktop
)
561 { /* strip off trailing newlines from command substitution only */
562 if ((*--staktop
) != NL
)
567 staktop
--; /* skip past backslashes if quoting */
575 subst(int in
, int ot
)
585 * DQUOTE used to stop it from quoting
587 while (c
= (getch(DQUOTE
, 0))) /* read characters from here document
588 and interpret them */
591 c
= readwc(); /* check if character in here document is
593 if(!escchar(c
) || c
== '"') {
594 if (staktop
>= brkend
)
600 /* c might be NULL */
603 if (staktop
>= brkend
)
608 if (staktop
>= brkend
)
625 write(ot
, stakbot
, staktop
- stakbot
);
627 write(output
, stakbot
, staktop
- stakbot
);