Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "rc.h"
2
#include "getflags.h"
3
#include "exec.h"
4
#include "io.h"
5
#include "fns.h"
6
/*
7
 * Start executing the given code at the given pc with the given redirection
8
 */
9
char *argv0="rc";
10
 
11
void
12
start(code *c, int pc, var *local)
13
{
14
	struct thread *p = new(struct thread);
15
 
16
	p->code = codecopy(c);
17
	p->pc = pc;
18
	p->argv = 0;
19
	p->redir = p->startredir = runq?runq->redir:0;
20
	p->local = local;
21
	p->cmdfile = 0;
22
	p->cmdfd = 0;
23
	p->eof = 0;
24
	p->iflag = 0;
25
	p->lineno = 1;
26
	p->ret = runq;
27
	runq = p;
28
}
29
 
30
word*
31
newword(char *wd, word *next)
32
{
33
	word *p = new(word);
34
	p->word = strdup(wd);
35
	p->next = next;
36
	return p;
37
}
38
 
39
void
40
pushword(char *wd)
41
{
42
	if(runq->argv==0)
43
		panic("pushword but no argv!", 0);
44
	runq->argv->words = newword(wd, runq->argv->words);
45
}
46
 
47
void
48
popword(void)
49
{
50
	word *p;
51
	if(runq->argv==0)
52
		panic("popword but no argv!", 0);
53
	p = runq->argv->words;
54
	if(p==0)
55
		panic("popword but no word!", 0);
56
	runq->argv->words = p->next;
57
	efree(p->word);
58
	efree((char *)p);
59
}
60
 
61
void
62
freelist(word *w)
63
{
64
	word *nw;
65
	while(w){
66
		nw = w->next;
67
		efree(w->word);
68
		efree((char *)w);
69
		w = nw;
70
	}
71
}
72
 
73
void
74
pushlist(void)
75
{
76
	list *p = new(list);
77
	p->next = runq->argv;
78
	p->words = 0;
79
	runq->argv = p;
80
}
81
 
82
void
83
poplist(void)
84
{
85
	list *p = runq->argv;
86
	if(p==0)
87
		panic("poplist but no argv", 0);
88
	freelist(p->words);
89
	runq->argv = p->next;
90
	efree((char *)p);
91
}
92
 
93
int
94
count(word *w)
95
{
96
	int n;
97
	for(n = 0;w;n++) w = w->next;
98
	return n;
99
}
100
 
101
void
102
pushredir(int type, int from, int to)
103
{
104
	redir * rp = new(redir);
105
	rp->type = type;
106
	rp->from = from;
107
	rp->to = to;
108
	rp->next = runq->redir;
109
	runq->redir = rp;
110
}
111
 
112
var*
113
newvar(char *name, var *next)
114
{
115
	var *v = new(var);
116
	v->name = name;
117
	v->val = 0;
118
	v->fn = 0;
119
	v->changed = 0;
120
	v->fnchanged = 0;
121
	v->next = next;
122
	return v;
123
}
124
/*
125
 * get command line flags, initialize keywords & traps.
126
 * get values from environment.
127
 * set $pid, $cflag, $*
128
 * fabricate bootstrap code and start it (*=(argv);. /usr/lib/rcmain $*)
129
 * start interpreting code
130
 */
131
 
