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