1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1982-2014 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * David Korn <dgkorn@gmail.com> *
18 * *
19 ***********************************************************************/
20 //
21 // UNIX shell parse tree executer.
22 //
23 // David Korn
24 // AT&T Labs
25 //
26 #include "config_ast.h" // IWYU pragma: keep
27
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <limits.h>
31 #include <math.h>
32 #include <setjmp.h>
33 #include <signal.h>
34 #include <stdbool.h>
35 #include <stddef.h>
36 #include <stdint.h>
37 #include <string.h>
38 #include <sys/stat.h>
39 #include <sys/time.h>
40 #include <sys/times.h>
41 #include <unistd.h>
42
43 #if _hdr_stdlib
44 #include <stdlib.h>
45 #elif _hdr_malloc
46 #include <malloc.h>
47 #endif
48
49 #include "argnod.h"
50 #include "ast.h"
51 #include "ast_assert.h"
52 #include "builtins.h"
53 #include "cdt.h"
54 #include "defs.h"
55 #include "error.h"
56 #include "fault.h"
57 #include "fcin.h"
58 #include "history.h"
59 #include "io.h"
60 #include "jobs.h"
61 #include "name.h"
62 #include "option.h"
63 #include "path.h"
64 #include "sfio.h"
65 #include "shcmd.h"
66 #include "shnodes.h"
67 #include "shtable.h"
68 #include "stk.h"
69 #include "streval.h"
70 #include "terminal.h"
71 #include "test.h"
72 #include "variables.h"
73
74 #if USE_SPAWN
75 #include "spawnvex.h"
76 #endif
77
78 #define SH_NTFORK SH_TIMING
79
80 extern int nice(int);
81 #if USE_SPAWN
82 static_fn pid_t sh_ntfork(Shell_t *, const Shnode_t *, char *[], int *, int);
83 #endif // USE_SPAWN
84
85 static_fn void sh_funct(Shell_t *, Namval_t *, int, char *[], struct argnod *, int);
86 static_fn void coproc_init(Shell_t *, int pipes[]);
87
88 static Timer_t *timeout;
89 static char nlock;
90 static char pipejob;
91 static int restorefd;
92 #if USE_SPAWN
93 static int restorevex;
94 #endif
95
96 struct funenv {
97 Namval_t *node;
98 struct argnod *env;
99 Namval_t **nref;
100 };
101
102 #if USE_SPAWN
io_usevex(struct ionod * iop)103 static_fn int io_usevex(struct ionod *iop) {
104 struct ionod *first = iop;
105 for (; iop; iop = iop->ionxt) {
106 if ((iop->iofile & IODOC) && !(iop->iofile & IOQUOTE) && iop != first) return 0;
107 }
108 return IOUSEVEX;
109 }
110 #endif // USE_SPAWN
111 #if 1
112 #undef IOUSEVEX
113 #define IOUSEVEX 0
114 #endif
115
116 // ======== command execution ========
117
118 #if !has_dev_fd
fifo_check(void * handle)119 static_fn void fifo_check(void *handle) {
120 Shell_t *shp = handle;
121 pid_t pid = getppid();
122 if (pid == 1) {
123 unlink(shp->fifo);
124 sh_done(shp, 0);
125 }
126 }
127 #endif // !has_dev_fd
128
129 #if _lib_getrusage
130
131 // Use getrusage() rather than times() since the former typically has higher resolution.
132 #include <sys/resource.h>
133
get_cpu_times(struct timeval * tv_usr,struct timeval * tv_sys)134 static_fn void get_cpu_times(struct timeval *tv_usr, struct timeval *tv_sys) {
135 struct rusage usage_self, usage_child;
136
137 getrusage(RUSAGE_SELF, &usage_self);
138 getrusage(RUSAGE_CHILDREN, &usage_child);
139 timeradd(&usage_self.ru_utime, &usage_child.ru_utime, tv_usr);
140 timeradd(&usage_self.ru_stime, &usage_child.ru_stime, tv_sys);
141 }
142
143 #else // _lib_getrusage
144
get_cpu_times(struct timeval * tv_usr,struct timeval * tv_sys)145 static_fn void get_cpu_times(struct timeval *tv_usr, struct timeval *tv_sys) {
146 struct timeval tv1, tv2;
147 double dtime;
148 long clk_tck = sysconf(_SC_CLK_TCK);
149 struct tms cpu_times;
150 times(&cpu_times);
151
152 dtime = (double)cpu_times.tms_utime / clk_tck;
153 tv1.tv_sec = dtime / 60;
154 tv1.tv_usec = 1000000 * (dtime - tv1.tv_sec);
155 dtime = (double)cpu_times.tms_cutime / clk_tck;
156 tv2.tv_sec = dtime / 60;
157 tv2.tv_usec = 1000000 * (dtime - tv2.tv_sec);
158 timeradd(&tv1, &tv2, tv_usr);
159
160 dtime = (double)cpu_times.tms_stime / clk_tck;
161 tv1.tv_sec = dtime / 60;
162 tv1.tv_usec = 1000000 * (dtime - tv1.tv_sec);
163 dtime = (double)cpu_times.tms_cstime / clk_tck;
164 tv2.tv_sec = dtime / 60;
165 tv2.tv_usec = 1000000 * (dtime - tv2.tv_sec);
166 timeradd(&tv1, &tv2, tv_sys);
167 }
168
169 #endif // _lib_getrusage
170
timeval_to_double(struct timeval tv)171 static inline double timeval_to_double(struct timeval tv) {
172 return (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0);
173 }
174
175 //
176 // The following two functions allow command substituion for non-builtins to use a pipe and to wait
177 // for the pipe to close before restoring to a temp file.
178 //
179 static int subpipe[3], subdup, tsetio, usepipe;
180
iousepipe(Shell_t * shp)181 static_fn void iousepipe(Shell_t *shp) {
182 int i;
183 int fd = sffileno(sfstdout);
184
185 if (!sh_iovalidfd(shp, fd)) abort();
186 if (usepipe) {
187 usepipe++;
188 sh_iounpipe(shp);
189 }
190 sh_rpipe(subpipe);
191 usepipe++;
192 if (shp->comsub != 1) {
193 subpipe[2] = sh_fcntl(subpipe[1], F_DUPFD, 10);
194 sh_close(subpipe[1]);
195 return;
196 }
197 subpipe[2] = sh_fcntl(fd, F_DUPFD_CLOEXEC, 10);
198 if (!sh_iovalidfd(shp, subpipe[2])) abort();
199 shp->fdstatus[subpipe[2]] = shp->fdstatus[1];
200
201 close(fd);
202 i = fcntl(subpipe[1], F_DUPFD, fd);
203 assert(i != -1); // it should be impossible for the fcntl() to fail
204
205 shp->fdstatus[1] = shp->fdstatus[subpipe[1]] & ~IOCLEX;
206 sh_close(subpipe[1]);
207 subdup = shp->subdup;
208 if (subdup) {
209 for (i = 0; i < 10; i++) {
210 if (subdup & (1 << i)) {
211 sh_close(i);
212 (void)fcntl(1, F_DUPFD, i); // this can't fail
213 shp->fdstatus[i] = shp->fdstatus[1];
214 }
215 }
216 }
217 }
218
sh_iounpipe(Shell_t * shp)219 void sh_iounpipe(Shell_t *shp) {
220 int n;
221 char buff[SF_BUFSIZE];
222 int fd = sffileno(sfstdout);
223
224 if (!usepipe) return;
225 --usepipe;
226 if (shp->comsub > 1) {
227 sh_close(subpipe[2]);
228 while (read(subpipe[0], buff, sizeof(buff)) > 0) {
229 ; // empty loop
230 }
231 goto done;
232 }
233
234 close(fd);
235 n = fcntl(subpipe[2], F_DUPFD, fd);
236 assert(n != -1); // it should be impossible for the fcntl() to fail
237
238 shp->fdstatus[1] = shp->fdstatus[subpipe[2]];
239 if (subdup) {
240 for (n = 0; n < 10; n++) {
241 if (subdup & (1 << n)) {
242 sh_close(n);
243 (void)fcntl(1, F_DUPFD, n); // this can't fail so we don't check the return value
244 shp->fdstatus[n] = shp->fdstatus[1];
245 }
246 }
247 }
248 shp->subdup = 0;
249 sh_close(subpipe[2]);
250 if (usepipe == 0) {
251 while (1) {
252 while (job.waitsafe && job.savesig == SIGCHLD) {
253 if (!vmbusy()) {
254 job.in_critical++;
255 job_reap(SIGCHLD);
256 job.in_critical--;
257 break;
258 }
259 sh_delay(1);
260 }
261 if ((n = read(subpipe[0], buff, sizeof(buff))) == 0) break;
262 if (n > 0) {
263 sfwrite(sfstdout, buff, n);
264 } else if (errno != EINTR) {
265 break;
266 }
267 }
268 }
269 done:
270 sh_close(subpipe[0]);
271 subpipe[0] = -1;
272 tsetio = 0;
273 usepipe = 0;
274 }
275
276 //
277 // Print time <t> in h:m:s format with precision <p>.
278 //
l_time(Sfio_t * outfile,struct timeval * tv,int precision)279 static_fn void l_time(Sfio_t *outfile, struct timeval *tv, int precision) {
280 int hr = tv->tv_sec / (60 * 60);
281 int min = (tv->tv_sec / 60) % 60;
282 int sec = tv->tv_sec % 60;
283 int frac = tv->tv_usec;
284
285 // Scale fraction from micro to milli, centi, or deci second according to precision.
286 for (int n = 3 + (3 - precision); n > 0; --n) frac /= 10;
287
288 if (hr) sfprintf(outfile, "%dh", hr);
289 if (precision) {
290 sfprintf(outfile, "%dm%d%c%0*ds", min, sec, getdecimal(), precision, frac);
291 } else {
292 sfprintf(outfile, "%dm%ds", min, sec);
293 }
294 }
295
296 #define TM_REAL_IDX 0
297 #define TM_USR_IDX 1
298 #define TM_SYS_IDX 2
299
p_time(Shell_t * shp,Sfio_t * out,const char * format,struct timeval tm[3])300 static_fn void p_time(Shell_t *shp, Sfio_t *out, const char *format, struct timeval tm[3]) {
301 int c, n, offset = stktell(shp->stk);
302 const char *first;
303 struct timeval tv_cpu_sum;
304 struct timeval *tvp;
305 Stk_t *stkp = shp->stk;
306
307 for (first = format; *format; format++) {
308 c = *format;
309 if (c != '%') continue;
310 bool l_modifier = false;
311 int precision = 3;
312
313 sfwrite(stkp, first, format - first);
314 c = *++format;
315 if (c == '\0') {
316 // If a lone percent is the last character of the format pretend
317 // the user had written `%%` for a literal percent.
318 sfwrite(stkp, "%", 1);
319 first = format + 1;
320 break;
321 } else if (c == '%') {
322 first = format;
323 continue;
324 }
325
326 if (c >= '0' && c <= '9') {
327 precision = (c > '3') ? 3 : (c - '0');
328 c = *++format;
329 }
330
331 if (c == 'P') {
332 struct timeval tv_real = tm[TM_REAL_IDX];
333 struct timeval tv_cpu;
334 timeradd(&tm[TM_USR_IDX], &tm[TM_SYS_IDX], &tv_cpu);
335
336 double d = timeval_to_double(tv_real);
337 if (d) d = 100.0 * timeval_to_double(tv_cpu) / d;
338 sfprintf(stkp, "%.*f", precision, d);
339 first = format + 1;
340 continue;
341 }
342
343 if (c == 'l') {
344 l_modifier = true;
345 c = *++format;
346 }
347
348 if (c == 'R') {
349 tvp = &tm[TM_REAL_IDX];
350 } else if (c == 'U') {
351 tvp = &tm[TM_USR_IDX];
352 } else if (c == 'S') {
353 tvp = &tm[TM_SYS_IDX];
354 } else if (c == 'C') {
355 timeradd(&tm[TM_USR_IDX], &tm[TM_SYS_IDX], &tv_cpu_sum);
356 tvp = &tv_cpu_sum;
357 } else {
358 errormsg(SH_DICT, ERROR_exit(0), e_badtformat, c);
359 continue;
360 }
361
362 if (l_modifier) {
363 l_time(stkp, tvp, precision);
364 } else {
365 // Scale fraction from micro to milli, centi, or deci second according to precision.
366 int frac = tvp->tv_usec;
367 for (int n = 3 + (3 - precision); n > 0; --n) frac /= 10;
368 sfprintf(stkp, "%d.%0*d", tvp->tv_sec, precision, frac);
369 }
370 first = format + 1;
371 }
372
373 if (format > first) sfwrite(stkp, first, format - first);
374 sfputc(stkp, '\n');
375 n = stktell(stkp) - offset;
376 sfwrite(out, stkptr(stkp, offset), n);
377 stkseek(stkp, offset);
378 }
379
380 //
381 // Clear argument pointers that point into the stack.
382 //
383 static_fn int xec_p_arg(Shell_t *, struct argnod *, int);
384 static_fn int xec_p_switch(Shell_t *, struct regnod *);
385
xec_p_comarg(Shell_t * shp,struct comnod * com)386 static_fn int xec_p_comarg(Shell_t *shp, struct comnod *com) {
387 Namval_t *np = com->comnamp;
388 int n = xec_p_arg(shp, com->comset, ARG_ASSIGN);
389 if (com->comarg && (com->comtyp & COMSCAN)) n += xec_p_arg(shp, com->comarg, 0);
390 if (com->comstate && np) {
391 // Call builtin to cleanup state.
392 Shbltin_t *bp = &shp->bltindata;
393 void *save_ptr = bp->ptr;
394 void *save_data = bp->data;
395 bp->bnode = np;
396 bp->vnode = com->comnamq;
397 bp->ptr = nv_context(np);
398 bp->data = com->comstate;
399 // Was bp->flags = SH_END_OPTIM but no builtin actually uses the flags structure member
400 // and it's companion symbols, SH_BEGIN_OPTIM, isn't used anywhere.
401 bp->flags = 0;
402 funptr(np)(0, NULL, bp);
403 bp->ptr = save_ptr;
404 bp->data = save_data;
405 }
406 com->comstate = NULL;
407 if (com->comarg && !np) n++;
408 return n;
409 }
410
411 extern void sh_optclear(Shell_t *, void *);
412
sh_tclear(Shell_t * shp,Shnode_t * t)413 static_fn int sh_tclear(Shell_t *shp, Shnode_t *t) {
414 if (!t) return 0;
415
416 int n;
417 switch (t->tre.tretyp & COMMSK) {
418 case TTIME:
419 case TPAR: {
420 return sh_tclear(shp, t->par.partre);
421 }
422 case TCOM: {
423 return xec_p_comarg(shp, (struct comnod *)t);
424 }
425 case TSETIO:
426 case TFORK: {
427 return sh_tclear(shp, t->fork.forktre);
428 }
429 case TIF: {
430 n = sh_tclear(shp, t->if_.iftre);
431 n += sh_tclear(shp, t->if_.thtre);
432 n += sh_tclear(shp, t->if_.eltre);
433 return n;
434 }
435 case TWH: {
436 n = 0;
437 if (t->wh.whinc) n = sh_tclear(shp, (Shnode_t *)(t->wh.whinc));
438 n += sh_tclear(shp, t->wh.whtre);
439 n += sh_tclear(shp, t->wh.dotre);
440 return n;
441 }
442 case TLST:
443 case TAND:
444 case TORF:
445 case TFIL: {
446 n = sh_tclear(shp, t->lst.lstlef);
447 return n + sh_tclear(shp, t->lst.lstrit);
448 }
449 case TARITH: {
450 return xec_p_arg(shp, t->ar.arexpr, ARG_ARITH);
451 }
452 case TFOR: {
453 n = sh_tclear(shp, t->for_.fortre);
454 return n + sh_tclear(shp, (Shnode_t *)t->for_.forlst);
455 }
456 case TSW: {
457 n = xec_p_arg(shp, t->sw.swarg, 0);
458 return n + xec_p_switch(shp, t->sw.swlst);
459 }
460 case TFUN: {
461 n = sh_tclear(shp, t->funct.functtre);
462 return n + sh_tclear(shp, (Shnode_t *)t->funct.functargs);
463 }
464 case TTST: {
465 if ((t->tre.tretyp & TPAREN) == TPAREN) {
466 return sh_tclear(shp, t->lst.lstlef);
467 }
468 n = xec_p_arg(shp, &(t->lst.lstlef->arg), 0);
469 if (t->tre.tretyp & TBINARY) n += xec_p_arg(shp, &(t->lst.lstrit->arg), 0);
470 return n;
471 }
472 default: { return 0; }
473 }
474 }
475
xec_p_arg(Shell_t * shp,struct argnod * arg,int flag)476 static_fn int xec_p_arg(Shell_t *shp, struct argnod *arg, int flag) {
477 while (arg) {
478 if (strlen(arg->argval) || (arg->argflag == ARG_RAW)) {
479 arg->argchn.ap = NULL;
480 } else if (flag == 0) {
481 sh_tclear(shp, (Shnode_t *)arg->argchn.ap);
482 } else {
483 sh_tclear(shp, ((struct fornod *)arg->argchn.ap)->fortre);
484 }
485 arg = arg->argnxt.ap;
486 }
487 return 0;
488 }
489
xec_p_switch(Shell_t * shp,struct regnod * reg)490 static_fn int xec_p_switch(Shell_t *shp, struct regnod *reg) {
491 int n = 0;
492 while (reg) {
493 n += xec_p_arg(shp, reg->regptr, 0);
494 n += sh_tclear(shp, reg->regcom);
495 reg = reg->regnxt;
496 }
497 return n;
498 }
499
out_pattern(Sfio_t * iop,const char * cp,int n)500 static_fn void out_pattern(Sfio_t *iop, const char *cp, int n) {
501 int c;
502
503 do {
504 switch (c = *cp) {
505 case 0: {
506 if (n < 0) return;
507 c = n;
508 break;
509 }
510 case '\n': {
511 sfputr(iop, "$'\\n", '\'');
512 continue;
513 }
514 case '\\': {
515 if (!(c = *++cp)) c = '\\';
516 }
517 // FALLTHRU
518 case ' ':
519 case '<':
520 case '>':
521 case ';':
522 case '$':
523 case '`':
524 case '\t': {
525 sfputc(iop, '\\');
526 break;
527 }
528 default: { break; }
529 }
530 sfputc(iop, c);
531 } while (*cp++);
532 }
533
out_string(Sfio_t * iop,const char * cp,int c,int quoted)534 static_fn void out_string(Sfio_t *iop, const char *cp, int c, int quoted) {
535 if (quoted) {
536 int n = stktell(stkstd);
537 cp = sh_fmtq(cp);
538 if (iop == stkstd && cp == stkptr(stkstd, n)) {
539 *stkptr(stkstd, stktell(stkstd) - 1) = c;
540 return;
541 }
542 }
543 sfputr(iop, cp, c);
544 }
545
546 struct Level {
547 Namfun_t namfun;
548 short maxlevel;
549 };
550
551 //
552 // This is for a debugger but it hasn't been tested yet. If a debug script sets .sh.level it should
553 // set up the scope as if you were executing in that level.
554 //
put_level(Namval_t * np,const void * val,nvflag_t flags,Namfun_t * fp)555 static_fn void put_level(Namval_t *np, const void *val, nvflag_t flags, Namfun_t *fp) {
556 Shell_t *shp = sh_ptr(np);
557 Shscope_t *sp;
558 struct Level *lp = (struct Level *)fp;
559 int16_t level, oldlevel = (int16_t)nv_getnum(np);
560
561 nv_putv(np, val, flags, fp);
562 if (!val) {
563 fp = nv_stack(np, NULL);
564 if (fp && !fp->nofree) free(fp);
565 return;
566 }
567 level = nv_getnum(np);
568 if (level < 0 || level > lp->maxlevel) {
569 nv_putv(np, (char *)&oldlevel, NV_INT16, fp);
570 // Perhaps this should be an error.
571 return;
572 }
573 if (level == oldlevel) return;
574 sp = sh_getscope(shp, level, SEEK_SET);
575 if (sp) {
576 sh_setscope(shp, sp);
577 error_info.id = sp->cmdname;
578 }
579 }
580
581 static const Namdisc_t level_disc = {.dsize = sizeof(struct Level), .putval = put_level};
582
init_level(Shell_t * shp,int level)583 static_fn struct Level *init_level(Shell_t *shp, int level) {
584 struct Level *lp = calloc(1, sizeof(struct Level));
585
586 lp->maxlevel = level;
587 _nv_unset(VAR_sh_level, 0);
588 nv_onattr(VAR_sh_level, NV_INT16 | NV_NOFREE);
589 shp->last_root = nv_dict(VAR_sh);
590 nv_putval(VAR_sh_level, (char *)&lp->maxlevel, NV_INT16);
591 lp->namfun.disc = &level_disc;
592 nv_disc(VAR_sh_level, &lp->namfun, DISC_OP_FIRST);
593 return lp;
594 }
595
596 //
597 // Write the current command on the stack and make it available as .sh.command.
598 //
sh_debug(Shell_t * shp,const char * trap,const char * name,const char * subscript,char * const argv[],int flags)599 int sh_debug(Shell_t *shp, const char *trap, const char *name, const char *subscript,
600 char *const argv[], int flags) {
601 Stk_t *stkp = shp->stk;
602 struct sh_scoped savst;
603 Namval_t *np = VAR_sh_command;
604 char *sav = stkptr(stkp, 0);
605 int n = 4, offset = stktell(stkp);
606 const char *cp = "+=( ";
607 Sfio_t *iop = stkstd;
608 short level;
609
610 if (shp->indebug) return 0;
611 shp->indebug = 1;
612 if (name) {
613 sfputr(iop, name, -1);
614 if (subscript) {
615 sfputc(iop, '[');
616 out_string(iop, subscript, ']', 1);
617 }
618 if (!(flags & ARG_APPEND)) cp += 1, n -= 1;
619 if (!(flags & ARG_ASSIGN)) n -= 2;
620 sfwrite(iop, cp, n);
621 }
622 if (*argv && !(flags & ARG_RAW)) out_string(iop, *argv++, ' ', 0);
623 n = (flags & ARG_ARITH);
624 while ((cp = *argv++)) {
625 if ((flags & ARG_EXP) && argv[1] == 0) {
626 out_pattern(iop, cp, ' ');
627 } else {
628 out_string(iop, cp, ' ', n ? 0 : (flags & (ARG_RAW | ARG_NOGLOB)) || *argv);
629 }
630 }
631 if (flags & ARG_ASSIGN) {
632 sfputc(iop, ')');
633 } else if (iop == stkstd) {
634 *stkptr(stkp, stktell(stkp) - 1) = 0;
635 }
636 STORE_VT(np->nvalue, const_cp, stkfreeze(stkp, 1));
637 // Now setup .sh.level variable.
638 shp->st.lineno = error_info.line;
639 level = shp->fn_depth + shp->dot_depth;
640 shp->last_root = nv_dict(VAR_sh);
641 if (!VAR_sh_level->nvfun || !VAR_sh_level->nvfun->disc ||
642 nv_isattr(VAR_sh_level, NV_INT16 | NV_NOFREE) != (NV_INT16 | NV_NOFREE)) {
643 init_level(shp, level);
644 } else {
645 nv_putval(VAR_sh_level, (char *)&level, NV_INT16);
646 }
647 savst = shp->st;
648 shp->st.trap[SH_DEBUGTRAP] = 0;
649 n = sh_trap(shp, trap, 0);
650 STORE_VT(np->nvalue, const_cp, NULL);
651 shp->indebug = 0;
652 if (shp->st.cmdname) error_info.id = shp->st.cmdname;
653 nv_putval(VAR_sh_file, shp->st.filename, NV_NOFREE);
654 nv_putval(VAR_sh_fun, shp->st.funname, NV_NOFREE);
655 shp->st = savst;
656 if (sav != stkptr(stkp, 0)) {
657 stkset(stkp, sav, 0);
658 } else {
659 stkseek(stkp, offset);
660 }
661 return n;
662 }
663
664 //
665 // Returns true when option -<c> is specified.
666 //
checkopt(char * argv[],int c)667 static_fn bool checkopt(char *argv[], int c) {
668 char *cp;
669
670 while ((cp = *++argv)) {
671 if (*cp == '+') continue;
672 if (*cp != '-' || cp[1] == '-') break;
673 if (strchr(++cp, c)) return 1;
674 if (*cp == 'h' && cp[1] == 0 && *++argv == 0) break;
675 }
676 return false;
677 }
678
free_list(struct openlist * olist)679 static_fn void free_list(struct openlist *olist) {
680 struct openlist *item, *next;
681
682 for (item = olist; item; item = next) {
683 next = item->next;
684 free(item);
685 }
686 }
687
688 //
689 // Set ${.sh.name} and ${.sh.subscript}.
690 // Set _ to reference for ${.sh.name}[$.sh.subscript].
691 //
set_instance(Shell_t * shp,Namval_t * nq,Namval_t * node,struct Namref * nr)692 static_fn nvflag_t set_instance(Shell_t *shp, Namval_t *nq, Namval_t *node, struct Namref *nr) {
693 char *sp = NULL;
694 char *cp;
695 Namarr_t *ap;
696 Namval_t *np;
697
698 if (!nv_isattr(nq, NV_MINIMAL | NV_EXPORT | NV_ARRAY) && (np = nq->nvenv) && nv_isarray(np)) {
699 nq = np;
700 } else if (nv_isattr(nq, NV_MINIMAL) == NV_MINIMAL && !nv_type(nq) &&
701 (np = nv_typeparent(nq))) {
702 nq = np;
703 }
704 cp = nv_name(nq);
705 memset(nr, 0, sizeof(*nr));
706 nr->np = nq;
707 nr->root = shp->var_tree;
708 nr->table = shp->last_table;
709 if (!nr->table && shp->namespace) nr->table = shp->namespace;
710 shp->instance = 1;
711 ap = nv_arrayptr(nq);
712 if (ap) {
713 sp = nv_getsub(nq);
714 if (sp) nr->sub = strdup(sp);
715 }
716 shp->instance = 0;
717 if (shp->var_tree != shp->var_base && !nv_search_namval(nq, nr->root, NV_NOSCOPE)) {
718 nr->root = shp->namespace ? nv_dict(shp->namespace) : shp->var_base;
719 }
720 nv_putval(VAR_sh_name, cp, NV_NOFREE);
721 memcpy(node, VAR_underscore, sizeof(*node));
722 STORE_VT(VAR_underscore->nvalue, nrp, nr);
723 nv_setattr(VAR_underscore, NV_REF | NV_NOFREE);
724 VAR_underscore->nvfun = NULL;
725 VAR_underscore->nvenv = NULL;
726 if (ap && nr->sub) {
727 nv_putval(VAR_sh_subscript, nr->sub, NV_NOFREE);
728 return ap->flags & ARRAY_SCAN;
729 }
730 return 0;
731 }
732
unset_instance(Namval_t * nq,Namval_t * node,struct Namref * nr,nvflag_t mode)733 static_fn void unset_instance(Namval_t *nq, Namval_t *node, struct Namref *nr, nvflag_t mode) {
734 UNUSED(nq);
735
736 STORE_VT(VAR_underscore->nvalue, nrp, FETCH_VT(node->nvalue, nrp));
737 nv_setattr(VAR_underscore, node->nvflag);
738 VAR_underscore->nvfun = node->nvfun;
739 if (nr->sub) {
740 nv_putsub(nr->np, nr->sub, 0, mode);
741 free(nr->sub);
742 }
743 _nv_unset(VAR_sh_name, 0);
744 _nv_unset(VAR_sh_subscript, 0);
745 }
746
openstream(Shell_t * shp,struct ionod * iop,int * save)747 static_fn Sfio_t *openstream(Shell_t *shp, struct ionod *iop, int *save) {
748 Sfio_t *sp;
749 int savein;
750 int fd = sh_redirect(shp, iop, 3);
751
752 savein = dup(0);
753 if (fd == 0) fd = savein;
754 sp = sfnew(NULL, NULL, SF_UNBOUND, fd, SF_READ);
755 close(0);
756 if (sh_open("/dev/null", O_RDONLY | O_CLOEXEC) != 0) abort();
757 shp->offsets[0] = -1;
758 shp->offsets[1] = 0;
759 *save = savein;
760 return sp;
761 }
762
enter_namespace(Shell_t * shp,Namval_t * nsp)763 static_fn Namval_t *enter_namespace(Shell_t *shp, Namval_t *nsp) {
764 Namval_t *path = nsp, *fpath = nsp, *onsp = shp->namespace;
765 Dt_t *root = NULL;
766 Dt_t *oroot = NULL;
767 char *val;
768
769 if (nsp) {
770 if (!nv_istable(nsp)) {
771 nsp = NULL;
772 } else if (nv_dict(nsp)->view != shp->var_base) {
773 return onsp;
774 }
775 }
776 if (!nsp && !onsp) return NULL;
777 if (onsp == nsp) return nsp;
778 if (onsp) {
779 oroot = nv_dict(onsp);
780 if (!nsp) {
781 path = nv_search(VAR_PATH->nvname, oroot, NV_NOSCOPE);
782 fpath = nv_search(VAR_FPATH->nvname, oroot, NV_NOSCOPE);
783 }
784 if (shp->var_tree == oroot) {
785 shp->var_tree = shp->var_tree->view;
786 oroot = shp->var_base;
787 }
788 }
789 if (nsp) {
790 if (shp->var_tree == shp->var_base) {
791 shp->var_tree = nv_dict(nsp);
792 } else {
793 for (root = shp->var_tree; root->view != oroot; root = root->view) {
794 ; // empty loop
795 }
796 dtview(root, nv_dict(nsp));
797 }
798 }
799 shp->namespace = nsp;
800 if (path && (path = nv_search(VAR_PATH->nvname, shp->var_tree, NV_NOSCOPE)) &&
801 (val = nv_getval(path))) {
802 nv_putval(path, val, NV_RDONLY);
803 }
804 if (fpath && (fpath = nv_search(VAR_FPATH->nvname, shp->var_tree, NV_NOSCOPE)) &&
805 (val = nv_getval(fpath))) {
806 nv_putval(fpath, val, NV_RDONLY);
807 }
808 return onsp;
809 }
810
forked_child(Shell_t * shp,const Shnode_t * t,int flags,int type,bool no_fork,char * com0,char ** com,pid_t parent,int topfd,int vexi)811 __attribute__((noreturn)) static_fn void forked_child(Shell_t *shp, const Shnode_t *t, int flags,
812 int type, bool no_fork, char *com0,
813 char **com, pid_t parent, int topfd,
814 int vexi) {
815 #if !USE_SPAWN
816 UNUSED(vexi);
817 #endif
818 // This is the FORKED branch (child) of execute.
819 volatile int jmpval;
820 checkpt_t *buffp = stkalloc(shp->stk, sizeof(checkpt_t));
821 struct ionod *iop;
822 int rewrite = 0;
823 if (no_fork) sh_sigreset(shp, 2);
824 sh_pushcontext(shp, buffp, SH_JMPEXIT);
825 jmpval = sigsetjmp(buffp->buff, 0);
826 if (jmpval) goto done;
827 if ((type & FINT) && !sh_isstate(shp, SH_MONITOR)) {
828 // Default std input for &.
829 sh_signal(SIGINT, (sh_sigfun_t)(SIG_IGN));
830 sh_signal(SIGQUIT, (sh_sigfun_t)(SIG_IGN));
831 shp->sigflag[SIGINT] = SH_SIGOFF;
832 shp->sigflag[SIGQUIT] = SH_SIGOFF;
833 if (!shp->st.ioset) {
834 if (sh_close(0) >= 0) {
835 int tmp_fd = sh_open("/dev/null", O_RDONLY, 0);
836 assert(tmp_fd == 0);
837 }
838 }
839 }
840 sh_offstate(shp, SH_MONITOR);
841 // Pipe in or out.
842 if ((type & FAMP) && sh_isoption(shp, SH_BGNICE)) nice(4);
843
844 #if !has_dev_fd
845 if (shp->fifo && (type & (FPIN | FPOU))) {
846 int fn, fd = (type & FPIN) ? 0 : 1;
847 Timer_t *fifo_timer = sh_timeradd(500, 1, fifo_check, shp);
848 fn = sh_open(shp->fifo, fd ? O_WRONLY : O_RDONLY);
849 timerdel(fifo_timer);
850 sh_iorenumber(shp, fn, fd);
851 sh_close(fn);
852 sh_delay(.001);
853 unlink(shp->fifo);
854 free(shp->fifo);
855 shp->fifo = NULL;
856 type &= ~(FPIN | FPOU);
857 }
858 #endif // !has_dev_fd
859 if (type & FPIN) {
860 sh_iorenumber(shp, shp->inpipe[0], 0);
861 if (!(type & FPOU) || (type & FCOOP)) sh_close(shp->inpipe[1]);
862 }
863 if (type & FPOU) {
864 sh_iorenumber(shp, shp->outpipe[1], 1);
865 sh_pclose(shp->outpipe);
866 }
867 if ((type & COMMSK) != TCOM) {
868 error_info.line = t->fork.forkline - shp->st.firstline;
869 }
870 if (shp->topfd) sh_iounsave(shp);
871 topfd = shp->topfd;
872 if (com0 && (iop = t->tre.treio)) {
873 for (; iop; iop = iop->ionxt) {
874 if (iop->iofile & IOREWRITE) rewrite = 1;
875 }
876 }
877 sh_redirect(shp, t->tre.treio, 1 | IOUSEVEX);
878 if (rewrite) {
879 job_lock();
880 while ((parent = fork()) < 0) _sh_fork(shp, parent, 0, NULL);
881 if (parent) {
882 job.toclear = 0;
883 job_post(shp, parent, 0);
884 job_wait(parent);
885 sh_iorestore(shp, topfd, SH_JMPCMD);
886 #if USE_SPAWN
887 if (shp->vexp->cur > vexi) sh_vexrestore(shp, vexi);
888 #endif
889 sh_done(shp, (shp->exitval & SH_EXITSIG) ? (shp->exitval & SH_EXITMASK) : 0);
890 }
891 job_unlock();
892 }
893 if ((type & COMMSK) != TCOM) {
894 // Don't clear job table for out pipes so that jobs comand can be used in a
895 // pipeline.
896 if (!no_fork && !(type & FPOU)) job_clear(shp);
897 sh_exec(shp, t->fork.forktre, flags | sh_state(SH_NOFORK) | sh_state(SH_FORKED));
898 } else if (com0) {
899 sh_offoption(shp, SH_ERREXIT);
900 sh_freeup(shp);
901 path_exec(shp, com0, com, t->com.comset);
902 }
903 done:
904 sh_popcontext(shp, buffp);
905 if (jmpval > SH_JMPEXIT) siglongjmp(shp->jmplist->buff, jmpval);
906 sh_done(shp, 0);
907 }
908
sh_exec(Shell_t * shp,const Shnode_t * t,int flags)909 int sh_exec(Shell_t *shp, const Shnode_t *t, int flags) {
910 sh_sigcheck(shp);
911
912 if (!t) return shp->exitval;
913 if (shp->st.execbrk) return shp->exitval;
914 if (sh_isoption(shp, SH_NOEXEC)) return shp->exitval;
915
916 Stk_t *stkp = shp->stk;
917 int type = flags;
918 char *com0 = NULL;
919 int errorflg = (type & sh_state(SH_ERREXIT)) | (flags & ARG_OPTIMIZE);
920 int execflg = (type & sh_state(SH_NOFORK));
921 int execflg2 = (type & sh_state(SH_FORKED));
922 int mainloop = (type & sh_state(SH_INTERACTIVE));
923 #if USE_SPAWN
924 int ntflag = (type & sh_state(SH_NTFORK));
925 #else
926 int ntflag = 0;
927 #endif
928 int topfd = shp->topfd;
929 char *sav = stkptr(stkp, 0);
930 char *cp = NULL;
931 char **com = NULL;
932 char *comn;
933 int argn;
934 int skipexitset = 0;
935 #if USE_SPAWN
936 int vexi = shp->vexp->cur;
937 #else
938 int vexi = 0;
939 #endif
940 pid_t *procsub = NULL;
941 volatile int was_interactive = 0;
942 volatile int was_errexit = sh_isstate(shp, SH_ERREXIT);
943 volatile int was_monitor = sh_isstate(shp, SH_MONITOR);
944 volatile int echeck = 0;
945
946 if (flags & sh_state(SH_INTERACTIVE)) {
947 if (pipejob == 2) job_unlock();
948 nlock = 0;
949 pipejob = 0;
950 job.curpgid = 0;
951 job.curjobid = 0;
952 flags &= ~sh_state(SH_INTERACTIVE);
953 }
954 sh_offstate(shp, SH_ERREXIT);
955 sh_offstate(shp, SH_DEFPATH);
956 if (was_errexit & flags) sh_onstate(shp, SH_ERREXIT);
957 if (was_monitor & flags) sh_onstate(shp, SH_MONITOR);
958 type = t->tre.tretyp;
959 if (!shp->intrap) shp->oldexit = shp->exitval;
960 shp->exitval = 0;
961 shp->lastsig = 0;
962 shp->lastpath = NULL;
963 if (shp->exittrap || shp->errtrap) execflg = 0;
964 switch (type & COMMSK) {
965 case TCOM: {
966 struct argnod *argp;
967 char *trap;
968 Namval_t *np, *nq, *last_table;
969 struct ionod *io;
970 int command = 0;
971 nvflag_t nvflags = NV_ASSIGN;
972 shp->bltindata.invariant = type >> (COMBITS + 2);
973 shp->bltindata.pwdfd = shp->pwdfd;
974 type &= (COMMSK | COMSCAN);
975 sh_stats(STAT_SCMDS);
976 error_info.line = t->com.comline - shp->st.firstline;
977 #if USE_SPAWN
978 spawnvex_add(shp->vex, SPAWN_frame, 0, 0, 0);
979 #endif
980 com = sh_argbuild(shp, &argn, &(t->com), flags & ARG_OPTIMIZE);
981 procsub = shp->procsub;
982 shp->procsub = NULL;
983 echeck = 1;
984 if (t->tre.tretyp & COMSCAN) {
985 argp = t->com.comarg;
986 if (argp && *com && !(argp->argflag & ARG_RAW)) sh_sigcheck(shp);
987 }
988 np = t->com.comnamp;
989 nq = t->com.comnamq;
990 if (np && shp->namespace && nq != shp->namespace &&
991 nv_isattr(np, NV_BLTIN | NV_INTEGER | BLT_SPC) != (NV_BLTIN | BLT_SPC)) {
992 Namval_t *mp;
993 mp = sh_fsearch(shp, com[0], 0);
994 if (mp) {
995 nq = shp->namespace;
996 np = mp;
997 }
998 }
999 com0 = com[0];
1000 shp->xargexit = 0;
1001 while (np == SYSCOMMAND) {
1002 int n = b_command(0, com, &shp->bltindata);
1003 if (n == 0) break;
1004 command += n;
1005 np = NULL;
1006 if (!(com0 = *(com += n))) break;
1007 np = nv_bfsearch(com0, shp->bltin_tree, &nq, &cp);
1008 }
1009 if (shp->xargexit) {
1010 shp->xargmin -= command;
1011 shp->xargmax -= command;
1012 } else {
1013 shp->xargmin = 0;
1014 }
1015 argn -= command;
1016 if (np && is_abuiltin(np)) {
1017 if (!command) {
1018 Namval_t *mp;
1019 if (shp->namespace && (mp = sh_fsearch(shp, np->nvname, 0))) {
1020 np = mp;
1021 } else {
1022 np = dtsearch(shp->fun_tree, np);
1023 }
1024 }
1025 }
1026 if (com0) {
1027 if (!np && !strchr(com0, '/')) {
1028 Dt_t *root = command ? shp->bltin_tree : shp->fun_tree;
1029 np = nv_bfsearch(com0, root, &nq, &cp);
1030 if (shp->namespace && !nq && !cp) np = sh_fsearch(shp, com0, 0);
1031 }
1032 comn = com[argn - 1];
1033 }
1034 io = t->tre.treio;
1035 tryagain:
1036 shp->envlist = argp = t->com.comset;
1037 if (shp->envlist) {
1038 if (argn == 0 ||
1039 (np && (nv_isattr(np, BLT_DCL) || (!command && nv_isattr(np, BLT_SPC))))) {
1040 Namval_t *tp = NULL;
1041 if (argn) {
1042 if (checkopt(com, 'A')) {
1043 nvflags |= NV_ARRAY;
1044 } else if (checkopt(com, 'a')) {
1045 nvflags |= NV_IARRAY;
1046 }
1047 }
1048 if (np) nvflags |= NV_UNJUST;
1049 if (np == SYSLOCAL) {
1050 if (!nv_getval(VAR_sh_fun)) {
1051 errormsg(SH_DICT, ERROR_exit(1), "%s: can only be used in a function",
1052 com0);
1053 __builtin_unreachable();
1054 }
1055 if (!shp->st.var_local) {
1056 sh_scope(shp, NULL, 0);
1057 shp->st.var_local = shp->var_tree;
1058 }
1059 }
1060 if (np == SYSTYPESET || (np && FETCH_VT(np->nvalue, shbltinp) ==
1061 FETCH_VT(SYSTYPESET->nvalue, shbltinp))) {
1062 if (np != SYSTYPESET) {
1063 shp->typeinit = np;
1064 tp = nv_type(np);
1065 }
1066 if (checkopt(com, 'C')) nvflags |= NV_COMVAR;
1067 if (checkopt(com, 'S')) nvflags |= NV_STATIC;
1068 if (checkopt(com, 'm')) nvflags |= NV_MOVE;
1069 if (checkopt(com, 'n')) {
1070 nvflags |= NV_NOREF;
1071 } else if (argn >= 3 && checkopt(com, 'T')) {
1072 if (shp->namespace) {
1073 char *sp, *xp;
1074 if (!shp->strbuf2) shp->strbuf2 = sfstropen();
1075 sfprintf(shp->strbuf2, "%s%s%c", NV_CLASS, nv_name(shp->namespace),
1076 0);
1077 char *p = sfstruse(shp->strbuf2);
1078 assert(p);
1079 shp->prefix = strdup(p);
1080 xp = shp->prefix + strlen(NV_CLASS);
1081 for (sp = xp + 1; sp;) {
1082 sp = strchr(sp, '.');
1083 if (sp) *sp = 0;
1084 nv_open(shp->prefix, shp->var_base, NV_VARNAME);
1085 if (sp) *sp++ = '.';
1086 }
1087 } else {
1088 shp->prefix = NV_CLASS;
1089 }
1090 nvflags |= NV_TYPE;
1091 }
1092 if ((shp->fn_depth && !shp->prefix) || np == SYSLOCAL) {
1093 nvflags |= NV_NOSCOPE;
1094 }
1095 } else if (np == SYSEXPORT) {
1096 nvflags |= NV_EXPORT;
1097 }
1098 if (nvflags & (NV_EXPORT | NV_NOREF)) {
1099 nvflags |= NV_IDENT;
1100 } else {
1101 nvflags |= NV_VARNAME;
1102 }
1103 if (np && nv_isattr(np, BLT_DCL)) nvflags |= NV_DECL;
1104 if (t->com.comtyp & COMFIXED) ((Shnode_t *)t)->com.comtyp &= ~COMFIXED;
1105 shp->nodelist = sh_setlist(shp, argp, nvflags, tp);
1106 if (np == shp->typeinit) shp->typeinit = NULL;
1107 shp->envlist = argp;
1108 argp = NULL;
1109 }
1110 }
1111 last_table = shp->last_table;
1112 shp->last_table = NULL;
1113 if ((io || argn)) {
1114 Shbltin_t *bp = NULL;
1115 static char *argv[2] = {NULL, NULL};
1116 int tflags = 1;
1117 if (np && nv_isattr(np, BLT_DCL)) tflags |= 2;
1118 if (argn == 0) {
1119 // Fake 'true' built-in.
1120 np = SYSTRUE;
1121 argv[0] = nv_name(np);
1122 com = argv;
1123 }
1124 // set +x doesn't echo.
1125 else if ((t->tre.tretyp & FSHOWME) && sh_isoption(shp, SH_SHOWME)) {
1126 int ison = sh_isoption(shp, SH_XTRACE);
1127 if (!ison) sh_onoption(shp, SH_XTRACE);
1128 sh_trace(shp, com - command, tflags);
1129 if (io) sh_redirect(shp, io, SH_SHOWME | IOHERESTRING);
1130 if (!ison) sh_offoption(shp, SH_XTRACE);
1131 break;
1132 } else if ((np != SYSSET) && sh_isoption(shp, SH_XTRACE)) {
1133 sh_trace(shp, com - command, tflags);
1134 }
1135 trap = shp->st.trap[SH_DEBUGTRAP];
1136 if (trap) {
1137 int n = sh_debug(shp, trap, NULL, NULL, com, ARG_RAW);
1138 if (n == 255 && shp->fn_depth + shp->dot_depth) {
1139 np = SYSRETURN;
1140 argn = 1;
1141 com[0] = np->nvname;
1142 com[1] = 0;
1143 io = 0;
1144 argp = NULL;
1145 } else if (n == 2) {
1146 break;
1147 }
1148 }
1149 if (io) sfsync(shp->outpool);
1150 shp->lastpath = NULL;
1151 if (!np && !strchr(com0, '/')) {
1152 if (path_search(shp, com0, NULL, 1)) {
1153 error_info.line = t->com.comline - shp->st.firstline;
1154 if (!shp->namespace || !(np = sh_fsearch(shp, com0, 0))) {
1155 np = nv_search(com0, shp->fun_tree, 0);
1156 }
1157 if (!np || !FETCH_VT(np->nvalue, ip)) {
1158 Namval_t *mp = nv_search(com0, shp->bltin_tree, 0);
1159 if (mp) np = mp;
1160 } else if ((t->com.comtyp & COMFIXED) && nv_type(np)) {
1161 ((Shnode_t *)t)->com.comtyp &= ~COMFIXED;
1162 goto tryagain;
1163 }
1164 } else {
1165 if ((np = nv_search(com0, shp->track_tree, 0)) &&
1166 !nv_isattr(np, NV_NOALIAS) && FETCH_VT(np->nvalue, const_cp)) {
1167 np = nv_search(nv_getval(np), shp->bltin_tree, 0);
1168 } else {
1169 np = NULL;
1170 }
1171 }
1172 }
1173 if (np && pipejob == 2) {
1174 if (shp->comsub == 1 && np && is_abuiltin(np) && *np->nvname == '/') {
1175 np = NULL;
1176 } else {
1177 job_unlock();
1178 nlock--;
1179 pipejob = 1;
1180 }
1181 }
1182 // Check for builtins.
1183 if (np && is_abuiltin(np)) {
1184 volatile int scope = 0, share = 0;
1185 volatile void *save_ptr;
1186 volatile void *save_data;
1187 int jmpval, save_prompt;
1188 int was_nofork = execflg ? sh_isstate(shp, SH_NOFORK) : 0;
1189 checkpt_t *buffp = stkalloc(shp->stk, sizeof(checkpt_t));
1190 volatile unsigned long was_vi = 0, was_emacs = 0, was_gmacs = 0;
1191 #if !O_SEARCH
1192 struct stat statb;
1193 #endif // O_SEARCH
1194 bp = &shp->bltindata;
1195 save_ptr = bp->ptr;
1196 save_data = bp->data;
1197 #if !O_SEARCH
1198 memset(&statb, 0, sizeof(struct stat));
1199 #endif // O_SEARCH
1200 if (strchr(nv_name(np), '/')) {
1201 // Disable editors for built-in versions of commands on PATH.
1202 was_vi = sh_isoption(shp, SH_VI);
1203 was_emacs = sh_isoption(shp, SH_EMACS);
1204 was_gmacs = sh_isoption(shp, SH_GMACS);
1205 sh_offoption(shp, SH_VI);
1206 sh_offoption(shp, SH_EMACS);
1207 sh_offoption(shp, SH_GMACS);
1208 }
1209 if (execflg) sh_onstate(shp, SH_NOFORK);
1210 sh_pushcontext(shp, buffp, SH_JMPCMD);
1211 jmpval = sigsetjmp(buffp->buff, 1);
1212 if (jmpval == 0) {
1213 if (!(nv_isattr(np, BLT_ENV))) error_info.flags |= ERROR_SILENT;
1214 errorpush(&buffp->err, 0);
1215 if (io) {
1216 struct openlist *item;
1217 if (np == SYSEXEC) {
1218 type = 1 + !com[1];
1219 } else {
1220 type = (execflg && !shp->subshell && !shp->st.trapcom[0]);
1221 }
1222 shp->redir0 = 1;
1223 sh_redirect(shp, io,
1224 type | (FETCH_VT(np->nvalue, shbltinp) == b_source
1225 ? 0
1226 : IOHERESTRING | IOUSEVEX));
1227 for (item = buffp->olist; item; item = item->next) item->strm = NULL;
1228 }
1229 if (!nv_isattr(np, BLT_ENV) && !nv_isattr(np, BLT_SPC)) {
1230 if (!shp->pwd) {
1231 path_pwd(shp);
1232 #if !O_SEARCH
1233 } else if (shp->pwdfd >= 0) {
1234 fstat(shp->pwdfd, &statb);
1235 } else if (shp->pwd) {
1236 stat(e_dot, &statb);
1237 #endif // O_SEARCH
1238 }
1239 sfsync(NULL);
1240 share = sfset(sfstdin, SF_SHARE, 0);
1241 sh_onstate(shp, SH_STOPOK);
1242 sfpool(sfstderr, NULL, SF_WRITE);
1243 sfset(sfstderr, SF_LINE, 1);
1244 save_prompt = shp->nextprompt;
1245 shp->nextprompt = 0;
1246 }
1247 if (argp) {
1248 scope++;
1249 sh_scope(shp, argp, 0);
1250 }
1251 opt_info.index = opt_info.offset = 0;
1252 opt_info.disc = NULL;
1253 error_info.id = *com;
1254 if (argn) shp->exitval = 0;
1255 shp->bltinfun = funptr(np);
1256 bp->bnode = np;
1257 bp->vnode = nq;
1258 bp->ptr = nv_context(np);
1259 bp->data = t->com.comstate;
1260 bp->sigset = 0;
1261 bp->notify = 0;
1262 bp->flags = ((flags & ARG_OPTIMIZE) != 0);
1263 if (shp->subshell && nv_isattr(np, BLT_NOSFIO)) sh_subtmpfile(shp);
1264 if (execflg && !shp->subshell && !shp->st.trapcom[0] &&
1265 !shp->st.trap[SH_ERRTRAP] && shp->fn_depth == 0 &&
1266 !nv_isattr(np, BLT_ENV)) {
1267 // Do close-on-exec.
1268 int fd;
1269 for (fd = 0; fd < shp->gd->lim.open_max; fd++) {
1270 if ((shp->fdstatus[fd] & IOCLEX) && fd != shp->infd &&
1271 (fd != shp->pwdfd)) {
1272 sh_close(fd);
1273 }
1274 }
1275 }
1276 if (argn) {
1277 shp->exitval = (*shp->bltinfun)(argn, com, bp);
1278 sfsync(NULL);
1279 }
1280 if (error_info.flags & ERROR_INTERACTIVE) tty_check(STDERR_FILENO);
1281 ((Shnode_t *)t)->com.comstate = shp->bltindata.data;
1282 bp->data = (void *)save_data;
1283 if (shp->exitval && errno == EINTR && shp->lastsig) {
1284 shp->exitval = SH_EXITSIG | shp->lastsig;
1285 } else if (!nv_isattr(np, BLT_EXIT)) {
1286 shp->exitval &= SH_EXITMASK;
1287 }
1288 } else {
1289 struct openlist *item;
1290 for (item = buffp->olist; item; item = item->next) {
1291 if (item->strm) {
1292 sfclrlock(item->strm);
1293 if (shp->gd->hist_ptr && item->strm == shp->gd->hist_ptr->histfp) {
1294 hist_close(shp->gd->hist_ptr);
1295 } else {
1296 sfclose(item->strm);
1297 }
1298 }
1299 }
1300 if (shp->bltinfun && (error_info.flags & ERROR_NOTIFY)) {
1301 (*shp->bltinfun)(-2, com, bp);
1302 sfsync(NULL);
1303 }
1304 // Failure on special built-ins fatal.
1305 if (jmpval <= SH_JMPCMD && (!nv_isattr(np, BLT_SPC) || command)) {
1306 jmpval = 0;
1307 }
1308 }
1309 #if USE_SPAWN
1310 if (np != SYSEXEC && shp->vex->cur) {
1311 #if 1
1312 spawnvex_apply(shp->vex, 0, SPAWN_RESET | SPAWN_FRAME);
1313 #else
1314 int fd;
1315 spawnvex_apply(shp->vex, 0, SPAWN_RESET | SPAWN_FRAME);
1316 if (shp->comsub && (fd = sffileno(sfstdout)) != 1 && fd >= 0)
1317 spawnvex_add(shp->vex, fd, 1, 0, 0);
1318 #endif
1319 }
1320 #endif
1321 bp->bnode = NULL;
1322 if (bp->ptr != nv_context(np)) np->nvfun = (Namfun_t *)bp->ptr;
1323 if (execflg && !was_nofork) sh_offstate(shp, SH_NOFORK);
1324 if (!(nv_isattr(np, BLT_ENV))) {
1325 #if O_SEARCH
1326 while ((sh_fchdir(shp->pwdfd) < 0) && errno == EINTR) errno = 0;
1327 #else // O_SEARCH
1328 if (shp->pwd || (shp->pwdfd >= 0)) {
1329 struct stat stata;
1330 stat(e_dot, &stata);
1331 // Restore directory changed.
1332 if (statb.st_ino != stata.st_ino || statb.st_dev != stata.st_dev) {
1333 // Chdir for directories on HSM/tapeworms may take minutes.
1334 int err = errno;
1335 if (shp->pwdfd >= 0) {
1336 while ((fchdir(shp->pwdfd) < 0) && errno == EINTR) {
1337 errno = err;
1338 }
1339 } else {
1340 while ((chdir(shp->pwd) < 0) && errno == EINTR) errno = err;
1341 }
1342 }
1343 }
1344 #endif // O_SEARCH
1345 sh_offstate(shp, SH_STOPOK);
1346 if (share & SF_SHARE) sfset(sfstdin, SF_PUBLIC | SF_SHARE, 1);
1347 sfset(sfstderr, SF_LINE, 0);
1348 sfpool(sfstderr, shp->outpool, SF_WRITE);
1349 sfpool(sfstdin, NULL, SF_WRITE);
1350 shp->nextprompt = save_prompt;
1351 }
1352 sh_popcontext(shp, buffp);
1353 errorpop(&buffp->err);
1354 error_info.flags &= ~(ERROR_SILENT | ERROR_NOTIFY);
1355 shp->bltinfun = 0;
1356 if (buffp->olist) free_list(buffp->olist);
1357 if (was_vi) {
1358 sh_onoption(shp, SH_VI);
1359 } else if (was_emacs) {
1360 sh_onoption(shp, SH_EMACS);
1361 } else if (was_gmacs) {
1362 sh_onoption(shp, SH_GMACS);
1363 }
1364 if (scope) sh_unscope(shp);
1365 bp->ptr = (void *)save_ptr;
1366 bp->data = (void *)save_data;
1367 // Don't restore for subshell exec.
1368 if ((shp->topfd > topfd) && !(shp->subshell && np == SYSEXEC)) {
1369 sh_iorestore(shp, topfd, jmpval);
1370 }
1371 #if USE_SPAWN
1372 if (shp->vexp->cur > vexi) sh_vexrestore(shp, vexi);
1373 #endif
1374 shp->redir0 = 0;
1375 if (jmpval) siglongjmp(shp->jmplist->buff, jmpval);
1376 if (shp->exitval >= 0) goto setexit;
1377 np = NULL;
1378 type = 0;
1379 }
1380 // Check for functions.
1381 if (!command && np && nv_isattr(np, NV_FUNCTION)) {
1382 volatile int indx;
1383 int jmpval = 0;
1384 checkpt_t *buffp = stkalloc(shp->stk, sizeof(checkpt_t));
1385 Namval_t node;
1386 Namval_t *namespace = NULL;
1387 struct Namref nr;
1388 nvflag_t mode;
1389 struct slnod *slp;
1390 if (!FETCH_VT(np->nvalue, ip)) {
1391 indx = path_search(shp, com0, NULL, 0);
1392 if (indx == 1) {
1393 if (shp->namespace) {
1394 np = sh_fsearch(shp, com0, 0);
1395 } else {
1396 np = nv_search(com0, shp->fun_tree, NV_NOSCOPE);
1397 }
1398 }
1399
1400 assert(np); // Coverity CID#253708
1401 if (!FETCH_VT(np->nvalue, ip)) {
1402 if (indx == 1) {
1403 errormsg(SH_DICT, ERROR_exit(0), e_defined, com0);
1404 shp->exitval = ERROR_NOEXEC;
1405 } else {
1406 errormsg(SH_DICT, ERROR_exit(0), e_found, "function");
1407 shp->exitval = ERROR_NOENT;
1408 }
1409 goto setexit;
1410 }
1411 }
1412 // Increase refcnt for unset.
1413 slp = (struct slnod *)np->nvenv;
1414 sh_funstaks(slp->slchild, 1);
1415 stklink(slp->slptr);
1416 if (nq) {
1417 Namval_t *mp = NULL;
1418 if (nv_isattr(np, NV_STATICF) && (mp = nv_type(nq))) nq = mp;
1419 shp->last_table = last_table;
1420 mode = set_instance(shp, nq, &node, &nr);
1421 }
1422 if (io) {
1423 indx = shp->topfd;
1424 sh_pushcontext(shp, buffp, SH_JMPCMD);
1425 jmpval = sigsetjmp(buffp->buff, 0);
1426 }
1427 if (jmpval == 0) {
1428 if (io) indx = sh_redirect(shp, io, execflg | IOUSEVEX);
1429 if (*np->nvname == '.') {
1430 char *ep;
1431 bool type = 0;
1432 cp = np->nvname + 1;
1433 if (strncmp(cp, "sh.type.", 8) == 0) {
1434 cp += 8;
1435 type = true;
1436 }
1437 ep = strrchr(cp, '.');
1438 if (ep) {
1439 if (type) {
1440 while (--ep > cp && *ep != '.') {
1441 ; // empty loop
1442 }
1443 }
1444 *ep = 0;
1445 namespace = nv_search(cp - 1, shp->var_base, NV_NOSCOPE);
1446 *ep = '.';
1447 }
1448 }
1449 namespace = enter_namespace(shp, namespace);
1450 sh_funct(shp, np, argn, com, t->com.comset, (flags & ~ARG_OPTIMIZE));
1451 }
1452 enter_namespace(shp, namespace);
1453 #if USE_SPAWN
1454 spawnvex_apply(shp->vex, 0, SPAWN_RESET | SPAWN_FRAME);
1455 if (shp->vexp->cur > vexi) sh_vexrestore(shp, vexi);
1456 #endif
1457 if (io) {
1458 if (buffp->olist) free_list(buffp->olist);
1459 sh_popcontext(shp, buffp);
1460 sh_iorestore(shp, indx, jmpval);
1461 }
1462 if (nq) unset_instance(nq, &node, &nr, mode);
1463 sh_funstaks(slp->slchild, -1);
1464 stkclose(slp->slptr);
1465 if (jmpval > SH_JMPFUN || (io && jmpval > SH_JMPIO)) {
1466 siglongjmp(shp->jmplist->buff, jmpval);
1467 }
1468 goto setexit;
1469 }
1470 } else if (!io) {
1471 #if USE_SPAWN
1472 spawnvex_apply(shp->vex, 0, SPAWN_RESET | SPAWN_FRAME);
1473 #endif
1474 setexit:
1475 exitset(shp);
1476 break;
1477 }
1478 }
1479 // FALLTHRU
1480 case TFORK: {
1481 pid_t parent;
1482 bool no_fork;
1483 int jobid;
1484 int pipes[3];
1485 #if USE_SPAWN
1486 bool unpipe = false;
1487 #endif
1488
1489 if (shp->subshell) {
1490 sh_subtmpfile(shp);
1491 if ((type & (FAMP | TFORK)) == (FAMP | TFORK)) {
1492 if (shp->comsub && !(shp->fdstatus[1] & IONOSEEK)) {
1493 iousepipe(shp);
1494 #if USE_SPAWN
1495 unpipe = true;
1496 #endif // USE_SPAWN
1497 }
1498 sh_subfork();
1499 }
1500 }
1501 no_fork =
1502 !ntflag && !(type & (FAMP | FPOU)) && !shp->subshell &&
1503 !(shp->st.trapcom[SIGINT] && *shp->st.trapcom[SIGINT]) && !shp->st.trapcom[0] &&
1504 !shp->st.trap[SH_ERRTRAP] && shp->jmplist->mode != SH_JMPEVAL &&
1505 (execflg2 ||
1506 (execflg && shp->fn_depth == 0 && !(pipejob && sh_isoption(shp, SH_PIPEFAIL))));
1507 if (sh_isstate(shp, SH_PROFILE) || shp->dot_depth) {
1508 // Disable foreground job monitor.
1509 if (!(type & FAMP)) {
1510 sh_offstate(shp, SH_MONITOR);
1511 #if has_dev_fd
1512 } else if (!(type & FINT)) {
1513 sh_offstate(shp, SH_MONITOR);
1514 #endif // has_dev_fd
1515 }
1516 }
1517 if (no_fork) {
1518 job.parent = parent = 0;
1519 } else {
1520 if (((type & (FAMP | FINT)) == (FAMP | FINT)) &&
1521 (job.maxjob = nv_getnum(VAR_JOBMAX)) > 0) {
1522 while (job.numbjob >= job.maxjob) {
1523 job_lock();
1524 job_reap(0);
1525 job_unlock();
1526 }
1527 }
1528 nv_getval(VAR_RANDOM);
1529 restorefd = shp->topfd;
1530 #if USE_SPAWN
1531 restorevex = shp->vexp->cur;
1532 #endif
1533 if (type & FCOOP) {
1534 pipes[2] = 0;
1535 coproc_init(shp, pipes);
1536 }
1537
1538 #if USE_SPAWN
1539 if (com) {
1540 parent = sh_ntfork(shp, t, com, &jobid, ntflag);
1541 } else {
1542 parent = sh_fork(shp, type, &jobid);
1543 }
1544
1545 if (parent < 0) {
1546 #if USE_SPAWN
1547 if (shp->comsub == 1 && usepipe && unpipe) sh_iounpipe(shp);
1548 #endif // USE_SPAWN
1549 break;
1550 }
1551 #else // USE_SPAWN
1552 parent = sh_fork(shp, type, &jobid);
1553 #endif // USE_SPAWN
1554 }
1555 job.parent = parent;
1556 if (!job.parent) {
1557 forked_child(shp, t, flags, type, no_fork, com0, com, parent, topfd, vexi);
1558 __builtin_unreachable();
1559 }
1560 // This is the parent branch of fork. It may or may not wait for the child.
1561 if (pipejob == 2) {
1562 pipejob = 1;
1563 nlock--;
1564 job_unlock();
1565 }
1566 if (shp->subshell) shp->spid = parent;
1567 if (type & FPCL) sh_close(shp->inpipe[0]);
1568 if (type & (FCOOP | FAMP)) {
1569 shp->bckpid = parent;
1570 } else if (!(type & (FAMP | FPOU))) {
1571 if (!sh_isoption(shp, SH_MONITOR)) {
1572 if (!(shp->sigflag[SIGINT] & (SH_SIGFAULT | SH_SIGOFF))) {
1573 sh_sigtrap(shp, SIGINT);
1574 }
1575 shp->trapnote |= SH_SIGIGNORE;
1576 }
1577 if (shp->pipepid) {
1578 shp->pipepid = parent;
1579 } else {
1580 job_wait(parent);
1581 if (parent == shp->spid) shp->spid = 0;
1582 }
1583 if (shp->topfd > topfd) sh_iorestore(shp, topfd, 0);
1584 #if USE_SPAWN
1585 if (shp->vexp->cur > vexi) sh_vexrestore(shp, vexi);
1586 #endif
1587 if (usepipe && tsetio && subdup) sh_iounpipe(shp);
1588 if (!sh_isoption(shp, SH_MONITOR)) {
1589 shp->trapnote &= ~SH_SIGIGNORE;
1590 if (shp->exitval == (SH_EXITSIG | SIGINT)) kill(getpid(), SIGINT);
1591 }
1592 }
1593 if (type & FAMP) {
1594 if (sh_isstate(shp, SH_PROFILE) || sh_isstate(shp, SH_INTERACTIVE)) {
1595 /* print job number */
1596 #ifdef JOBS
1597 sfprintf(sfstderr, "[%d]\t%d\n", jobid, parent);
1598 #else // JOBS
1599 sfprintf(sfstderr, "%d\n", parent);
1600 #endif // JOBS
1601 }
1602 }
1603 break;
1604 }
1605 case TSETIO: {
1606 // Don't create a new process, just save and restore io-streams.
1607 pid_t pid;
1608 int jmpval, waitall;
1609 int simple = (t->fork.forktre->tre.tretyp & COMMSK) == TCOM;
1610 checkpt_t *buffp = stkalloc(shp->stk, sizeof(checkpt_t));
1611 if (shp->subshell) execflg = 0;
1612 sh_pushcontext(shp, buffp, SH_JMPIO);
1613 if (type & FPIN) {
1614 was_interactive = sh_isstate(shp, SH_INTERACTIVE);
1615 sh_offstate(shp, SH_INTERACTIVE);
1616 shp->pipepid = simple;
1617 sh_iosave(shp, 0, shp->topfd, NULL);
1618 sh_iorenumber(shp, shp->inpipe[0], 0);
1619 // if read end of pipe is a simple command treat as non-sharable to improve
1620 // performance.
1621 if (simple) sfset(sfstdin, SF_PUBLIC | SF_SHARE, 0);
1622 waitall = job.waitall;
1623 job.waitall = 0;
1624 pid = job.parent;
1625 } else {
1626 error_info.line = t->fork.forkline - shp->st.firstline;
1627 }
1628 jmpval = sigsetjmp(buffp->buff, 0);
1629 if (jmpval == 0) {
1630 if (shp->comsub) tsetio = 1;
1631 sh_redirect(shp, t->fork.forkio, execflg);
1632 (t->fork.forktre)->tre.tretyp |= t->tre.tretyp & FSHOWME;
1633 t = t->fork.forktre;
1634 #if SHOPT_BASH
1635 if ((t->tre.tretyp & COMMSK) == TCOM && sh_isoption(shp, SH_BASH) &&
1636 !sh_isoption(shp, SH_LASTPIPE)) {
1637 Shnode_t *tt = stkalloc(shp->stk, sizeof(Shnode_t));
1638 tt->par.partyp = type = TPAR;
1639 tt->par.partre = (Shnode_t *)t;
1640 t = tt;
1641 }
1642 #endif // SHOPT_BASH
1643 sh_exec(shp, t, flags & ~simple);
1644 } else {
1645 sfsync(shp->outpool);
1646 }
1647 sh_popcontext(shp, buffp);
1648 sh_iorestore(shp, buffp->topfd, jmpval);
1649 #if USE_SPAWN
1650 if (shp->vexp->cur > vexi) sh_vexrestore(shp, buffp->vexi);
1651 #endif
1652 if (buffp->olist) free_list(buffp->olist);
1653 if (type & FPIN) {
1654 job.waitall = waitall;
1655 type = shp->exitval;
1656 if (!(type & SH_EXITSIG)) {
1657 // Wait for remainder of pipline.
1658 if (shp->pipepid > 1 && shp->comsub != 1) {
1659 job_wait(shp->pipepid);
1660 type = shp->exitval;
1661 } else {
1662 job_wait(waitall ? pid : 0);
1663 }
1664 if (type || !sh_isoption(shp, SH_PIPEFAIL)) shp->exitval = type;
1665 }
1666 shp->pipepid = 0;
1667 shp->st.ioset = 0;
1668 if (simple && was_errexit) {
1669 echeck = 1;
1670 sh_onstate(shp, SH_ERREXIT);
1671 }
1672 }
1673 if (jmpval > SH_JMPIO) siglongjmp(shp->jmplist->buff, jmpval);
1674 break;
1675 }
1676 case TPAR: {
1677 echeck = 1;
1678 flags &= ~ARG_OPTIMIZE;
1679 if (!shp->subshell && !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] &&
1680 (flags & sh_state(SH_NOFORK))) {
1681 char *savsig;
1682 int nsig, jmpval;
1683 checkpt_t *buffp = stkalloc(shp->stk, sizeof(checkpt_t));
1684 shp->st.otrapcom = NULL;
1685
1686 nsig = shp->st.trapmax;
1687 if (nsig > 0 || shp->st.trapcom[0]) {
1688 int trapcom_size = (shp->st.trapmax + 1) * sizeof(char *);
1689 savsig = malloc(trapcom_size);
1690 memcpy(savsig, shp->st.trapcom, trapcom_size);
1691 shp->st.otrapcom = (char **)savsig;
1692 }
1693 sh_sigreset(shp, 0);
1694 sh_pushcontext(shp, buffp, SH_JMPEXIT);
1695 jmpval = sigsetjmp(buffp->buff, 0);
1696 if (jmpval == 0) sh_exec(shp, t->par.partre, flags);
1697 sh_popcontext(shp, buffp);
1698 if (jmpval > SH_JMPEXIT) siglongjmp(shp->jmplist->buff, jmpval);
1699 if (shp->exitval > 256) shp->exitval -= 128;
1700 sh_done(shp, 0);
1701 } else if (((type = t->par.partre->tre.tretyp) & FAMP) && ((type & COMMSK) == TFORK)) {
1702 pid_t pid;
1703 sfsync(NULL);
1704 while ((pid = fork()) < 0) _sh_fork(shp, pid, 0, 0);
1705 if (pid == 0) {
1706 sh_exec(shp, t->par.partre, flags);
1707 shp->st.trapcom[0] = 0;
1708 sh_offoption(shp, SH_INTERACTIVE);
1709 sh_done(shp, 0);
1710 }
1711 } else {
1712 sh_subshell(shp, t->par.partre, flags, 0);
1713 }
1714 break;
1715 }
1716 case TFIL: {
1717 // This code sets up a pipe. All elements of the pipe are started by the parent. The
1718 // last element executes in current environment.
1719 int pvo[3]; // old pipe for multi-stage
1720 int pvn[3]; // current set up pipe
1721 int savepipe = pipejob;
1722 int savelock = nlock;
1723 int showme = t->tre.tretyp & FSHOWME;
1724 int n, waitall, savewaitall = job.waitall;
1725 int savejobid = job.curjobid;
1726 int *exitval = NULL, *saveexitval = job.exitval;
1727 pid_t savepgid = job.curpgid;
1728 job.exitval = NULL;
1729 job.curjobid = 0;
1730 if (shp->subshell) {
1731 sh_subtmpfile(shp);
1732 if (shp->comsub == 1 && !(shp->fdstatus[1] & IONOSEEK)) iousepipe(shp);
1733 }
1734 shp->inpipe = pvo;
1735 shp->outpipe = pvn;
1736 pvo[1] = -1;
1737 if (sh_isoption(shp, SH_PIPEFAIL)) {
1738 const Shnode_t *tn = t;
1739 job.waitall = 2;
1740 job.curpgid = 0;
1741 while ((tn = tn->lst.lstrit) && tn->tre.tretyp == TFIL) job.waitall++;
1742 exitval = job.exitval = stkalloc(shp->stk, job.waitall * sizeof(int));
1743 memset(exitval, 0, job.waitall * sizeof(int));
1744 } else {
1745 job.waitall |= !pipejob && sh_isstate(shp, SH_MONITOR);
1746 }
1747 job_lock();
1748 nlock++;
1749 do {
1750 // Create the pipe.
1751 sh_pipe(pvn);
1752 // Execute out part of pipe no wait.
1753 (t->lst.lstlef)->tre.tretyp |= showme;
1754 type = sh_exec(shp, t->lst.lstlef, errorflg);
1755 // Close out-part of pipe.
1756 sh_close(pvn[1]);
1757 pipejob = 1;
1758 // Save the pipe stream-ids.
1759 pvo[0] = pvn[0];
1760 // Pipeline all in one process group.
1761 t = t->lst.lstrit;
1762 }
1763 // Repeat until end of pipeline.
1764 while (!type && t->tre.tretyp == TFIL);
1765 shp->inpipe = pvn;
1766 shp->outpipe = NULL;
1767 pipejob = 2;
1768 waitall = job.waitall;
1769 job.waitall = 0;
1770 if (type == 0) {
1771 // Execute last element of pipeline in the current process.
1772 ((Shnode_t *)t)->tre.tretyp |= showme;
1773 sh_exec(shp, t, flags);
1774 } else {
1775 // Execution failure, close pipe.
1776 sh_pclose(pvn);
1777 }
1778 if (pipejob == 2) job_unlock();
1779 if ((pipejob = savepipe) && nlock < savelock) pipejob = 1;
1780 n = shp->exitval;
1781 job.waitall = waitall;
1782 if (job.waitall) {
1783 if (sh_isstate(shp, SH_MONITOR)) {
1784 job_wait(0);
1785 } else {
1786 shp->intrap++;
1787 job_wait(0);
1788 shp->intrap--;
1789 }
1790 }
1791 if (n == 0 && exitval) {
1792 while (exitval <= --job.exitval) {
1793 if (*job.exitval) {
1794 n = *job.exitval;
1795 break;
1796 }
1797 }
1798 }
1799 shp->exitval = n;
1800 #ifdef SIGTSTP
1801 if (!pipejob && sh_isstate(shp, SH_MONITOR) && sh_isoption(shp, SH_INTERACTIVE)) {
1802 tcsetpgrp(JOBTTY, shp->gd->pid);
1803 }
1804 #endif // SIGTSTP
1805 job.curpgid = savepgid;
1806 job.exitval = saveexitval;
1807 job.waitall = savewaitall;
1808 job.curjobid = savejobid;
1809 break;
1810 }
1811 case TLST: {
1812 // A list of commands are executed here.
1813 do {
1814 sh_exec(shp, t->lst.lstlef, errorflg | (flags & ARG_OPTIMIZE));
1815 t = t->lst.lstrit;
1816 } while (t->tre.tretyp == TLST);
1817 sh_exec(shp, t, flags);
1818 break;
1819 }
1820 case TAND: {
1821 if (type & TTEST) skipexitset++;
1822 if (sh_exec(shp, t->lst.lstlef, (flags & ARG_OPTIMIZE)) == 0) {
1823 sh_exec(shp, t->lst.lstrit, flags);
1824 }
1825 break;
1826 }
1827 case TORF: {
1828 if (type & TTEST) skipexitset++;
1829 if (sh_exec(shp, t->lst.lstlef, flags & ARG_OPTIMIZE) != 0) {
1830 sh_exec(shp, t->lst.lstrit, flags);
1831 }
1832 break;
1833 }
1834 case TFOR: { // for and select
1835 char **args;
1836 int nargs;
1837 Namval_t *np;
1838 int flag = errorflg | ARG_OPTIMIZE;
1839 struct dolnod *argsav = NULL;
1840 struct comnod *tp;
1841 char *trap;
1842 char *nullptr = NULL;
1843 int nameref, refresh = 1;
1844 char *av[5];
1845 int jmpval = shp->jmplist->mode;
1846 checkpt_t *buffp = stkalloc(shp->stk, sizeof(checkpt_t));
1847 void *optlist = shp->optlist;
1848 shp->optlist = NULL;
1849 sh_tclear(shp, t->for_.fortre);
1850 sh_pushcontext(shp, buffp, jmpval);
1851 jmpval = sigsetjmp(buffp->buff, 0);
1852 if (jmpval) goto endfor;
1853 error_info.line = t->for_.forline - shp->st.firstline;
1854 if (!(tp = t->for_.forlst)) {
1855 args = shp->st.dolv + 1;
1856 nargs = shp->st.dolc;
1857 argsav = sh_arguse(shp);
1858 } else {
1859 args = sh_argbuild(shp, &argn, tp, 0);
1860 nargs = argn;
1861 }
1862 np = nv_open(t->for_.fornam, shp->var_tree, NV_NOARRAY | NV_VARNAME | NV_NOREF);
1863 nameref = nv_isref(np) != 0;
1864 shp->st.loopcnt++;
1865 cp = *args;
1866 while (cp && shp->st.execbrk == 0) {
1867 if (t->tre.tretyp & COMSCAN) {
1868 char *val;
1869 int save_prompt;
1870 // Reuse.
1871 if (refresh) {
1872 sh_menu(shp, sfstderr, nargs, args);
1873 refresh = 0;
1874 }
1875 save_prompt = shp->nextprompt;
1876 shp->nextprompt = 3;
1877 shp->timeout = 0;
1878 shp->exitval =
1879 sh_readline(shp, &nullptr, NULL, 0, 1, (size_t)0, 1000 * shp->st.tmout);
1880 shp->nextprompt = save_prompt;
1881 if (shp->exitval || sfeof(sfstdin) || sferror(sfstdin)) {
1882 shp->exitval = 1;
1883 break;
1884 }
1885 if (!(val = nv_getval(sh_scoped(shp, VAR_REPLY)))) {
1886 continue;
1887 } else {
1888 if (*(cp = val) == 0) {
1889 refresh++;
1890 goto check;
1891 }
1892 while ((type = *cp++)) {
1893 if (type < '0' && type > '9') break;
1894 }
1895 if (type != 0) {
1896 type = nargs;
1897 } else {
1898 type = (int)strtol(val, NULL, 10) - 1;
1899 }
1900 if (type < 0 || type >= nargs) {
1901 cp = "";
1902 } else {
1903 cp = args[type];
1904 }
1905 }
1906 }
1907 if (nameref) {
1908 nv_offattr(np, NV_REF | NV_TABLE);
1909 } else if (nv_isattr(np, NV_ARRAY)) {
1910 nv_putsub(np, NULL, 0L, 0);
1911 }
1912 nv_putval(np, cp, 0);
1913 if (nameref) {
1914 nv_setref(np, NULL, NV_VARNAME);
1915 nv_onattr(np, NV_TABLE);
1916 }
1917 trap = shp->st.trap[SH_DEBUGTRAP];
1918 if (trap) {
1919 av[0] = (t->tre.tretyp & COMSCAN) ? "select" : "for";
1920 av[1] = t->for_.fornam;
1921 av[2] = "in";
1922 av[3] = cp;
1923 av[4] = 0;
1924 sh_debug(shp, trap, NULL, NULL, av, 0);
1925 }
1926 sh_exec(shp, t->for_.fortre, flag);
1927 flag &= ~ARG_OPTIMIZE;
1928 if (t->tre.tretyp & COMSCAN) {
1929 if ((cp = nv_getval(sh_scoped(shp, VAR_REPLY))) && *cp == 0) refresh++;
1930 } else {
1931 cp = *++args;
1932 }
1933 check:
1934 if (shp->st.breakcnt < 0) shp->st.execbrk = (++shp->st.breakcnt != 0);
1935 }
1936 if (nameref) nv_offattr(np, NV_TABLE);
1937 endfor:
1938 sh_popcontext(shp, buffp);
1939 sh_tclear(shp, t->for_.fortre);
1940 sh_optclear(shp, optlist);
1941 if (jmpval) siglongjmp(shp->jmplist->buff, jmpval);
1942 if (shp->st.breakcnt > 0) shp->st.execbrk = (--shp->st.breakcnt != 0);
1943 shp->st.loopcnt--;
1944 sh_argfree(shp, argsav);
1945 nv_close(np);
1946 break;
1947 }
1948 case TWH: { // while and until
1949 volatile int r = 0;
1950 int first = ARG_OPTIMIZE;
1951 Shnode_t *tt = t->wh.whtre;
1952 Sfio_t *iop = NULL;
1953 int savein;
1954 int jmpval = shp->jmplist->mode;
1955 checkpt_t *buffp = stkalloc(shp->stk, sizeof(checkpt_t));
1956 void *optlist = shp->optlist;
1957 shp->optlist = NULL;
1958 sh_tclear(shp, t->wh.whtre);
1959 sh_tclear(shp, t->wh.dotre);
1960 sh_pushcontext(shp, buffp, jmpval);
1961 jmpval = sigsetjmp(buffp->buff, 0);
1962 if (jmpval) goto endwhile;
1963 if (type == TWH && tt->tre.tretyp == TCOM && !tt->com.comarg && tt->com.comio) {
1964 iop = openstream(shp, tt->com.comio, &savein);
1965 if (tt->com.comset) sh_setlist(shp, tt->com.comset, NV_IDENT | NV_ASSIGN, 0);
1966 }
1967 shp->st.loopcnt++;
1968 while (shp->st.execbrk == 0) {
1969 if (iop) {
1970 if (!(shp->cur_line = sfgetr(iop, '\n', SF_STRING))) break;
1971 } else if ((sh_exec(shp, tt, first) == 0) != (type == TWH)) {
1972 break;
1973 }
1974 r = sh_exec(shp, t->wh.dotre, first | errorflg);
1975 if (shp->st.breakcnt < 0) shp->st.execbrk = (++shp->st.breakcnt != 0);
1976 // This is for the arithmetic for.
1977 if (shp->st.execbrk == 0 && t->wh.whinc) {
1978 sh_exec(shp, (Shnode_t *)t->wh.whinc, first);
1979 }
1980 first = 0;
1981 errorflg &= ~ARG_OPTIMIZE;
1982 shp->offsets[0] = -1;
1983 shp->offsets[1] = 0;
1984 }
1985 endwhile:
1986 sh_popcontext(shp, buffp);
1987 sh_tclear(shp, t->wh.whtre);
1988 sh_tclear(shp, t->wh.dotre);
1989 sh_optclear(shp, optlist);
1990 if (jmpval) siglongjmp(shp->jmplist->buff, jmpval);
1991 if (shp->st.breakcnt > 0) shp->st.execbrk = (--shp->st.breakcnt != 0);
1992 shp->st.loopcnt--;
1993 shp->exitval = r;
1994 if (iop) {
1995 int err = errno;
1996 sfclose(iop);
1997 while (close(0) < 0 && errno == EINTR) errno = err;
1998 int dup_fd = dup(savein); // it has to return zero
1999 assert(dup_fd == 0);
2000 shp->cur_line = NULL;
2001 }
2002 break;
2003 }
2004 case TARITH: { // (( expression ))
2005 char *trap;
2006 char *arg[4];
2007 error_info.line = t->ar.arline - shp->st.firstline;
2008 arg[0] = "((";
2009 if (!(t->ar.arexpr->argflag & ARG_RAW)) {
2010 arg[1] = sh_macpat(shp, t->ar.arexpr, (flags & ARG_OPTIMIZE) | ARG_ARITH);
2011 } else {
2012 arg[1] = t->ar.arexpr->argval;
2013 }
2014 arg[2] = "))";
2015 arg[3] = 0;
2016 trap = shp->st.trap[SH_DEBUGTRAP];
2017 if (trap) {
2018 sh_debug(shp, trap, NULL, NULL, arg, ARG_ARITH);
2019 }
2020 if (sh_isoption(shp, SH_XTRACE)) {
2021 sh_trace(shp, NULL, 0);
2022 sfprintf(sfstderr, "((%s))\n", arg[1]);
2023 }
2024 if (t->ar.arcomp) {
2025 shp->exitval = !arith_exec((Arith_t *)t->ar.arcomp);
2026 } else {
2027 shp->exitval = !sh_arith(shp, arg[1]);
2028 }
2029 break;
2030 }
2031 case TIF: {
2032 if (sh_exec(shp, t->if_.iftre, flags & ARG_OPTIMIZE) == 0) {
2033 sh_exec(shp, t->if_.thtre, flags);
2034 } else if (t->if_.eltre) {
2035 sh_exec(shp, t->if_.eltre, flags);
2036 } else {
2037 shp->exitval = 0; // force zero exit for if-then-fi
2038 }
2039 break;
2040 }
2041 case TSW: {
2042 Shnode_t *tt = (Shnode_t *)t;
2043 char *trap, *r = sh_macpat(shp, tt->sw.swarg, flags & ARG_OPTIMIZE);
2044 error_info.line = t->sw.swline - shp->st.firstline;
2045 t = (Shnode_t *)(tt->sw.swlst);
2046 trap = shp->st.trap[SH_DEBUGTRAP];
2047 if (trap) {
2048 char *av[4];
2049 av[0] = "case";
2050 av[1] = r;
2051 av[2] = "in";
2052 av[3] = 0;
2053 sh_debug(shp, trap, NULL, NULL, av, 0);
2054 }
2055 while (t) {
2056 struct argnod *rex = (struct argnod *)t->reg.regptr;
2057 while (rex) {
2058 char *s;
2059 if (rex->argflag & ARG_MAC) {
2060 s = sh_macpat(shp, rex, (flags & ARG_OPTIMIZE) | ARG_EXP | ARG_CASE);
2061 while (*s == '\\' && s[1] == 0) s += 2;
2062 } else {
2063 s = rex->argval;
2064 }
2065 type = (rex->argflag & ARG_RAW);
2066 if ((type && strcmp(r, s) == 0) || (!type && strmatch(r, s))) {
2067 do {
2068 sh_exec(shp, t->reg.regcom,
2069 (t->reg.regflag ? (flags & sh_state(SH_ERREXIT)) : flags));
2070 } while (t->reg.regflag && (t = (Shnode_t *)t->reg.regnxt));
2071 t = 0;
2072 break;
2073 } else {
2074 rex = rex->argnxt.ap;
2075 }
2076 }
2077 if (t) t = (Shnode_t *)t->reg.regnxt;
2078 }
2079 break;
2080 }
2081 case TTIME: { // time the command
2082 const char *format = e_timeformat;
2083 struct timeval ta, tb, tm[3];
2084 struct timeval before_usr, before_sys, after_usr, after_sys;
2085
2086 if (type != TTIME) {
2087 sh_exec(shp, t->par.partre, flags & ARG_OPTIMIZE);
2088 shp->exitval = !shp->exitval;
2089 break;
2090 }
2091 gettimeofday(&tb, NULL);
2092 get_cpu_times(&before_usr, &before_sys);
2093 if (t->par.partre) {
2094 if (shp->subshell && shp->comsub == 1) sh_subfork();
2095 long timer_on = sh_isstate(shp, SH_TIMING);
2096 job.waitall = 1;
2097 sh_onstate(shp, SH_TIMING);
2098 sh_exec(shp, t->par.partre, flags & ARG_OPTIMIZE);
2099 if (!timer_on) sh_offstate(shp, SH_TIMING);
2100 job.waitall = 0;
2101 }
2102 get_cpu_times(&after_usr, &after_sys);
2103 gettimeofday(&ta, NULL);
2104 timersub(&ta, &tb, &tm[TM_REAL_IDX]); // calculate elapsed real-time
2105 timersub(&after_usr, &before_usr, &tm[TM_USR_IDX]);
2106 timersub(&after_sys, &before_sys, &tm[TM_SYS_IDX]);
2107
2108 if (t->par.partre) {
2109 Namval_t *np = nv_open("TIMEFORMAT", shp->var_tree, NV_NOADD);
2110 if (np) {
2111 format = nv_getval(np);
2112 nv_close(np);
2113 }
2114 if (!format) format = e_timeformat;
2115 } else {
2116 format = strchr(format + 1, '\n') + 1;
2117 }
2118 if (format && *format) p_time(shp, sfstderr, sh_translate(format), tm);
2119 break;
2120 }
2121 case TFUN: {
2122 Namval_t *np = NULL;
2123 struct slnod *slp;
2124 char *fname = ((struct functnod *)t)->functnam;
2125 Namval_t *npv = 0, *mp;
2126 cp = strrchr(fname, '.');
2127 if (t->tre.tretyp == TNSPACE) {
2128 Namval_t *oldnspace = NULL;
2129 int offset = stktell(stkp);
2130 nvflag_t nvflags = NV_NOARRAY | NV_VARNAME;
2131 char *sp, *xp;
2132 sfputc(stkp, '.');
2133 sfputr(stkp, fname, 0);
2134 xp = stkptr(stkp, offset);
2135 for (sp = xp + 1; sp;) {
2136 sp = strchr(sp, '.');
2137 if (sp) *sp = 0;
2138 np = nv_open(xp, shp->var_tree, nvflags);
2139 if (sp) *sp++ = '.';
2140 }
2141 if (!nv_istable(np)) {
2142 Dt_t *root = dtopen(&_Nvdisc, Dtoset);
2143 dtuserdata(root, shp, 1);
2144 nv_mount(np, NULL, root);
2145 STORE_VT(np->nvalue, const_cp, Empty);
2146 dtview(root, shp->var_base);
2147 }
2148 oldnspace = enter_namespace(shp, np);
2149 sh_exec(shp, t->for_.fortre, nvflags | sh_state(SH_ERREXIT));
2150 enter_namespace(shp, oldnspace);
2151 break;
2152 }
2153 // Look for discipline functions.
2154 error_info.line = t->funct.functline - shp->st.firstline;
2155 // Function names cannot be special builtin.
2156 if (cp || shp->prefix) {
2157 int offset = stktell(stkp);
2158 if (shp->prefix) {
2159 cp = shp->prefix;
2160 shp->prefix = NULL;
2161 npv = nv_open(cp, shp->var_tree, NV_NOARRAY | NV_VARNAME);
2162 shp->prefix = cp;
2163 cp = fname;
2164 } else {
2165 sfwrite(stkp, fname, cp++ - fname);
2166 sfputc(stkp, 0);
2167 npv = nv_open(stkptr(stkp, offset), shp->var_tree, NV_NOARRAY | NV_VARNAME);
2168 }
2169 offset = stktell(stkp);
2170 sfprintf(stkp, "%s.%s%c", nv_name(npv), cp, 0);
2171 fname = stkptr(stkp, offset);
2172 } else if ((mp = nv_search(fname, shp->bltin_tree, 0)) && nv_isattr(mp, BLT_SPC)) {
2173 errormsg(SH_DICT, ERROR_exit(1), e_badfun, fname);
2174 __builtin_unreachable();
2175 }
2176 if (shp->namespace && !shp->prefix && *fname != '.') {
2177 np = sh_fsearch(shp, fname, NV_ADD | NV_NOSCOPE);
2178 }
2179 if (!np) {
2180 np = nv_open(fname, sh_subfuntree(shp, true), NV_NOARRAY | NV_VARNAME | NV_NOSCOPE);
2181 }
2182 if (npv) {
2183 if (!shp->mktype) cp = nv_setdisc(npv, cp, np, (Namfun_t *)npv);
2184 if (!cp) {
2185 errormsg(SH_DICT, ERROR_exit(1), e_baddisc, fname);
2186 __builtin_unreachable();
2187 }
2188 }
2189 if (FETCH_VT(np->nvalue, rp)) {
2190 struct Ufunction *rp = FETCH_VT(np->nvalue, rp);
2191 slp = (struct slnod *)np->nvenv;
2192 sh_funstaks(slp->slchild, -1);
2193 stkclose(slp->slptr);
2194 if (rp->sdict) {
2195 Namval_t *nq;
2196 shp->last_root = rp->sdict;
2197 for (mp = dtfirst(rp->sdict); mp; mp = nq) {
2198 _nv_unset(mp, NV_RDONLY);
2199 nq = dtnext(rp->sdict, mp);
2200 nv_delete(mp, rp->sdict, 0);
2201 }
2202 dtclose(rp->sdict);
2203 rp->sdict = NULL;
2204 }
2205 if (shp->funload) {
2206 if (!shp->fpathdict) free(FETCH_VT(np->nvalue, rp));
2207 STORE_VT(np->nvalue, rp, NULL);
2208 }
2209 }
2210 if (!FETCH_VT(np->nvalue, rp)) {
2211 struct Ufunction *rp =
2212 calloc(1, sizeof(struct Ufunction) + (shp->funload ? sizeof(Dtlink_t) : 0));
2213 STORE_VT(np->nvalue, rp, rp);
2214 }
2215 if (t->funct.functstak) {
2216 static Dtdisc_t _Rpdisc = {.key = offsetof(struct Ufunction, fname),
2217 .size = -1,
2218 .link = sizeof(struct Ufunction)};
2219 struct functnod *fp;
2220 struct comnod *ac = t->funct.functargs;
2221 slp = t->funct.functstak;
2222 sh_funstaks(slp->slchild, 1);
2223 stklink(slp->slptr);
2224 np->nvenv = (Namval_t *)slp;
2225 nv_funtree(np) = (int *)(t->funct.functtre);
2226 FETCH_VT(np->nvalue, rp)->hoffset = t->funct.functloc;
2227 FETCH_VT(np->nvalue, rp)->lineno = t->funct.functline;
2228 FETCH_VT(np->nvalue, rp)->nspace = shp->namespace;
2229 FETCH_VT(np->nvalue, rp)->fname = NULL;
2230 FETCH_VT(np->nvalue, rp)->argv = ac ? ((struct dolnod *)ac->comarg)->dolval + 1 : 0;
2231 FETCH_VT(np->nvalue, rp)->argc = ac ? ((struct dolnod *)ac->comarg)->dolnum : 0;
2232 FETCH_VT(np->nvalue, rp)->fdict = shp->fun_tree;
2233 fp = (struct functnod *)(slp + 1);
2234 if (fp->functtyp == (TFUN | FAMP)) FETCH_VT(np->nvalue, rp)->fname = fp->functnam;
2235 nv_setsize(np, fp->functline);
2236 nv_offattr(np, NV_FPOSIX);
2237 if (shp->funload) {
2238 struct Ufunction *rp = FETCH_VT(np->nvalue, rp);
2239 rp->np = np;
2240 if (!shp->fpathdict) shp->fpathdict = dtopen(&_Rpdisc, Dtobag);
2241 if (shp->fpathdict) {
2242 dtuserdata(shp->fpathdict, shp, 1);
2243 dtinsert(shp->fpathdict, rp);
2244 }
2245 }
2246 } else {
2247 _nv_unset(np, 0);
2248 }
2249 if (type & FPOSIX) {
2250 nv_onattr(np, NV_FUNCTION | NV_FPOSIX);
2251 } else {
2252 nv_onattr(np, NV_FUNCTION);
2253 }
2254 if (type & FPIN) nv_onattr(np, NV_FTMP);
2255 if (type & FOPTGET) nv_onattr(np, NV_OPTGET);
2256 if (type & FSHVALUE) nv_onattr(np, NV_SHVALUE);
2257 break;
2258 }
2259 case TTST: { // new test compound command
2260 int n;
2261 char *left;
2262 int negate = (type & TNEGATE) != 0;
2263 if (type & TTEST) skipexitset++;
2264 error_info.line = t->tst.tstline - shp->st.firstline;
2265 echeck = 1;
2266 if ((type & TPAREN) == TPAREN) {
2267 sh_exec(shp, t->lst.lstlef, flags & ARG_OPTIMIZE);
2268 n = !shp->exitval;
2269 } else {
2270 bool traceon = 0;
2271 char *right;
2272 char *trap;
2273 char *argv[6];
2274 int savexit = shp->savexit;
2275 n = type >> TSHIFT;
2276 left = sh_macpat(shp, &(t->lst.lstlef->arg), flags & ARG_OPTIMIZE);
2277 if (type & TBINARY) {
2278 right = sh_macpat(
2279 shp, &(t->lst.lstrit->arg),
2280 ((n == TEST_PEQ || n == TEST_PNE) ? ARG_EXP : 0) | (flags & ARG_OPTIMIZE));
2281 }
2282 shp->savexit = savexit;
2283 trap = shp->st.trap[SH_DEBUGTRAP];
2284 if (trap) {
2285 argv[0] = (type & TNEGATE) ? ((char *)e_tstbegin) : "[[";
2286 }
2287 if (sh_isoption(shp, SH_XTRACE)) {
2288 traceon = sh_trace(shp, NULL, 0);
2289 sfwrite(sfstderr, e_tstbegin, (type & TNEGATE ? 5 : 3));
2290 }
2291 if (type & TUNARY) {
2292 if (traceon) sfprintf(sfstderr, "-%c %s", n, sh_fmtq(left));
2293 if (trap) {
2294 char unop[3];
2295 unop[0] = '-';
2296 unop[1] = n;
2297 unop[2] = 0;
2298 argv[1] = unop;
2299 argv[2] = left;
2300 argv[3] = "]]";
2301 argv[4] = 0;
2302 sh_debug(shp, trap, NULL, NULL, argv, 0);
2303 }
2304 n = test_unop(shp, n, left);
2305 } else if (type & TBINARY) {
2306 char *op;
2307 int pattern = 0;
2308 if (trap || traceon) op = (char *)(shtab_testops + (n & 037) - 1)->sh_name;
2309 type >>= TSHIFT;
2310 if (type == TEST_PEQ || type == TEST_PNE) pattern = ARG_EXP;
2311 if (trap) {
2312 argv[1] = left;
2313 argv[2] = op;
2314 argv[3] = right;
2315 argv[4] = "]]";
2316 argv[5] = 0;
2317 sh_debug(shp, trap, NULL, NULL, argv, pattern);
2318 }
2319 n = test_binop(shp, n, left, right);
2320 if (traceon) {
2321 sfprintf(sfstderr, "%s %s ", sh_fmtq(left), op);
2322 if (pattern) {
2323 out_pattern(sfstderr, right, -1);
2324 } else {
2325 sfputr(sfstderr, sh_fmtq(right), -1);
2326 }
2327 }
2328 }
2329 if (traceon) sfwrite(sfstderr, e_tstend, 4);
2330 }
2331 shp->exitval = ((!n) ^ negate);
2332 if (!skipexitset) exitset(shp);
2333 break;
2334 }
2335 default: { break; }
2336 }
2337
2338 if (procsub && *procsub) {
2339 pid_t pid;
2340 int exitval = shp->exitval;
2341 while ((pid = *procsub++)) job_wait(pid);
2342 shp->exitval = exitval;
2343 }
2344 if (shp->trapnote || (shp->exitval && sh_isstate(shp, SH_ERREXIT) && t && echeck)) {
2345 sh_chktrap(shp);
2346 }
2347 // Set $_.
2348 if (mainloop && com0) {
2349 // Store last argument here if it fits.
2350 static char lastarg[PATH_MAX];
2351 if (sh_isstate(shp, SH_FORKED)) sh_done(shp, 0);
2352 if (shp->lastarg != lastarg && shp->lastarg) free(shp->lastarg);
2353 // Although this node is marked as NV_NOFREE, it should get free'd above when $_ is
2354 // reset
2355 nv_onattr(VAR_underscore, NV_NOFREE);
2356 if (strlen(comn) < sizeof(lastarg)) {
2357 shp->lastarg = strcpy(lastarg, comn);
2358 } else {
2359 shp->lastarg = strdup(comn);
2360 }
2361 }
2362 if (!skipexitset) exitset(shp);
2363 if (!(flags & ARG_OPTIMIZE)) {
2364 if (sav != stkptr(stkp, 0)) {
2365 stkset(stkp, sav, 0);
2366 } else if (stktell(stkp)) {
2367 stkseek(stkp, 0);
2368 }
2369 }
2370 if (shp->trapnote & SH_SIGSET) sh_exit(shp, SH_EXITSIG | shp->lastsig);
2371 if (was_interactive) sh_onstate(shp, SH_INTERACTIVE);
2372 if (was_monitor && sh_isoption(shp, SH_MONITOR)) sh_onstate(shp, SH_MONITOR);
2373 if (was_errexit) sh_onstate(shp, SH_ERREXIT);
2374
2375 return shp->exitval;
2376 }
2377
2378 //
2379 // Print out the command line if set -x is on.
2380 //
sh_trace(Shell_t * shp,char * argv[],int nl)2381 bool sh_trace(Shell_t *shp, char *argv[], int nl) {
2382 char *cp;
2383 int bracket = 0;
2384 int decl = (nl & 2);
2385 nl &= ~2;
2386 if (sh_isoption(shp, SH_XTRACE)) {
2387 // Make this trace atomic.
2388 sfset(sfstderr, SF_SHARE | SF_PUBLIC, 0);
2389 if (!(cp = nv_getval(sh_scoped(shp, VAR_PS4)))) {
2390 cp = "+ ";
2391 } else {
2392 shp->intrace = 1;
2393 sh_offoption(shp, SH_XTRACE);
2394 cp = sh_mactry(shp, cp);
2395 sh_onoption(shp, SH_XTRACE);
2396 shp->intrace = 0;
2397 }
2398 if (*cp) sfputr(sfstderr, cp, -1);
2399 if (argv) {
2400 char *argv0 = *argv;
2401 nl = (nl ? '\n' : -1);
2402 // Don't quote [ and [[.
2403 cp = argv[0];
2404 if (*cp == '[' && (!cp[1] || (!cp[2] && cp[1] == '['))) {
2405 sfputr(sfstderr, cp, *++argv ? ' ' : nl);
2406 bracket = 1;
2407 }
2408 while ((cp = *argv++)) {
2409 if (bracket == 0 || *argv || *cp != ']') cp = sh_fmtq(cp);
2410 if (decl && shp->prefix && cp != argv0 && *cp != '-') {
2411 if (*cp == '.' && cp[1] == 0) {
2412 cp = shp->prefix;
2413 } else {
2414 sfputr(sfstderr, shp->prefix, '.');
2415 }
2416 }
2417 sfputr(sfstderr, cp, *argv ? ' ' : nl);
2418 }
2419 sfset(sfstderr, SF_SHARE | SF_PUBLIC, 1);
2420 }
2421 return true;
2422 }
2423 return false;
2424 }
2425
2426 //
2427 // This routine creates a subshell by calling fork().
2428 // If ((flags&COMASK)==TCOM), then fork() is permitted.
2429 // If fork fails, the shell sleeps for exponentially longer periods
2430 // and tries again until a limit is reached.
2431 // SH_FORKLIM is the max period between forks - power of 2 usually.
2432 // Currently shell tries after 2,4,8,16, and 32 seconds and then quits
2433 // Failures cause the routine to error exit.
2434 // Parent links to here-documents are removed by the child.
2435 // Traps are reset by the child.
2436 // The process-id of the child is returned to the parent, 0 to the child.
2437 //
timed_out(void * handle)2438 static_fn void timed_out(void *handle) {
2439 UNUSED(handle);
2440 timeout = NULL;
2441 }
2442
2443 //
2444 // Called by parent and child after fork by sh_fork().
2445 //
_sh_fork(Shell_t * shp,pid_t parent,int flags,int * jobid)2446 pid_t _sh_fork(Shell_t *shp, pid_t parent, int flags, int *jobid) {
2447 static long forkcnt = 1000L;
2448 pid_t curpgid = job.curpgid;
2449 pid_t postid = (flags & FAMP) ? 0 : curpgid;
2450 int sig, nochild;
2451
2452 if (parent < 0) {
2453 sh_sigcheck(shp);
2454 forkcnt *= 2;
2455 if (forkcnt > 1000L * SH_FORKLIM) {
2456 forkcnt = 1000L;
2457 errormsg(SH_DICT, ERROR_system(ERROR_NOEXEC), e_nofork);
2458 __builtin_unreachable();
2459 }
2460 timeout = sh_timeradd(forkcnt, 0, timed_out, NULL);
2461 nochild = job_wait((pid_t)1);
2462 if (timeout) {
2463 if (nochild) {
2464 pause();
2465 } else if (forkcnt > 1000L) {
2466 forkcnt /= 2;
2467 }
2468 timerdel(timeout);
2469 timeout = NULL;
2470 }
2471 return -1;
2472 }
2473 forkcnt = 1000L;
2474 if (parent) {
2475 int myjob, waitall = job.waitall;
2476 shp->gd->nforks++;
2477 if (job.toclear) job_clear(shp);
2478 job.waitall = waitall;
2479 #ifdef JOBS
2480 // First process defines process group.
2481 if (sh_isstate(shp, SH_MONITOR)) {
2482 // errno==EPERM means that an earlier processes completed. Make parent the job group
2483 // id.
2484 if (postid == 0) job.curpgid = job.jobcontrol ? parent : getpid();
2485 if (job.jobcontrol || (flags & FAMP)) {
2486 if (setpgid(parent, job.curpgid) < 0 && errno == EPERM) setpgid(parent, parent);
2487 }
2488 }
2489 #endif // JOBS
2490 if (!sh_isstate(shp, SH_MONITOR) && job.waitall && postid == 0) job.curpgid = parent;
2491 if (flags & FCOOP) shp->cpid = parent;
2492 if (!postid && job.curjobid && (flags & FPOU)) postid = job.curpgid;
2493 if (!postid && (flags & (FAMP | FINT)) == (FAMP | FINT)) postid = 1;
2494 myjob = job_post(shp, parent, postid);
2495 if (job.waitall && (flags & FPOU)) {
2496 if (!job.curjobid) job.curjobid = myjob;
2497 if (job.exitval) job.exitval++;
2498 }
2499 if (flags & FAMP) job.curpgid = curpgid;
2500 if (jobid) *jobid = myjob;
2501 if (shp->comsub == 1 && usepipe) {
2502 if (!tsetio || !subdup) {
2503 #if USE_SPAWN
2504 if (shp->vexp->cur > restorevex) sh_vexrestore(shp, restorevex);
2505 #endif
2506 if (shp->topfd > restorefd) sh_iorestore(shp, restorefd, 0);
2507 sh_iounpipe(shp);
2508 }
2509 }
2510 return parent;
2511 }
2512 shp->outpipepid = ((flags & FPOU) ? getpid() : 0);
2513 // This is the child process.
2514 if (shp->trapnote & SH_SIGTERM) sh_exit(shp, SH_EXITSIG | SIGTERM);
2515 shp->gd->nforks = 0;
2516 timerdel(NULL);
2517 #ifdef JOBS
2518 if (!job.jobcontrol && !(flags & FAMP)) sh_offstate(shp, SH_MONITOR);
2519 if (sh_isstate(shp, SH_MONITOR)) {
2520 parent = getpid();
2521 if (postid == 0) job.curpgid = parent;
2522 while (setpgid(0, job.curpgid) < 0 && job.curpgid != parent) job.curpgid = parent;
2523 #ifdef SIGTSTP
2524 if (job.curpgid == parent && !(flags & FAMP)) tcsetpgrp(job.fd, job.curpgid);
2525 #endif // SIGTSTP
2526 }
2527 #ifdef SIGTSTP
2528 if (job.jobcontrol) {
2529 sh_signal(SIGTTIN, (sh_sigfun_t)(SIG_DFL));
2530 sh_signal(SIGTTOU, (sh_sigfun_t)(SIG_DFL));
2531 sh_signal(SIGTSTP, (sh_sigfun_t)(SIG_DFL));
2532 }
2533 #endif // SIGTSTP
2534 job.jobcontrol = 0;
2535 #endif // JOBS
2536 job.toclear = 1;
2537 shp->login_sh = 0;
2538 sh_offoption(shp, SH_LOGIN_SHELL);
2539 sh_onstate(shp, SH_FORKED);
2540 sh_onstate(shp, SH_NOLOG);
2541 if (shp->fn_reset) shp->fn_depth = shp->fn_reset = 0;
2542 // Reset remaining signals to parent except for those `lost' by trap.
2543 if (!(flags & FSHOWME)) sh_sigreset(shp, 2);
2544 shp->subshell = 0;
2545 shp->comsub = 0;
2546 shp->spid = 0;
2547 if ((flags & FAMP) && shp->coutpipe > 1) sh_close(shp->coutpipe);
2548 sig = shp->savesig;
2549 shp->savesig = 0;
2550 if (sig > 0) kill(getpid(), sig);
2551 sh_sigcheck(shp);
2552 usepipe = 0;
2553 return 0;
2554 }
2555
sh_fork(Shell_t * shp,int flags,int * jobid)2556 pid_t sh_fork(Shell_t *shp, int flags, int *jobid) {
2557 pid_t parent;
2558 sigset_t set, oset;
2559
2560 if (!shp->pathlist) path_get(shp, "");
2561 sfsync(NULL);
2562 shp->trapnote &= ~SH_SIGTERM;
2563 job_fork(-1);
2564 sigfillset(&set);
2565 sigprocmask(SIG_BLOCK, &set, &oset);
2566 while (_sh_fork(shp, parent = fork(), flags, jobid) < 0) {
2567 ; // empty loop
2568 }
2569 sh_stats(STAT_FORKS);
2570 #if USE_SPAWN
2571 if (parent == 0 && shp->vex) {
2572 spawnvex_apply(shp->vex, 0, 0);
2573 spawnvex_apply(shp->vexp, 0, SPAWN_RESET);
2574 }
2575 #endif // USE_SPAWN
2576 sigprocmask(SIG_SETMASK, &oset, NULL);
2577 job_fork(parent);
2578 return parent;
2579 }
2580
2581 struct Tdata {
2582 Shell_t *sh;
2583 Namval_t *tp;
2584 void *extra[2];
2585 };
2586
2587 //
2588 // Add exports from previous scope to the new scope.
2589 //
local_exports(Namval_t * np,void * data)2590 static_fn void local_exports(Namval_t *np, void *data) {
2591 Shell_t *shp = ((struct Tdata *)data)->sh;
2592 Namval_t *mp;
2593 char *cp;
2594
2595 if (nv_isarray(np)) nv_putsub(np, NULL, 0, 0);
2596 cp = nv_getval(np);
2597 if (cp && (mp = nv_search(nv_name(np), shp->var_tree, NV_ADD | NV_NOSCOPE)) && nv_isnull(mp)) {
2598 nv_putval(mp, cp, 0);
2599 nv_setattr(mp, np->nvflag);
2600 }
2601 }
2602
2603 //
2604 // This routine executes .sh.math functions from within ((...))).
2605 //
sh_mathfun(Shell_t * shp,void * fp,int nargs,Sfdouble_t * arg)2606 Sfdouble_t sh_mathfun(Shell_t *shp, void *fp, int nargs, Sfdouble_t *arg) {
2607 // The initialization of this var isn't really needed because it is indirectly modified by the
2608 // sh_funscope() call below. But this stops lint tools from complaining that we're returning
2609 // garbage from an uninitialized var.
2610 Sfdouble_t d = 0.0;
2611 Namval_t node, *mp, *nref[9], **nr = nref;
2612 char *argv[2];
2613 struct funenv funenv;
2614 int i;
2615
2616 Namval_t *np = fp;
2617 funenv.node = np;
2618 funenv.nref = nref;
2619 funenv.env = NULL;
2620 memcpy(&node, VAR_sh_value, sizeof(node));
2621 VAR_sh_value->nvfun = NULL;
2622 VAR_sh_value->nvenv = NULL;
2623 nv_setattr(VAR_sh_value, NV_LDOUBLE | NV_NOFREE);
2624 STORE_VT(VAR_sh_value->nvalue, sfdoublep, NULL);
2625 for (i = 0; i < nargs; i++) {
2626 *nr++ = mp = nv_namptr(shp->mathnodes, i);
2627 STORE_VT(mp->nvalue, sfdoublep, arg++);
2628 }
2629 *nr = 0;
2630 STORE_VT(VAR_sh_value->nvalue, sfdoublep, &d);
2631 argv[0] = np->nvname;
2632 argv[1] = NULL;
2633 sh_funscope(shp, 1, argv, 0, &funenv, 0);
2634 while ((mp = *nr++)) STORE_VT(mp->nvalue, sfdoublep, NULL);
2635 VAR_sh_value->nvfun = node.nvfun;
2636 nv_setattr(VAR_sh_value, node.nvflag);
2637 VAR_sh_value->nvenv = node.nvenv;
2638 STORE_VT(VAR_sh_value->nvalue, sfdoublep, FETCH_VT(node.nvalue, sfdoublep));
2639 return d;
2640 }
2641
sh_funct(Shell_t * shp,Namval_t * np,int argn,char * argv[],struct argnod * envlist,int execflg)2642 static_fn void sh_funct(Shell_t *shp, Namval_t *np, int argn, char *argv[], struct argnod *envlist,
2643 int execflg) {
2644 struct funenv fun;
2645 char *fname = nv_getval(VAR_sh_fun);
2646 struct Level *lp = (struct Level *)(VAR_sh_level->nvfun);
2647 int level, pipepid = shp->pipepid;
2648
2649 shp->pipepid = 0;
2650 sh_stats(STAT_FUNCT);
2651 if (!lp->namfun.disc) lp = init_level(shp, 0);
2652 if ((struct sh_scoped *)shp->topscope != shp->st.self) sh_setscope(shp, shp->topscope);
2653 level = lp->maxlevel = shp->dot_depth + shp->fn_depth + 1;
2654 STORE_VT(VAR_sh_level->nvalue, i16, lp->maxlevel);
2655 shp->st.lineno = error_info.line;
2656 FETCH_VT(np->nvalue, rp)->running += 2;
2657 if (nv_isattr(np, NV_FPOSIX) && !sh_isoption(shp, SH_BASH)) {
2658 int loopcnt = shp->st.loopcnt;
2659 shp->posix_fun = np;
2660 shp->st.funname = nv_name(np);
2661 shp->last_root = nv_dict(VAR_sh);
2662 nv_putval(VAR_sh_fun, nv_name(np), NV_NOFREE);
2663 opt_info.index = opt_info.offset = 0;
2664 error_info.errors = 0;
2665 shp->st.loopcnt = 0;
2666 if (argn == 1) {
2667 // The vast majority of the time this is called with argn == 1 so optimize that case.
2668 // The first arg is ignored and could be anything.
2669 char *source_argv[3] = {"sh_funct", argv[0], NULL};
2670 b_source(2, source_argv, &shp->bltindata);
2671 } else {
2672 char **source_argv = malloc((argn + 2) * sizeof(char *));
2673 source_argv[0] = "sh_funct";
2674 source_argv[argn + 1] = NULL;
2675 memcpy(source_argv + 1, argv, argn * sizeof(char *));
2676 b_source(argn + 1, source_argv, &shp->bltindata);
2677 free(source_argv);
2678 }
2679 shp->st.loopcnt = loopcnt;
2680 } else {
2681 fun.env = envlist;
2682 fun.node = np;
2683 fun.nref = NULL;
2684 sh_funscope(shp, argn, argv, 0, &fun, execflg);
2685 }
2686 if (level-- != nv_getnum(VAR_sh_level)) {
2687 Shscope_t *sp = sh_getscope(shp, 0, SEEK_END);
2688 sh_setscope(shp, sp);
2689 }
2690 lp->maxlevel = level;
2691 STORE_VT(VAR_sh_level->nvalue, i16, lp->maxlevel);
2692 shp->last_root = nv_dict(VAR_sh);
2693 nv_putval(VAR_sh_fun, fname, NV_NOFREE);
2694 nv_putval(VAR_sh_file, shp->st.filename, NV_NOFREE);
2695 shp->pipepid = pipepid;
2696 FETCH_VT(np->nvalue, rp)->running -= 2;
2697 if (FETCH_VT(np->nvalue, rp) && FETCH_VT(np->nvalue, rp)->running == 1) {
2698 FETCH_VT(np->nvalue, rp)->running = 0;
2699 _nv_unset(np, NV_RDONLY);
2700 }
2701 }
2702
2703 //
2704 // External interface to execute a function without arguments. <np> is the function node. If <nq> is
2705 // not-null, then sh.name and sh.subscript will be set.
2706 //
sh_fun(Shell_t * shp,Namval_t * np,Namval_t * nq,char * argv[])2707 int sh_fun(Shell_t *shp, Namval_t *np, Namval_t *nq, char *argv[]) {
2708 int offset;
2709 char *base;
2710 Namval_t node;
2711 struct Namref nr;
2712 nvflag_t mode;
2713 char *prefix = shp->prefix;
2714 int n = 0;
2715 char *av[3];
2716
2717 Fcin_t save;
2718 fcsave(&save);
2719 offset = stktell(shp->stk);
2720 if (offset > 0) base = stkfreeze(shp->stk, 0);
2721 shp->prefix = NULL;
2722 if (!argv) {
2723 argv = av + 1;
2724 argv[1] = 0;
2725 }
2726 argv[0] = nv_name(np);
2727 while (argv[n]) n++;
2728 if (nq) mode = set_instance(shp, nq, &node, &nr);
2729 if (is_abuiltin(np)) {
2730 int jmpval;
2731 checkpt_t *buffp = stkalloc(shp->stk, sizeof(checkpt_t));
2732 Shbltin_t *bp = &shp->bltindata;
2733 sh_pushcontext(shp, buffp, SH_JMPCMD);
2734 jmpval = sigsetjmp(buffp->buff, 1);
2735 if (jmpval == 0) {
2736 bp->bnode = np;
2737 bp->ptr = nv_context(np);
2738 errorpush(&buffp->err, 0);
2739 error_info.id = argv[0];
2740 opt_info.index = opt_info.offset = 0;
2741 opt_info.disc = NULL;
2742 shp->exitval = 0;
2743 shp->exitval = (funptr(np))(n, argv, bp);
2744 }
2745 sh_popcontext(shp, buffp);
2746 if (jmpval > SH_JMPCMD) siglongjmp(shp->jmplist->buff, jmpval);
2747 } else {
2748 sh_funct(shp, np, n, argv, NULL, sh_isstate(shp, SH_ERREXIT));
2749 }
2750 if (nq) unset_instance(nq, &node, &nr, mode);
2751 fcrestore(&save);
2752 if (offset > 0) stkset(shp->stk, base, offset);
2753 shp->prefix = prefix;
2754 return shp->exitval;
2755 }
2756
2757 //
2758 // Set up pipe for cooperating process.
2759 //
coproc_init(Shell_t * shp,int pipes[])2760 static_fn void coproc_init(Shell_t *shp, int pipes[]) {
2761 int outfd;
2762 if (shp->coutpipe >= 0 && shp->cpid) {
2763 errormsg(SH_DICT, ERROR_exit(1), e_copexists);
2764 __builtin_unreachable();
2765 }
2766 shp->cpid = 0;
2767 if (shp->cpipe[0] <= 0 || shp->cpipe[1] <= 0) {
2768 // First co-process.
2769 sh_pclose(shp->cpipe);
2770 sh_pipe(shp->cpipe);
2771 outfd = shp->cpipe[1];
2772 if (outfd < 10) {
2773 int fd = sh_fcntl(shp->cpipe[1], F_DUPFD_CLOEXEC, 10);
2774 if (fd >= 10) {
2775 shp->fdstatus[fd] = (shp->fdstatus[outfd] & ~IOCLEX);
2776 sh_close(outfd);
2777 shp->fdstatus[outfd] = IOCLOSE;
2778 shp->cpipe[1] = fd;
2779 }
2780 }
2781 shp->fdptrs[shp->cpipe[0]] = shp->cpipe;
2782 }
2783 shp->outpipe = shp->cpipe;
2784 sh_pipe(shp->inpipe = pipes);
2785 shp->coutpipe = shp->inpipe[1];
2786 shp->fdptrs[shp->coutpipe] = &shp->coutpipe;
2787 }
2788
2789 #if USE_SPAWN
2790
sigreset(Shell_t * shp,int mode)2791 static_fn void sigreset(Shell_t *shp, int mode) {
2792 char *trap;
2793 int sig = shp->st.trapmax;
2794
2795 while (sig-- > 0) {
2796 #ifdef SIGCLD
2797 #if SIGCLD != SIGCHLD
2798 if (sig == SIGCLD) continue;
2799 #endif
2800 #endif
2801 if (sig == SIGCHLD) continue;
2802 if (shp->sigflag[sig] & SH_SIGOFF) return;
2803 trap = shp->st.trapcom[sig];
2804 if (trap && *trap == 0) {
2805 sh_signal(sig, mode ? (sh_sigfun_t)sh_fault : (sh_sigfun_t)(SIG_IGN));
2806 }
2807 }
2808 }
2809
2810 //
2811 // A combined fork/exec for systems with slow or non-existent fork().
2812 //
sh_ntfork(Shell_t * shp,const Shnode_t * t,char * argv[],int * jobid,int flag)2813 static_fn pid_t sh_ntfork(Shell_t *shp, const Shnode_t *t, char *argv[], int *jobid, int flag) {
2814 static pid_t spawnpid;
2815 static int savetype;
2816 static int savejobid;
2817 checkpt_t *buffp = stkalloc(shp->stk, sizeof(checkpt_t));
2818 int otype = 0, jmpval, jobfork = 0, lineno = shp->st.firstline;
2819 volatile int scope = 0, sigwasset = 0;
2820 char **arge, *path;
2821 volatile pid_t grp = 0;
2822 Pathcomp_t *pp;
2823
2824 if (flag) {
2825 otype = savetype;
2826 savetype = 0;
2827 }
2828 sh_pushcontext(shp, buffp, SH_JMPCMD);
2829 errorpush(&buffp->err, ERROR_SILENT);
2830 jmpval = sigsetjmp(buffp->buff, 0);
2831 if (jmpval == 0) {
2832 if ((otype & FINT) && !sh_isstate(shp, SH_MONITOR)) {
2833 sh_signal(SIGQUIT, (sh_sigfun_t)(SIG_IGN));
2834 sh_signal(SIGINT, (sh_sigfun_t)(SIG_IGN));
2835 }
2836 spawnpid = -1;
2837 if (t->com.comio) {
2838 shp->errorfd = error_info.fd;
2839 #if 1
2840 sh_redirect(shp, t->com.comio, io_usevex(t->com.comio));
2841 #else
2842 sh_redirect(shp, t->com.comio, 0);
2843 #endif
2844 }
2845 error_info.id = *argv;
2846 if (t->com.comset) {
2847 scope++;
2848 sh_scope(shp, t->com.comset, 0);
2849 }
2850 if (!strchr(path = argv[0], '/')) {
2851 Namval_t *np;
2852 np = nv_search(path, shp->track_tree, 0);
2853 if (np && !nv_isattr(np, NV_NOALIAS) && FETCH_VT(np->nvalue, const_cp)) {
2854 path = nv_getval(np);
2855 } else if (path_absolute(shp, path, NULL)) {
2856 path = stkptr(shp->stk, PATH_OFFSET);
2857 stkfreeze(shp->stk, 0);
2858 } else {
2859 pp = path_get(shp, path);
2860 while (pp) {
2861 if (pp->len == 1 && *pp->name == '.') break;
2862 pp = pp->next;
2863 }
2864 if (!pp) path = 0;
2865 }
2866 } else if (sh_isoption(shp, SH_RESTRICTED)) {
2867 errormsg(SH_DICT, ERROR_exit(1), e_restricted, path);
2868 __builtin_unreachable();
2869 }
2870 if (!path) {
2871 spawnpid = -1;
2872 goto fail;
2873 }
2874 arge = sh_envgen(shp);
2875 // Restore firstline in case LINENO was exported.
2876 shp->st.firstline = lineno;
2877 shp->exitval = 0;
2878 #ifdef JOBS
2879 if (sh_isstate(shp, SH_MONITOR) && (job.jobcontrol || (otype & FAMP))) {
2880 if ((otype & FAMP) || job.curpgid == 0) {
2881 grp = 1;
2882 } else {
2883 grp = job.curpgid;
2884 }
2885 }
2886 #endif // JOBS
2887
2888 sfsync(NULL);
2889 sigreset(shp, 0); // set signals to ignore
2890 sigwasset++;
2891 // Find first path that has a library component.
2892 for (pp = path_get(shp, argv[0]); pp && !pp->lib; pp = pp->next) {
2893 ; // empty loop
2894 }
2895 job_fork(-1);
2896 jobfork = 1;
2897 spawnpid = path_spawn(shp, path, argv, arge, pp, (grp << 1) | 1);
2898 if (spawnpid < 0 && errno == ENOEXEC) {
2899 char *devfd;
2900 int fd = open(path, O_RDONLY);
2901 argv[-1] = argv[0];
2902 argv[0] = path;
2903 if (fd >= 0) {
2904 struct stat statb;
2905 sfprintf(shp->strbuf, "/dev/fd/%d", fd);
2906 if (stat(devfd = sfstruse(shp->strbuf), &statb) >= 0) argv[0] = devfd;
2907 }
2908 if (!shp->gd->shpath) shp->gd->shpath = pathshell();
2909 spawnpid = path_spawn(shp, shp->gd->shpath, &argv[-1], arge, pp, (grp << 1) | 1);
2910 if (fd >= 0) sh_close(fd);
2911 argv[0] = argv[-1];
2912 }
2913 fail:
2914 if (jobfork && spawnpid < 0) job_fork(0);
2915 if (spawnpid < 0) {
2916 switch (errno = shp->path_err) {
2917 case ENOENT: {
2918 errormsg(SH_DICT, ERROR_system(ERROR_NOENT), e_found + 4);
2919 __builtin_unreachable();
2920 }
2921 default: {
2922 errormsg(SH_DICT, ERROR_system(ERROR_NOEXEC), e_exec + 4);
2923 __builtin_unreachable();
2924 }
2925 }
2926 }
2927 } else {
2928 exitset(shp);
2929 }
2930 sh_popcontext(shp, buffp);
2931 if (buffp->olist) free_list(buffp->olist);
2932 if (sigwasset) sigreset(shp, 1); /* restore ignored signals */
2933 if (scope) {
2934 sh_unscope(shp);
2935 if (jmpval == SH_JMPSCRIPT) {
2936 sh_setlist(shp, t->com.comset, NV_EXPORT | NV_IDENT | NV_ASSIGN, 0);
2937 }
2938 }
2939 if (t->com.comio && (jmpval || spawnpid <= 0)) {
2940 sh_iorestore(shp, buffp->topfd, jmpval);
2941 #if USE_SPAWN
2942 if (shp->vexp->cur > buffp->vexi) sh_vexrestore(shp, buffp->vexi);
2943 #endif
2944 }
2945 if (jmpval > SH_JMPCMD) siglongjmp(shp->jmplist->buff, jmpval);
2946 if (spawnpid > 0) {
2947 _sh_fork(shp, spawnpid, otype, jobid);
2948 job_fork(spawnpid);
2949 #ifdef JOBS
2950 if (grp == 1) job.curpgid = spawnpid;
2951 #ifdef SIGTSTP
2952 if (grp > 0 && !(otype & FAMP)) {
2953 while (tcsetpgrp(job.fd, job.curpgid) < 0 && job.curpgid != spawnpid) {
2954 job.curpgid = spawnpid;
2955 }
2956 }
2957 #endif // SIGTSTP
2958 #endif // JOBS
2959 savejobid = *jobid;
2960 if (otype) return 0;
2961 }
2962 return spawnpid;
2963 }
2964
2965 #endif // USE_SPAWN
2966
2967 //
2968 // This routine is used to execute the given function <fun> in a new scope. If <fun> is NULL, then
2969 // arg points to a structure containing a pointer to a function that will be executed in the current
2970 // environment.
2971 //
sh_funscope(Shell_t * shp,int argn,char * argv[],int (* fun)(void *),void * arg,int execflg)2972 int sh_funscope(Shell_t *shp, int argn, char *argv[], int (*fun)(void *), void *arg, int execflg) {
2973 UNUSED(argn);
2974 char *trap;
2975 int nsig;
2976 struct dolnod *argsav = NULL;
2977 struct dolnod *saveargfor;
2978 struct sh_scoped savst, *prevscope;
2979 struct argnod *envlist = NULL;
2980 int isig, jmpval;
2981 volatile int r = 0;
2982 int n;
2983 char **savsig;
2984 struct funenv *fp = NULL;
2985 checkpt_t *buffp = stkalloc(shp->stk, sizeof(checkpt_t));
2986 Namval_t *nspace = shp->namespace;
2987 Dt_t *last_root = shp->last_root;
2988 Shopt_t options;
2989
2990 options = shp->options;
2991 if (shp->fn_depth == 0) {
2992 shp->glob_options = shp->options;
2993 } else {
2994 shp->options = shp->glob_options;
2995 }
2996 prevscope = shp->st.self;
2997 *prevscope = shp->st;
2998 sh_offoption(shp, SH_ERREXIT);
2999 shp->st.prevst = prevscope;
3000 memset(&savst, 0, sizeof(savst));
3001 shp->st.self = &savst;
3002 shp->topscope = (Shscope_t *)shp->st.self;
3003 shp->st.opterror = shp->st.optchar = 0;
3004 shp->st.optindex = 1;
3005 shp->st.loopcnt = 0;
3006 if (!fun) {
3007 fp = (struct funenv *)arg;
3008 shp->st.real_fun = FETCH_VT((fp->node)->nvalue, rp);
3009 envlist = fp->env;
3010 }
3011 prevscope->save_tree = shp->var_tree;
3012 n = dtvnext(prevscope->save_tree) != (shp->namespace ? shp->var_base : 0);
3013 sh_scope(shp, envlist, 1);
3014 if (n) {
3015 struct Tdata tdata;
3016 memset(&tdata, 0, sizeof(tdata));
3017 tdata.sh = shp;
3018 // Eliminate parent scope.
3019 nv_scan(prevscope->save_tree, local_exports, &tdata, NV_EXPORT, NV_EXPORT | NV_NOSCOPE);
3020 }
3021 shp->st.save_tree = shp->var_tree;
3022 if (!fun) {
3023 if (nv_isattr(fp->node, NV_TAGGED)) {
3024 sh_onoption(shp, SH_XTRACE);
3025 } else {
3026 sh_offoption(shp, SH_XTRACE);
3027 }
3028 }
3029 shp->st.cmdname = argv[0];
3030 // Save trap table.
3031 nsig = shp->st.trapmax;
3032 if (nsig > 0 || shp->st.trapcom[0]) {
3033 savsig = malloc(nsig * sizeof(char *));
3034 // Contents of shp->st.trapcom may change
3035 for (isig = 0; isig < nsig; ++isig) {
3036 savsig[isig] = shp->st.trapcom[isig] ? strdup(shp->st.trapcom[isig]) : NULL;
3037 }
3038 }
3039 sh_sigreset(shp, 0);
3040 argsav = sh_argnew(shp, argv, &saveargfor);
3041 sh_pushcontext(shp, buffp, SH_JMPFUN);
3042 errorpush(&buffp->err, 0);
3043 error_info.id = argv[0];
3044 shp->st.var_local = shp->var_tree;
3045 if (!fun) {
3046 shp->st.filename = FETCH_VT(fp->node->nvalue, rp)->fname;
3047 shp->st.funname = nv_name(fp->node);
3048 shp->last_root = nv_dict(VAR_sh);
3049 nv_putval(VAR_sh_file, shp->st.filename, NV_NOFREE);
3050 nv_putval(VAR_sh_fun, shp->st.funname, NV_NOFREE);
3051 }
3052 if ((execflg & sh_state(SH_NOFORK))) shp->end_fn = 1;
3053 jmpval = sigsetjmp(buffp->buff, 0);
3054 if (jmpval == 0) {
3055 if (shp->fn_depth++ > MAXDEPTH) {
3056 shp->toomany = 1;
3057 siglongjmp(shp->jmplist->buff, SH_JMPERRFN);
3058 } else if (fun) {
3059 r = (*fun)(arg);
3060 } else {
3061 char **args = shp->st.real_fun->argv;
3062 Namval_t *np, *nq, **nref;
3063 nref = fp->nref;
3064 if (nref) {
3065 shp->last_root = NULL;
3066 for (r = 0; args[r]; r++) {
3067 np = nv_search(args[r], shp->var_tree, NV_NOSCOPE | NV_ADD);
3068 if (!np || !*nref) continue;
3069
3070 nq = *nref++;
3071 struct Namref *nrp = calloc(1, sizeof(struct Namref));
3072 STORE_VT(np->nvalue, nrp, nrp);
3073 if (nv_isattr(nq, NV_LDOUBLE) == NV_LDOUBLE) {
3074 nrp->np = nq;
3075 } else {
3076 // TODO: Figure out where the assignment to nq->nvalue.ldp is occurring.
3077 // This used to be the sole use of `pointerof()` which simply did what
3078 // we're now doing. But when spelled out like this it is obvious there
3079 // is a problem.
3080 nrp->np = (void *)((uintptr_t)*FETCH_VT(nq->nvalue, sfdoublep));
3081 nv_onattr(nq, NV_LDOUBLE);
3082 }
3083 nv_onattr(np, NV_REF | NV_NOFREE);
3084 }
3085 }
3086 sh_exec(shp, (Shnode_t *)(nv_funtree((fp->node))), execflg | SH_ERREXIT);
3087 r = shp->exitval;
3088 }
3089 }
3090 if (shp->topscope != (Shscope_t *)shp->st.self) sh_setscope(shp, shp->topscope);
3091 if (--shp->fn_depth == 1 && jmpval == SH_JMPERRFN) {
3092 errormsg(SH_DICT, ERROR_exit(1), e_toodeep, argv[0]);
3093 __builtin_unreachable();
3094 }
3095 sh_popcontext(shp, buffp);
3096 sh_unscope(shp);
3097 shp->namespace = nspace;
3098 shp->var_tree = prevscope->save_tree;
3099 sh_argreset(shp, argsav, saveargfor);
3100 trap = shp->st.trapcom[0];
3101 shp->st.trapcom[0] = 0;
3102 sh_sigreset(shp, 1);
3103 shp->st = *prevscope;
3104 shp->topscope = (Shscope_t *)prevscope;
3105 nv_getval(sh_scoped(shp, VAR_IFS));
3106 shp->end_fn = 0;
3107 if (nsig) {
3108 for (isig = 0; isig < nsig; ++isig) {
3109 if (shp->st.trapcom[isig]) {
3110 free(shp->st.trapcom[isig]);
3111 }
3112 }
3113 memcpy(shp->st.trapcom, savsig, nsig * sizeof(char *));
3114 free(savsig);
3115 }
3116 shp->trapnote = 0;
3117 shp->options = options;
3118 shp->last_root = last_root;
3119 if (jmpval == SH_JMPSUB) siglongjmp(shp->jmplist->buff, jmpval);
3120 if (trap) {
3121 sh_trap(shp, trap, 0);
3122 free(trap);
3123 }
3124 if (jmpval) r = shp->exitval;
3125 if (!sh_isstate(shp, SH_IOPROMPT) && r > SH_EXITSIG &&
3126 ((r & SH_EXITMASK) == SIGINT || ((r & SH_EXITMASK) == SIGQUIT))) {
3127 kill(getpid(), r & SH_EXITMASK);
3128 }
3129 if (jmpval > SH_JMPFUN) {
3130 sh_chktrap(shp);
3131 siglongjmp(shp->jmplist->buff, jmpval);
3132 }
3133 return r;
3134 }
3135
3136 //
3137 // Given stream <iop> compile and execute.
3138 //
sh_eval(Shell_t * shp,Sfio_t * iop,int mode)3139 int sh_eval(Shell_t *shp, Sfio_t *iop, int mode) {
3140 Shnode_t *t;
3141 struct slnod *saveslp = shp->st.staklist;
3142 int jmpval;
3143 checkpt_t *pp = shp->jmplist;
3144 checkpt_t *buffp = stkalloc(shp->stk, sizeof(checkpt_t));
3145 static Sfio_t *io_save;
3146 volatile bool traceon = false;
3147 volatile int lineno = 0;
3148 int binscript = shp->binscript;
3149 char comsub = shp->comsub;
3150 Sfio_t *iosaved = io_save;
3151
3152 io_save = iop; // preserve correct value across longjmp
3153 shp->binscript = 0;
3154 shp->comsub = 0;
3155 #define SH_TOPFUN 0x8000 // this is a temporary tksh hack
3156 if (mode & SH_TOPFUN) {
3157 mode ^= SH_TOPFUN;
3158 shp->fn_reset = 1;
3159 }
3160 sh_pushcontext(shp, buffp, SH_JMPEVAL);
3161 buffp->olist = pp->olist;
3162 jmpval = sigsetjmp(buffp->buff, 0);
3163 while (jmpval == 0) {
3164 if (mode & SH_READEVAL) {
3165 lineno = shp->inlineno;
3166 traceon = sh_isoption(shp, SH_XTRACE);
3167 if (traceon) sh_offoption(shp, SH_XTRACE);
3168 }
3169 t = sh_parse(shp, iop, (mode & (SH_READEVAL | SH_FUNEVAL)) ? mode & SH_FUNEVAL : SH_NL);
3170 if (!(mode & SH_FUNEVAL) || !sfreserve(iop, 0, 0)) {
3171 if (!(mode & SH_READEVAL)) sfclose(iop);
3172 io_save = 0;
3173 mode &= ~SH_FUNEVAL;
3174 }
3175 mode &= ~SH_READEVAL;
3176 if (!sh_isoption(shp, SH_VERBOSE)) sh_offstate(shp, SH_VERBOSE);
3177 if ((mode & ~SH_FUNEVAL) && shp->gd->hist_ptr) {
3178 hist_flush(shp->gd->hist_ptr);
3179 mode = sh_state(SH_INTERACTIVE);
3180 }
3181 sh_exec(shp, t,
3182 sh_isstate(shp, SH_ERREXIT) | sh_isstate(shp, SH_NOFORK) | (mode & ~SH_FUNEVAL));
3183 if (!io_save) break;
3184 }
3185 sh_popcontext(shp, buffp);
3186 shp->binscript = binscript;
3187 shp->comsub = comsub;
3188 if (traceon) sh_onoption(shp, SH_XTRACE);
3189 if (lineno) shp->inlineno = lineno;
3190 if (io_save) sfclose(io_save);
3191 io_save = iosaved == iop ? 0 : iosaved; /* io_save is static so assignment is meaningful. */
3192 sh_freeup(shp);
3193 shp->st.staklist = saveslp;
3194 shp->fn_reset = 0;
3195 if (jmpval > SH_JMPEVAL) siglongjmp(shp->jmplist->buff, jmpval);
3196 return shp->exitval;
3197 }
3198
sh_run(Shell_t * shp,int argn,char * argv[])3199 int sh_run(Shell_t *shp, int argn, char *argv[]) {
3200 struct dolnod *dp;
3201 struct comnod *t = stkalloc(shp->stk, sizeof(struct comnod));
3202 int savtop = stktell(shp->stk);
3203 char *savptr = stkfreeze(stkstd, 0);
3204 Shbltin_t bltindata;
3205
3206 bltindata = shp->bltindata;
3207 memset(t, 0, sizeof(struct comnod));
3208 dp = stkalloc(shp->stk,
3209 sizeof(struct dolnod) + ARG_SPARE * sizeof(char *) + argn * sizeof(char *));
3210 dp->dolnum = argn;
3211 dp->dolbot = ARG_SPARE;
3212 memcpy(dp->dolval + ARG_SPARE, argv, (argn + 1) * sizeof(char *));
3213 t->comarg = (struct argnod *)dp;
3214 if (!strchr(argv[0], '/')) {
3215 t->comnamp = nv_bfsearch(argv[0], shp->fun_tree, (Namval_t **)&t->comnamq, NULL);
3216 }
3217 argn = sh_exec(shp, (Shnode_t *)t, sh_isstate(shp, SH_ERREXIT));
3218 shp->bltindata = bltindata;
3219 if (savptr != stkptr(shp->stk, 0)) {
3220 stkset(shp->stk, savptr, savtop);
3221 } else {
3222 stkseek(shp->stk, savtop);
3223 }
3224 return argn;
3225 }
3226