132
void
133
main(int argc, char *argv[])
134
{
135
	code bootstrap[17];
136
	char num[12], *rcmain;
137
	int i;
138
	argc = getflags(argc, argv, "SsrdiIlxepvVc:1m:1[command]", 1);
139
	if(argc==-1)
140
		usage("[file [arg ...]]");
141
	if(argv[0][0]=='-')
142
		flag['l'] = flagset;
143
	if(flag['I'])
144
		flag['i'] = 0;
145
	else if(flag['i']==0 && argc==1 && Isatty(0)) flag['i'] = flagset;
146
	rcmain = flag['m']?flag['m'][0]:Rcmain; 
147
	err = openfd(2);
148
	kinit();
149
	Trapinit();
150
	Vinit();
151
	inttoascii(num, mypid = getpid());
152
	setvar("pid", newword(num, (word *)0));
153
	setvar("cflag", flag['c']?newword(flag['c'][0], (word *)0)
154
				:(word *)0);
155
	setvar("rcname", newword(argv[0], (word *)0));
156
	i = 0;
157
	memset(bootstrap, 0, sizeof bootstrap);
158
	bootstrap[i++].i = 1;
159
	bootstrap[i++].f = Xmark;
160
	bootstrap[i++].f = Xword;
161
	bootstrap[i++].s="*";
162
	bootstrap[i++].f = Xassign;
163
	bootstrap[i++].f = Xmark;
164
	bootstrap[i++].f = Xmark;
165
	bootstrap[i++].f = Xword;
166
	bootstrap[i++].s="*";
167
	bootstrap[i++].f = Xdol;
168
	bootstrap[i++].f = Xword;
169
	bootstrap[i++].s = rcmain;
170
	bootstrap[i++].f = Xword;
171
	bootstrap[i++].s=".";
172
	bootstrap[i++].f = Xsimple;
173
	bootstrap[i++].f = Xexit;
174
	bootstrap[i].i = 0;
175
	start(bootstrap, 1, (var *)0);
176
	/* prime bootstrap argv */
177
	pushlist();
178
	argv0 = strdup(argv[0]);
179
	for(i = argc-1;i!=0;--i) pushword(argv[i]);
180
	for(;;){
181
		if(flag['r'])
182
			pfnc(err, runq);
183
		runq->pc++;
184
		(*runq->code[runq->pc-1].f)();
185
		if(ntrap)
186
			dotrap();
187
	}
188
}
189
/*
190
 * Opcode routines
191
 * Arguments on stack (...)
192
 * Arguments in line [...]
193
 * Code in line with jump around {...}
194
 *
195
 * Xappend(file)[fd]			open file to append
196
 * Xassign(name, val)			assign val to name
197
 * Xasync{... Xexit}			make thread for {}, no wait
198
 * Xbackq{... Xreturn}			make thread for {}, push stdout
199
 * Xbang				complement condition
200
 * Xcase(pat, value){...}		exec code on match, leave (value) on
201
 * 					stack
202
 * Xclose[i]				close file descriptor
203
 * Xconc(left, right)			concatenate, push results
204
 * Xcount(name)				push var count
205
 * Xdelfn(name)				delete function definition
206
 * Xdelhere
207
 * Xdol(name)				get variable value
208
 * Xdup[i j]				dup file descriptor
209
 * Xeflag
210
 * Xerror
211
 * Xexit				rc exits with status
212
 * Xfalse{...}				execute {} if false
213
 * Xfn(name){... Xreturn}			define function
214
 * Xfor(var, list){... Xreturn}		for loop
215
 * Xglob
216
 * Xif
217
 * Xifnot
218
 * Xjump[addr]				goto
219
 * Xlocal(name, val)			create local variable, assign value
220
 * Xmark				mark stack
221
 * Xmatch(pat, str)			match pattern, set status
222
 * Xpipe[i j]{... Xreturn}{... Xreturn}	construct a pipe between 2 new threads,
223
 * 					wait for both
224
 * Xpipefd[type]{... Xreturn}		connect {} to pipe (input or output,
225
 * 					depending on type), push /dev/fd/??
226
 * Xpipewait
227
 * Xpopm(value)				pop value from stack
228
 * Xpopredir
229
 * Xrdcmds
230
 * Xrdfn
231
 * Xrdwr(file)[fd]			open file for reading and writing
232
 * Xread(file)[fd]			open file to read
233
 * Xqdol(name)				concatenate variable components
234
 * Xreturn				kill thread
235
 * Xsimple(args)			run command and wait
236
 * Xsub
237
 * Xsubshell{... Xexit}			execute {} in a subshell and wait
238
 * Xtrue{...}				execute {} if true
239
 * Xunlocal				delete local variable
240
 * Xwastrue
241
 * Xword[string]			push string
242
 * Xwrite(file)[fd]			open file to write
243
 */
