8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / sh / xec.c
blob2d3d6ebaf32b8615c29efb1efa501f86b78e5fd0
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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 */
32 * UNIX shell
37 #include "defs.h"
38 #include <errno.h>
39 #include "sym.h"
40 #include "hash.h"
41 #include <sys/types.h>
42 #include <sys/times.h>
44 pid_t parent;
46 void execprint(unsigned char **);
48 /* ======== command execution ======== */
50 /*VARARGS3*/
51 int
52 execute(argt, xflags, errorflg, pf1, pf2)
53 struct trenod *argt;
54 int xflags, errorflg;
55 int *pf1, *pf2;
58 * `stakbot' is preserved by this routine
60 struct trenod *t;
61 unsigned char *sav = savstak();
63 sigchk();
64 if (!errorflg)
65 flags &= ~errflg;
67 if ((t = argt) && execbrk == 0) {
68 int treeflgs;
69 unsigned char **com;
70 int type;
71 short pos;
73 treeflgs = t->tretyp;
74 type = treeflgs & COMMSK;
76 switch (type)
78 case TFND:
80 struct fndnod *f = fndptr(t);
81 struct namnod *n = lookup(f->fndnam);
83 exitval = 0;
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) {
96 freefunc(n);
97 } else {
98 free(n->namval);
99 free(n->namenv);
101 n->namval = 0;
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)
112 f->fndref++;
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;
120 attrib(n, N_FUNCTN);
121 hash_func(n->namid);
122 break;
125 case TCOM:
127 unsigned char *a1, *name;
128 int argn, internal;
129 struct argnod *schain = gchain;
130 struct ionod *io = t->treio;
131 short cmdhash;
132 short comtype;
134 exitval = 0;
136 gchain = 0;
137 argn = getarg(t);
138 com = scan(argn);
139 a1 = com[1];
140 gchain = schain;
142 if (argn != 0)
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 */
153 if (flags & execpr)
154 execprint(com);
156 if (comtype == NOTFOUND)
158 pos = hashdata(cmdhash);
159 if (pos == 1)
160 failure(*com, notfound);
161 else if (pos == 2)
162 failure(*com, badexec);
163 else
164 failure(*com, badperm);
165 break;
168 else if (comtype == PATH_COMMAND)
170 pos = -1;
173 else if (comtype & (COMMAND | REL_COMMAND))
175 pos = hashdata(cmdhash);
178 else if (comtype == BUILTIN) {
179 builtin(hashdata(cmdhash),argn,com,t);
180 freejobs();
181 break;
183 else if (comtype == FUNCTION)
185 struct dolnod *olddolh;
186 struct namnod *n, *opt;
187 struct fndnod *f;
188 short index;
189 unsigned char **olddolv = dolv;
190 int olddolc = dolc;
192 n = findnam(com[0]);
193 f = fndptr(n->namenv);
194 /* just in case */
195 if (f == NULL)
196 break;
197 /* save current positional parameters */
198 olddolh = (struct dolnod *)savargs(funcnt);
199 f->fndref++;
200 funcnt++;
201 index = initio(io, 1);
202 setargs(com);
203 execute(f->fndval, xflags,
204 errorflg, pf1, pf2);
205 execbrk = 0;
206 restore(index);
207 (void) restorargs(olddolh, funcnt);
208 dolv = olddolv;
209 dolc = olddolc;
210 funcnt--;
212 * n->namenv may have been
213 * pointing different func.
214 * Therefore, we can't use
215 * freefunc(n).
217 freetree((struct trenod *)f);
219 break;
222 else if (t->treio == 0)
224 chktrap();
225 break;
230 case TFORK:
232 int monitor = 0;
233 int linked = 0;
235 exitval = 0;
237 if (!(xflags & XEC_EXECED) || treeflgs&(FPOU|FAMP))
240 int forkcnt = 1;
242 if (!(treeflgs&FPOU))
244 monitor = (!(xflags & XEC_NOSTOP)
245 && (flags&(monitorflg|jcflg|jcoff))
246 == (monitorflg|jcflg));
247 if (monitor) {
248 int savefd;
249 unsigned char *savebot;
250 savefd = setb(-1);
251 savebot = stakbot;
252 prcmd(t);
253 (void)setb(savefd);
254 allocjob(savebot, cwdget(), monitor);
255 } else
256 allocjob("", "", 0);
260 if (treeflgs & (FPOU|FAMP)) {
261 link_iodocs(iotemp);
262 linked = 1;
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)
275 switch (errno)
277 case ENOMEM:
278 deallocjob();
279 error(noswap);
280 break;
281 default:
282 deallocjob();
283 error(nofork);
284 break;
286 } else if (errno == EPERM) {
287 deallocjob();
288 error(eacces);
289 break;
291 sigchk();
292 sh_sleep(forkcnt);
295 if (parent) {
296 if (monitor)
297 setpgid(parent, 0);
298 if (treeflgs & FPIN)
299 closepipe(pf1);
300 if (!(treeflgs&FPOU)) {
301 postjob(parent,!(treeflgs&FAMP));
302 freejobs();
304 chktrap();
305 break;
307 mypid = getpid();
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);
320 fiotemp = 0;
322 if (linked == 1) {
323 swap_iodoc_nm(iotemp);
324 xflags |= XEC_LINKED;
325 } else if (!(xflags & XEC_LINKED))
326 iotemp = 0;
327 #ifdef ACCT
328 suspacct();
329 #endif
330 settmp();
331 oldsigs();
333 if (!(treeflgs & FPOU))
334 makejob(monitor, !(treeflgs & FAMP));
337 * pipe in or out
339 if (treeflgs & FPIN)
341 renamef(pf1[INPIPE], 0);
342 close(pf1[OTPIPE]);
345 if (treeflgs & FPOU)
347 close(pf2[INPIPE]);
348 renamef(pf2[OTPIPE], 1);
352 * io redirection
354 initio(t->treio, 0);
356 if (type == TFORK)
357 execute(forkptr(t)->forktre, xflags | XEC_EXECED, errorflg);
358 else if (com[0] != ENDARGS)
360 eflag = 0;
361 setlist(comptr(t)->comset, N_EXPORT);
362 rmtemp(0);
363 clearjobs();
364 execa(com, pos);
366 done(0);
369 case TPAR:
370 /* Forked process is subshell: may want job control */
371 flags &= ~jcoff;
372 clearjobs();
373 execute(parptr(t)->partre, xflags, errorflg);
374 done(0);
376 case TFIL:
378 int pv[2];
380 chkpipe(pv);
381 if (execute(lstptr(t)->lstlef, xflags & XEC_NOSTOP, errorflg, pf1, pv) == 0)
382 execute(lstptr(t)->lstrit, xflags, errorflg, pv, pf2);
383 else
384 closepipe(pv);
386 break;
388 case TLST:
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)));
392 break;
394 case TAND:
395 case TORF:
397 int xval;
398 xval = execute(lstptr(t)->lstlef, XEC_NOSTOP, 0);
399 if ((xval == 0) == (type == TAND))
400 execute(lstptr(t)->lstrit, xflags|XEC_NOSTOP, errorflg);
401 break;
404 case TFOR:
406 struct namnod *n = lookup(forptr(t)->fornam);
407 unsigned char **args;
408 struct dolnod *argsav = 0;
410 if (forptr(t)->forlst == 0)
412 args = dolv + 1;
413 argsav = useargs();
415 else
417 struct argnod *schain = gchain;
419 gchain = 0;
420 args = scan(getarg(forptr(t)->forlst));
421 gchain = schain;
423 loopcnt++;
424 while (*args != ENDARGS && execbrk == 0)
426 assign(n, *args++);
427 execute(forptr(t)->fortre, XEC_NOSTOP, errorflg);
428 if (breakcnt < 0)
429 execbrk = (++breakcnt != 0);
431 if (breakcnt > 0)
432 execbrk = (--breakcnt != 0);
434 loopcnt--;
435 if(argsav)
436 argfor = (struct dolnod *)freeargs(argsav);
438 break;
440 case TWH:
441 case TUN:
443 int i = 0;
445 loopcnt++;
446 while (execbrk == 0 && (execute(whptr(t)->whtre,
447 XEC_NOSTOP, 0) == 0) == (type == TWH) &&
448 (flags&noexec) == 0)
450 i = execute(whptr(t)->dotre, XEC_NOSTOP, errorflg);
451 if (breakcnt < 0)
452 execbrk = (++breakcnt != 0);
454 if (breakcnt > 0)
455 execbrk = (--breakcnt != 0);
457 loopcnt--;
458 exitval = i;
460 break;
462 case TIF:
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);
467 else
468 exitval = 0; /* force zero exit for if-then-fi */
469 break;
471 case TSW:
473 unsigned char *r = mactrim(swptr(t)->swarg);
474 struct regnod *regp;
476 regp = swptr(t)->swlst;
477 while (regp)
479 struct argnod *rex = regp->regptr;
481 while (rex)
483 unsigned char *s;
485 if (gmatch(r, s = macro(rex->argval)) || (trim(s), eq(r, s)))
487 execute(regp->regcom, XEC_NOSTOP, errorflg);
488 regp = 0;
489 break;
491 else
492 rex = rex->argnxt;
494 if (regp)
495 regp = regp->regnxt;
498 break;
500 exitset();
502 sigchk();
503 tdystak(sav);
504 flags |= eflag;
505 return(exitval);
508 void
509 execexp(unsigned char *s, int f)
511 struct fileblk fb;
513 push(&fb);
514 if (s)
516 estabf(s);
517 fb.feval = (unsigned char **)(f);
519 else if (f >= 0)
520 initf(f);
521 execute(cmd(NL, NLFLG | MTFLG), 0, (int)(flags & errflg));
522 pop();
525 void
526 execprint(unsigned char **com)
528 int argn = 0;
529 unsigned char *s;
531 prs(_gettext(execpmsg));
532 while(com[argn] != ENDARGS)
534 s = com[argn++];
535 write(output, s, length(s) - 1);
536 blank();
539 newline();