Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/ksh93/sh/xec.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1982-2012 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 <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* UNIX shell parse tree executer
23
*
24
* David Korn
25
* AT&T Labs
26
*
27
*/
28
29
#include "defs.h"
30
#include <fcin.h>
31
#include "variables.h"
32
#include "path.h"
33
#include "name.h"
34
#include "io.h"
35
#include "shnodes.h"
36
#include "jobs.h"
37
#include "test.h"
38
#include "builtins.h"
39
#include "FEATURE/time"
40
#include "FEATURE/externs"
41
#include "FEATURE/locale"
42
#include "streval.h"
43
44
#if !_std_malloc
45
# include <vmalloc.h>
46
#endif
47
48
#if _lib_vfork
49
# include <ast_vfork.h>
50
#else
51
# define vfork() fork()
52
#endif
53
54
#define SH_NTFORK SH_TIMING
55
#define NV_BLTPFSH NV_ARRAY
56
57
#if _lib_nice
58
extern int nice(int);
59
#endif /* _lib_nice */
60
#if !_lib_spawnveg
61
# define spawnveg(a,b,c,d) spawnve(a,b,c)
62
#endif /* !_lib_spawnveg */
63
#if SHOPT_SPAWN
64
static pid_t sh_ntfork(Shell_t*,const Shnode_t*,char*[],int*,int);
65
#endif /* SHOPT_SPAWN */
66
67
static void sh_funct(Shell_t *,Namval_t*, int, char*[], struct argnod*,int);
68
static int trim_eq(const char*, const char*);
69
static void coproc_init(Shell_t*, int pipes[]);
70
71
static void *timeout;
72
static char nlock;
73
static char pipejob;
74
static char nopost;
75
static int restorefd;
76
77
struct funenv
78
{
79
Namval_t *node;
80
struct argnod *env;
81
Namval_t **nref;
82
};
83
84
/* ======== command execution ========*/
85
86
#if !SHOPT_DEVFD
87
static void fifo_check(void *handle)
88
{
89
Shell_t *shp = (Shell_t*)handle;
90
pid_t pid = getppid();
91
if(pid==1)
92
{
93
unlink(shp->fifo);
94
sh_done(shp,0);
95
}
96
}
97
#endif /* !SHOPT_DEVFD */
98
99
/*
100
* The following two functions allow command substituion for non-builtins
101
* to use a pipe and to wait for the pipe to close before restoring to a
102
* temp file.
103
*/
104
static int subpipe[3],subdup,tsetio,usepipe;
105
static void iounpipe(Shell_t*);
106
107
static int iousepipe(Shell_t *shp)
108
{
109
int i;
110
if(usepipe)
111
{
112
usepipe++;
113
iounpipe(shp);
114
}
115
if(sh_rpipe(subpipe) < 0)
116
return(0);
117
usepipe++;
118
fcntl(subpipe[0],F_SETFD,FD_CLOEXEC);
119
subpipe[2] = fcntl(1,F_DUPFD,10);
120
fcntl(subpipe[2],F_SETFD,FD_CLOEXEC);
121
shp->fdstatus[subpipe[2]] = shp->fdstatus[1];
122
close(1);
123
fcntl(subpipe[1],F_DUPFD,1);
124
shp->fdstatus[1] = shp->fdstatus[subpipe[1]];
125
sh_close(subpipe[1]);
126
if(subdup=shp->subdup) for(i=0; i < 10; i++)
127
{
128
if(subdup&(1<<i))
129
{
130
sh_close(i);
131
fcntl(1,F_DUPFD,i);
132
shp->fdstatus[i] = shp->fdstatus[1];
133
}
134
}
135
return(1);
136
}
137
138
static void iounpipe(Shell_t *shp)
139
{
140
int n;
141
char buff[SF_BUFSIZE];
142
close(1);
143
fcntl(subpipe[2], F_DUPFD, 1);
144
shp->fdstatus[1] = shp->fdstatus[subpipe[2]];
145
--usepipe;
146
if(subdup) for(n=0; n < 10; n++)
147
{
148
if(subdup&(1<<n))
149
{
150
sh_close(n);
151
fcntl(1, F_DUPFD, n);
152
shp->fdstatus[n] = shp->fdstatus[1];
153
}
154
}
155
shp->subdup = 0;
156
sh_close(subpipe[2]);
157
if(usepipe==0) while(1)
158
{
159
while(job.waitsafe && job.savesig==SIGCHLD)
160
{
161
if(!vmbusy())
162
{
163
job.in_critical++;
164
job_reap(SIGCHLD);
165
job.in_critical--;
166
break;
167
}
168
sh_delay(1);
169
}
170
if((n = read(subpipe[0],buff,sizeof(buff)))==0)
171
break;
172
if(n>0)
173
sfwrite(sfstdout,buff,n);
174
else if(errno!=EINTR)
175
break;
176
}
177
sh_close(subpipe[0]);
178
subpipe[0] = -1;
179
tsetio = 0;
180
usepipe = 0;
181
}
182
183
/*
184
* print time <t> in h:m:s format with precision <p>
185
*/
186
static void l_time(Sfio_t *outfile,register clock_t t,int p)
187
{
188
register int min, sec, frac;
189
register int hr;
190
if(p)
191
{
192
frac = t%shgd->lim.clk_tck;
193
frac = (frac*100)/shgd->lim.clk_tck;
194
}
195
t /= shgd->lim.clk_tck;
196
sec = t%60;
197
t /= 60;
198
min = t%60;
199
if(hr=t/60)
200
sfprintf(outfile,"%dh",hr);
201
if(p)
202
sfprintf(outfile,"%dm%d%c%0*ds",min,sec,GETDECIMAL(0),p,frac);
203
else
204
sfprintf(outfile,"%dm%ds",min,sec);
205
}
206
207
static int p_time(Shell_t *shp, Sfio_t *out, const char *format, clock_t *tm)
208
{
209
int c,p,l,n,offset = staktell();
210
const char *first;
211
double d;
212
Stk_t *stkp = shp->stk;
213
for(first=format ; c= *format; format++)
214
{
215
if(c!='%')
216
continue;
217
sfwrite(stkp, first, format-first);
218
n = l = 0;
219
p = 3;
220
if((c= *++format) == '%')
221
{
222
first = format;
223
continue;
224
}
225
if(c>='0' && c <='9')
226
{
227
p = (c>'3')?3:(c-'0');
228
c = *++format;
229
}
230
else if(c=='P')
231
{
232
if(d=tm[0])
233
d = 100.*(((double)(tm[1]+tm[2]))/d);
234
p = 2;
235
goto skip;
236
}
237
if(c=='l')
238
{
239
l = 1;
240
c = *++format;
241
}
242
if(c=='U')
243
n = 1;
244
else if(c=='S')
245
n = 2;
246
else if(c!='R')
247
{
248
stkseek(stkp,offset);
249
errormsg(SH_DICT,ERROR_exit(0),e_badtformat,c);
250
return(0);
251
}
252
d = (double)tm[n]/shp->gd->lim.clk_tck;
253
skip:
254
if(l)
255
l_time(stkp, tm[n], p);
256
else
257
sfprintf(stkp,"%.*f",p, d);
258
first = format+1;
259
}
260
if(format>first)
261
sfwrite(stkp,first, format-first);
262
sfputc(stkp,'\n');
263
n = stktell(stkp)-offset;
264
sfwrite(out,stkptr(stkp,offset),n);
265
stkseek(stkp,offset);
266
return(n);
267
}
268
269
#if SHOPT_OPTIMIZE
270
/*
271
* clear argument pointers that point into the stack
272
*/
273
static int p_arg(struct argnod*,int);
274
static int p_switch(struct regnod*);
275
static int p_comarg(register struct comnod *com)
276
{
277
Namval_t *np=com->comnamp;
278
int n = p_arg(com->comset,ARG_ASSIGN);
279
if(com->comarg && (com->comtyp&COMSCAN))
280
n+= p_arg(com->comarg,0);
281
if(com->comstate && np)
282
{
283
/* call builtin to cleanup state */
284
Shbltin_t *bp = &sh.bltindata;
285
void *save_ptr = bp->ptr;
286
void *save_data = bp->data;
287
bp->bnode = np;
288
bp->vnode = com->comnamq;
289
bp->ptr = nv_context(np);
290
bp->data = com->comstate;
291
bp->flags = SH_END_OPTIM;
292
((Shbltin_f)funptr(np))(0,(char**)0, bp);
293
bp->ptr = save_ptr;
294
bp->data = save_data;
295
}
296
com->comstate = 0;
297
if(com->comarg && !np)
298
n++;
299
return(n);
300
}
301
302
extern void sh_optclear(Shell_t*, void*);
303
304
static int sh_tclear(register Shnode_t *t)
305
{
306
int n=0;
307
if(!t)
308
return(0);
309
switch(t->tre.tretyp&COMMSK)
310
{
311
case TTIME:
312
case TPAR:
313
return(sh_tclear(t->par.partre));
314
case TCOM:
315
return(p_comarg((struct comnod*)t));
316
case TSETIO:
317
case TFORK:
318
return(sh_tclear(t->fork.forktre));
319
case TIF:
320
n=sh_tclear(t->if_.iftre);
321
n+=sh_tclear(t->if_.thtre);
322
n+=sh_tclear(t->if_.eltre);
323
return(n);
324
case TWH:
325
if(t->wh.whinc)
326
n=sh_tclear((Shnode_t*)(t->wh.whinc));
327
n+=sh_tclear(t->wh.whtre);
328
n+=sh_tclear(t->wh.dotre);
329
return(n);
330
case TLST:
331
case TAND:
332
case TORF:
333
case TFIL:
334
n=sh_tclear(t->lst.lstlef);
335
return(n+sh_tclear(t->lst.lstrit));
336
case TARITH:
337
return(p_arg(t->ar.arexpr,ARG_ARITH));
338
case TFOR:
339
n=sh_tclear(t->for_.fortre);
340
return(n+sh_tclear((Shnode_t*)t->for_.forlst));
341
case TSW:
342
n=p_arg(t->sw.swarg,0);
343
return(n+p_switch(t->sw.swlst));
344
case TFUN:
345
n=sh_tclear(t->funct.functtre);
346
return(n+sh_tclear((Shnode_t*)t->funct.functargs));
347
case TTST:
348
if((t->tre.tretyp&TPAREN)==TPAREN)
349
return(sh_tclear(t->lst.lstlef));
350
else
351
{
352
n=p_arg(&(t->lst.lstlef->arg),0);
353
if(t->tre.tretyp&TBINARY)
354
n+=p_arg(&(t->lst.lstrit->arg),0);
355
}
356
}
357
return(n);
358
}
359
360
static int p_arg(register struct argnod *arg,int flag)
361
{
362
while(arg)
363
{
364
if(strlen(arg->argval) || (arg->argflag==ARG_RAW))
365
arg->argchn.ap = 0;
366
else if(flag==0)
367
sh_tclear((Shnode_t*)arg->argchn.ap);
368
else
369
sh_tclear(((struct fornod*)arg->argchn.ap)->fortre);
370
arg = arg->argnxt.ap;
371
}
372
return(0);
373
}
374
375
static int p_switch(register struct regnod *reg)
376
{
377
int n=0;
378
while(reg)
379
{
380
n+=p_arg(reg->regptr,0);
381
n+=sh_tclear(reg->regcom);
382
reg = reg->regnxt;
383
}
384
return(n);
385
}
386
# define OPTIMIZE_FLAG (ARG_OPTIMIZE)
387
# define OPTIMIZE (flags&OPTIMIZE_FLAG)
388
#else
389
# define OPTIMIZE_FLAG (0)
390
# define OPTIMIZE (0)
391
# define sh_tclear(x)
392
#endif /* SHOPT_OPTIMIZE */
393
394
static void out_pattern(Sfio_t *iop, register const char *cp, int n)
395
{
396
register int c;
397
do
398
{
399
switch(c= *cp)
400
{
401
case 0:
402
if(n<0)
403
return;
404
c = n;
405
break;
406
case '\n':
407
sfputr(iop,"$'\\n",'\'');
408
continue;
409
case '\\':
410
if (!(c = *++cp))
411
c = '\\';
412
/*FALLTHROUGH*/
413
case ' ':
414
case '<': case '>': case ';':
415
case '$': case '`': case '\t':
416
sfputc(iop,'\\');
417
break;
418
}
419
sfputc(iop,c);
420
}
421
while(*cp++);
422
}
423
424
static void out_string(Sfio_t *iop, register const char *cp, int c, int quoted)
425
{
426
if(quoted)
427
{
428
int n = stktell(stkstd);
429
cp = sh_fmtq(cp);
430
if(iop==stkstd && cp==stkptr(stkstd,n))
431
{
432
*stkptr(stkstd,stktell(stkstd)-1) = c;
433
return;
434
}
435
}
436
sfputr(iop,cp,c);
437
}
438
439
struct Level
440
{
441
Namfun_t hdr;
442
short maxlevel;
443
};
444
445
/*
446
* this is for a debugger but it hasn't been tested yet
447
* if a debug script sets .sh.level it should set up the scope
448
* as if you were executing in that level
449
*/
450
static void put_level(Namval_t* np,const char *val,int flags,Namfun_t *fp)
451
{
452
Shscope_t *sp;
453
struct Level *lp = (struct Level*)fp;
454
int16_t level, oldlevel = (int16_t)nv_getnum(np);
455
nv_putv(np,val,flags,fp);
456
if(!val)
457
{
458
fp = nv_stack(np, NIL(Namfun_t*));
459
if(fp && !fp->nofree)
460
free((void*)fp);
461
return;
462
}
463
level = nv_getnum(np);
464
if(level<0 || level > lp->maxlevel)
465
{
466
nv_putv(np, (char*)&oldlevel, NV_INT16, fp);
467
/* perhaps this should be an error */
468
return;
469
}
470
if(level==oldlevel)
471
return;
472
if(sp = sh_getscope(level,SEEK_SET))
473
{
474
sh_setscope(sp);
475
error_info.id = sp->cmdname;
476
477
}
478
}
479
480
static const Namdisc_t level_disc = { sizeof(struct Level), put_level };
481
482
static struct Level *init_level(Shell_t *shp,int level)
483
{
484
struct Level *lp = newof(NiL,struct Level,1,0);
485
lp->maxlevel = level;
486
_nv_unset(SH_LEVELNOD,0);
487
nv_onattr(SH_LEVELNOD,NV_INT16|NV_NOFREE);
488
shp->last_root = nv_dict(DOTSHNOD);
489
nv_putval(SH_LEVELNOD,(char*)&lp->maxlevel,NV_INT16);
490
lp->hdr.disc = &level_disc;
491
nv_disc(SH_LEVELNOD,&lp->hdr,NV_FIRST);
492
return(lp);
493
}
494
495
/*
496
* write the current command on the stack and make it available as .sh.command
497
*/
498
int sh_debug(Shell_t *shp, const char *trap, const char *name, const char *subscript, char *const argv[], int flags)
499
{
500
Stk_t *stkp=shp->stk;
501
struct sh_scoped savst;
502
Namval_t *np = SH_COMMANDNOD;
503
char *sav = stkptr(stkp,0);
504
int n=4, offset=stktell(stkp);
505
const char *cp = "+=( ";
506
Sfio_t *iop = stkstd;
507
short level;
508
if(shp->indebug)
509
return(0);
510
shp->indebug = 1;
511
if(name)
512
{
513
sfputr(iop,name,-1);
514
if(subscript)
515
{
516
sfputc(iop,'[');
517
out_string(iop,subscript,']',1);
518
}
519
if(!(flags&ARG_APPEND))
520
cp+=1, n-=1;
521
if(!(flags&ARG_ASSIGN))
522
n -= 2;
523
sfwrite(iop,cp,n);
524
}
525
if(*argv && !(flags&ARG_RAW))
526
out_string(iop, *argv++,' ', 0);
527
n = (flags&ARG_ARITH);
528
while(cp = *argv++)
529
{
530
if((flags&ARG_EXP) && argv[1]==0)
531
out_pattern(iop, cp,' ');
532
else
533
out_string(iop, cp,' ',n?0: (flags&(ARG_RAW|ARG_NOGLOB))||*argv);
534
}
535
if(flags&ARG_ASSIGN)
536
sfputc(iop,')');
537
else if(iop==stkstd)
538
*stkptr(stkp,stktell(stkp)-1) = 0;
539
np->nvalue.cp = stkfreeze(stkp,1);
540
/* now setup .sh.level variable */
541
shp->st.lineno = error_info.line;
542
level = shp->fn_depth+shp->dot_depth;
543
shp->last_root = nv_dict(DOTSHNOD);
544
if(!SH_LEVELNOD->nvfun || !SH_LEVELNOD->nvfun->disc || nv_isattr(SH_LEVELNOD,NV_INT16|NV_NOFREE)!=(NV_INT16|NV_NOFREE))
545
init_level(shp,level);
546
else
547
nv_putval(SH_LEVELNOD,(char*)&level,NV_INT16);
548
savst = shp->st;
549
shp->st.trap[SH_DEBUGTRAP] = 0;
550
n = sh_trap(trap,0);
551
np->nvalue.cp = 0;
552
shp->indebug = 0;
553
if(shp->st.cmdname)
554
error_info.id = shp->st.cmdname;
555
nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
556
nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
557
shp->st = savst;
558
if(sav != stkptr(stkp,0))
559
stkset(stkp,sav,0);
560
else
561
stkseek(stkp,offset);
562
return(n);
563
}
564
565
/*
566
* Given stream <iop> compile and execute
567
*/
568
int sh_eval(register Sfio_t *iop, int mode)
569
{
570
register Shnode_t *t;
571
Shell_t *shp = sh_getinterp();
572
struct slnod *saveslp = shp->st.staklist;
573
int jmpval;
574
struct checkpt *pp = (struct checkpt*)shp->jmplist;
575
struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
576
static Sfio_t *io_save;
577
volatile int traceon=0, lineno=0;
578
int binscript=shp->binscript;
579
char comsub = shp->comsub;
580
io_save = iop; /* preserve correct value across longjmp */
581
shp->binscript = 0;
582
shp->comsub = 0;
583
#define SH_TOPFUN 0x8000 /* this is a temporary tksh hack */
584
if (mode & SH_TOPFUN)
585
{
586
mode ^= SH_TOPFUN;
587
shp->fn_reset = 1;
588
}
589
sh_pushcontext(shp,buffp,SH_JMPEVAL);
590
buffp->olist = pp->olist;
591
jmpval = sigsetjmp(buffp->buff,0);
592
while(jmpval==0)
593
{
594
if(mode&SH_READEVAL)
595
{
596
lineno = shp->inlineno;
597
if(traceon=sh_isoption(SH_XTRACE))
598
sh_offoption(SH_XTRACE);
599
}
600
t = (Shnode_t*)sh_parse(shp,iop,(mode&(SH_READEVAL|SH_FUNEVAL))?mode&SH_FUNEVAL:SH_NL);
601
if(!(mode&SH_FUNEVAL) || !sfreserve(iop,0,0))
602
{
603
if(!(mode&SH_READEVAL))
604
sfclose(iop);
605
io_save = 0;
606
mode &= ~SH_FUNEVAL;
607
}
608
mode &= ~SH_READEVAL;
609
if(!sh_isoption(SH_VERBOSE))
610
sh_offstate(SH_VERBOSE);
611
if((mode&~SH_FUNEVAL) && shp->gd->hist_ptr)
612
{
613
hist_flush(shp->gd->hist_ptr);
614
mode = sh_state(SH_INTERACTIVE);
615
}
616
sh_exec(t,sh_isstate(SH_ERREXIT)|sh_isstate(SH_NOFORK)|(mode&~SH_FUNEVAL));
617
if(!(mode&SH_FUNEVAL))
618
break;
619
}
620
sh_popcontext(shp,buffp);
621
shp->binscript = binscript;
622
shp->comsub = comsub;
623
if(traceon)
624
sh_onoption(SH_XTRACE);
625
if(lineno)
626
shp->inlineno = lineno;
627
if(io_save)
628
sfclose(io_save);
629
sh_freeup(shp);
630
shp->st.staklist = saveslp;
631
shp->fn_reset = 0;
632
if(jmpval>SH_JMPEVAL)
633
siglongjmp(*shp->jmplist,jmpval);
634
return(shp->exitval);
635
}
636
637
/*
638
* returns 1 when option -<c> is specified
639
*/
640
static int checkopt(char *argv[], int c)
641
{
642
char *cp;
643
while(cp = *++argv)
644
{
645
if(*cp=='+')
646
continue;
647
if(*cp!='-' || cp[1]=='-')
648
break;
649
if(strchr(++cp,c))
650
return(1);
651
if(*cp=='h' && cp[1]==0 && *++argv==0)
652
break;
653
}
654
return(0);
655
}
656
657
static void free_list(struct openlist *olist)
658
{
659
struct openlist *item,*next;
660
for(item=olist;item;item=next)
661
{
662
next = item->next;
663
free((void*)item);
664
}
665
}
666
667
/*
668
* set ${.sh.name} and ${.sh.subscript}
669
* set _ to reference for ${.sh.name}[$.sh.subscript]
670
*/
671
static int set_instance(Shell_t *shp,Namval_t *nq, Namval_t *node, struct Namref *nr)
672
{
673
char *sp=0,*cp;
674
Namarr_t *ap;
675
Namval_t *np;
676
if(!nv_isattr(nq,NV_MINIMAL|NV_EXPORT|NV_ARRAY) && (np=(Namval_t*)nq->nvenv) && nv_isarray(np))
677
nq = np;
678
cp = nv_name(nq);
679
memset(nr,0,sizeof(*nr));
680
nr->np = nq;
681
nr->root = shp->var_tree;
682
nr->table = shp->last_table;
683
#if SHOPT_NAMESPACE
684
if(!nr->table && shp->namespace)
685
nr->table = shp->namespace;
686
#endif /* SHOPT_NAMESPACE */
687
shp->instance = 1;
688
if((ap=nv_arrayptr(nq)) && (sp = nv_getsub(nq)))
689
sp = strdup(sp);
690
shp->instance = 0;
691
if(shp->var_tree!=shp->var_base && !nv_search((char*)nq,nr->root,HASH_BUCKET|HASH_NOSCOPE))
692
{
693
#if SHOPT_NAMESPACE
694
nr->root = shp->namespace?nv_dict(shp->namespace):shp->var_base;
695
#else
696
nr->root = shp->var_base;
697
#endif /* SHOPT_NAMESPACE */
698
}
699
nv_putval(SH_NAMENOD, cp, NV_NOFREE);
700
memcpy(node,L_ARGNOD,sizeof(*node));
701
L_ARGNOD->nvalue.nrp = nr;
702
L_ARGNOD->nvflag = NV_REF|NV_NOFREE;
703
L_ARGNOD->nvfun = 0;
704
L_ARGNOD->nvenv = 0;
705
if(sp)
706
{
707
nv_putval(SH_SUBSCRNOD,nr->sub=sp,NV_NOFREE);
708
return(ap->nelem&ARRAY_SCAN);
709
}
710
return(0);
711
}
712
713
static void unset_instance(Namval_t *nq, Namval_t *node, struct Namref *nr,long mode)
714
{
715
L_ARGNOD->nvalue.nrp = node->nvalue.nrp;
716
L_ARGNOD->nvflag = node->nvflag;
717
L_ARGNOD->nvfun = node->nvfun;
718
if(nr->sub)
719
{
720
nv_putsub(nr->np, nr->sub, mode);
721
free((void*)nr->sub);
722
}
723
_nv_unset(SH_NAMENOD,0);
724
_nv_unset(SH_SUBSCRNOD,0);
725
}
726
727
#if SHOPT_COSHELL
728
uintmax_t coused;
729
/*
730
* print out function definition
731
*/
732
static void print_fun(register Namval_t* np, void *data)
733
{
734
register char *format;
735
NOT_USED(data);
736
if(!is_afunction(np) || !np->nvalue.ip)
737
return;
738
if(nv_isattr(np,NV_FPOSIX))
739
format="%s()\n{ ";
740
else
741
format="function %s\n{ ";
742
sfprintf(sfstdout,format,nv_name(np));
743
sh_deparse(sfstdout,(Shnode_t*)(nv_funtree(np)),0);
744
sfwrite(sfstdout,"}\n",2);
745
}
746
747
static void *sh_coinit(Shell_t *shp,char **argv)
748
{
749
struct cosh *csp = job.colist;
750
const char *name = argv?argv[0]:0;
751
int id, open=1;
752
if(!name)
753
return(0);
754
if(*name=='-')
755
{
756
name++;
757
open=0;
758
}
759
nv_open(name,shp->var_tree,NV_IDENT|NV_NOADD);
760
while(csp)
761
{
762
if(strcmp(name,csp->name)==0)
763
{
764
if(open)
765
{
766
coattr(csp->coshell,argv[1]);
767
return((void*)csp);
768
}
769
coclose(csp->coshell);
770
return(0);
771
}
772
csp = csp->next;
773
}
774
if(!open)
775
errormsg(SH_DICT,ERROR_exit(1),"%s: unknown namespace",name);
776
environ[0][2]=0;
777
csp = newof(0,struct cosh,1,strlen(name)+1);
778
if(!(csp->coshell = coopen(NULL,CO_SHELL|CO_SILENT,argv[1])))
779
{
780
free((void*)csp);
781
errormsg(SH_DICT,ERROR_exit(1),"%s: unable to create namespace",name);
782
}
783
csp->coshell->data = (void*)csp;
784
csp->name = (char*)(csp+1);
785
strcpy(csp->name,name);
786
for(id=0; coused&(1<<id); id++);
787
coused |= (1<<id);
788
csp->id = id;
789
csp->next = job.colist;
790
job.colist = csp;
791
return((void*)csp);
792
}
793
794
int sh_coaddfile(Shell_t *shp, char *name)
795
{
796
Namval_t *np = dtmatch(shp->inpool,name);
797
if(!np)
798
{
799
np = (Namval_t*)stakalloc(sizeof(Dtlink_t)+sizeof(char*));
800
np->nvname = name;
801
(Namval_t*)dtinsert(shp->inpool,np);
802
shp->poolfiles++;
803
return(1);
804
}
805
return(0);
806
}
807
808
static int sh_coexec(Shell_t *shp,const Shnode_t *t, int filt)
809
{
810
struct cosh *csp = ((struct cosh*)shp->coshell);
811
Cojob_t *cjp;
812
char *str,*trap,host[PATH_MAX];
813
int lineno,sig,trace = sh_isoption(SH_XTRACE);
814
int verbose = sh_isoption(SH_VERBOSE);
815
sh_offoption(SH_XTRACE);
816
sh_offoption(SH_VERBOSE);
817
if(!shp->strbuf2)
818
shp->strbuf2 = sfstropen();
819
sfswap(shp->strbuf2,sfstdout);
820
sh_trap("typeset -p\nprint cd \"$PWD\"\nprint .sh.dollar=$$\nprint umask $(umask)",0);
821
for(sig=shp->st.trapmax;--sig>0;)
822
{
823
if((trap=shp->st.trapcom[sig]) && *trap==0)
824
sfprintf(sfstdout,"trap '' %d\n",sig);
825
}
826
if(t->tre.tretyp==TFIL)
827
lineno = ((struct forknod*)t->lst.lstlef)->forkline;
828
else
829
lineno = t->fork.forkline;
830
if(filt)
831
{
832
if(gethostname(host,sizeof(host)) < 0)
833
errormsg(SH_DICT,ERROR_system(1),e_pipe);
834
if(shp->inpipe[2]>=20000)
835
sfprintf(sfstdout,"command exec < /dev/tcp/%s/%d || print -u2 'cannot create pipe'\n",host,shp->inpipe[2]);
836
sfprintf(sfstdout,"command exec > /dev/tcp/%s/%d || print -u2 'cannot create pipe'\n",host,shp->outpipe[2]);
837
if(filt==3)
838
t = t->fork.forktre;
839
}
840
else
841
t = t->fork.forktre;
842
nv_scan(shp->fun_tree, print_fun, (void*)0,0, 0);
843
if(1)
844
{
845
Dt_t *top = shp->var_tree;
846
sh_scope(shp,(struct argnod*)0,0);
847
shp->inpool = dtopen(&_Nvdisc,Dtset);
848
sh_exec(t,filt==1||filt==2?SH_NOFORK:0);
849
if(shp->poolfiles)
850
{
851
Namval_t *np;
852
sfprintf(sfstdout,"[[ ${.sh} == *pool* ]] && .sh.pool.files=(\n");
853
for(np=(Namval_t*)dtfirst(shp->inpool);np;np=(Namval_t*)dtnext(shp->inpool,np))
854
{
855
sfprintf(sfstdout,"\t%s\n",sh_fmtq(np->nvname));
856
}
857
sfputr(sfstdout,")",'\n');
858
;
859
}
860
dtclose(shp->inpool);
861
shp->inpool = 0;
862
shp->poolfiles = 0;
863
sh_unscope(shp);
864
shp->var_tree = top;
865
}
866
sfprintf(sfstdout,"typeset -f .sh.pool.init && .sh.pool.init\n");
867
sfprintf(sfstdout,"LINENO=%d\n",lineno);
868
if(trace)
869
sh_onoption(SH_XTRACE);
870
if(verbose)
871
sh_onoption(SH_VERBOSE);
872
sh_trap("set +o",0);
873
sh_deparse(sfstdout,t,filt==1||filt==2?FALTPIPE:0);
874
sfputc(sfstdout,0);
875
sfswap(shp->strbuf2,sfstdout);
876
str = sfstruse(shp->strbuf2);
877
if(cjp=coexec(csp->coshell,str,0,NULL,NULL,NULL))
878
{
879
csp->cojob = cjp;
880
cjp->local = shp->coshell;
881
if(filt)
882
{
883
if(filt>1)
884
sh_coaccept(shp,shp->inpipe,1);
885
sh_coaccept(shp,shp->outpipe,0);
886
if(filt > 2)
887
{
888
shp->coutpipe = shp->inpipe[1];
889
shp->fdptrs[shp->coutpipe] = &shp->coutpipe;
890
}
891
}
892
return(sh_copid(csp));
893
}
894
return(-1);
895
}
896
#endif /*SHOPT_COSHELL*/
897
898
#if SHOPT_FILESCAN
899
static Sfio_t *openstream(Shell_t *shp, struct ionod *iop, int *save)
900
{
901
int savein, fd = sh_redirect(shp,iop,3);
902
Sfio_t *sp;
903
savein = dup(0);
904
if(fd==0)
905
fd = savein;
906
sp = sfnew(NULL,NULL,SF_UNBOUND,fd,SF_READ);
907
close(0);
908
open(e_devnull,O_RDONLY);
909
shp->offsets[0] = -1;
910
shp->offsets[1] = 0;
911
*save = savein;
912
return(sp);
913
}
914
#endif /* SHOPT_FILESCAN */
915
916
#if SHOPT_NAMESPACE
917
static Namval_t *enter_namespace(Shell_t *shp, Namval_t *nsp)
918
{
919
Namval_t *path=nsp, *fpath=nsp, *onsp=shp->namespace;
920
Dt_t *root=0,*oroot=0;
921
char *val;
922
if(nsp)
923
{
924
if(!nv_istable(nsp))
925
nsp = 0;
926
else if(nv_dict(nsp)->view!=shp->var_base)
927
return(onsp);
928
}
929
if(!nsp && !onsp)
930
return(0);
931
if(onsp == nsp)
932
return(nsp);
933
if(onsp)
934
{
935
oroot = nv_dict(onsp);
936
if(!nsp)
937
{
938
path = nv_search(PATHNOD->nvname,oroot,HASH_NOSCOPE);
939
fpath = nv_search(FPATHNOD->nvname,oroot,HASH_NOSCOPE);
940
}
941
if(shp->var_tree==oroot)
942
{
943
shp->var_tree = shp->var_tree->view;
944
oroot = shp->var_base;
945
}
946
}
947
if(nsp)
948
{
949
if(shp->var_tree==shp->var_base)
950
shp->var_tree = nv_dict(nsp);
951
else
952
{
953
for(root=shp->var_tree; root->view!=oroot;root=root->view);
954
dtview(root,nv_dict(nsp));
955
}
956
}
957
shp->namespace = nsp;
958
if(path && (path = nv_search(PATHNOD->nvname,shp->var_tree,HASH_NOSCOPE)) && (val=nv_getval(path)))
959
nv_putval(path,val,NV_RDONLY);
960
if(fpath && (fpath = nv_search(FPATHNOD->nvname,shp->var_tree,HASH_NOSCOPE)) && (val=nv_getval(fpath)))
961
nv_putval(fpath,val,NV_RDONLY);
962
return(onsp);
963
}
964
#endif /* SHOPT_NAMESPACE */
965
966
int sh_exec(register const Shnode_t *t, int flags)
967
{
968
register Shell_t *shp = sh_getinterp();
969
Stk_t *stkp = shp->stk;
970
int unpipe=0;
971
sh_sigcheck(shp);
972
if(t && !shp->st.execbrk && !sh_isoption(SH_NOEXEC))
973
{
974
register int type = flags;
975
register char *com0 = 0;
976
int errorflg = (type&sh_state(SH_ERREXIT))|OPTIMIZE;
977
int execflg = (type&sh_state(SH_NOFORK));
978
int execflg2 = (type&sh_state(SH_FORKED));
979
int mainloop = (type&sh_state(SH_INTERACTIVE));
980
#if SHOPT_AMP || SHOPT_SPAWN
981
int ntflag = (type&sh_state(SH_NTFORK));
982
#else
983
int ntflag = 0;
984
#endif
985
int topfd = shp->topfd;
986
char *sav=stkptr(stkp,0);
987
char *cp=0, **com=0, *comn;
988
int argn;
989
int skipexitset = 0;
990
volatile int was_interactive = 0;
991
volatile int was_errexit = sh_isstate(SH_ERREXIT);
992
volatile int was_monitor = sh_isstate(SH_MONITOR);
993
volatile int echeck = 0;
994
if(flags&sh_state(SH_INTERACTIVE))
995
{
996
if(pipejob==2)
997
job_unlock();
998
nlock = 0;
999
pipejob = 0;
1000
job.curpgid = 0;
1001
job.curjobid = 0;
1002
flags &= ~sh_state(SH_INTERACTIVE);
1003
}
1004
sh_offstate(SH_ERREXIT);
1005
sh_offstate(SH_DEFPATH);
1006
if(was_errexit&flags)
1007
sh_onstate(SH_ERREXIT);
1008
if(was_monitor&flags)
1009
sh_onstate(SH_MONITOR);
1010
type = t->tre.tretyp;
1011
if(!shp->intrap)
1012
shp->oldexit=shp->exitval;
1013
shp->exitval=0;
1014
shp->lastsig = 0;
1015
shp->lastpath = 0;
1016
switch(type&COMMSK)
1017
{
1018
case TCOM:
1019
{
1020
register struct argnod *argp;
1021
char *trap;
1022
Namval_t *np, *nq, *last_table;
1023
struct ionod *io;
1024
int command=0, flgs=NV_ASSIGN;
1025
shp->bltindata.invariant = type>>(COMBITS+2);
1026
type &= (COMMSK|COMSCAN);
1027
sh_stats(STAT_SCMDS);
1028
error_info.line = t->com.comline-shp->st.firstline;
1029
com = sh_argbuild(shp,&argn,&(t->com),OPTIMIZE);
1030
echeck = 1;
1031
if(t->tre.tretyp&COMSCAN)
1032
{
1033
argp = t->com.comarg;
1034
if(argp && *com && !(argp->argflag&ARG_RAW))
1035
sh_sigcheck(shp);
1036
}
1037
np = (Namval_t*)(t->com.comnamp);
1038
nq = (Namval_t*)(t->com.comnamq);
1039
#if SHOPT_NAMESPACE
1040
if(np && shp->namespace && nq!=shp->namespace && nv_isattr(np,NV_BLTIN|NV_INTEGER|BLT_SPC)!=(NV_BLTIN|BLT_SPC))
1041
{
1042
Namval_t *mp;
1043
if(mp = sh_fsearch(shp,com[0],0))
1044
{
1045
nq = shp->namespace;
1046
np = mp;
1047
}
1048
}
1049
#endif /* SHOPT_NAMESPACE */
1050
com0 = com[0];
1051
shp->xargexit = 0;
1052
while(np==SYSCOMMAND)
1053
{
1054
register int n = b_command(0,com,&shp->bltindata);
1055
if(n==0)
1056
break;
1057
command += n;
1058
np = 0;
1059
if(!(com0= *(com+=n)))
1060
break;
1061
np = nv_bfsearch(com0, shp->bltin_tree, &nq, &cp);
1062
}
1063
if(shp->xargexit)
1064
{
1065
shp->xargmin -= command;
1066
shp->xargmax -= command;
1067
}
1068
else
1069
shp->xargmin = 0;
1070
argn -= command;
1071
#if SHOPT_COSHELL
1072
if(argn && shp->inpool)
1073
{
1074
if(io=t->tre.treio)
1075
sh_redirect(shp,io,0);
1076
if(!np || !is_abuiltin(np) || *np->nvname=='/' || np==SYSCD)
1077
{
1078
char **argv, *cp;
1079
for(argv=com+1; cp= *argv; argv++)
1080
{
1081
if(cp && *cp && *cp!='-')
1082
sh_coaddfile(shp,*argv);
1083
}
1084
break;
1085
}
1086
if(np->nvalue.bfp!=SYSTYPESET->nvalue.bfp)
1087
break;
1088
}
1089
if(t->tre.tretyp&FAMP)
1090
{
1091
shp->coshell = sh_coinit(shp,com);
1092
com0 = 0;
1093
break;
1094
}
1095
#endif /* SHOPT_COSHELL */
1096
if(np && is_abuiltin(np))
1097
{
1098
if(!command)
1099
{
1100
Namval_t *mp;
1101
#if SHOPT_NAMESPACE
1102
if(shp->namespace && (mp=sh_fsearch(shp,np->nvname,0)))
1103
np = mp;
1104
else
1105
#endif /* SHOPT_NAMESPACE */
1106
np = dtsearch(shp->fun_tree,np);
1107
}
1108
#if SHOPT_PFSH
1109
if(sh_isoption(SH_PFSH) && nv_isattr(np,NV_BLTINOPT) && !nv_isattr(np,NV_BLTPFSH))
1110
{
1111
if(path_xattr(shp,np->nvname,(char*)0))
1112
{
1113
dtdelete(shp->bltin_tree,np);
1114
np = 0;
1115
}
1116
else
1117
nv_onattr(np,NV_BLTPFSH);
1118
1119
}
1120
#endif /* SHOPT_PFSH */
1121
}
1122
if(com0)
1123
{
1124
if(!np && !strchr(com0,'/'))
1125
{
1126
Dt_t *root = command?shp->bltin_tree:shp->fun_tree;
1127
np = nv_bfsearch(com0, root, &nq, &cp);
1128
#if SHOPT_NAMESPACE
1129
if(shp->namespace && !nq && !cp)
1130
np = sh_fsearch(shp,com0,0);
1131
#endif /* SHOPT_NAMESPACE */
1132
}
1133
comn = com[argn-1];
1134
}
1135
io = t->tre.treio;
1136
if(shp->envlist = argp = t->com.comset)
1137
{
1138
if(argn==0 || (np && nv_isattr(np,(BLT_DCL|BLT_SPC))))
1139
{
1140
Namval_t *tp=0;
1141
if(argn)
1142
{
1143
if(checkopt(com,'A'))
1144
flgs |= NV_ARRAY;
1145
else if(checkopt(com,'a'))
1146
flgs |= NV_IARRAY;
1147
}
1148
if(np)
1149
flgs |= NV_UNJUST;
1150
#if SHOPT_BASH
1151
if(np==SYSLOCAL)
1152
{
1153
if(!nv_getval(SH_FUNNAMENOD))
1154
errormsg(SH_DICT,ERROR_exit(1),"%s: can only be used in a function",com0);
1155
if(!shp->st.var_local)
1156
{
1157
sh_scope(shp,(struct argnod*)0,0);
1158
shp->st.var_local = shp->var_tree;
1159
}
1160
1161
}
1162
#endif /* SHOPT_BASH */
1163
if(np==SYSTYPESET || (np && np->nvalue.bfp==SYSTYPESET->nvalue.bfp))
1164
{
1165
if(np!=SYSTYPESET)
1166
{
1167
shp->typeinit = np;
1168
tp = nv_type(np);
1169
}
1170
if(checkopt(com,'C'))
1171
flgs |= NV_COMVAR;
1172
if(checkopt(com,'S'))
1173
flgs |= NV_STATIC;
1174
if(checkopt(com,'m'))
1175
flgs |= NV_MOVE;
1176
if(checkopt(com,'n'))
1177
flgs |= NV_NOREF;
1178
#if SHOPT_TYPEDEF
1179
else if(argn>=3 && checkopt(com,'T'))
1180
{
1181
# if SHOPT_NAMESPACE
1182
if(shp->namespace)
1183
{
1184
if(!shp->strbuf2)
1185
shp->strbuf2 = sfstropen();
1186
sfprintf(shp->strbuf2,"%s%s%c",NV_CLASS,nv_name(shp->namespace),0);
1187
shp->prefix = strdup(sfstruse(shp->strbuf2));
1188
nv_open(shp->prefix,shp->var_base,NV_VARNAME);
1189
}
1190
else
1191
# endif /* SHOPT_NAMESPACE */
1192
shp->prefix = NV_CLASS;
1193
flgs |= NV_TYPE;
1194
1195
}
1196
#endif /* SHOPT_TYPEDEF */
1197
if((shp->fn_depth && !shp->prefix) || np==SYSLOCAL)
1198
flgs |= NV_NOSCOPE;
1199
}
1200
else if(np==SYSEXPORT)
1201
flgs |= NV_EXPORT;
1202
if(flgs&(NV_EXPORT|NV_NOREF))
1203
flgs |= NV_IDENT;
1204
else
1205
flgs |= NV_VARNAME;
1206
#if 0
1207
if(OPTIMIZE)
1208
flgs |= NV_TAGGED;
1209
#endif
1210
nv_setlist(argp,flgs,tp);
1211
if(np==shp->typeinit)
1212
shp->typeinit = 0;
1213
shp->envlist = argp;
1214
argp = NULL;
1215
}
1216
}
1217
last_table = shp->last_table;
1218
shp->last_table = 0;
1219
if((io||argn))
1220
{
1221
Shbltin_t *bp=0;
1222
static char *argv[1];
1223
int tflags = 1;
1224
if(np && nv_isattr(np,BLT_DCL))
1225
tflags |= 2;
1226
if(argn==0)
1227
{
1228
/* fake 'true' built-in */
1229
np = SYSTRUE;
1230
*argv = nv_name(np);
1231
com = argv;
1232
}
1233
/* set +x doesn't echo */
1234
else if((t->tre.tretyp&FSHOWME) && sh_isoption(SH_SHOWME))
1235
{
1236
int ison = sh_isoption(SH_XTRACE);
1237
if(!ison)
1238
sh_onoption(SH_XTRACE);
1239
sh_trace(shp,com-command,tflags);
1240
if(io)
1241
sh_redirect(shp,io,SH_SHOWME);
1242
if(!ison)
1243
sh_offoption(SH_XTRACE);
1244
break;
1245
}
1246
else if((np!=SYSSET) && sh_isoption(SH_XTRACE))
1247
sh_trace(shp,com-command,tflags);
1248
if(trap=shp->st.trap[SH_DEBUGTRAP])
1249
{
1250
int n = sh_debug(shp,trap,(char*)0,(char*)0, com, ARG_RAW);
1251
if(n==255 && shp->fn_depth+shp->dot_depth)
1252
{
1253
np = SYSRETURN;
1254
argn = 1;
1255
com[0] = np->nvname;
1256
com[1] = 0;
1257
io = 0;
1258
argp = 0;
1259
}
1260
else if(n==2)
1261
break;
1262
}
1263
if(io)
1264
sfsync(shp->outpool);
1265
shp->lastpath = 0;
1266
if(!np && !strchr(com0,'/'))
1267
{
1268
if(path_search(shp,com0,NIL(Pathcomp_t**),1))
1269
{
1270
error_info.line = t->com.comline-shp->st.firstline;
1271
#if SHOPT_NAMESPACE
1272
if(!shp->namespace || !(np=sh_fsearch(shp,com0,0)))
1273
#endif /* SHOPT_NAMESPACE */
1274
np=nv_search(com0,shp->fun_tree,0);
1275
if(!np || !np->nvalue.ip)
1276
{
1277
Namval_t *mp=nv_search(com0,shp->bltin_tree,0);
1278
if(mp)
1279
np = mp;
1280
}
1281
}
1282
else
1283
{
1284
if((np=nv_search(com0,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && np->nvalue.cp)
1285
np=nv_search(nv_getval(np),shp->bltin_tree,0);
1286
else
1287
np = 0;
1288
}
1289
}
1290
if(np && pipejob==2)
1291
{
1292
job_unlock();
1293
nlock--;
1294
pipejob = 1;
1295
}
1296
/* check for builtins */
1297
if(np && is_abuiltin(np))
1298
{
1299
volatile int scope=0, share=0;
1300
volatile void *save_ptr;
1301
volatile void *save_data;
1302
int jmpval, save_prompt;
1303
int was_nofork = execflg?sh_isstate(SH_NOFORK):0;
1304
struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
1305
volatile unsigned long was_vi=0, was_emacs=0, was_gmacs=0;
1306
struct stat statb;
1307
bp = &shp->bltindata;
1308
save_ptr = bp->ptr;
1309
save_data = bp->data;
1310
memset(&statb, 0, sizeof(struct stat));
1311
if(strchr(nv_name(np),'/'))
1312
{
1313
/*
1314
* disable editors for built-in
1315
* versions of commands on PATH
1316
*/
1317
was_vi = sh_isoption(SH_VI);
1318
was_emacs = sh_isoption(SH_EMACS);
1319
was_gmacs = sh_isoption(SH_GMACS);
1320
sh_offoption(SH_VI);
1321
sh_offoption(SH_EMACS);
1322
sh_offoption(SH_GMACS);
1323
}
1324
if(execflg)
1325
sh_onstate(SH_NOFORK);
1326
sh_pushcontext(shp,buffp,SH_JMPCMD);
1327
jmpval = sigsetjmp(buffp->buff,1);
1328
if(jmpval == 0)
1329
{
1330
if(!(nv_isattr(np,BLT_ENV)))
1331
error_info.flags |= ERROR_SILENT;
1332
errorpush(&buffp->err,0);
1333
if(io)
1334
{
1335
struct openlist *item;
1336
if(np==SYSLOGIN)
1337
type=1;
1338
else if(np==SYSEXEC)
1339
type=1+!com[1];
1340
else
1341
type = (execflg && !shp->subshell && !shp->st.trapcom[0]);
1342
shp->redir0 = 1;
1343
sh_redirect(shp,io,type);
1344
for(item=buffp->olist;item;item=item->next)
1345
item->strm=0;
1346
}
1347
if(!(nv_isattr(np,BLT_ENV)))
1348
{
1349
if(!shp->pwd)
1350
path_pwd(shp,0);
1351
if(shp->pwd)
1352
stat(".",&statb);
1353
sfsync(NULL);
1354
share = sfset(sfstdin,SF_SHARE,0);
1355
sh_onstate(SH_STOPOK);
1356
sfpool(sfstderr,NIL(Sfio_t*),SF_WRITE);
1357
sfset(sfstderr,SF_LINE,1);
1358
save_prompt = shp->nextprompt;
1359
shp->nextprompt = 0;
1360
}
1361
if(argp)
1362
{
1363
scope++;
1364
sh_scope(shp,argp,0);
1365
}
1366
opt_info.index = opt_info.offset = 0;
1367
opt_info.disc = 0;
1368
error_info.id = *com;
1369
if(argn)
1370
shp->exitval = 0;
1371
shp->bltinfun = (Shbltin_f)funptr(np);
1372
bp->bnode = np;
1373
bp->vnode = nq;
1374
bp->ptr = nv_context(np);
1375
bp->data = t->com.comstate;
1376
bp->sigset = 0;
1377
bp->notify = 0;
1378
bp->flags = (OPTIMIZE!=0);
1379
if(shp->subshell && nv_isattr(np,BLT_NOSFIO))
1380
sh_subtmpfile(shp);
1381
if(execflg && !shp->subshell &&
1382
!shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && shp->fn_depth==0 && !nv_isattr(np,BLT_ENV))
1383
{
1384
/* do close-on-exec */
1385
int fd;
1386
for(fd=0; fd < shp->gd->lim.open_max; fd++)
1387
if((shp->fdstatus[fd]&IOCLEX)&&fd!=shp->infd)
1388
sh_close(fd);
1389
}
1390
if(argn)
1391
shp->exitval = (*shp->bltinfun)(argn,com,(void*)bp);
1392
if(error_info.flags&ERROR_INTERACTIVE)
1393
tty_check(ERRIO);
1394
((Shnode_t*)t)->com.comstate = shp->bltindata.data;
1395
bp->data = (void*)save_data;
1396
if(sh.exitval && errno==EINTR && shp->lastsig)
1397
sh.exitval = SH_EXITSIG|shp->lastsig;
1398
else if(!nv_isattr(np,BLT_EXIT) && shp->exitval!=SH_RUNPROG)
1399
shp->exitval &= SH_EXITMASK;
1400
}
1401
else
1402
{
1403
struct openlist *item;
1404
for(item=buffp->olist;item;item=item->next)
1405
{
1406
if(item->strm)
1407
{
1408
sfclrlock(item->strm);
1409
if(shp->gd->hist_ptr && item->strm == shp->gd->hist_ptr->histfp)
1410
hist_close(shp->gd->hist_ptr);
1411
else
1412
sfclose(item->strm);
1413
}
1414
}
1415
if(shp->bltinfun && (error_info.flags&ERROR_NOTIFY))
1416
(*shp->bltinfun)(-2,com,(void*)bp);
1417
/* failure on special built-ins fatal */
1418
if(jmpval<=SH_JMPCMD && (!nv_isattr(np,BLT_SPC) || command))
1419
jmpval=0;
1420
}
1421
if(bp)
1422
{
1423
bp->bnode = 0;
1424
if( bp->ptr!= nv_context(np))
1425
np->nvfun = (Namfun_t*)bp->ptr;
1426
}
1427
if(execflg && !was_nofork)
1428
sh_offstate(SH_NOFORK);
1429
if(!(nv_isattr(np,BLT_ENV)))
1430
{
1431
if(shp->pwd)
1432
{
1433
struct stat stata;
1434
stat(".",&stata);
1435
/* restore directory changed */
1436
if(statb.st_ino!=stata.st_ino || statb.st_dev!=stata.st_dev)
1437
chdir(shp->pwd);
1438
}
1439
sh_offstate(SH_STOPOK);
1440
if(share&SF_SHARE)
1441
sfset(sfstdin,SF_PUBLIC|SF_SHARE,1);
1442
sfset(sfstderr,SF_LINE,0);
1443
sfpool(sfstderr,shp->outpool,SF_WRITE);
1444
sfpool(sfstdin,NIL(Sfio_t*),SF_WRITE);
1445
shp->nextprompt = save_prompt;
1446
}
1447
sh_popcontext(shp,buffp);
1448
errorpop(&buffp->err);
1449
error_info.flags &= ~(ERROR_SILENT|ERROR_NOTIFY);
1450
shp->bltinfun = 0;
1451
if(buffp->olist)
1452
free_list(buffp->olist);
1453
if(was_vi)
1454
sh_onoption(SH_VI);
1455
else if(was_emacs)
1456
sh_onoption(SH_EMACS);
1457
else if(was_gmacs)
1458
sh_onoption(SH_GMACS);
1459
if(scope)
1460
sh_unscope(shp);
1461
bp->ptr = (void*)save_ptr;
1462
bp->data = (void*)save_data;
1463
/* don't restore for subshell exec */
1464
if((shp->topfd>topfd) && !(shp->subshell && np==SYSEXEC))
1465
sh_iorestore(shp,topfd,jmpval);
1466
1467
shp->redir0 = 0;
1468
if(jmpval)
1469
siglongjmp(*shp->jmplist,jmpval);
1470
#if 0
1471
if(flgs&NV_STATIC)
1472
((Shnode_t*)t)->com.comset = 0;
1473
#endif
1474
if(shp->exitval >=0)
1475
goto setexit;
1476
np = 0;
1477
type=0;
1478
}
1479
/* check for functions */
1480
if(!command && np && nv_isattr(np,NV_FUNCTION))
1481
{
1482
volatile int indx;
1483
int jmpval=0;
1484
struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
1485
#if SHOPT_NAMESPACE
1486
Namval_t node, *namespace=0;
1487
#else
1488
Namval_t node;
1489
#endif /* SHOPT_NAMESPACE */
1490
struct Namref nr;
1491
long mode;
1492
register struct slnod *slp;
1493
if(!np->nvalue.ip)
1494
{
1495
indx = path_search(shp,com0,NIL(Pathcomp_t**),0);
1496
if(indx==1)
1497
{
1498
#if SHOPT_NAMESPACE
1499
if(shp->namespace)
1500
np = sh_fsearch(shp,com0,0);
1501
else
1502
#endif /* SHOPT_NAMESPACE */
1503
np = nv_search(com0,shp->fun_tree,HASH_NOSCOPE);
1504
}
1505
1506
if(!np->nvalue.ip)
1507
{
1508
if(indx==1)
1509
{
1510
errormsg(SH_DICT,ERROR_exit(0),e_defined,com0);
1511
shp->exitval = ERROR_NOEXEC;
1512
}
1513
else
1514
{
1515
errormsg(SH_DICT,ERROR_exit(0),e_found,"function");
1516
shp->exitval = ERROR_NOENT;
1517
}
1518
goto setexit;
1519
}
1520
}
1521
/* increase refcnt for unset */
1522
slp = (struct slnod*)np->nvenv;
1523
sh_funstaks(slp->slchild,1);
1524
staklink(slp->slptr);
1525
if(nq)
1526
{
1527
Namval_t *mp=0;
1528
if(nv_isattr(np,NV_STATICF) && (mp=nv_type(nq)))
1529
nq = mp;
1530
shp->last_table = last_table;
1531
mode = set_instance(shp,nq,&node,&nr);
1532
}
1533
if(io)
1534
{
1535
indx = shp->topfd;
1536
sh_pushcontext(shp,buffp,SH_JMPCMD);
1537
jmpval = sigsetjmp(buffp->buff,0);
1538
}
1539
if(jmpval == 0)
1540
1541
{
1542
if(io)
1543
indx = sh_redirect(shp,io,execflg);
1544
#if SHOPT_NAMESPACE
1545
if(*np->nvname=='.')
1546
{
1547
char *cp = strchr(np->nvname+1,'.');
1548
if(cp)
1549
{
1550
*cp = 0;
1551
namespace = nv_search(np->nvname,shp->var_base,HASH_NOSCOPE);
1552
*cp = '.';
1553
}
1554
}
1555
namespace = enter_namespace(shp,namespace);
1556
#endif /* SHOPT_NAMESPACE */
1557
sh_funct(shp,np,argn,com,t->com.comset,(flags&~OPTIMIZE_FLAG));
1558
}
1559
#if SHOPT_NAMESPACE
1560
enter_namespace(shp,namespace);
1561
#endif /* SHOPT_NAMESPACE */
1562
if(io)
1563
{
1564
if(buffp->olist)
1565
free_list(buffp->olist);
1566
sh_popcontext(shp,buffp);
1567
sh_iorestore(shp,indx,jmpval);
1568
}
1569
if(nq)
1570
unset_instance(nq,&node,&nr,mode);
1571
sh_funstaks(slp->slchild,-1);
1572
stakdelete(slp->slptr);
1573
if(jmpval > SH_JMPFUN)
1574
siglongjmp(*shp->jmplist,jmpval);
1575
goto setexit;
1576
}
1577
}
1578
else if(!io)
1579
{
1580
setexit:
1581
exitset();
1582
break;
1583
}
1584
}
1585
case TFORK:
1586
{
1587
register pid_t parent;
1588
int no_fork,jobid;
1589
int pipes[3];
1590
#if SHOPT_COSHELL
1591
if(shp->inpool)
1592
{
1593
sh_exec(t->fork.forktre,0);
1594
break;
1595
}
1596
#endif /* SHOPT_COSHELL */
1597
if(shp->subshell)
1598
{
1599
sh_subtmpfile(shp);
1600
if(shp->comsub==1 && !(shp->fdstatus[1]&IONOSEEK))
1601
unpipe=iousepipe(shp);
1602
if((type&(FAMP|TFORK))==(FAMP|TFORK))
1603
sh_subfork();
1604
}
1605
no_fork = !ntflag && !(type&(FAMP|FPOU)) && !shp->subshell &&
1606
!(shp->st.trapcom[SIGINT] && *shp->st.trapcom[SIGINT]) &&
1607
!shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] &&
1608
((struct checkpt*)shp->jmplist)->mode!=SH_JMPEVAL &&
1609
(execflg2 || (execflg && shp->fn_depth==0 &&
1610
!(pipejob && sh_isoption(SH_PIPEFAIL))
1611
));
1612
if(sh_isstate(SH_PROFILE) || shp->dot_depth)
1613
{
1614
/* disable foreground job monitor */
1615
if(!(type&FAMP))
1616
sh_offstate(SH_MONITOR);
1617
#if SHOPT_DEVFD
1618
else if(!(type&FINT))
1619
sh_offstate(SH_MONITOR);
1620
#endif /* SHOPT_DEVFD */
1621
}
1622
if(no_fork)
1623
job.parent=parent=0;
1624
else
1625
{
1626
#ifdef SHOPT_BGX
1627
int maxjob;
1628
if(((type&(FAMP|FINT)) == (FAMP|FINT)) && (maxjob=nv_getnum(JOBMAXNOD))>0)
1629
{
1630
while(job.numbjob >= maxjob)
1631
{
1632
job_lock();
1633
job_reap(0);
1634
job_unlock();
1635
}
1636
}
1637
#endif /* SHOPT_BGX */
1638
nv_getval(RANDNOD);
1639
restorefd = shp->topfd;
1640
if(type&FCOOP)
1641
{
1642
pipes[2] = 0;
1643
#if SHOPT_COSHELL
1644
if(shp->coshell)
1645
{
1646
if(shp->cpipe[0]<0 || shp->cpipe[1] < 0)
1647
{
1648
sh_copipe(shp,shp->outpipe=shp->cpipe,0);
1649
shp->fdptrs[shp->cpipe[0]] = shp->cpipe;
1650
}
1651
sh_copipe(shp,shp->inpipe=pipes,0);
1652
parent = sh_coexec(shp,t,3);
1653
shp->cpid = parent;
1654
jobid = job_post(shp,parent,0);
1655
goto skip;
1656
}
1657
#endif /* SHOPT_COSHELL */
1658
coproc_init(shp,pipes);
1659
}
1660
#if SHOPT_COSHELL
1661
if((type&(FAMP|FINT)) == (FAMP|FINT))
1662
{
1663
if(shp->coshell)
1664
{
1665
parent = sh_coexec(shp,t,0);
1666
jobid = job_post(shp,parent,0);
1667
goto skip;
1668
}
1669
}
1670
#endif /* SHOPT_COSHELL */
1671
#if SHOPT_AMP
1672
if((type&(FAMP|FINT)) == (FAMP|FINT))
1673
parent = sh_ntfork(shp,t,com,&jobid,ntflag);
1674
else
1675
parent = sh_fork(shp,type,&jobid);
1676
if(parent<0)
1677
{
1678
if(shp->comsub==1 && usepipe && unpipe)
1679
iounpipe(shp);
1680
break;
1681
}
1682
#else
1683
#if SHOPT_SPAWN
1684
# ifdef _lib_fork
1685
if(com)
1686
parent = sh_ntfork(shp,t,com,&jobid,ntflag);
1687
else
1688
parent = sh_fork(shp,type,&jobid);
1689
# else
1690
if((parent = sh_ntfork(shp,t,com,&jobid,ntflag))<=0)
1691
break;
1692
# endif /* _lib_fork */
1693
if(parent<0)
1694
{
1695
if(shp->comsub==1 && usepipe && unpipe)
1696
iounpipe(shp);
1697
break;
1698
}
1699
#else
1700
parent = sh_fork(shp,type,&jobid);
1701
#endif /* SHOPT_SPAWN */
1702
#endif
1703
}
1704
#if SHOPT_COSHELL
1705
skip:
1706
#endif /* SHOPT_COSHELL */
1707
if(job.parent=parent)
1708
/* This is the parent branch of fork
1709
* It may or may not wait for the child
1710
*/
1711
{
1712
if(pipejob==2)
1713
{
1714
pipejob = 1;
1715
nlock--;
1716
job_unlock();
1717
}
1718
if(type&FPCL)
1719
sh_close(shp->inpipe[0]);
1720
if(type&(FCOOP|FAMP))
1721
shp->bckpid = parent;
1722
else if(!(type&(FAMP|FPOU)))
1723
{
1724
if(!sh_isoption(SH_MONITOR))
1725
{
1726
if(!(shp->sigflag[SIGINT]&(SH_SIGFAULT|SH_SIGOFF)))
1727
sh_sigtrap(SIGINT);
1728
shp->trapnote |= SH_SIGIGNORE;
1729
}
1730
if(shp->pipepid)
1731
shp->pipepid = parent;
1732
else
1733
job_wait(parent);
1734
if(shp->topfd > topfd)
1735
sh_iorestore(shp,topfd,0);
1736
if(usepipe && tsetio && subdup && unpipe)
1737
iounpipe(shp);
1738
if(!sh_isoption(SH_MONITOR))
1739
{
1740
shp->trapnote &= ~SH_SIGIGNORE;
1741
if(shp->exitval == (SH_EXITSIG|SIGINT))
1742
kill(getpid(),SIGINT);
1743
}
1744
}
1745
if(type&FAMP)
1746
{
1747
if(sh_isstate(SH_PROFILE) || sh_isstate(SH_INTERACTIVE))
1748
{
1749
/* print job number */
1750
#ifdef JOBS
1751
# if SHOPT_COSHELL
1752
sfprintf(sfstderr,"[%d]\t%s\n",jobid,sh_pid2str(shp,parent));
1753
# else
1754
sfprintf(sfstderr,"[%d]\t%d\n",jobid,parent);
1755
# endif /* SHOPT_COSHELL */
1756
#else
1757
sfprintf(sfstderr,"%d\n",parent);
1758
#endif /* JOBS */
1759
}
1760
}
1761
break;
1762
}
1763
else
1764
/*
1765
* this is the FORKED branch (child) of execute
1766
*/
1767
{
1768
volatile int jmpval;
1769
struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
1770
struct ionod *iop;
1771
int rewrite=0;
1772
if(no_fork)
1773
sh_sigreset(2);
1774
sh_pushcontext(shp,buffp,SH_JMPEXIT);
1775
jmpval = sigsetjmp(buffp->buff,0);
1776
if(jmpval)
1777
goto done;
1778
if((type&FINT) && !sh_isstate(SH_MONITOR))
1779
{
1780
/* default std input for & */
1781
signal(SIGINT,SIG_IGN);
1782
signal(SIGQUIT,SIG_IGN);
1783
if(!shp->st.ioset)
1784
{
1785
if(sh_close(0)>=0)
1786
sh_chkopen(e_devnull);
1787
}
1788
}
1789
sh_offstate(SH_MONITOR);
1790
/* pipe in or out */
1791
#ifdef _lib_nice
1792
if((type&FAMP) && sh_isoption(SH_BGNICE))
1793
nice(4);
1794
#endif /* _lib_nice */
1795
#if !SHOPT_DEVFD
1796
if(shp->fifo && (type&(FPIN|FPOU)))
1797
{
1798
int fn,fd = (type&FPIN)?0:1;
1799
void *fifo_timer=sh_timeradd(500,1,fifo_check,(void*)shp);
1800
fn = sh_open(shp->fifo,fd?O_WRONLY:O_RDONLY);
1801
timerdel(fifo_timer);
1802
sh_iorenumber(shp,fn,fd);
1803
sh_close(fn);
1804
sh_delay(.001);
1805
unlink(shp->fifo);
1806
free(shp->fifo);
1807
shp->fifo = 0;
1808
type &= ~(FPIN|FPOU);
1809
}
1810
#endif /* !SHOPT_DEVFD */
1811
if(type&FPIN)
1812
{
1813
#if SHOPT_COSHELL
1814
if(shp->inpipe[2]>20000)
1815
sh_coaccept(shp,shp->inpipe,0);
1816
#endif /* SHOPT_COSHELL */
1817
sh_iorenumber(shp,shp->inpipe[0],0);
1818
if(!(type&FPOU) || (type&FCOOP))
1819
sh_close(shp->inpipe[1]);
1820
}
1821
if(type&FPOU)
1822
{
1823
#if SHOPT_COSHELL
1824
if(shp->outpipe[2]>20000)
1825
sh_coaccept(shp,shp->outpipe,1);
1826
#endif /* SHOPT_COSHELL */
1827
sh_iorenumber(shp,shp->outpipe[1],1);
1828
sh_pclose(shp->outpipe);
1829
}
1830
if((type&COMMSK)!=TCOM)
1831
error_info.line = t->fork.forkline-shp->st.firstline;
1832
if(shp->topfd)
1833
sh_iounsave(shp);
1834
topfd = shp->topfd;
1835
if(com0 && (iop=t->tre.treio))
1836
{
1837
for(;iop;iop=iop->ionxt)
1838
{
1839
if(iop->iofile&IOREWRITE)
1840
rewrite = 1;
1841
}
1842
}
1843
sh_redirect(shp,t->tre.treio,1);
1844
if(rewrite)
1845
{
1846
job_lock();
1847
while((parent = vfork()) < 0)
1848
_sh_fork(shp,parent, 0, (int*)0);
1849
if(parent)
1850
{
1851
job.toclear = 0;
1852
job_post(shp,parent,0);
1853
job_wait(parent);
1854
sh_iorestore(shp,topfd,SH_JMPCMD);
1855
sh_done(shp,(shp->exitval&SH_EXITSIG)?(shp->exitval&SH_EXITMASK):0);
1856
1857
}
1858
job_unlock();
1859
}
1860
if((type&COMMSK)!=TCOM)
1861
{
1862
/* don't clear job table for out
1863
pipes so that jobs comand can
1864
be used in a pipeline
1865
*/
1866
if(!no_fork && !(type&FPOU))
1867
job_clear();
1868
sh_exec(t->fork.forktre,flags|sh_state(SH_NOFORK)|sh_state(SH_FORKED));
1869
}
1870
else if(com0)
1871
{
1872
sh_offoption(SH_ERREXIT);
1873
sh_freeup(shp);
1874
path_exec(shp,com0,com,t->com.comset);
1875
}
1876
done:
1877
sh_popcontext(shp,buffp);
1878
if(jmpval>SH_JMPEXIT)
1879
siglongjmp(*shp->jmplist,jmpval);
1880
sh_done(shp,0);
1881
}
1882
}
1883
1884
case TSETIO:
1885
{
1886
/*
1887
* don't create a new process, just
1888
* save and restore io-streams
1889
*/
1890
pid_t pid;
1891
int jmpval, waitall;
1892
int simple = (t->fork.forktre->tre.tretyp&COMMSK)==TCOM;
1893
struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
1894
#if SHOPT_COSHELL
1895
if(shp->inpool)
1896
{
1897
sh_redirect(shp,t->fork.forkio,0);
1898
sh_exec(t->fork.forktre,0);
1899
break;
1900
}
1901
#endif /*SHOPT_COSHELL */
1902
if(shp->subshell)
1903
execflg = 0;
1904
sh_pushcontext(shp,buffp,SH_JMPIO);
1905
if(type&FPIN)
1906
{
1907
was_interactive = sh_isstate(SH_INTERACTIVE);
1908
sh_offstate(SH_INTERACTIVE);
1909
sh_iosave(shp,0,shp->topfd,(char*)0);
1910
shp->pipepid = simple;
1911
sh_iorenumber(shp,shp->inpipe[0],0);
1912
/*
1913
* if read end of pipe is a simple command
1914
* treat as non-sharable to improve performance
1915
*/
1916
if(simple)
1917
sfset(sfstdin,SF_PUBLIC|SF_SHARE,0);
1918
waitall = job.waitall;
1919
job.waitall = 0;
1920
pid = job.parent;
1921
}
1922
else
1923
error_info.line = t->fork.forkline-shp->st.firstline;
1924
jmpval = sigsetjmp(buffp->buff,0);
1925
if(jmpval==0)
1926
{
1927
if(shp->comsub==1)
1928
tsetio = 1;
1929
sh_redirect(shp,t->fork.forkio,execflg);
1930
(t->fork.forktre)->tre.tretyp |= t->tre.tretyp&FSHOWME;
1931
sh_exec(t->fork.forktre,flags&~simple);
1932
}
1933
else
1934
sfsync(shp->outpool);
1935
sh_popcontext(shp,buffp);
1936
sh_iorestore(shp,buffp->topfd,jmpval);
1937
if(buffp->olist)
1938
free_list(buffp->olist);
1939
if(type&FPIN)
1940
{
1941
job.waitall = waitall;
1942
type = shp->exitval;
1943
if(!(type&SH_EXITSIG))
1944
{
1945
/* wait for remainder of pipline */
1946
if(shp->pipepid>1)
1947
{
1948
job_wait(shp->pipepid);
1949
type = shp->exitval;
1950
}
1951
else
1952
job_wait(waitall?pid:0);
1953
if(type || !sh_isoption(SH_PIPEFAIL))
1954
shp->exitval = type;
1955
}
1956
if(shp->comsub==1 && usepipe)
1957
iounpipe(shp);
1958
shp->pipepid = 0;
1959
shp->st.ioset = 0;
1960
if(simple && was_errexit)
1961
{
1962
echeck = 1;
1963
sh_onstate(SH_ERREXIT);
1964
}
1965
}
1966
if(jmpval>SH_JMPIO)
1967
siglongjmp(*shp->jmplist,jmpval);
1968
break;
1969
}
1970
1971
case TPAR:
1972
#if SHOPT_COSHELL
1973
if(shp->inpool)
1974
{
1975
sh_exec(t->par.partre,0);
1976
break;
1977
}
1978
#endif /* SHOPT_COSHELL */
1979
echeck = 1;
1980
flags &= ~OPTIMIZE_FLAG;
1981
if(!shp->subshell && !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && (flags&sh_state(SH_NOFORK)))
1982
{
1983
char *savsig;
1984
int nsig,jmpval;
1985
struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
1986
shp->st.otrapcom = 0;
1987
if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
1988
{
1989
nsig += sizeof(char*);
1990
memcpy(savsig=malloc(nsig),(char*)&shp->st.trapcom[0],nsig);
1991
shp->st.otrapcom = (char**)savsig;
1992
}
1993
sh_sigreset(0);
1994
sh_pushcontext(shp,buffp,SH_JMPEXIT);
1995
jmpval = sigsetjmp(buffp->buff,0);
1996
if(jmpval==0)
1997
sh_exec(t->par.partre,flags);
1998
sh_popcontext(shp,buffp);
1999
if(jmpval > SH_JMPEXIT)
2000
siglongjmp(*shp->jmplist,jmpval);
2001
if(shp->exitval > 256)
2002
shp->exitval -= 128;
2003
sh_done(shp,0);
2004
}
2005
else if(((type=t->par.partre->tre.tretyp)&FAMP) && ((type&COMMSK)==TFORK))
2006
{
2007
pid_t pid;
2008
sfsync(NIL(Sfio_t*));
2009
while((pid=fork())< 0)
2010
_sh_fork(shp,pid,0,0);
2011
if(pid==0)
2012
{
2013
sh_exec(t->par.partre,flags);
2014
shp->st.trapcom[0]=0;
2015
sh_done(shp,0);
2016
}
2017
}
2018
else
2019
sh_subshell(shp,t->par.partre,flags,0);
2020
break;
2021
2022
case TFIL:
2023
{
2024
/*
2025
* This code sets up a pipe.
2026
* All elements of the pipe are started by the parent.
2027
* The last element executes in current environment
2028
*/
2029
int pvo[3]; /* old pipe for multi-stage */
2030
int pvn[3]; /* current set up pipe */
2031
int savepipe = pipejob;
2032
int savelock = nlock;
2033
int showme = t->tre.tretyp&FSHOWME;
2034
int n,waitall,savewaitall=job.waitall;
2035
int savejobid = job.curjobid;
2036
int *exitval=0,*saveexitval = job.exitval;
2037
pid_t savepgid = job.curpgid;
2038
#if SHOPT_COSHELL
2039
int copipe=0;
2040
Shnode_t *tt;
2041
#endif /* SHOPT_COSHELL */
2042
job.exitval = 0;
2043
#if SHOPT_COSHELL
2044
if(shp->inpool)
2045
{
2046
do
2047
{
2048
sh_exec(t->lst.lstlef, 0);
2049
t = t->lst.lstrit;
2050
if(flags && (t->tre.tretyp!=TFIL || !(t->lst.lstlef->tre.tretyp&FALTPIPE)))
2051
goto coskip1;
2052
}
2053
while(t->tre.tretyp==TFIL);
2054
sh_exec(t,0);
2055
coskip1:
2056
break;
2057
}
2058
pvo[2] = pvn[2] = 0;
2059
#endif /* SHOPT_COSHELL */
2060
job.curjobid = 0;
2061
if(shp->subshell)
2062
{
2063
sh_subtmpfile(shp);
2064
if(shp->comsub==1 && !(shp->fdstatus[1]&IONOSEEK))
2065
iousepipe(shp);
2066
}
2067
shp->inpipe = pvo;
2068
shp->outpipe = pvn;
2069
pvo[1] = -1;
2070
if(sh_isoption(SH_PIPEFAIL))
2071
{
2072
const Shnode_t* tn=t;
2073
job.waitall = 2;
2074
job.curpgid = 0;
2075
while((tn=tn->lst.lstrit) && tn->tre.tretyp==TFIL)
2076
job.waitall++;
2077
exitval = job.exitval = (int*)stakalloc(job.waitall*sizeof(int));
2078
memset(exitval,0,job.waitall*sizeof(int));
2079
}
2080
else
2081
job.waitall |= !pipejob && sh_isstate(SH_MONITOR);
2082
job_lock();
2083
nlock++;
2084
do
2085
{
2086
/* create the pipe */
2087
#if SHOPT_COSHELL
2088
tt = t->lst.lstrit;
2089
if(shp->coshell && !showme)
2090
{
2091
if(t->lst.lstlef->tre.tretyp&FALTPIPE)
2092
{
2093
sh_copipe(shp,pvn,0);
2094
type = sh_coexec(shp,t,1+copipe);
2095
pvn[1] = -1;
2096
pipejob=1;
2097
if(type>0)
2098
{
2099
job_post(shp,type,0);
2100
type = 0;
2101
}
2102
copipe = 1;
2103
pvo[0] = pvn[0];
2104
while(tt->tre.tretyp==TFIL && tt->lst.lstlef->tre.tretyp&FALTPIPE)
2105
tt = tt->lst.lstrit;
2106
t = tt;
2107
continue;
2108
}
2109
else if(tt->tre.tretyp==TFIL && tt->lst.lstlef->tre.tretyp&FALTPIPE)
2110
{
2111
sh_copipe(shp,pvn,0);
2112
pvo[2] = pvn[2];
2113
copipe = 0;
2114
goto coskip2;
2115
}
2116
}
2117
#endif /* SHOPT_COSHELL */
2118
sh_pipe(pvn);
2119
#if SHOPT_COSHELL
2120
pvn[2] = 0;
2121
coskip2:
2122
#endif /* SHOPT_COSHELL */
2123
/* execute out part of pipe no wait */
2124
(t->lst.lstlef)->tre.tretyp |= showme;
2125
type = sh_exec(t->lst.lstlef, errorflg);
2126
/* close out-part of pipe */
2127
sh_close(pvn[1]);
2128
pipejob=1;
2129
/* save the pipe stream-ids */
2130
pvo[0] = pvn[0];
2131
/* pipeline all in one process group */
2132
t = t->lst.lstrit;
2133
}
2134
/* repeat until end of pipeline */
2135
while(!type && t->tre.tretyp==TFIL);
2136
shp->inpipe = pvn;
2137
shp->outpipe = 0;
2138
pipejob = 2;
2139
waitall = job.waitall;
2140
job.waitall = 0;
2141
if(type == 0)
2142
{
2143
/*
2144
* execute last element of pipeline
2145
* in the current process
2146
*/
2147
((Shnode_t*)t)->tre.tretyp |= showme;
2148
sh_exec(t,flags);
2149
}
2150
else
2151
/* execution failure, close pipe */
2152
sh_pclose(pvn);
2153
if(pipejob==2)
2154
job_unlock();
2155
if((pipejob = savepipe) && nlock<savelock)
2156
pipejob = 1;
2157
n = shp->exitval;
2158
if(job.waitall = waitall)
2159
{
2160
if(sh_isstate(SH_MONITOR))
2161
job_wait(0);
2162
else
2163
{
2164
shp->intrap++;
2165
job_wait(0);
2166
shp->intrap--;
2167
}
2168
}
2169
if(n==0 && exitval)
2170
{
2171
while(exitval <= --job.exitval)
2172
{
2173
if(*job.exitval)
2174
{
2175
n = *job.exitval;
2176
break;
2177
}
2178
}
2179
}
2180
shp->exitval = n;
2181
#ifdef SIGTSTP
2182
if(!pipejob && sh_isstate(SH_MONITOR))
2183
tcsetpgrp(JOBTTY,shp->gd->pid);
2184
#endif /*SIGTSTP */
2185
job.curpgid = savepgid;
2186
job.exitval = saveexitval;
2187
job.waitall = savewaitall;
2188
job.curjobid = savejobid;
2189
break;
2190
}
2191
2192
case TLST:
2193
{
2194
/* a list of commands are executed here */
2195
do
2196
{
2197
sh_exec(t->lst.lstlef,errorflg|OPTIMIZE);
2198
t = t->lst.lstrit;
2199
}
2200
while(t->tre.tretyp == TLST);
2201
sh_exec(t,flags);
2202
break;
2203
}
2204
2205
case TAND:
2206
#if SHOPT_COSHELL
2207
if(shp->inpool)
2208
{
2209
andor:
2210
sh_exec(t->lst.lstlef,0);
2211
sh_exec(t->lst.lstrit,0);
2212
break;
2213
}
2214
#endif /* SHOPT_COSHELL */
2215
if(type&TTEST)
2216
skipexitset++;
2217
if(sh_exec(t->lst.lstlef,OPTIMIZE)==0)
2218
sh_exec(t->lst.lstrit,flags);
2219
break;
2220
2221
case TORF:
2222
#if SHOPT_COSHELL
2223
if(shp->inpool)
2224
goto andor;
2225
#endif /* SHOPT_COSHELL */
2226
if(type&TTEST)
2227
skipexitset++;
2228
if(sh_exec(t->lst.lstlef,OPTIMIZE)!=0)
2229
sh_exec(t->lst.lstrit,flags);
2230
break;
2231
2232
case TFOR: /* for and select */
2233
{
2234
register char **args;
2235
register int nargs;
2236
register Namval_t *np;
2237
int flag = errorflg|OPTIMIZE_FLAG;
2238
struct dolnod *argsav=0;
2239
struct comnod *tp;
2240
char *cp, *trap, *nullptr = 0;
2241
int nameref, refresh=1;
2242
char *av[5];
2243
#if SHOPT_COSHELL
2244
int poolfiles;
2245
#endif /* SHOPT_COSHELL */
2246
#if SHOPT_OPTIMIZE
2247
int jmpval = ((struct checkpt*)shp->jmplist)->mode;
2248
struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
2249
void *optlist = shp->optlist;
2250
shp->optlist = 0;
2251
sh_tclear(t->for_.fortre);
2252
sh_pushcontext(shp,buffp,jmpval);
2253
jmpval = sigsetjmp(buffp->buff,0);
2254
if(jmpval)
2255
goto endfor;
2256
#endif /* SHOPT_OPTIMIZE */
2257
error_info.line = t->for_.forline-shp->st.firstline;
2258
if(!(tp=t->for_.forlst))
2259
{
2260
args=shp->st.dolv+1;
2261
nargs = shp->st.dolc;
2262
argsav=sh_arguse(shp);
2263
}
2264
else
2265
{
2266
args=sh_argbuild(shp,&argn,tp,0);
2267
nargs = argn;
2268
}
2269
np = nv_open(t->for_.fornam, shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOREF);
2270
nameref = nv_isref(np)!=0;
2271
shp->st.loopcnt++;
2272
cp = *args;
2273
while(cp && shp->st.execbrk==0)
2274
{
2275
if(t->tre.tretyp&COMSCAN)
2276
{
2277
char *val;
2278
int save_prompt;
2279
/* reuse register */
2280
if(refresh)
2281
{
2282
sh_menu(sfstderr,nargs,args);
2283
refresh = 0;
2284
}
2285
save_prompt = shp->nextprompt;
2286
shp->nextprompt = 3;
2287
shp->timeout = 0;
2288
shp->exitval=sh_readline(shp,&nullptr,0,1,(size_t)0,1000*shp->st.tmout);
2289
shp->nextprompt = save_prompt;
2290
if(shp->exitval||sfeof(sfstdin)||sferror(sfstdin))
2291
{
2292
shp->exitval = 1;
2293
break;
2294
}
2295
if(!(val=nv_getval(sh_scoped(shp,REPLYNOD))))
2296
continue;
2297
else
2298
{
2299
if(*(cp=val) == 0)
2300
{
2301
refresh++;
2302
goto check;
2303
}
2304
while(type = *cp++)
2305
if(type < '0' && type > '9')
2306
break;
2307
if(type!=0)
2308
type = nargs;
2309
else
2310
type = (int)strtol(val, (char**)0, 10)-1;
2311
if(type<0 || type >= nargs)
2312
cp = "";
2313
else
2314
cp = args[type];
2315
}
2316
}
2317
if(nameref)
2318
nv_offattr(np,NV_REF);
2319
else if(nv_isattr(np, NV_ARRAY))
2320
nv_putsub(np,NIL(char*),0L);
2321
nv_putval(np,cp,0);
2322
if(nameref)
2323
nv_setref(np,(Dt_t*)0,NV_VARNAME);
2324
if(trap=shp->st.trap[SH_DEBUGTRAP])
2325
{
2326
av[0] = (t->tre.tretyp&COMSCAN)?"select":"for";
2327
av[1] = t->for_.fornam;
2328
av[2] = "in";
2329
av[3] = cp;
2330
av[4] = 0;
2331
sh_debug(shp,trap,(char*)0,(char*)0,av,0);
2332
}
2333
#if SHOPT_COSHELL
2334
if(shp->inpool)
2335
{
2336
poolfiles = shp->poolfiles;
2337
sh_exec(t->for_.fortre,0);
2338
if(poolfiles==shp->poolfiles)
2339
break;
2340
}
2341
#endif /* SHOPT_COSHELL */
2342
sh_exec(t->for_.fortre,flag);
2343
flag &= ~OPTIMIZE_FLAG;
2344
if(t->tre.tretyp&COMSCAN)
2345
{
2346
if((cp=nv_getval(sh_scoped(shp,REPLYNOD))) && *cp==0)
2347
refresh++;
2348
}
2349
else
2350
cp = *++args;
2351
check:
2352
if(shp->st.breakcnt<0)
2353
shp->st.execbrk = (++shp->st.breakcnt !=0);
2354
}
2355
#if SHOPT_OPTIMIZE
2356
endfor:
2357
sh_popcontext(shp,buffp);
2358
sh_tclear(t->for_.fortre);
2359
sh_optclear(shp,optlist);
2360
if(jmpval)
2361
siglongjmp(*shp->jmplist,jmpval);
2362
#endif /*SHOPT_OPTIMIZE */
2363
if(shp->st.breakcnt>0)
2364
shp->st.execbrk = (--shp->st.breakcnt !=0);
2365
shp->st.loopcnt--;
2366
sh_argfree(shp,argsav,0);
2367
nv_close(np);
2368
break;
2369
}
2370
2371
case TWH: /* while and until */
2372
{
2373
volatile int r=0;
2374
int first = OPTIMIZE_FLAG;
2375
Shnode_t *tt = t->wh.whtre;
2376
#if SHOPT_FILESCAN
2377
Sfio_t *iop=0;
2378
int savein;
2379
#endif /*SHOPT_FILESCAN*/
2380
#if SHOPT_OPTIMIZE
2381
int jmpval = ((struct checkpt*)shp->jmplist)->mode;
2382
struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
2383
void *optlist = shp->optlist;
2384
#endif /* SHOPT_OPTIMIZE */
2385
#if SHOPT_COSHELL
2386
if(shp->inpool)
2387
{
2388
int poolfiles;
2389
# if SHOPT_FILESCAN
2390
if(type==TWH && tt->tre.tretyp==TCOM && !tt->com.comarg && tt->com.comio)
2391
{
2392
sh_redirect(shp,tt->com.comio,0);
2393
break;
2394
}
2395
# endif /* SHOPT_FILESCAN */
2396
sh_exec(tt,0);
2397
do
2398
{
2399
if((sh_exec(tt,0)==0)!=(type==TWH))
2400
break;
2401
poolfiles = shp->poolfiles;
2402
sh_exec(t->wh.dotre,0);
2403
if(t->wh.whinc)
2404
sh_exec((Shnode_t*)t->wh.whinc,0);
2405
}
2406
while(poolfiles != shp->poolfiles);
2407
break;
2408
}
2409
#endif /*SHOPT_COSHELL */
2410
#if SHOPT_OPTIMIZE
2411
shp->optlist = 0;
2412
sh_tclear(t->wh.whtre);
2413
sh_tclear(t->wh.dotre);
2414
sh_pushcontext(shp,buffp,jmpval);
2415
jmpval = sigsetjmp(buffp->buff,0);
2416
if(jmpval)
2417
goto endwhile;
2418
#endif /* SHOPT_OPTIMIZE */
2419
#if SHOPT_FILESCAN
2420
if(type==TWH && tt->tre.tretyp==TCOM && !tt->com.comarg && tt->com.comio)
2421
{
2422
iop = openstream(shp,tt->com.comio,&savein);
2423
if(tt->com.comset)
2424
nv_setlist(tt->com.comset,NV_IDENT|NV_ASSIGN,0);
2425
}
2426
#endif /*SHOPT_FILESCAN */
2427
shp->st.loopcnt++;
2428
while(shp->st.execbrk==0)
2429
{
2430
#if SHOPT_FILESCAN
2431
if(iop)
2432
{
2433
if(!(shp->cur_line=sfgetr(iop,'\n',SF_STRING)))
2434
break;
2435
}
2436
else
2437
#endif /*SHOPT_FILESCAN */
2438
if((sh_exec(tt,first)==0)!=(type==TWH))
2439
break;
2440
r = sh_exec(t->wh.dotre,first|errorflg);
2441
if(shp->st.breakcnt<0)
2442
shp->st.execbrk = (++shp->st.breakcnt !=0);
2443
/* This is for the arithmetic for */
2444
if(shp->st.execbrk==0 && t->wh.whinc)
2445
sh_exec((Shnode_t*)t->wh.whinc,first);
2446
first = 0;
2447
errorflg &= ~OPTIMIZE_FLAG;
2448
#if SHOPT_FILESCAN
2449
shp->offsets[0] = -1;
2450
shp->offsets[1] = 0;
2451
#endif /*SHOPT_FILESCAN */
2452
}
2453
#if SHOPT_OPTIMIZE
2454
endwhile:
2455
sh_popcontext(shp,buffp);
2456
sh_tclear(t->wh.whtre);
2457
sh_tclear(t->wh.dotre);
2458
sh_optclear(shp,optlist);
2459
if(jmpval)
2460
siglongjmp(*shp->jmplist,jmpval);
2461
#endif /*SHOPT_OPTIMIZE */
2462
if(shp->st.breakcnt>0)
2463
shp->st.execbrk = (--shp->st.breakcnt !=0);
2464
shp->st.loopcnt--;
2465
shp->exitval= r;
2466
#if SHOPT_FILESCAN
2467
if(iop)
2468
{
2469
sfclose(iop);
2470
close(0);
2471
dup(savein);
2472
shp->cur_line = 0;
2473
}
2474
#endif /*SHOPT_FILESCAN */
2475
break;
2476
}
2477
case TARITH: /* (( expression )) */
2478
{
2479
register char *trap;
2480
char *arg[4];
2481
error_info.line = t->ar.arline-shp->st.firstline;
2482
arg[0] = "((";
2483
if(!(t->ar.arexpr->argflag&ARG_RAW))
2484
arg[1] = sh_macpat(shp,t->ar.arexpr,OPTIMIZE|ARG_ARITH);
2485
else
2486
arg[1] = t->ar.arexpr->argval;
2487
arg[2] = "))";
2488
arg[3] = 0;
2489
if(trap=shp->st.trap[SH_DEBUGTRAP])
2490
sh_debug(shp,trap,(char*)0, (char*)0, arg, ARG_ARITH);
2491
if(sh_isoption(SH_XTRACE))
2492
{
2493
sh_trace(shp,NIL(char**),0);
2494
sfprintf(sfstderr,"((%s))\n",arg[1]);
2495
}
2496
if(t->ar.arcomp)
2497
shp->exitval = !arith_exec((Arith_t*)t->ar.arcomp);
2498
else
2499
shp->exitval = !sh_arith(shp,arg[1]);
2500
break;
2501
}
2502
2503
case TIF:
2504
#if SHOPT_COSHELL
2505
if(shp->inpool)
2506
{
2507
sh_exec(t->if_.thtre,0);
2508
if(t->if_.eltre)
2509
sh_exec(t->if_.eltre, 0);
2510
break;
2511
}
2512
#endif /*SHOPT_COSHELL */
2513
if(sh_exec(t->if_.iftre,OPTIMIZE)==0)
2514
sh_exec(t->if_.thtre,flags);
2515
else if(t->if_.eltre)
2516
sh_exec(t->if_.eltre, flags);
2517
else
2518
shp->exitval=0; /* force zero exit for if-then-fi */
2519
break;
2520
2521
case TSW:
2522
{
2523
Shnode_t *tt = (Shnode_t*)t;
2524
char *trap, *r = sh_macpat(shp,tt->sw.swarg,OPTIMIZE);
2525
error_info.line = t->sw.swline-shp->st.firstline;
2526
t= (Shnode_t*)(tt->sw.swlst);
2527
if(trap=shp->st.trap[SH_DEBUGTRAP])
2528
{
2529
char *av[4];
2530
av[0] = "case";
2531
av[1] = r;
2532
av[2] = "in";
2533
av[3] = 0;
2534
sh_debug(shp,trap, (char*)0, (char*)0, av, 0);
2535
}
2536
while(t)
2537
{
2538
register struct argnod *rex=(struct argnod*)t->reg.regptr;
2539
#if SHOPT_COSHELL
2540
if(shp->inpool)
2541
{
2542
sh_exec(t->reg.regcom,0);
2543
continue;
2544
}
2545
#endif /*SHOPT_COSHELL */
2546
while(rex)
2547
{
2548
register char *s;
2549
if(rex->argflag&ARG_MAC)
2550
{
2551
s = sh_macpat(shp,rex,OPTIMIZE|ARG_EXP);
2552
while(*s=='\\' && s[1]==0)
2553
s+=2;
2554
}
2555
else
2556
s = rex->argval;
2557
type = (rex->argflag&ARG_RAW);
2558
if((type && strcmp(r,s)==0) ||
2559
(!type && (strmatch(r,s)
2560
|| trim_eq(r,s))))
2561
{
2562
do sh_exec(t->reg.regcom,(t->reg.regflag?(flags&sh_state(SH_ERREXIT)):flags));
2563
while(t->reg.regflag &&
2564
(t=(Shnode_t*)t->reg.regnxt));
2565
t=0;
2566
break;
2567
}
2568
else
2569
rex=rex->argnxt.ap;
2570
}
2571
if(t)
2572
t=(Shnode_t*)t->reg.regnxt;
2573
}
2574
break;
2575
}
2576
2577
case TTIME:
2578
{
2579
/* time the command */
2580
struct tms before,after;
2581
const char *format = e_timeformat;
2582
clock_t at, tm[3];
2583
#ifdef timeofday
2584
struct timeval tb,ta;
2585
#else
2586
clock_t bt;
2587
#endif /* timeofday */
2588
#if SHOPT_COSHELL
2589
if(shp->inpool)
2590
{
2591
if(t->par.partre)
2592
sh_exec(t->par.partre,0);
2593
break;
2594
}
2595
#endif /*SHOPT_COSHELL */
2596
if(type!=TTIME)
2597
{
2598
sh_exec(t->par.partre,OPTIMIZE);
2599
shp->exitval = !shp->exitval;
2600
break;
2601
}
2602
if(t->par.partre)
2603
{
2604
long timer_on;
2605
if(shp->subshell && shp->comsub==1)
2606
sh_subfork();
2607
timer_on = sh_isstate(SH_TIMING);
2608
#ifdef timeofday
2609
timeofday(&tb);
2610
times(&before);
2611
#else
2612
bt = times(&before);
2613
#endif /* timeofday */
2614
job.waitall = 1;
2615
sh_onstate(SH_TIMING);
2616
sh_exec(t->par.partre,OPTIMIZE);
2617
if(!timer_on)
2618
sh_offstate(SH_TIMING);
2619
job.waitall = 0;
2620
}
2621
else
2622
{
2623
#ifndef timeofday
2624
bt = 0;
2625
#endif /* timeofday */
2626
before.tms_utime = before.tms_cutime = 0;
2627
before.tms_stime = before.tms_cstime = 0;
2628
}
2629
#ifdef timeofday
2630
times(&after);
2631
timeofday(&ta);
2632
at = shp->gd->lim.clk_tck*(ta.tv_sec-tb.tv_sec);
2633
at += ((shp->gd->lim.clk_tck*(((1000000L/2)/shp->gd->lim.clk_tck)+(ta.tv_usec-tb.tv_usec)))/1000000L);
2634
#else
2635
at = times(&after) - bt;
2636
#endif /* timeofday */
2637
tm[0] = at;
2638
if(t->par.partre)
2639
{
2640
Namval_t *np = nv_open("TIMEFORMAT",shp->var_tree,NV_NOADD);
2641
if(np)
2642
{
2643
format = nv_getval(np);
2644
nv_close(np);
2645
}
2646
if(!format)
2647
format = e_timeformat;
2648
}
2649
else
2650
format = strchr(format+1,'\n')+1;
2651
tm[1] = after.tms_utime - before.tms_utime;
2652
tm[1] += after.tms_cutime - before.tms_cutime;
2653
tm[2] = after.tms_stime - before.tms_stime;
2654
tm[2] += after.tms_cstime - before.tms_cstime;
2655
if(format && *format)
2656
p_time(shp,sfstderr,sh_translate(format),tm);
2657
break;
2658
}
2659
case TFUN:
2660
{
2661
register Namval_t *np=0;
2662
register struct slnod *slp;
2663
register char *fname = ((struct functnod*)t)->functnam;
2664
register char *cp = strrchr(fname,'.');
2665
register Namval_t *npv=0,*mp;
2666
#if SHOPT_COSHELL
2667
if(shp->inpool)
2668
{
2669
sh_exec(t->funct.functtre,0);
2670
break;
2671
}
2672
#endif /* SHOPT_COSHELL */
2673
#if SHOPT_NAMESPACE
2674
if(t->tre.tretyp==TNSPACE)
2675
{
2676
Dt_t *root;
2677
Namval_t *oldnspace = shp->namespace;
2678
int offset = stktell(stkp);
2679
int flags=NV_NOASSIGN|NV_NOARRAY|NV_VARNAME;
2680
if(cp)
2681
errormsg(SH_DICT,ERROR_exit(1),e_ident,fname);
2682
sfputc(stkp,'.');
2683
sfputr(stkp,fname,0);
2684
np = nv_open(stkptr(stkp,offset),shp->var_tree,flags);
2685
offset = stktell(stkp);
2686
if(nv_istable(np))
2687
root = nv_dict(np);
2688
else
2689
{
2690
root = dtopen(&_Nvdisc,Dtoset);
2691
nv_mount(np, (char*)0, root);
2692
np->nvalue.cp = Empty;
2693
dtview(root,shp->var_base);
2694
}
2695
oldnspace = enter_namespace(shp,np);
2696
sh_exec(t->for_.fortre,flags|sh_state(SH_ERREXIT));
2697
enter_namespace(shp,oldnspace);
2698
break;
2699
}
2700
#endif /* SHOPT_NAMESPACE */
2701
/* look for discipline functions */
2702
error_info.line = t->funct.functline-shp->st.firstline;
2703
/* Function names cannot be special builtin */
2704
if(cp || shp->prefix)
2705
{
2706
int offset = stktell(stkp);
2707
if(shp->prefix)
2708
{
2709
cp = shp->prefix;
2710
shp->prefix = 0;
2711
npv = nv_open(cp,shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME);
2712
shp->prefix = cp;
2713
cp = fname;
2714
}
2715
else
2716
{
2717
sfwrite(stkp,fname,cp++-fname);
2718
sfputc(stkp,0);
2719
npv = nv_open(stkptr(stkp,offset),shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME);
2720
}
2721
offset = stktell(stkp);
2722
sfprintf(stkp,"%s.%s%c",nv_name(npv),cp,0);
2723
fname = stkptr(stkp,offset);
2724
}
2725
else if((mp=nv_search(fname,shp->bltin_tree,0)) && nv_isattr(mp,BLT_SPC))
2726
errormsg(SH_DICT,ERROR_exit(1),e_badfun,fname);
2727
#if SHOPT_NAMESPACE
2728
if(shp->namespace && !shp->prefix && *fname!='.')
2729
np = sh_fsearch(shp,fname,NV_ADD|HASH_NOSCOPE);
2730
if(!np)
2731
#endif /* SHOPT_NAMESPACE */
2732
np = nv_open(fname,sh_subfuntree(1),NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOSCOPE);
2733
if(npv)
2734
{
2735
if(!shp->mktype)
2736
cp = nv_setdisc(npv,cp,np,(Namfun_t*)npv);
2737
if(!cp)
2738
errormsg(SH_DICT,ERROR_exit(1),e_baddisc,fname);
2739
}
2740
if(np->nvalue.rp)
2741
{
2742
struct Ufunction *rp = np->nvalue.rp;
2743
slp = (struct slnod*)np->nvenv;
2744
sh_funstaks(slp->slchild,-1);
2745
stakdelete(slp->slptr);
2746
if(shp->funload)
2747
{
2748
free((void*)np->nvalue.rp);
2749
np->nvalue.rp = 0;
2750
}
2751
if(rp->sdict)
2752
{
2753
Namval_t *mp, *nq;
2754
shp->last_root = rp->sdict;
2755
for(mp=(Namval_t*)dtfirst(rp->sdict);mp;mp=nq)
2756
{
2757
_nv_unset(mp,NV_RDONLY);
2758
nq = dtnext(rp->sdict,mp);
2759
nv_delete(mp,rp->sdict,0);
2760
}
2761
dtclose(rp->sdict);
2762
rp->sdict = 0;
2763
}
2764
}
2765
if(!np->nvalue.rp)
2766
{
2767
np->nvalue.rp = new_of(struct Ufunction,shp->funload?sizeof(Dtlink_t):0);
2768
memset((void*)np->nvalue.rp,0,sizeof(struct Ufunction));
2769
}
2770
if(t->funct.functstak)
2771
{
2772
static Dtdisc_t _Rpdisc =
2773
{
2774
offsetof(struct Ufunction,fname), -1, sizeof(struct Ufunction)
2775
};
2776
struct functnod *fp;
2777
struct comnod *ac = t->funct.functargs;
2778
slp = t->funct.functstak;
2779
sh_funstaks(slp->slchild,1);
2780
staklink(slp->slptr);
2781
np->nvenv = (char*)slp;
2782
nv_funtree(np) = (int*)(t->funct.functtre);
2783
np->nvalue.rp->hoffset = t->funct.functloc;
2784
np->nvalue.rp->lineno = t->funct.functline;
2785
np->nvalue.rp->nspace = shp->namespace;
2786
np->nvalue.rp->fname = 0;
2787
np->nvalue.rp->argv = ac?((struct dolnod*)ac->comarg)->dolval+1:0;
2788
np->nvalue.rp->argc = ac?((struct dolnod*)ac->comarg)->dolnum:0;
2789
np->nvalue.rp->fdict = shp->fun_tree;
2790
fp = (struct functnod*)(slp+1);
2791
if(fp->functtyp==(TFUN|FAMP))
2792
np->nvalue.rp->fname = fp->functnam;
2793
nv_setsize(np,fp->functline);
2794
nv_offattr(np,NV_FPOSIX);
2795
if(shp->funload)
2796
{
2797
struct Ufunction *rp = np->nvalue.rp;
2798
rp->np = np;
2799
if(!shp->fpathdict)
2800
shp->fpathdict = dtopen(&_Rpdisc,Dtobag);
2801
if(shp->fpathdict)
2802
dtinsert(shp->fpathdict,rp);
2803
}
2804
}
2805
else
2806
_nv_unset(np,0);
2807
if(type&FPOSIX)
2808
nv_onattr(np,NV_FUNCTION|NV_FPOSIX);
2809
else
2810
nv_onattr(np,NV_FUNCTION);
2811
if(type&FPIN)
2812
nv_onattr(np,NV_FTMP);
2813
if(type&FOPTGET)
2814
nv_onattr(np,NV_OPTGET);
2815
break;
2816
}
2817
2818
/* new test compound command */
2819
case TTST:
2820
{
2821
register int n;
2822
register char *left;
2823
int negate = (type&TNEGATE)!=0;
2824
#if SHOPT_COSHELL
2825
if(shp->inpool)
2826
break;
2827
#endif /* SHOPT_COSHELL */
2828
if(type&TTEST)
2829
skipexitset++;
2830
error_info.line = t->tst.tstline-shp->st.firstline;
2831
echeck = 1;
2832
if((type&TPAREN)==TPAREN)
2833
{
2834
sh_exec(t->lst.lstlef,OPTIMIZE);
2835
n = !shp->exitval;
2836
}
2837
else
2838
{
2839
register int traceon=0;
2840
register char *right;
2841
register char *trap;
2842
char *argv[6];
2843
n = type>>TSHIFT;
2844
left = sh_macpat(shp,&(t->lst.lstlef->arg),OPTIMIZE);
2845
if(type&TBINARY)
2846
right = sh_macpat(shp,&(t->lst.lstrit->arg),((n==TEST_PEQ||n==TEST_PNE)?ARG_EXP:0)|OPTIMIZE);
2847
if(trap=shp->st.trap[SH_DEBUGTRAP])
2848
argv[0] = (type&TNEGATE)?((char*)e_tstbegin):"[[";
2849
if(sh_isoption(SH_XTRACE))
2850
{
2851
traceon = sh_trace(shp,NIL(char**),0);
2852
sfwrite(sfstderr,e_tstbegin,(type&TNEGATE?5:3));
2853
}
2854
if(type&TUNARY)
2855
{
2856
if(traceon)
2857
sfprintf(sfstderr,"-%c %s",n,sh_fmtq(left));
2858
if(trap)
2859
{
2860
char unop[3];
2861
unop[0] = '-';
2862
unop[1] = n;
2863
unop[2] = 0;
2864
argv[1] = unop;
2865
argv[2] = left;
2866
argv[3] = "]]";
2867
argv[4] = 0;
2868
sh_debug(shp,trap,(char*)0,(char*)0,argv, 0);
2869
}
2870
n = test_unop(shp,n,left);
2871
}
2872
else if(type&TBINARY)
2873
{
2874
char *op;
2875
int pattern = 0;
2876
if(trap || traceon)
2877
op = (char*)(shtab_testops+(n&037)-1)->sh_name;
2878
type >>= TSHIFT;
2879
if(type==TEST_PEQ || type==TEST_PNE)
2880
pattern=ARG_EXP;
2881
if(trap)
2882
{
2883
argv[1] = left;
2884
argv[2] = op;
2885
argv[3] = right;
2886
argv[4] = "]]";
2887
argv[5] = 0;
2888
sh_debug(shp,trap,(char*)0,(char*)0,argv, pattern);
2889
}
2890
n = test_binop(shp,n,left,right);
2891
if(traceon)
2892
{
2893
sfprintf(sfstderr,"%s %s ",sh_fmtq(left),op);
2894
if(pattern)
2895
out_pattern(sfstderr,right,-1);
2896
else
2897
sfputr(sfstderr,sh_fmtq(right),-1);
2898
}
2899
}
2900
if(traceon)
2901
sfwrite(sfstderr,e_tstend,4);
2902
}
2903
shp->exitval = ((!n)^negate);
2904
if(!skipexitset)
2905
exitset();
2906
break;
2907
}
2908
}
2909
if(shp->trapnote || (shp->exitval && sh_isstate(SH_ERREXIT)) &&
2910
t && echeck)
2911
sh_chktrap(shp);
2912
/* set $_ */
2913
if(mainloop && com0)
2914
{
2915
/* store last argument here if it fits */
2916
static char lastarg[32];
2917
if(sh_isstate(SH_FORKED))
2918
sh_done(shp,0);
2919
if(shp->lastarg!= lastarg && shp->lastarg)
2920
free(shp->lastarg);
2921
if(strlen(comn) < sizeof(lastarg))
2922
{
2923
nv_onattr(L_ARGNOD,NV_NOFREE);
2924
shp->lastarg = strcpy(lastarg,comn);
2925
}
2926
else
2927
{
2928
nv_offattr(L_ARGNOD,NV_NOFREE);
2929
shp->lastarg = strdup(comn);
2930
}
2931
}
2932
if(!skipexitset)
2933
exitset();
2934
#if SHOPT_COSHELL
2935
if(!shp->inpool && !(OPTIMIZE))
2936
#else
2937
if(!(OPTIMIZE))
2938
#endif /* SHOPT_COSHELL */
2939
{
2940
if(sav != stkptr(stkp,0))
2941
stkset(stkp,sav,0);
2942
else if(stktell(stkp))
2943
stkseek(stkp,0);
2944
}
2945
if(shp->trapnote&SH_SIGSET)
2946
sh_exit(SH_EXITSIG|shp->lastsig);
2947
if(was_interactive)
2948
sh_onstate(SH_INTERACTIVE);
2949
if(was_monitor && sh_isoption(SH_MONITOR))
2950
sh_onstate(SH_MONITOR);
2951
if(was_errexit)
2952
sh_onstate(SH_ERREXIT);
2953
}
2954
return(shp->exitval);
2955
}
2956
2957
int sh_run(int argn, char *argv[])
2958
{
2959
Shell_t *shp = sh_getinterp();
2960
register struct dolnod *dp;
2961
register struct comnod *t = (struct comnod*)stakalloc(sizeof(struct comnod));
2962
int savtop = staktell();
2963
char *savptr = stakfreeze(0);
2964
Opt_t *op, *np = optctx(0, 0);
2965
Shbltin_t bltindata;
2966
bltindata = shp->bltindata;
2967
op = optctx(np, 0);
2968
memset(t, 0, sizeof(struct comnod));
2969
dp = (struct dolnod*)stakalloc((unsigned)sizeof(struct dolnod) + ARG_SPARE*sizeof(char*) + argn*sizeof(char*));
2970
dp->dolnum = argn;
2971
dp->dolbot = ARG_SPARE;
2972
memcpy(dp->dolval+ARG_SPARE, argv, (argn+1)*sizeof(char*));
2973
t->comarg = (struct argnod*)dp;
2974
if(!strchr(argv[0],'/'))
2975
t->comnamp = (void*)nv_bfsearch(argv[0],shp->fun_tree,(Namval_t**)&t->comnamq,(char**)0);
2976
argn=sh_exec((Shnode_t*)t,sh_isstate(SH_ERREXIT));
2977
optctx(op,np);
2978
shp->bltindata = bltindata;
2979
if(savptr!=stakptr(0))
2980
stakset(savptr,savtop);
2981
else
2982
stakseek(savtop);
2983
return(argn);
2984
}
2985
2986
/*
2987
* test for equality with second argument trimmed
2988
* returns 1 if r == trim(s) otherwise 0
2989
*/
2990
2991
static int trim_eq(register const char *r,register const char *s)
2992
{
2993
register char c;
2994
while(c = *s++)
2995
{
2996
if(c=='\\')
2997
c = *s++;
2998
if(c && c != *r++)
2999
return(0);
3000
}
3001
return(*r==0);
3002
}
3003
3004
/*
3005
* print out the command line if set -x is on
3006
*/
3007
3008
int sh_trace(Shell_t *shp,register char *argv[], register int nl)
3009
{
3010
register char *cp;
3011
register int bracket = 0;
3012
int decl = (nl&2);
3013
nl &= ~2;
3014
if(sh_isoption(SH_XTRACE))
3015
{
3016
/* make this trace atomic */
3017
sfset(sfstderr,SF_SHARE|SF_PUBLIC,0);
3018
if(!(cp=nv_getval(sh_scoped(shp,PS4NOD))))
3019
cp = "+ ";
3020
else
3021
{
3022
sh_offoption(SH_XTRACE);
3023
cp = sh_mactry(shp,cp);
3024
sh_onoption(SH_XTRACE);
3025
}
3026
if(*cp)
3027
sfputr(sfstderr,cp,-1);
3028
if(argv)
3029
{
3030
char *argv0 = *argv;
3031
nl = (nl?'\n':-1);
3032
/* don't quote [ and [[ */
3033
if(*(cp=argv[0])=='[' && (!cp[1] || !cp[2]&&cp[1]=='['))
3034
{
3035
sfputr(sfstderr,cp,*++argv?' ':nl);
3036
bracket = 1;
3037
}
3038
while(cp = *argv++)
3039
{
3040
if(bracket==0 || *argv || *cp!=']')
3041
cp = sh_fmtq(cp);
3042
if(decl && shp->prefix && cp!=argv0 && *cp!='-')
3043
{
3044
if(*cp=='.' && cp[1]==0)
3045
cp = shp->prefix;
3046
else
3047
sfputr(sfstderr,shp->prefix,'.');
3048
}
3049
sfputr(sfstderr,cp,*argv?' ':nl);
3050
}
3051
sfset(sfstderr,SF_SHARE|SF_PUBLIC,1);
3052
}
3053
return(1);
3054
}
3055
return(0);
3056
}
3057
3058
/*
3059
* This routine creates a subshell by calling fork() or vfork()
3060
* If ((flags&COMASK)==TCOM), then vfork() is permitted
3061
* If fork fails, the shell sleeps for exponentially longer periods
3062
* and tries again until a limit is reached.
3063
* SH_FORKLIM is the max period between forks - power of 2 usually.
3064
* Currently shell tries after 2,4,8,16, and 32 seconds and then quits
3065
* Failures cause the routine to error exit.
3066
* Parent links to here-documents are removed by the child
3067
* Traps are reset by the child
3068
* The process-id of the child is returned to the parent, 0 to the child.
3069
*/
3070
3071
static void timed_out(void *handle)
3072
{
3073
NOT_USED(handle);
3074
timeout = 0;
3075
}
3076
3077
3078
/*
3079
* called by parent and child after fork by sh_fork()
3080
*/
3081
pid_t _sh_fork(Shell_t *shp,register pid_t parent,int flags,int *jobid)
3082
{
3083
static long forkcnt = 1000L;
3084
pid_t curpgid = job.curpgid;
3085
pid_t postid = (flags&FAMP)?0:curpgid;
3086
int sig,nochild;
3087
if(parent<0)
3088
{
3089
sh_sigcheck(shp);
3090
if((forkcnt *= 2) > 1000L*SH_FORKLIM)
3091
{
3092
forkcnt=1000L;
3093
errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_nofork);
3094
}
3095
timeout = (void*)sh_timeradd(forkcnt, 0, timed_out, NIL(void*));
3096
nochild = job_wait((pid_t)1);
3097
if(timeout)
3098
{
3099
if(nochild)
3100
pause();
3101
else if(forkcnt>1000L)
3102
forkcnt /= 2;
3103
timerdel(timeout);
3104
timeout = 0;
3105
}
3106
return(-1);
3107
}
3108
forkcnt = 1000L;
3109
if(parent)
3110
{
3111
int myjob,waitall=job.waitall;
3112
shp->gd->nforks++;
3113
if(job.toclear)
3114
job_clear();
3115
job.waitall = waitall;
3116
#ifdef JOBS
3117
/* first process defines process group */
3118
if(sh_isstate(SH_MONITOR))
3119
{
3120
/*
3121
* errno==EPERM means that an earlier processes
3122
* completed. Make parent the job group id.
3123
*/
3124
if(postid==0)
3125
job.curpgid = parent;
3126
if(job.jobcontrol || (flags&FAMP))
3127
{
3128
if(setpgid(parent,job.curpgid)<0 && errno==EPERM)
3129
setpgid(parent,parent);
3130
}
3131
}
3132
#endif /* JOBS */
3133
if(!sh_isstate(SH_MONITOR) && job.waitall && postid==0)
3134
job.curpgid = parent;
3135
if(flags&FCOOP)
3136
shp->cpid = parent;
3137
if(!postid && job.curjobid && (flags&FPOU))
3138
postid = job.curpgid;
3139
#ifdef SHOPT_BGX
3140
if(!postid && (flags&(FAMP|FINT)) == (FAMP|FINT))
3141
postid = 1;
3142
myjob = job_post(shp,parent,postid);
3143
if(postid==1)
3144
postid = 0;
3145
#else
3146
myjob = job_post(shp,parent,postid);
3147
#endif /* SHOPT_BGX */
3148
if(job.waitall && (flags&FPOU))
3149
{
3150
if(!job.curjobid)
3151
job.curjobid = myjob;
3152
if(job.exitval)
3153
job.exitval++;
3154
}
3155
if(flags&FAMP)
3156
job.curpgid = curpgid;
3157
if(jobid)
3158
*jobid = myjob;
3159
if(shp->comsub==1 && usepipe)
3160
{
3161
if(!tsetio || !subdup)
3162
{
3163
if(shp->topfd > restorefd)
3164
sh_iorestore(shp,restorefd,0);
3165
iounpipe(shp);
3166
}
3167
}
3168
return(parent);
3169
}
3170
#if !_std_malloc
3171
vmtrace(-1);
3172
#endif
3173
shp->outpipepid = ((flags&FPOU)?getpid():0);
3174
/* This is the child process */
3175
if(shp->trapnote&SH_SIGTERM)
3176
sh_exit(SH_EXITSIG|SIGTERM);
3177
shp->gd->nforks=0;
3178
timerdel(NIL(void*));
3179
#ifdef JOBS
3180
if(!job.jobcontrol && !(flags&FAMP))
3181
sh_offstate(SH_MONITOR);
3182
if(sh_isstate(SH_MONITOR))
3183
{
3184
parent = getpid();
3185
if(postid==0)
3186
job.curpgid = parent;
3187
while(setpgid(0,job.curpgid)<0 && job.curpgid!=parent)
3188
job.curpgid = parent;
3189
# ifdef SIGTSTP
3190
if(job.curpgid==parent && !(flags&FAMP))
3191
tcsetpgrp(job.fd,job.curpgid);
3192
# endif /* SIGTSTP */
3193
}
3194
# ifdef SIGTSTP
3195
if(job.jobcontrol)
3196
{
3197
signal(SIGTTIN,SIG_DFL);
3198
signal(SIGTTOU,SIG_DFL);
3199
signal(SIGTSTP,SIG_DFL);
3200
}
3201
# endif /* SIGTSTP */
3202
job.jobcontrol = 0;
3203
#endif /* JOBS */
3204
job.toclear = 1;
3205
shp->login_sh = 0;
3206
sh_offoption(SH_LOGIN_SHELL);
3207
sh_onstate(SH_FORKED);
3208
sh_onstate(SH_NOLOG);
3209
if (shp->fn_reset)
3210
shp->fn_depth = shp->fn_reset = 0;
3211
#if SHOPT_ACCT
3212
sh_accsusp();
3213
#endif /* SHOPT_ACCT */
3214
/* Reset remaining signals to parent */
3215
/* except for those `lost' by trap */
3216
if(!(flags&FSHOWME))
3217
sh_sigreset(2);
3218
shp->subshell = 0;
3219
shp->comsub = 0;
3220
shp->spid = 0;
3221
if((flags&FAMP) && shp->coutpipe>1)
3222
sh_close(shp->coutpipe);
3223
sig = shp->savesig;
3224
shp->savesig = 0;
3225
if(sig>0)
3226
kill(getpid(),sig);
3227
sh_sigcheck(shp);
3228
usepipe=0;
3229
return(0);
3230
}
3231
3232
pid_t sh_fork(Shell_t *shp,int flags, int *jobid)
3233
{
3234
register pid_t parent;
3235
register int sig;
3236
if(!shp->pathlist)
3237
path_get(shp,"");
3238
sfsync(NIL(Sfio_t*));
3239
shp->trapnote &= ~SH_SIGTERM;
3240
job_fork(-1);
3241
shp->savesig = -1;
3242
while(_sh_fork(shp,parent=fork(),flags,jobid) < 0);
3243
sh_stats(STAT_FORKS);
3244
if(!shp->subshell)
3245
{
3246
sig = shp->savesig;
3247
shp->savesig = 0;
3248
if(sig>0)
3249
kill(getpid(),sig);
3250
}
3251
job_fork(parent);
3252
return(parent);
3253
}
3254
3255
struct Tdata
3256
{
3257
Shell_t *sh;
3258
Namval_t *tp;
3259
void *extra[2];
3260
};
3261
3262
/*
3263
* add exports from previous scope to the new scope
3264
*/
3265
static void local_exports(register Namval_t *np, void *data)
3266
{
3267
Shell_t *shp = ((struct Tdata*)data)->sh;
3268
register Namval_t *mp;
3269
register char *cp;
3270
if(nv_isarray(np))
3271
nv_putsub(np,NIL(char*),0);
3272
if((cp = nv_getval(np)) && (mp = nv_search(nv_name(np), shp->var_tree, NV_ADD|HASH_NOSCOPE)) && nv_isnull(mp))
3273
nv_putval(mp, cp, 0);
3274
}
3275
3276
/*
3277
* This routine executes .sh.math functions from within ((...)))
3278
*/
3279
Sfdouble_t sh_mathfun(Shell_t *shp,void *fp, int nargs, Sfdouble_t *arg)
3280
{
3281
Sfdouble_t d;
3282
Namval_t node,*mp,*np, *nref[9], **nr=nref;
3283
char *argv[2];
3284
struct funenv funenv;
3285
int i;
3286
np = (Namval_t*)fp;
3287
funenv.node = np;
3288
funenv.nref = nref;
3289
funenv.env = 0;
3290
memcpy(&node,SH_VALNOD,sizeof(node));
3291
SH_VALNOD->nvfun = 0;
3292
SH_VALNOD->nvenv = 0;
3293
SH_VALNOD->nvflag = NV_LDOUBLE|NV_NOFREE;
3294
SH_VALNOD->nvalue.ldp = 0;
3295
for(i=0; i < nargs; i++)
3296
{
3297
*nr++ = mp = nv_namptr(shp->mathnodes,i);
3298
mp->nvalue.ldp = arg++;
3299
}
3300
*nr = 0;
3301
SH_VALNOD->nvalue.ldp = &d;
3302
argv[0] = np->nvname;
3303
argv[1] = 0;
3304
sh_funscope(1,argv,0,&funenv,0);
3305
while(mp= *nr++)
3306
mp->nvalue.ldp = 0;
3307
SH_VALNOD->nvfun = node.nvfun;
3308
SH_VALNOD->nvflag = node.nvflag;
3309
SH_VALNOD->nvenv = node.nvenv;
3310
SH_VALNOD->nvalue.ldp = node.nvalue.ldp;
3311
return(d);
3312
}
3313
3314
/*
3315
* This routine is used to execute the given function <fun> in a new scope
3316
* If <fun> is NULL, then arg points to a structure containing a pointer
3317
* to a function that will be executed in the current environment.
3318
*/
3319
int sh_funscope(int argn, char *argv[],int(*fun)(void*),void *arg,int execflg)
3320
{
3321
register char *trap;
3322
register int nsig;
3323
register Shell_t *shp = sh_getinterp();
3324
struct dolnod *argsav=0,*saveargfor;
3325
struct sh_scoped savst, *prevscope = shp->st.self;
3326
struct argnod *envlist=0;
3327
int jmpval;
3328
volatile int r = 0;
3329
int n;
3330
char *savstak;
3331
struct funenv *fp = 0;
3332
struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
3333
Namval_t *nspace = shp->namespace;
3334
Dt_t *last_root = shp->last_root;
3335
Shopt_t options;
3336
options = shp->options;
3337
if(shp->fn_depth==0)
3338
shp->glob_options = shp->options;
3339
else
3340
shp->options = shp->glob_options;
3341
#if 0
3342
shp->st.lineno = error_info.line;
3343
#endif
3344
*prevscope = shp->st;
3345
sh_offoption(SH_ERREXIT);
3346
shp->st.prevst = prevscope;
3347
shp->st.self = &savst;
3348
shp->topscope = (Shscope_t*)shp->st.self;
3349
shp->st.opterror = shp->st.optchar = 0;
3350
shp->st.optindex = 1;
3351
shp->st.loopcnt = 0;
3352
if(!fun)
3353
{
3354
fp = (struct funenv*)arg;
3355
shp->st.real_fun = (fp->node)->nvalue.rp;
3356
envlist = fp->env;
3357
}
3358
prevscope->save_tree = shp->var_tree;
3359
n = dtvnext(prevscope->save_tree)!= (shp->namespace?shp->var_base:0);
3360
sh_scope(shp,envlist,1);
3361
if(n)
3362
{
3363
struct Tdata tdata;
3364
memset(&tdata,0,sizeof(tdata));
3365
tdata.sh = shp;
3366
/* eliminate parent scope */
3367
nv_scan(prevscope->save_tree, local_exports,&tdata, NV_EXPORT, NV_EXPORT|NV_NOSCOPE);
3368
}
3369
shp->st.save_tree = shp->var_tree;
3370
if(!fun)
3371
{
3372
if(nv_isattr(fp->node,NV_TAGGED))
3373
sh_onoption(SH_XTRACE);
3374
else
3375
sh_offoption(SH_XTRACE);
3376
}
3377
shp->st.cmdname = argv[0];
3378
/* save trap table */
3379
if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
3380
{
3381
nsig += sizeof(char*);
3382
memcpy(savstak=stakalloc(nsig),(char*)&shp->st.trapcom[0],nsig);
3383
}
3384
sh_sigreset(0);
3385
argsav = sh_argnew(shp,argv,&saveargfor);
3386
sh_pushcontext(shp,buffp,SH_JMPFUN);
3387
errorpush(&buffp->err,0);
3388
error_info.id = argv[0];
3389
shp->st.var_local = shp->var_tree;
3390
if(!fun)
3391
{
3392
shp->st.filename = fp->node->nvalue.rp->fname;
3393
shp->st.funname = nv_name(fp->node);
3394
shp->last_root = nv_dict(DOTSHNOD);
3395
nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
3396
nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
3397
}
3398
jmpval = sigsetjmp(buffp->buff,0);
3399
if(jmpval == 0)
3400
{
3401
if(shp->fn_depth++ > MAXDEPTH)
3402
{
3403
shp->toomany = 1;
3404
siglongjmp(*shp->jmplist,SH_JMPERRFN);
3405
}
3406
else if(fun)
3407
r= (*fun)(arg);
3408
else
3409
{
3410
char **arg = shp->st.real_fun->argv;
3411
Namval_t *np, *nq, **nref;
3412
if(nref=fp->nref)
3413
{
3414
shp->last_root = 0;
3415
for(r=0; arg[r]; r++)
3416
{
3417
np = nv_search(arg[r],shp->var_tree,HASH_NOSCOPE|NV_ADD);
3418
if(np && (nq=*nref++))
3419
{
3420
np->nvalue.nrp = newof(0,struct Namref,1,0);
3421
np->nvalue.nrp->np = nq;
3422
nv_onattr(np,NV_REF|NV_NOFREE);
3423
}
3424
}
3425
}
3426
sh_exec((Shnode_t*)(nv_funtree((fp->node))),execflg|SH_ERREXIT);
3427
r = shp->exitval;
3428
}
3429
}
3430
if(shp->topscope != (Shscope_t*)shp->st.self)
3431
sh_setscope(shp->topscope);
3432
if(--shp->fn_depth==1 && jmpval==SH_JMPERRFN)
3433
errormsg(SH_DICT,ERROR_exit(1),e_toodeep,argv[0]);
3434
sh_popcontext(shp,buffp);
3435
sh_unscope(shp);
3436
shp->namespace = nspace;
3437
shp->var_tree = (Dt_t*)prevscope->save_tree;
3438
sh_argreset(shp,argsav,saveargfor);
3439
trap = shp->st.trapcom[0];
3440
shp->st.trapcom[0] = 0;
3441
sh_sigreset(1);
3442
shp->st = *prevscope;
3443
shp->topscope = (Shscope_t*)prevscope;
3444
nv_getval(sh_scoped(shp,IFSNOD));
3445
if(nsig)
3446
memcpy((char*)&shp->st.trapcom[0],savstak,nsig);
3447
shp->trapnote=0;
3448
if(nsig)
3449
stakset(savstak,0);
3450
shp->options = options;
3451
shp->last_root = last_root;
3452
if(jmpval == SH_JMPSUB)
3453
siglongjmp(*shp->jmplist,jmpval);
3454
if(trap)
3455
{
3456
sh_trap(trap,0);
3457
free(trap);
3458
}
3459
if(jmpval)
3460
r=shp->exitval;
3461
if(r>SH_EXITSIG && ((r&SH_EXITMASK)==SIGINT || ((r&SH_EXITMASK)==SIGQUIT)))
3462
kill(getpid(),r&SH_EXITMASK);
3463
if(jmpval > SH_JMPFUN)
3464
{
3465
sh_chktrap(shp);
3466
siglongjmp(*shp->jmplist,jmpval);
3467
}
3468
return(r);
3469
}
3470
3471
static void sh_funct(Shell_t *shp,Namval_t *np,int argn, char *argv[],struct argnod *envlist,int execflg)
3472
{
3473
struct funenv fun;
3474
char *fname = nv_getval(SH_FUNNAMENOD);
3475
struct Level *lp =(struct Level*)(SH_LEVELNOD->nvfun);
3476
int level, pipepid=shp->pipepid, comsub=shp->comsub;
3477
shp->comsub = 0;
3478
shp->pipepid = 0;
3479
sh_stats(STAT_FUNCT);
3480
if(!lp->hdr.disc)
3481
lp = init_level(shp,0);
3482
if((struct sh_scoped*)shp->topscope != shp->st.self)
3483
sh_setscope(shp->topscope);
3484
level = lp->maxlevel = shp->dot_depth + shp->fn_depth+1;
3485
SH_LEVELNOD->nvalue.s = lp->maxlevel;
3486
shp->st.lineno = error_info.line;
3487
np->nvalue.rp->running += 2;
3488
if(nv_isattr(np,NV_FPOSIX))
3489
{
3490
char *save;
3491
int loopcnt = shp->st.loopcnt;
3492
shp->posix_fun = np;
3493
save = argv[-1];
3494
argv[-1] = 0;
3495
shp->st.funname = nv_name(np);
3496
shp->last_root = nv_dict(DOTSHNOD);
3497
nv_putval(SH_FUNNAMENOD, nv_name(np),NV_NOFREE);
3498
opt_info.index = opt_info.offset = 0;
3499
error_info.errors = 0;
3500
shp->st.loopcnt = 0;
3501
b_dot_cmd(argn+1,argv-1,&shp->bltindata);
3502
shp->st.loopcnt = loopcnt;
3503
argv[-1] = save;
3504
}
3505
else
3506
{
3507
fun.env = envlist;
3508
fun.node = np;
3509
fun.nref = 0;
3510
sh_funscope(argn,argv,0,&fun,execflg);
3511
}
3512
if(level-- != nv_getnum(SH_LEVELNOD))
3513
{
3514
Shscope_t *sp = sh_getscope(0,SEEK_END);
3515
sh_setscope(sp);
3516
}
3517
lp->maxlevel = level;
3518
SH_LEVELNOD->nvalue.s = lp->maxlevel;
3519
shp->last_root = nv_dict(DOTSHNOD);
3520
shp->comsub = comsub;
3521
#if 0
3522
nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
3523
#else
3524
nv_putval(SH_FUNNAMENOD,fname,NV_NOFREE);
3525
#endif
3526
nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
3527
shp->pipepid = pipepid;
3528
np->nvalue.rp->running -= 2;
3529
}
3530
3531
/*
3532
* external interface to execute a function without arguments
3533
* <np> is the function node
3534
* If <nq> is not-null, then sh.name and sh.subscript will be set
3535
*/
3536
int sh_fun(Namval_t *np, Namval_t *nq, char *argv[])
3537
{
3538
Shell_t *shp = sh_getinterp();
3539
register int offset;
3540
register char *base;
3541
Namval_t node;
3542
struct Namref nr;
3543
long mode;
3544
char *prefix = shp->prefix;
3545
int n=0;
3546
char *av[3];
3547
Fcin_t save;
3548
fcsave(&save);
3549
if((offset=staktell())>0)
3550
base=stakfreeze(0);
3551
shp->prefix = 0;
3552
if(!argv)
3553
{
3554
argv = av+1;
3555
argv[1]=0;
3556
}
3557
argv[0] = nv_name(np);
3558
while(argv[n])
3559
n++;
3560
if(nq)
3561
mode = set_instance(shp,nq,&node, &nr);
3562
if(is_abuiltin(np))
3563
{
3564
int jmpval;
3565
struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
3566
Shbltin_t *bp = &shp->bltindata;
3567
sh_pushcontext(shp,buffp,SH_JMPCMD);
3568
jmpval = sigsetjmp(buffp->buff,1);
3569
if(jmpval == 0)
3570
{
3571
bp->bnode = np;
3572
bp->ptr = nv_context(np);
3573
errorpush(&buffp->err,0);
3574
error_info.id = argv[0];
3575
opt_info.index = opt_info.offset = 0;
3576
opt_info.disc = 0;
3577
shp->exitval = 0;
3578
shp->exitval = ((Shbltin_f)funptr(np))(n,argv,bp);
3579
}
3580
sh_popcontext(shp,buffp);
3581
if(jmpval>SH_JMPCMD)
3582
siglongjmp(*shp->jmplist,jmpval);
3583
}
3584
else
3585
sh_funct(shp,np,n,argv,(struct argnod*)0,sh_isstate(SH_ERREXIT));
3586
if(nq)
3587
unset_instance(nq, &node, &nr, mode);
3588
fcrestore(&save);
3589
if(offset>0)
3590
stakset(base,offset);
3591
shp->prefix = prefix;
3592
return(shp->exitval);
3593
}
3594
3595
/*
3596
* This dummy routine is called by built-ins that do recursion
3597
* on the file system (chmod, chgrp, chown). It causes
3598
* the shell to invoke the non-builtin version in this case
3599
*/
3600
int cmdrecurse(int argc, char* argv[], int ac, char* av[])
3601
{
3602
NOT_USED(argc);
3603
NOT_USED(argv[0]);
3604
NOT_USED(ac);
3605
NOT_USED(av[0]);
3606
return(SH_RUNPROG);
3607
}
3608
3609
/*
3610
* set up pipe for cooperating process
3611
*/
3612
static void coproc_init(Shell_t *shp, int pipes[])
3613
{
3614
int outfd;
3615
if(shp->coutpipe>=0 && shp->cpid)
3616
errormsg(SH_DICT,ERROR_exit(1),e_pexists);
3617
shp->cpid = 0;
3618
if(shp->cpipe[0]<=0 || shp->cpipe[1]<=0)
3619
{
3620
/* first co-process */
3621
sh_pclose(shp->cpipe);
3622
sh_pipe(shp->cpipe);
3623
if((outfd=shp->cpipe[1]) < 10)
3624
{
3625
int fd=fcntl(shp->cpipe[1],F_DUPFD,10);
3626
if(fd>=10)
3627
{
3628
shp->fdstatus[fd] = (shp->fdstatus[outfd]&~IOCLEX);
3629
close(outfd);
3630
shp->fdstatus[outfd] = IOCLOSE;
3631
shp->cpipe[1] = fd;
3632
}
3633
}
3634
if(fcntl(*shp->cpipe,F_SETFD,FD_CLOEXEC)>=0)
3635
shp->fdstatus[shp->cpipe[0]] |= IOCLEX;
3636
shp->fdptrs[shp->cpipe[0]] = shp->cpipe;
3637
3638
if(fcntl(shp->cpipe[1],F_SETFD,FD_CLOEXEC) >=0)
3639
shp->fdstatus[shp->cpipe[1]] |= IOCLEX;
3640
}
3641
shp->outpipe = shp->cpipe;
3642
sh_pipe(shp->inpipe=pipes);
3643
shp->coutpipe = shp->inpipe[1];
3644
shp->fdptrs[shp->coutpipe] = &shp->coutpipe;
3645
if(fcntl(shp->outpipe[0],F_SETFD,FD_CLOEXEC)>=0)
3646
shp->fdstatus[shp->outpipe[0]] |= IOCLEX;
3647
}
3648
3649
#if SHOPT_SPAWN
3650
3651
3652
#if SHOPT_AMP || !defined(_lib_fork)
3653
3654
/*
3655
* create a shell script consisting of t->fork.forktre and execute it
3656
*/
3657
static int run_subshell(Shell_t *shp,const Shnode_t *t,pid_t grp)
3658
{
3659
static const char prolog[] = "(print $(typeset +A);set; typeset -p; print .sh.dollar=$$;set +o)";
3660
register int i, fd, trace = sh_isoption(SH_XTRACE);
3661
int pin,pout;
3662
pid_t pid;
3663
char *arglist[3], *envlist[2], devfd[12], *cp;
3664
Sfio_t *sp = sftmp(0);
3665
envlist[0] = "_=" SH_ID;
3666
envlist[1] = 0;
3667
arglist[0] = error_info.id?error_info.id:shp->shname;
3668
if(*arglist[0]=='-')
3669
arglist[0]++;
3670
arglist[1] = devfd;
3671
strncpy(devfd,e_devfdNN,sizeof(devfd));
3672
arglist[2] = 0;
3673
sfstack(sfstdout,sp);
3674
if(trace)
3675
sh_offoption(SH_XTRACE);
3676
sfwrite(sfstdout,"typeset -A -- ",14);
3677
sh_trap(prolog,0);
3678
nv_scan(shp->fun_tree, print_fun, (void*)0,0, 0);
3679
if(shp->st.dolc>0)
3680
{
3681
/* pass the positional parameters */
3682
char **argv = shp->st.dolv+1;
3683
sfwrite(sfstdout,"set --",6);
3684
while(*argv)
3685
sfprintf(sfstdout," %s",sh_fmtq(*argv++));
3686
sfputc(sfstdout,'\n');
3687
}
3688
pin = (shp->inpipe?shp->inpipe[1]:0);
3689
pout = (shp->outpipe?shp->outpipe[0]:0);
3690
for(i=3; i < 10; i++)
3691
{
3692
if(shp->fdstatus[i]&IOCLEX && i!=pin && i!=pout)
3693
{
3694
sfprintf(sfstdout,"exec %d<&%d\n",i,i);
3695
fcntl(i,F_SETFD,0);
3696
}
3697
}
3698
sfprintf(sfstdout,"LINENO=%d\n",t->fork.forkline);
3699
if(trace)
3700
{
3701
sfwrite(sfstdout,"set -x\n",7);
3702
sh_onoption(SH_XTRACE);
3703
}
3704
sfstack(sfstdout,NIL(Sfio_t*));
3705
sh_deparse(sp,t->fork.forktre,0);
3706
sfseek(sp,(Sfoff_t)0,SEEK_SET);
3707
fd = sh_dup(sffileno(sp));
3708
cp = devfd+8;
3709
if(fd>9)
3710
*cp++ = '0' + (fd/10);
3711
*cp++ = '0' + fd%10;
3712
*cp = 0;
3713
sfclose(sp);
3714
sfsync(NIL(Sfio_t*));
3715
if(!shp->gd->shpath)
3716
shp->gd->shpath = pathshell();
3717
pid = spawnveg(shp->shpath,arglist,envlist,grp);
3718
close(fd);
3719
for(i=3; i < 10; i++)
3720
{
3721
if(shp->fdstatus[i]&IOCLEX && i!=pin && i!=pout)
3722
fcntl(i,F_SETFD,FD_CLOEXEC);
3723
}
3724
if(pid <=0)
3725
errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,arglist[0]);
3726
return(pid);
3727
}
3728
#endif /* !_lib_fork */
3729
3730
static void sigreset(Shell_t *shp,int mode)
3731
{
3732
register char *trap;
3733
register int sig=shp->st.trapmax;
3734
while(sig-- > 0)
3735
{
3736
if(sig==SIGCHLD)
3737
continue;
3738
if((trap=shp->st.trapcom[sig]) && *trap==0)
3739
signal(sig,mode?sh_fault:SIG_IGN);
3740
}
3741
}
3742
3743
/*
3744
* A combined fork/exec for systems with slow or non-existent fork()
3745
*/
3746
static pid_t sh_ntfork(Shell_t *shp,const Shnode_t *t,char *argv[],int *jobid,int flag)
3747
{
3748
static pid_t spawnpid;
3749
static int savetype;
3750
static int savejobid;
3751
struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
3752
int otype=0, jmpval,jobfork=0;
3753
volatile int jobwasset=0, scope=0, sigwasset=0;
3754
char **arge, *path;
3755
volatile pid_t grp = 0;
3756
Pathcomp_t *pp;
3757
if(flag)
3758
{
3759
otype = savetype;
3760
savetype=0;
3761
}
3762
# if SHOPT_AMP || !defined(_lib_fork)
3763
if(!argv)
3764
{
3765
register Shnode_t *tchild = t->fork.forktre;
3766
int optimize=0;
3767
otype = t->tre.tretyp;
3768
savetype = otype;
3769
spawnpid = 0;
3770
# ifndef _lib_fork
3771
if((tchild->tre.tretyp&COMMSK)==TCOM)
3772
{
3773
Namval_t *np = (Namval_t*)(tchild->com.comnamp);
3774
if(np)
3775
{
3776
path = nv_name(np);
3777
if(!nv_isattr(np,BLT_ENV))
3778
np=0;
3779
else if(strcmp(path,"echo")==0 || memcmp(path,"print",5)==0)
3780
np=0;
3781
}
3782
else if(!tchild->com.comarg)
3783
optimize=1;
3784
else if(tchild->com.comtyp&COMSCAN)
3785
{
3786
if(tchild->com.comarg->argflag&ARG_RAW)
3787
path = tchild->com.comarg->argval;
3788
else
3789
path = 0;
3790
}
3791
else
3792
path = ((struct dolnod*)tchild->com.comarg)->dolval[ARG_SPARE];
3793
if(!np && path && !nv_search(path,shp->fun_tree,0))
3794
optimize=1;
3795
}
3796
# endif
3797
sh_pushcontext(shp,buffp,SH_JMPIO);
3798
jmpval = sigsetjmp(buffp->buff,0);
3799
{
3800
if((otype&FINT) && !sh_isstate(SH_MONITOR))
3801
{
3802
signal(SIGQUIT,SIG_IGN);
3803
signal(SIGINT,SIG_IGN);
3804
if(!shp->st.ioset)
3805
{
3806
sh_iosave(shp,0,buffp->topfd,(char*)0);
3807
sh_iorenumber(shp,sh_chkopen(e_devnull),0);
3808
}
3809
}
3810
if(otype&FPIN)
3811
{
3812
int fd = shp->inpipe[1];
3813
sh_iosave(shp,0,buffp->topfd,(char*)0);
3814
sh_iorenumber(shp,shp->inpipe[0],0);
3815
if(fd>=0 && (!(otype&FPOU) || (otype&FCOOP)) && fcntl(fd,F_SETFD,FD_CLOEXEC)>=0)
3816
shp->fdstatus[fd] |= IOCLEX;
3817
}
3818
if(otype&FPOU)
3819
{
3820
#if SHOPT_COSHELL
3821
if(shp->outpipe[2] > 20000)
3822
sh_coaccept(shp,shp->outpipe,1);
3823
#endif /* SHOPT_COSHELL */
3824
sh_iosave(shp,1,buffp->topfd,(char*)0);
3825
sh_iorenumber(shp,sh_dup(shp->outpipe[1]),1);
3826
if(fcntl(shp->outpipe[0],F_SETFD,FD_CLOEXEC)>=0)
3827
shp->fdstatus[shp->outpipe[0]] |= IOCLEX;
3828
}
3829
3830
if(t->fork.forkio)
3831
sh_redirect(shp,t->fork.forkio,0);
3832
if(optimize==0)
3833
{
3834
#ifdef SIGTSTP
3835
if(job.jobcontrol)
3836
{
3837
signal(SIGTTIN,SIG_DFL);
3838
signal(SIGTTOU,SIG_DFL);
3839
}
3840
#endif /* SIGTSTP */
3841
#ifdef JOBS
3842
if(sh_isstate(SH_MONITOR) && (job.jobcontrol || (otype&FAMP)))
3843
{
3844
if((otype&FAMP) || job.curpgid==0)
3845
grp = 1;
3846
else
3847
grp = job.curpgid;
3848
}
3849
#endif /* JOBS */
3850
spawnpid = run_subshell(shp,t,grp);
3851
}
3852
else
3853
{
3854
sh_exec(tchild,SH_NTFORK);
3855
if(jobid)
3856
*jobid = savejobid;
3857
}
3858
}
3859
sh_popcontext(shp,buffp);
3860
if((otype&FINT) && !sh_isstate(SH_MONITOR))
3861
{
3862
signal(SIGQUIT,sh_fault);
3863
signal(SIGINT,sh_fault);
3864
}
3865
if((otype&FPIN) && (!(otype&FPOU) || (otype&FCOOP)) && fcntl(shp->inpipe[1],F_SETFD,FD_CLOEXEC)>=0)
3866
shp->fdstatus[shp->inpipe[1]] &= ~IOCLEX;
3867
if(t->fork.forkio || otype)
3868
sh_iorestore(shp,buffp->topfd,jmpval);
3869
if(optimize==0)
3870
{
3871
#ifdef SIGTSTP
3872
if(job.jobcontrol)
3873
{
3874
signal(SIGTTIN,SIG_IGN);
3875
signal(SIGTTOU,SIG_IGN);
3876
}
3877
#endif /* SIGTSTP */
3878
if(spawnpid>0)
3879
_sh_fork(shp,spawnpid,otype,jobid);
3880
if(grp>0 && !(otype&FAMP))
3881
{
3882
while(tcsetpgrp(job.fd,job.curpgid)<0 && job.curpgid!=spawnpid)
3883
job.curpgid = spawnpid;
3884
}
3885
}
3886
savetype=0;
3887
if(jmpval>SH_JMPIO)
3888
siglongjmp(*shp->jmplist,jmpval);
3889
if(spawnpid<0 && (otype&FCOOP))
3890
{
3891
sh_close(shp->coutpipe);
3892
sh_close(shp->cpipe[1]);
3893
shp->cpipe[1] = -1;
3894
shp->coutpipe = -1;
3895
}
3896
shp->exitval = 0;
3897
return(spawnpid);
3898
}
3899
# endif /* !_lib_fork */
3900
sh_pushcontext(shp,buffp,SH_JMPCMD);
3901
errorpush(&buffp->err,ERROR_SILENT);
3902
jmpval = sigsetjmp(buffp->buff,0);
3903
if(jmpval == 0)
3904
{
3905
if((otype&FINT) && !sh_isstate(SH_MONITOR))
3906
{
3907
signal(SIGQUIT,SIG_IGN);
3908
signal(SIGINT,SIG_IGN);
3909
}
3910
spawnpid = -1;
3911
if(t->com.comio)
3912
sh_redirect(shp,t->com.comio,0);
3913
error_info.id = *argv;
3914
if(t->com.comset)
3915
{
3916
scope++;
3917
sh_scope(shp,t->com.comset,0);
3918
}
3919
if(!strchr(path=argv[0],'/'))
3920
{
3921
Namval_t *np;
3922
if((np=nv_search(path,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && np->nvalue.cp)
3923
path = nv_getval(np);
3924
else if(path_absolute(shp,path,NIL(Pathcomp_t*)))
3925
{
3926
path = stkptr(shp->stk,PATH_OFFSET);
3927
stkfreeze(shp->stk,0);
3928
}
3929
else
3930
{
3931
pp=path_get(shp,path);
3932
while(pp)
3933
{
3934
if(pp->len==1 && *pp->name=='.')
3935
break;
3936
pp = pp->next;
3937
}
3938
if(!pp)
3939
path = 0;
3940
}
3941
}
3942
else if(sh_isoption(SH_RESTRICTED))
3943
errormsg(SH_DICT,ERROR_exit(1),e_restricted,path);
3944
if(!path)
3945
{
3946
spawnpid = -1;
3947
goto fail;
3948
}
3949
arge = sh_envgen();
3950
shp->exitval = 0;
3951
#ifdef SIGTSTP
3952
if(job.jobcontrol)
3953
{
3954
signal(SIGTTIN,SIG_DFL);
3955
signal(SIGTTOU,SIG_DFL);
3956
jobwasset++;
3957
}
3958
#endif /* SIGTSTP */
3959
#ifdef JOBS
3960
if(sh_isstate(SH_MONITOR) && (job.jobcontrol || (otype&FAMP)))
3961
{
3962
if((otype&FAMP) || job.curpgid==0)
3963
grp = 1;
3964
else
3965
grp = job.curpgid;
3966
}
3967
#endif /* JOBS */
3968
3969
sfsync(NIL(Sfio_t*));
3970
sigreset(shp,0); /* set signals to ignore */
3971
sigwasset++;
3972
/* find first path that has a library component */
3973
for(pp=path_get(shp,argv[0]); pp && !pp->lib ; pp=pp->next);
3974
job_fork(-1);
3975
jobfork = 1;
3976
spawnpid = path_spawn(shp,path,argv,arge,pp,(grp<<1)|1);
3977
if(spawnpid < 0 && errno==ENOEXEC)
3978
{
3979
char *devfd;
3980
int fd = open(path,O_RDONLY);
3981
argv[-1] = argv[0];
3982
argv[0] = path;
3983
if(fd>=0)
3984
{
3985
struct stat statb;
3986
sfprintf(shp->strbuf,"/dev/fd/%d",fd);
3987
if(stat(devfd=sfstruse(shp->strbuf),&statb)>=0)
3988
argv[0] = devfd;
3989
}
3990
if(!shp->gd->shpath)
3991
shp->gd->shpath = pathshell();
3992
spawnpid = path_spawn(shp,shp->gd->shpath,&argv[-1],arge,pp,(grp<<1)|1);
3993
if(fd>=0)
3994
close(fd);
3995
argv[0] = argv[-1];
3996
}
3997
fail:
3998
if(jobfork && spawnpid<0)
3999
job_fork(0);
4000
if(spawnpid < 0) switch(errno=shp->path_err)
4001
{
4002
case ENOENT:
4003
errormsg(SH_DICT,ERROR_system(ERROR_NOENT),e_found+4);
4004
default:
4005
errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec+4);
4006
}
4007
}
4008
else
4009
exitset();
4010
sh_popcontext(shp,buffp);
4011
if(buffp->olist)
4012
free_list(buffp->olist);
4013
#ifdef SIGTSTP
4014
if(jobwasset)
4015
{
4016
signal(SIGTTIN,SIG_IGN);
4017
signal(SIGTTOU,SIG_IGN);
4018
}
4019
#endif /* SIGTSTP */
4020
if(sigwasset)
4021
sigreset(shp,1); /* restore ignored signals */
4022
if(scope)
4023
{
4024
sh_unscope(shp);
4025
if(jmpval==SH_JMPSCRIPT)
4026
nv_setlist(t->com.comset,NV_EXPORT|NV_IDENT|NV_ASSIGN,0);
4027
}
4028
if(t->com.comio && (jmpval || spawnpid<=0))
4029
sh_iorestore(shp,buffp->topfd,jmpval);
4030
if(jmpval>SH_JMPCMD)
4031
siglongjmp(*shp->jmplist,jmpval);
4032
if(spawnpid>0)
4033
{
4034
_sh_fork(shp,spawnpid,otype,jobid);
4035
job_fork(spawnpid);
4036
#ifdef JOBS
4037
if(grp==1)
4038
job.curpgid = spawnpid;
4039
# ifdef SIGTSTP
4040
if(grp>0 && !(otype&FAMP))
4041
{
4042
while(tcsetpgrp(job.fd,job.curpgid)<0 && job.curpgid!=spawnpid)
4043
job.curpgid = spawnpid;
4044
}
4045
# endif /* SIGTSTP */
4046
#endif /* JOBS */
4047
savejobid = *jobid;
4048
if(otype)
4049
return(0);
4050
}
4051
return(spawnpid);
4052
}
4053
4054
# ifdef _was_lib_fork
4055
# define _lib_fork 1
4056
# endif
4057
# ifndef _lib_fork
4058
pid_t fork(void)
4059
{
4060
errormsg(SH_DICT,ERROR_exit(3),e_notimp,"fork");
4061
return(-1);
4062
}
4063
# endif /* _lib_fork */
4064
#endif /* SHOPT_SPAWN */
4065
4066