244
 
245
void
246
Xappend(void)
247
{
248
	char *file;
249
	int f;
250
	switch(count(runq->argv->words)){
251
	default:
252
		Xerror1(">> requires singleton");
253
		return;
254
	case 0:
255
		Xerror1(">> requires file");
256
		return;
257
	case 1:
258
		break;
259
	}
260
	file = runq->argv->words->word;
261
	if((f = open(file, 1))<0 && (f = Creat(file))<0){
262
		pfmt(err, "%s: ", file);
263
		Xerror("can't open");
264
		return;
265
	}
266
	Seek(f, 0L, 2);
267
	pushredir(ROPEN, f, runq->code[runq->pc].i);
268
	runq->pc++;
269
	poplist();
270
}
271
 
272
void
273
Xsettrue(void)
274
{
275
	setstatus("");
276
}
277
 
278
void
279
Xbang(void)
280
{
281
	setstatus(truestatus()?"false":"");
282
}
283
 
284
void
285
Xclose(void)
286
{
287
	pushredir(RCLOSE, runq->code[runq->pc].i, 0);
288
	runq->pc++;
289
}
290
 
291
void
292
Xdup(void)
293
{
294
	pushredir(RDUP, runq->code[runq->pc].i, runq->code[runq->pc+1].i);
295
	runq->pc+=2;
296
}
297
 
298
void
299
Xeflag(void)
300
{
301
	if(eflagok && !truestatus()) Xexit();
302
}
303
 
304
void
305
Xexit(void)
306
{
307
	struct var *trapreq;
308
	struct word *starval;
309
	static int beenhere = 0;
310
	if(getpid()==mypid && !beenhere){
311
		trapreq = vlook("sigexit");
312
		if(trapreq->fn){
313
			beenhere = 1;
314
			--runq->pc;
315
			starval = vlook("*")->val;
316
			start(trapreq->fn, trapreq->pc, (struct var *)0);
317
			runq->local = newvar(strdup("*"), runq->local);
318
			runq->local->val = copywords(starval, (struct word *)0);
319
			runq->local->changed = 1;
320
			runq->redir = runq->startredir = 0;
321
			return;
322
		}
323
	}
324
	Exit(getstatus());
325
}
326
 
327
void
328
Xfalse(void)
329
{
330
	if(truestatus()) runq->pc = runq->code[runq->pc].i;
331
	else runq->pc++;
332
}
333
int ifnot;		/* dynamic if not flag */
334
 
335
void
336
Xifnot(void)
337
{
338
	if(ifnot)
339
		runq->pc++;
340
	else
341
		runq->pc = runq->code[runq->pc].i;
342
}
343
 
344
void
345
Xjump(void)
346
{
347
	runq->pc = runq->code[runq->pc].i;
348
}
349
 
350
void
351
Xmark(void)
352
{
353
	pushlist();
354
}
355
 
356
void
357
Xpopm(void)
358
{
359
	poplist();
360
}
361
 
362
void
363
Xread(void)
364
{
365
	char *file;
366
	int f;
367
	switch(count(runq->argv->words)){
368
	default:
369
		Xerror1("< requires singleton\n");
370
		return;
371
	case 0:
372
		Xerror1("< requires file\n");
373
		return;
374
	case 1:
375
		break;
376
	}
377
	file = runq->argv->words->word;
378
	if((f = open(file, 0))<0){
379
		pfmt(err, "%s: ", file);
380
		Xerror("can't open");
381
		return;
382
	}
383
	pushredir(ROPEN, f, runq->code[runq->pc].i);
384
	runq->pc++;
385
	poplist();
386
}
387
 
388
void
389
Xrdwr(void)
390
{
391
	char *file;
392
	int f;
393
 
394
	switch(count(runq->argv->words)){
395
	default:
396
		Xerror1("<> requires singleton\n");
397
		return;
398
	case 0:
399
		Xerror1("<> requires file\n");
400
		return;
401
	case 1:
402
		break;
403
	}
404
	file = runq->argv->words->word;
405
	if((f = open(file, ORDWR))<0){
406
		pfmt(err, "%s: ", file);
407
		Xerror("can't open");
408
		return;
409
	}
410
	pushredir(ROPEN, f, runq->code[runq->pc].i);
411
	runq->pc++;
412
	poplist();
413
}
414
 
