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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
41 #include <sys/types.h>
42 #include <sys/times.h>
46 void execprint(unsigned char **);
48 /* ======== command execution ======== */
52 execute(argt
, xflags
, errorflg
, pf1
, pf2
)
58 * `stakbot' is preserved by this routine
61 unsigned char *sav
= savstak();
67 if ((t
= argt
) && execbrk
== 0) {
74 type
= treeflgs
& COMMSK
;
80 struct fndnod
*f
= fndptr(t
);
81 struct namnod
*n
= lookup(f
->fndnam
);
85 if (n
->namflg
& N_RDONLY
)
86 failed(n
->namid
, wtfailed
);
88 if (flags
& rshflg
&& (n
== &pathnod
||
89 eq(n
->namid
, "SHELL")))
90 failed(n
->namid
, restricted
);
92 * If function of same name is previously
93 * defined, it will no longer be used.
95 if (n
->namflg
& N_FUNCTN
) {
102 n
->namflg
&= ~(N_EXPORT
| N_ENVCHG
);
105 * If function is defined within function,
106 * we don't want to free it along with the
107 * free of the defining function. If we are
108 * in a loop, fndnod may be reused, so it
109 * should never be freed.
111 if (funcnt
!= 0 || loopcnt
!= 0)
115 * We hang a fndnod on the namenv so that
116 * ref cnt(fndref) can be increased while
117 * running in the function.
119 n
->namenv
= (unsigned char *)f
;
127 unsigned char *a1
, *name
;
129 struct argnod
*schain
= gchain
;
130 struct ionod
*io
= t
->treio
;
143 cmdhash
= pathlook(com
[0], 1, comptr(t
)->comset
);
145 if (argn
== 0 || (comtype
= hashtype(cmdhash
)) == BUILTIN
) {
146 setlist(comptr(t
)->comset
, 0);
149 if (argn
&& (flags
&noexec
) == 0)
152 /* print command if execpr */
156 if (comtype
== NOTFOUND
)
158 pos
= hashdata(cmdhash
);
160 failure(*com
, notfound
);
162 failure(*com
, badexec
);
164 failure(*com
, badperm
);
168 else if (comtype
== PATH_COMMAND
)
173 else if (comtype
& (COMMAND
| REL_COMMAND
))
175 pos
= hashdata(cmdhash
);
178 else if (comtype
== BUILTIN
) {
179 builtin(hashdata(cmdhash
),argn
,com
,t
);
183 else if (comtype
== FUNCTION
)
185 struct dolnod
*olddolh
;
186 struct namnod
*n
, *opt
;
189 unsigned char **olddolv
= dolv
;
193 f
= fndptr(n
->namenv
);
197 /* save current positional parameters */
198 olddolh
= (struct dolnod
*)savargs(funcnt
);
201 index
= initio(io
, 1);
203 execute(f
->fndval
, xflags
,
207 (void) restorargs(olddolh
, funcnt
);
212 * n->namenv may have been
213 * pointing different func.
214 * Therefore, we can't use
217 freetree((struct trenod
*)f
);
222 else if (t
->treio
== 0)
237 if (!(xflags
& XEC_EXECED
) || treeflgs
&(FPOU
|FAMP
))
242 if (!(treeflgs
&FPOU
))
244 monitor
= (!(xflags
& XEC_NOSTOP
)
245 && (flags
&(monitorflg
|jcflg
|jcoff
))
246 == (monitorflg
|jcflg
));
249 unsigned char *savebot
;
254 allocjob(savebot
, cwdget(), monitor
);
260 if (treeflgs
& (FPOU
|FAMP
)) {
265 while ((parent
= fork()) == -1)
268 * FORKLIM is the max period between forks -
269 * power of 2 usually. Currently shell tries
270 * after 2,4,8,16, and 32 seconds and then quits
273 if ((forkcnt
= (forkcnt
* 2)) > FORKLIM
)
286 } else if (errno
== EPERM
) {
300 if (!(treeflgs
&FPOU
)) {
301 postjob(parent
,!(treeflgs
&FAMP
));
311 * Forked process: assume it is not a subshell for
312 * now. If it is, the presence of a left parenthesis
313 * will trigger the jcoff flag to be turned off.
314 * When jcoff is turned on, monitoring is not going on
315 * and waitpid will not look for WUNTRACED.
318 flags
|= (forked
|jcoff
);
323 swap_iodoc_nm(iotemp
);
324 xflags
|= XEC_LINKED
;
325 } else if (!(xflags
& XEC_LINKED
))
333 if (!(treeflgs
& FPOU
))
334 makejob(monitor
, !(treeflgs
& FAMP
));
341 renamef(pf1
[INPIPE
], 0);
348 renamef(pf2
[OTPIPE
], 1);
357 execute(forkptr(t
)->forktre
, xflags
| XEC_EXECED
, errorflg
);
358 else if (com
[0] != ENDARGS
)
361 setlist(comptr(t
)->comset
, N_EXPORT
);
370 /* Forked process is subshell: may want job control */
373 execute(parptr(t
)->partre
, xflags
, errorflg
);
381 if (execute(lstptr(t
)->lstlef
, xflags
& XEC_NOSTOP
, errorflg
, pf1
, pv
) == 0)
382 execute(lstptr(t
)->lstrit
, xflags
, errorflg
, pv
, pf2
);
389 execute(lstptr(t
)->lstlef
, xflags
&XEC_NOSTOP
, errorflg
);
390 /* Update errorflg if set -e is invoked in the sub-sh*/
391 execute(lstptr(t
)->lstrit
, xflags
, (errorflg
| (eflag
& errflg
)));
398 xval
= execute(lstptr(t
)->lstlef
, XEC_NOSTOP
, 0);
399 if ((xval
== 0) == (type
== TAND
))
400 execute(lstptr(t
)->lstrit
, xflags
|XEC_NOSTOP
, errorflg
);
406 struct namnod
*n
= lookup(forptr(t
)->fornam
);
407 unsigned char **args
;
408 struct dolnod
*argsav
= 0;
410 if (forptr(t
)->forlst
== 0)
417 struct argnod
*schain
= gchain
;
420 args
= scan(getarg(forptr(t
)->forlst
));
424 while (*args
!= ENDARGS
&& execbrk
== 0)
427 execute(forptr(t
)->fortre
, XEC_NOSTOP
, errorflg
);
429 execbrk
= (++breakcnt
!= 0);
432 execbrk
= (--breakcnt
!= 0);
436 argfor
= (struct dolnod
*)freeargs(argsav
);
446 while (execbrk
== 0 && (execute(whptr(t
)->whtre
,
447 XEC_NOSTOP
, 0) == 0) == (type
== TWH
) &&
450 i
= execute(whptr(t
)->dotre
, XEC_NOSTOP
, errorflg
);
452 execbrk
= (++breakcnt
!= 0);
455 execbrk
= (--breakcnt
!= 0);
463 if (execute(ifptr(t
)->iftre
, XEC_NOSTOP
, 0) == 0)
464 execute(ifptr(t
)->thtre
, xflags
|XEC_NOSTOP
, errorflg
);
465 else if (ifptr(t
)->eltre
)
466 execute(ifptr(t
)->eltre
, xflags
|XEC_NOSTOP
, errorflg
);
468 exitval
= 0; /* force zero exit for if-then-fi */
473 unsigned char *r
= mactrim(swptr(t
)->swarg
);
476 regp
= swptr(t
)->swlst
;
479 struct argnod
*rex
= regp
->regptr
;
485 if (gmatch(r
, s
= macro(rex
->argval
)) || (trim(s
), eq(r
, s
)))
487 execute(regp
->regcom
, XEC_NOSTOP
, errorflg
);
509 execexp(unsigned char *s
, int f
)
517 fb
.feval
= (unsigned char **)(f
);
521 execute(cmd(NL
, NLFLG
| MTFLG
), 0, (int)(flags
& errflg
));
526 execprint(unsigned char **com
)
531 prs(_gettext(execpmsg
));
532 while(com
[argn
] != ENDARGS
)
535 write(output
, s
, length(s
) - 1);