415
void
416
turfredir(void)
417
{
418
	while(runq->redir!=runq->startredir)
419
		Xpopredir();
420
}
421
 
422
void
423
Xpopredir(void)
424
{
425
	struct redir *rp = runq->redir;
426
	if(rp==0)
427
		panic("turfredir null!", 0);
428
	runq->redir = rp->next;
429
	if(rp->type==ROPEN)
430
		close(rp->from);
431
	efree((char *)rp);
432
}
433
 
434
void
435
Xreturn(void)
436
{
437
	struct thread *p = runq;
438
	turfredir();
439
	while(p->argv) poplist();
440
	codefree(p->code);
441
	runq = p->ret;
442
	efree((char *)p);
443
	if(runq==0)
444
		Exit(getstatus());
445
}
446
 
447
void
448
Xtrue(void)
449
{
450
	if(truestatus()) runq->pc++;
451
	else runq->pc = runq->code[runq->pc].i;
452
}
453
 
454
void
455
Xif(void)
456
{
457
	ifnot = 1;
458
	if(truestatus()) runq->pc++;
459
	else runq->pc = runq->code[runq->pc].i;
460
}
461
 
462
void
463
Xwastrue(void)
464
{
465
	ifnot = 0;
466
}
467
 
468
void
469
Xword(void)
470
{
471
	pushword(runq->code[runq->pc++].s);
472
}
473
 
474
void
475
Xwrite(void)
476
{
477
	char *file;
478
	int f;
479
	switch(count(runq->argv->words)){
480
	default:
481
		Xerror1("> requires singleton\n");
482
		return;
483
	case 0:
484
		Xerror1("> requires file\n");
485
		return;
486
	case 1:
487
		break;
488
	}
489
	file = runq->argv->words->word;
490
	if((f = Creat(file))<0){
491
		pfmt(err, "%s: ", file);
492
		Xerror("can't open");
493
		return;
494
	}
495
	pushredir(ROPEN, f, runq->code[runq->pc].i);
496
	runq->pc++;
497
	poplist();
498
}
499
 
500
char*
501
list2str(word *words)
502
{
503
	char *value, *s, *t;
504
	int len = 0;
505
	word *ap;
506
	for(ap = words;ap;ap = ap->next)
507
		len+=1+strlen(ap->word);
508
	value = emalloc(len+1);
509
	s = value;
510
	for(ap = words;ap;ap = ap->next){
511
		for(t = ap->word;*t;) *s++=*t++;
512
		*s++=' ';
513
	}
514
	if(s==value)
515
		*s='\0';
516
	else s[-1]='\0';
517
	return value;
518
}
519
 
520
void
521
Xmatch(void)
522
{
523
	word *p;
524
	char *subject;
525
	subject = list2str(runq->argv->words);
526
	setstatus("no match");
527
	for(p = runq->argv->next->words;p;p = p->next)
528
		if(match(subject, p->word, '\0')){
529
			setstatus("");
530
			break;
531
		}
532
	efree(subject);
533
	poplist();
534
	poplist();
535
}
536
 
537
void
538
Xcase(void)
539
{
540
	word *p;
541
	char *s;
542
	int ok = 0;
543
	s = list2str(runq->argv->next->words);
544
	for(p = runq->argv->words;p;p = p->next){
545
		if(match(s, p->word, '\0')){
546
			ok = 1;
547
			break;
548
		}
549
	}
550
	efree(s);
551
	if(ok)
552
		runq->pc++;
553
	else
554
		runq->pc = runq->code[runq->pc].i;
555
	poplist();
556
}
557
 
558
word*
559
conclist(word *lp, word *rp, word *tail)
560
{
561
	char *buf;
562
	word *v;
563
	if(lp->next || rp->next)
564
		tail = conclist(lp->next==0? lp: lp->next,
565
			rp->next==0? rp: rp->next, tail);
566
	buf = emalloc(strlen(lp->word)+strlen((char *)rp->word)+1);
567
	strcpy(buf, lp->word);
568
	strcat(buf, rp->word);
569
	v = newword(buf, tail);
570
	efree(buf);
571
	return v;
572
}
573
 
574
void
575
Xconc(void)
576
{
577
	word *lp = runq->argv->words;
578
	word *rp = runq->argv->next->words;
579
	word *vp = runq->argv->next->next->words;
580
	int lc = count(lp), rc = count(rp);
581
	if(lc!=0 || rc!=0){
582
		if(lc==0 || rc==0){
583
			Xerror1("null list in concatenation");
584
			return;
585
		}
586
		if(lc!=1 && rc!=1 && lc!=rc){
587
			Xerror1("mismatched list lengths in concatenation");
588
			return;
589
		}
590
		vp = conclist(lp, rp, vp);
591
	}
592
	poplist();
593
	poplist();
594
	runq->argv->words = vp;
595
}
596
 
597
void
598
Xassign(void)
599
{
600
	var *v;
601
	if(count(runq->argv->words)!=1){
602
		Xerror1("variable name not singleton!");
603
		return;
604
	}
605
	deglob(runq->argv->words->word);
606
	v = vlook(runq->argv->words->word);
607
	poplist();
608
	globlist();
609
	freewords(v->val);
610
	v->val = runq->argv->words;
611
	v->changed = 1;
612
	runq->argv->words = 0;
613
	poplist();
614
}
615
/*
616
 * copy arglist a, adding the copy to the front of tail
617
 */
618
 
619
word*
620
copywords(word *a, word *tail)
621
{
622
	word *v = 0, **end;
623
	for(end=&v;a;a = a->next,end=&(*end)->next)
624
		*end = newword(a->word, 0);
625
	*end = tail;
626
	return v;
627
}
628
 
629
void
630
Xdol(void)
631
{
632
	word *a, *star;
633
	char *s, *t;
634
	int n;
635
	if(count(runq->argv->words)!=1){
636
		Xerror1("variable name not singleton!");
637
		return;
638
	}
639
	s = runq->argv->words->word;
640
	deglob(s);
641
	n = 0;
642
	for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0';
643
	a = runq->argv->next->words;
644
	if(n==0 || *t)
645
		a = copywords(vlook(s)->val, a);
646
	else{
647
		star = vlook("*")->val;
648
		if(star && 1<=n && n<=count(star)){
649
			while(--n) star = star->next;
650
			a = newword(star->word, a);
651
		}
652
	}
653
	poplist();
654
	runq->argv->words = a;
655
}
656
 
657
void
658
Xqdol(void)
659
{
660
	word *a, *p;
661
	char *s;
662
	int n;
663
	if(count(runq->argv->words)!=1){
664
		Xerror1("variable name not singleton!");
665
		return;
666
	}
667
	s = runq->argv->words->word;
668
	deglob(s);
669
	a = vlook(s)->val;
670
	poplist();
671
	n = count(a);
672
	if(n==0){
673
		pushword("");
674
		return;
675
	}
676
	for(p = a;p;p = p->next) n+=strlen(p->word);
677
	s = emalloc(n);
678
	if(a){
679
		strcpy(s, a->word);
680
		for(p = a->next;p;p = p->next){
681
			strcat(s, " ");
682
			strcat(s, p->word);
683
		}
684
	}
685
	else
686
		s[0]='\0';
687
	pushword(s);
688
	efree(s);
689
}
690
 
691
word*
692
copynwords(word *a, word *tail, int n)
693
{
694
	word *v, **end;
695
 
696
	v = 0;
697
	end = &v;
698
	while(n-- > 0){
699
		*end = newword(a->word, 0);
700
		end = &(*end)->next;
701
		a = a->next;
702
	}
703
	*end = tail;
704
	return v;
705
}
706
 
707
word*
708
subwords(word *val, int len, word *sub, word *a)
709
{
710
	int n, m;
711
	char *s;
712
	if(!sub)
713
		return a;
714
	a = subwords(val, len, sub->next, a);
715
	s = sub->word;
716
	deglob(s);
717
	m = 0;
718
	n = 0;
719
	while('0'<=*s && *s<='9')
720
		n = n*10+ *s++ -'0';
721
	if(*s == '-'){
722
		if(*++s == 0)
723
			m = len - n;
724
		else{
725
			while('0'<=*s && *s<='9')
726
				m = m*10+ *s++ -'0';
727
			m -= n;
728
		}
729
	}
730
	if(n<1 || n>len || m<0)
731
		return a;
732
	if(n+m>len)
733
		m = len-n;
734
	while(--n > 0)
735
		val = val->next;
736
	return copynwords(val, a, m+1);
737
}
738
 
739
void
740
Xsub(void)
741
{
742
	word *a, *v;
743
	char *s;
744
	if(count(runq->argv->next->words)!=1){
745
		Xerror1("variable name not singleton!");
746
		return;
747
	}
748
	s = runq->argv->next->words->word;
749
	deglob(s);
750
	a = runq->argv->next->next->words;
751
	v = vlook(s)->val;
752
	a = subwords(v, count(v), runq->argv->words, a);
753
	poplist();
754
	poplist();
755
	runq->argv->words = a;
756
}
757
 
758
void
759
Xcount(void)
760
{
761
	word *a;
762
	char *s, *t;
763
	int n;
764
	char num[12];
765
	if(count(runq->argv->words)!=1){
766
		Xerror1("variable name not singleton!");
767
		return;
768
	}
769
	s = runq->argv->words->word;
770
	deglob(s);
771
	n = 0;
772
	for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0';
773
	if(n==0 || *t){
774
		a = vlook(s)->val;
775
		inttoascii(num, count(a));
776
	}
777
	else{
778
		a = vlook("*")->val;
779
		inttoascii(num, a && 1<=n && n<=count(a)?1:0);
780
	}
781
	poplist();
782
	pushword(num);
783
}
784
 
785
void
786
Xlocal(void)
787
{
788
	if(count(runq->argv->words)!=1){
789
		Xerror1("variable name must be singleton\n");
790
		return;
791
	}
792
	deglob(runq->argv->words->word);
793
	runq->local = newvar(strdup(runq->argv->words->word), runq->local);
794
	poplist();
795
	globlist();
796
	runq->local->val = runq->argv->words;
797
	runq->local->changed = 1;
798
	runq->argv->words = 0;
799
	poplist();
800
}
801
 
802
void
803
Xunlocal(void)
804
{
805
	var *v = runq->local, *hid;
806
	if(v==0)
807
		panic("Xunlocal: no locals!", 0);
808
	runq->local = v->next;
809
	hid = vlook(v->name);
810
	hid->changed = 1;
811
	efree(v->name);
812
	freewords(v->val);
813
	efree((char *)v);
814
}
815
 
816
void
817
freewords(word *w)
818
{
819
	word *nw;
820
	while(w){
821
		efree(w->word);
822
		nw = w->next;
823
		efree((char *)w);
824
		w = nw;
825
	}
826
}
827
 
828
void
829
Xfn(void)
830
{
831
	var *v;
832
	word *a;
833
	int end;
834
	end = runq->code[runq->pc].i;
835
	globlist();
836
	for(a = runq->argv->words;a;a = a->next){
837
		v = gvlook(a->word);
838
		if(v->fn)
839
			codefree(v->fn);
840
		v->fn = codecopy(runq->code);
841
		v->pc = runq->pc+2;
842
		v->fnchanged = 1;
843
	}
844
	runq->pc = end;
845
	poplist();
846
}
847
 
848
void
849
Xdelfn(void)
850
{
851
	var *v;
852
	word *a;
853
	for(a = runq->argv->words;a;a = a->next){
854
		v = gvlook(a->word);
855
		if(v->fn)
856
			codefree(v->fn);
857
		v->fn = 0;
858
		v->fnchanged = 1;
859
	}
860
	poplist();
861
}
862
 
863
char*
864
concstatus(char *s, char *t)
865
{
866
	static char v[NSTATUS+1];
867
	int n = strlen(s);
868
	strncpy(v, s, NSTATUS);
869
	if(n<NSTATUS){
870
		v[n]='|';
871
		strncpy(v+n+1, t, NSTATUS-n-1);
872
	}
873
	v[NSTATUS]='\0';
874
	return v;
875
}
876
 
877
void
878
Xpipewait(void)
879
{
880
	char status[NSTATUS+1];
881
	if(runq->pid==-1)
882
		setstatus(concstatus(runq->status, getstatus()));
883
	else{
884
		strncpy(status, getstatus(), NSTATUS);
885
		status[NSTATUS]='\0';
886
		Waitfor(runq->pid, 1);
887
		runq->pid=-1;
888
		setstatus(concstatus(getstatus(), status));
889
	}
890
}
891
 
892
void
893
Xrdcmds(void)
894
{
895
	struct thread *p = runq;
896
	word *prompt;
897
	flush(err);
898
	nerror = 0;
899
	if(flag['s'] && !truestatus())
900
		pfmt(err, "status=%v\n", vlook("status")->val);
901
	if(runq->iflag){
902
		prompt = vlook("prompt")->val;
903
		if(prompt)
904
			promptstr = prompt->word;
905
		else
906
			promptstr="% ";
907
	}
908
	Noerror();
909
	if(yyparse()){
910
		if(!p->iflag || p->eof && !Eintr()){
911
			if(p->cmdfile)
912
				efree(p->cmdfile);
913
			closeio(p->cmdfd);
914
			Xreturn();	/* should this be omitted? */
915
		}
916
		else{
917
			if(Eintr()){
918
				pchr(err, '\n');
919
				p->eof = 0;
920
			}
921
			--p->pc;	/* go back for next command */
922
		}
923
	}
924
	else{
925
		ntrap = 0;	/* avoid double-interrupts during blocked writes */
926
		--p->pc;	/* re-execute Xrdcmds after codebuf runs */
927
		start(codebuf, 1, runq->local);
928
	}
929
	freenodes();
930
}
931
 
932
void
933
Xerror(char *s)
934
{
935
	if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
936
		pfmt(err, "rc: %s: %r\n", s);
937
	else
938
		pfmt(err, "rc (%s): %s: %r\n", argv0, s);
939
	flush(err);
940
	setstatus("error");
941
	while(!runq->iflag) Xreturn();
942
}
943
 
944
void
945
Xerror1(char *s)
946
{
947
	if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
948
		pfmt(err, "rc: %s\n", s);
949
	else
950
		pfmt(err, "rc (%s): %s\n", argv0, s);
951
	flush(err);
952
	setstatus("error");
953
	while(!runq->iflag) Xreturn();
954
}
955
 
956
void
957
setstatus(char *s)
958
{
959
	setvar("status", newword(s, (word *)0));
960
}
961
 
962
char*
963
getstatus(void)
964
{
965
	var *status = vlook("status");
966
	return status->val?status->val->word:"";
967
}
968
 
969
int
970
truestatus(void)
971
{
972
	char *s;
973
	for(s = getstatus();*s;s++)
974
		if(*s!='|' && *s!='0')
975
			return 0;
976
	return 1;
977
}
978
 
979
void
980
Xdelhere(void)
981
{
982
	Unlink(runq->code[runq->pc++].s);
983
}
984
 
985
void
986
Xfor(void)
987
{
988
	if(runq->argv->words==0){
989
		poplist();
990
		runq->pc = runq->code[runq->pc].i;
991
	}
992
	else{
993
		freelist(runq->local->val);
994
		runq->local->val = runq->argv->words;
995
		runq->local->changed = 1;
996
		runq->argv->words = runq->argv->words->next;
997
		runq->local->val->next = 0;
998
		runq->pc++;
999
	}
1000
}
1001
 
1002
void
1003
Xglob(void)
1004
{
1005
	globlist();
1006
}