1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96#define FOR_sh
97#include "toys.h"
98
99GLOBALS(
100 char *command;
101
102 long lineno;
103
104 struct double_list functions;
105 unsigned options;
106
107
108 struct sh_job {
109 struct sh_job *next, *prev;
110 unsigned jobno;
111
112
113 struct sh_arg {
114 char **v;
115 int c;
116 } pipeline;
117
118
119 struct sh_process {
120 struct string_list *delete;
121 int pid, exit;
122 struct sh_arg arg;
123 } *procs, *proc;
124 } *jobs, *job;
125 unsigned jobcnt;
126)
127
128#define SH_NOCLOBBER 1
129
130void cd_main(void)
131{
132 char *dest = *toys.optargs ? *toys.optargs : getenv("HOME");
133
134
135
136 xchdir(dest ? dest : "/");
137}
138
139void exit_main(void)
140{
141 exit(*toys.optargs ? atoi(*toys.optargs) : 0);
142}
143
144
145void syntax_err(char *msg, ...)
146{
147 va_list va;
148
149 va_start(va, msg);
150 verror_msg(msg, 0, va);
151 va_end(va);
152
153 if (*toys.optargs) xexit();
154}
155
156
157static void do_prompt(char *prompt)
158{
159 char *s, c, cc;
160
161 if (!prompt) prompt = "\\$ ";
162 while (*prompt) {
163 c = *(prompt++);
164
165 if (c=='!') {
166 if (*prompt=='!') prompt++;
167 else {
168 printf("%ld", TT.lineno);
169 continue;
170 }
171 } else if (c=='\\') {
172 int i = 0;
173
174 cc = *(prompt++);
175 if (!cc) goto down;
176
177
178
179 if (cc=='[' || cc==']') continue;
180 else if (cc=='$') putchar(getuid() ? '$' : '#');
181 else if (cc=='h' || cc=='H') {
182 *toybuf = 0;
183 gethostname(toybuf, sizeof(toybuf)-1);
184 if (cc=='h' && (s = strchr(toybuf, '.'))) *s = 0;
185 fputs(toybuf, stdout);
186 } else if (cc=='s') fputs(getbasename(*toys.argv), stdout);
187 else {
188 if (!(c = unescape(cc))) {
189 c = '\\';
190 prompt--;
191 }
192 i++;
193 }
194 if (!i) continue;
195 }
196down:
197 putchar(c);
198 }
199 fflush(stdout);
200}
201
202
203
204#define NO_PATH (1<<0)
205#define NO_SPLIT (1<<1)
206
207
208
209
210
211
212
213static void expand_arg(struct sh_arg *arg, char *new, unsigned flags,
214 struct string_list **delete)
215{
216 if (!(arg->c&32)) arg->v = xrealloc(arg->v, sizeof(void *)*(arg->c+33));
217
218 arg->v[arg->c++] = new;
219 arg->v[arg->c] = 0;
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237}
238
239
240
241
242#define TAKE_MEM 0x80000000
243
244
245void setvar(char *s, unsigned type)
246{
247 if (type&TAKE_MEM) type ^= TAKE_MEM;
248 else s = xstrdup(s);
249
250
251 xsetenv(s, 0);
252}
253
254char *getvar(char *s)
255{
256 return getenv(s);
257}
258
259
260static int anystart(char *s, char **try)
261{
262 while (*try) {
263 if (strstart(&s, *try)) return strlen(*try);
264 try++;
265 }
266
267 return 0;
268}
269
270static int anystr(char *s, char **try)
271{
272 while (*try) if (!strcmp(s, *try++)) return 1;
273
274 return 0;
275}
276
277
278int redir_prefix(char *word)
279{
280 char *s = word;
281
282 if (*s == '{') {
283 for (s++; isalnum(*s) || *s=='_'; s++);
284 if (*s == '}' && s != word+1) s++;
285 else s = word;
286 } else while (isdigit(*s)) s++;
287
288 return s-word;
289}
290
291
292
293
294
295struct sh_process *run_command(struct sh_arg *arg, int **rdlist)
296{
297 struct sh_process *pp = xzalloc(sizeof(struct sh_process));
298 struct toy_list *tl;
299 char *s, *ss, *sss;
300 unsigned envlen, j;
301 int fd, here = 0, rdcount = 0, *rd = 0, *rr, hfd = 0;
302
303
304 for (envlen = 0; envlen<arg->c; envlen++) {
305 s = arg->v[envlen];
306 for (j=0; s[j] && (s[j]=='_' || !ispunct(s[j])); j++);
307 if (!j || s[j] != '=') break;
308 }
309
310
311 if (envlen == arg->c) {
312 for (j = 0; j<envlen; j++) {
313 struct sh_arg aa;
314
315 aa.c = 0;
316 expand_arg(&aa, arg->v[j], NO_PATH|NO_SPLIT, 0);
317 setvar(*aa.v, TAKE_MEM);
318 free(aa.v);
319 }
320 free(pp);
321
322 return 0;
323 }
324
325
326
327
328
329
330
331
332
333 for (j = envlen; j<arg->c; j++) {
334
335
336 ss = (s = arg->v[j]) + redir_prefix(arg->v[j]);
337 if (!anystr(ss, (char *[]){"<<<", "<<-", "<<", "<&", "<>", "<", ">>", ">&",
338 ">|", ">", "&>>", "&>", 0}))
339 {
340
341 expand_arg(&pp->arg, s, 0, 0);
342
343 continue;
344 }
345
346
347 if (!(rdcount&31)) {
348 if (rd) dlist_lpop((void *)rdlist);
349 rd = xrealloc(rd, (2*rdcount+3+2*32)*sizeof(int *));
350 dlist_add_nomalloc((void *)rdlist, (void *)rd);
351 }
352 rr = rd+3+rdcount;
353 if (!hfd)
354 for (hfd = 10; hfd<99999; hfd++) if (-1 == fcntl(hfd, F_GETFL)) break;
355
356
357 if (++j == arg->c || (isdigit(*s) && ss-s>5)) goto flush;
358 fd = pp->arg.c;
359
360
361 if (strncmp(ss, "<<", 2) || ss[2] == '<') {
362 expand_arg(&pp->arg, arg->v[j], NO_PATH|(NO_SPLIT*!strcmp(ss, "<<<")), 0);
363 if (fd+1 != pp->arg.c) goto flush;
364 sss = pp->arg.v[--pp->arg.c];
365 } else dlist_add((void *)&pp->delete, sss = xstrdup(arg->v[j]));
366
367
368
369
370 if (isdigit(*ss)) fd = atoi(ss);
371 else if (*ss == '{') {
372 ss++;
373
374 if ((!strcmp(s, "<&") || !strcmp(s, ">&")) && !strcmp(sss, "-")) {
375 ss = xstrndup(ss, (s-ss)-1);
376 sss = getvar(ss);
377 free(ss);
378 fd = -1;
379 if (sss) fd = atoi(sss);
380 if (fd<0) goto flush;
381 if (fd>2) {
382 rr[0] = fd;
383 rr[1] = fd<<1;
384 rdcount++;
385 }
386 continue;
387 } else setvar(xmprintf("%.*s=%d", (int)(s-ss), ss, hfd), TAKE_MEM);
388 } else fd = *ss != '<';
389 *rr = fd;
390
391
392
393
394
395
396
397
398 if (!strcmp(s, "<<<") || !strcmp(s, "<<-") || !strcmp(s, "<<")) {
399 fd = --here<<2;
400 if (s[2] == '-') fd += 1;
401 if (s[strcspn(s, "\"'")]) fd += 2;
402 rr[1] = fd;
403 rdcount++;
404
405 continue;
406 }
407
408
409 if (strchr(ss, '&') && ss[2] != '>') {
410 char *dig = sss;
411
412
413 while (isdigit(dig)) dig++;
414 if (dig-sss>5) {
415 s = sss;
416 goto flush;
417 }
418
419
420 if (!*dig || (*dig=='-' && !dig[1])) {
421 rr[1] = (((dig==sss) ? *rr : atoi(sss))<<1)+(*dig != '-');
422 rdcount++;
423
424 continue;
425 }
426 }
427
428
429 if (!strcmp(ss, "<>")) fd = O_CREAT|O_RDWR;
430 else if (strstr(ss, ">>")) fd = O_CREAT|O_APPEND;
431 else {
432 fd = (*ss != '<') ? O_CREAT|O_WRONLY|O_TRUNC : O_RDONLY;
433 if (!strcmp(ss, ">") && (TT.options&SH_NOCLOBBER)) {
434 struct stat st;
435
436
437 if (stat(sss, &st) || !S_ISREG(st.st_mode)) fd |= O_EXCL;
438 }
439 }
440
441
442
443 if (-1 == (fd = xcreate(sss, fd|WARN_ONLY, 777)) || hfd != dup2(fd, hfd)) {
444 pp->exit = 1;
445 s = 0;
446
447 goto flush;
448 }
449 if (fd != hfd) close(fd);
450 rr[1] = hfd<<1;
451 rdcount++;
452
453
454 if (strchr(ss, '&')) {
455 if (!(31&++rdcount)) rd = xrealloc(rd, (2*rdcount+66)*sizeof(int *));
456 rr = rd+3+rdcount;
457 rr[0] = 2;
458 rr[1] = 1+(1<<1);
459 rdcount++;
460 }
461 }
462 if (rd) rd[2] = rdcount;
463
464
465
466
467
468
469
470
471
472 if ((tl = toy_find(*pp->arg.v))
473 && (tl->flags & (TOYFLAG_NOFORK|TOYFLAG_MAYFORK)))
474 {
475 struct toy_context temp;
476 sigjmp_buf rebound;
477
478
479 memcpy(&temp, &toys, sizeof(struct toy_context));
480 memset(&toys, 0, sizeof(struct toy_context));
481
482
483 if (!sigsetjmp(rebound, 1)) {
484 toys.rebound = &rebound;
485
486 toy_init(tl, pp->arg.v);
487 tl->toy_main();
488 }
489 pp->exit = toys.exitval;
490 if (toys.optargs != toys.argv+1) free(toys.optargs);
491 if (toys.old_umask) umask(toys.old_umask);
492 memcpy(&toys, &temp, sizeof(struct toy_context));
493 } else {
494 int pipe[2];
495
496 pipe[0] = 0;
497 pipe[1] = 1;
498
499
500 if (-1 == (pp->pid = xpopen_both(pp->arg.v, pipe)))
501 perror_msg("%s: vfork", *pp->arg.v);
502
503 else pp->exit = xpclose_both(pp->pid, 0);
504 }
505
506 s = 0;
507flush:
508 if (s) {
509 syntax_err("bad %s", s);
510 if (!pp->exit) pp->exit = 1;
511 }
512 for (j = 0; j<rdcount; j++) if (rd[4+2*j]>6) close(rd[4+2*j]>>1);
513 if (rdcount) free(dlist_lpop((void *)rdlist));
514
515 return pp;
516}
517
518
519
520static char *parse_word(char *start)
521{
522 int i, j, quote = 0, q, qc = 0;
523 char *end = start, *s;
524
525
526 if (strstart(&end, "((")) toybuf[quote++] = 255;
527
528
529 while (*end) {
530 i = 0;
531
532
533 if (quote>4000) {
534 syntax_err("tilt");
535 return (void *)1;
536 }
537
538 q = quote ? toybuf[quote-1] : 0;
539
540 if (q) {
541
542
543 if ((q == ')' || q == '\xff') && (*end == '(' || *end == ')')) {
544 if (*end == '(') qc++;
545 else if (qc) qc--;
546 else if (q == '\xff') {
547
548 if (strstart(&end, "))")) quote--;
549 else return start+1;
550 }
551 end++;
552
553
554 } else if (*end == q) quote--, end++;
555
556
557 else if (q == '\'') end++;
558 else i++;
559
560
561 if (!i) continue;
562 } else {
563
564
565 if (isspace(*end)) break;
566
567
568
569
570
571 s = end + redir_prefix(end);
572 j = anystart(s, (char *[]){"<<<", "<<-", "<<", "<&", "<>", "<", ">>",
573 ">&", ">|", ">", 0});
574 if (j) s += j;
575
576
577 else s = end + anystart(end, (char *[]){";;&", ";;", ";&", ";", "||",
578 "|&", "|", "&&", "&>>", "&>", "&", "(", ")", 0});
579 if (s != end) return (end == start) ? s : end;
580 i++;
581 }
582
583
584
585
586 if (strchr("\"'`", *end)) toybuf[quote++] = *end++;
587 else if (q != '"' && (strstart(&end, "<(") || strstart(&end,">(")))
588 toybuf[quote++]=')';
589
590
591 else if (*end == '\\') {
592 if (!end[1] || (end[1]=='\n' && !end[2])) return 0;
593 end += 2;
594 } else if (*end++ == '$') {
595 if (-1 != (i = stridx("({[", *end))) {
596 toybuf[quote++] = ")}]"[i];
597 end++;
598 }
599 }
600 }
601
602 return quote ? 0 : end;
603}
604
605
606
607
608void argxtend(struct sh_arg *arg)
609{
610 if (!(arg->c&31)) arg->v = xrealloc(arg->v, (33+arg->c)*sizeof(void *));
611}
612
613
614struct sh_pipeline {
615 struct sh_pipeline *next, *prev;
616 int count, here, type;
617 struct sh_arg arg[1];
618};
619
620
621int run_pipeline(struct sh_pipeline **pl, int *rd)
622{
623 struct sh_process *pp;
624 int rc = 0;
625
626 for (;;) {
627
628 if (!(pp = run_command((*pl)->arg, &rd))) rc = 0;
629 else {
630
631 llist_traverse(pp->delete, free);
632 rc = pp->exit;
633 free(pp);
634 }
635
636 if ((*pl)->next && !(*pl)->next->type) *pl = (*pl)->next;
637 else return rc;
638 }
639}
640
641
642
643
644
645struct sh_function {
646 char *name;
647 struct sh_pipeline *pipeline;
648 struct double_list *expect;
649
650 struct sh_arg *arg;
651 char *end;
652};
653
654
655void free_pipeline(void *pipeline)
656{
657 struct sh_pipeline *pl = pipeline;
658 int i, j;
659
660 if (pl) for (j=0; j<=pl->count; j++) {
661 for (i = 0; i<=pl->arg->c; i++) free(pl->arg[j].v[i]);
662 free(pl->arg[j].v);
663 }
664 free(pl);
665}
666
667
668struct sh_pipeline *block_end(struct sh_pipeline *pl)
669{
670 int i = 0;
671
672 while (pl) {
673 if (pl->type == 1 || pl->type == 'f') i++;
674 else if (pl->type == 3) if (--i<1) break;
675 pl = pl->next;
676 }
677
678 return 0;
679}
680
681void free_function(struct sh_function *sp)
682{
683 llist_traverse(sp->pipeline, free_pipeline);
684 llist_traverse(sp->expect, free);
685 memset(sp, 0, sizeof(struct sh_function));
686}
687
688
689struct sh_pipeline *add_function(char *name, struct sh_pipeline *pl)
690{
691dprintf(2, "stub add_function");
692
693 return block_end(pl->next);
694}
695
696
697
698static int parse_line(char *line, struct sh_function *sp)
699{
700 char *start = line, *delete = 0, *end, *last = 0, *s, *ex, done = 0;
701 struct sh_pipeline *pl = sp->pipeline ? sp->pipeline->prev : 0;
702 struct sh_arg *arg = 0;
703 long i;
704
705
706 if (pl) {
707 arg = pl->arg;
708
709
710 if (arg->c<0) {
711 delete = start = xmprintf("%s%s", arg->v[arg->c = (-arg->c)-1], start);
712 free(arg->v[arg->c]);
713 arg->v[arg->c] = 0;
714
715
716 } else if (pl->count != pl->here) {
717 arg += 1+pl->here;
718
719 argxtend(arg);
720 if (strcmp(line, arg->v[arg->c])) {
721
722 arg->v[arg->c+1] = arg->v[arg->c];
723 arg->v[arg->c++] = xstrdup(line);
724
725 } else {
726 arg->v[arg->c] = 0;
727 pl->here++;
728 }
729 start = 0;
730
731
732 } else pl = 0;
733 }
734
735
736 if (start) for (;;) {
737 ex = sp->expect ? sp->expect->prev->data : 0;
738
739
740 if (pl && pl->count == -1) {
741 pl->count = 0;
742 arg = pl->arg;
743
744
745 for (i = 0; i<arg->c; i++) {
746 s = arg->v[i] + redir_prefix(arg->v[i]);
747 if (strcmp(s, "<<") && strcmp(s, "<<-") && strcmp(s, "<<<")) continue;
748 if (i+1 == arg->c) goto flush;
749
750
751
752 dlist_lpop(&sp->pipeline);
753 pl = xrealloc(pl, sizeof(*pl) + ++pl->count*sizeof(struct sh_arg));
754 dlist_add_nomalloc((void *)&sp->pipeline, (void *)pl);
755
756
757 arg[pl->count].v = xzalloc(2*sizeof(void *));
758 *arg[pl->count].v = arg->v[++i];
759 arg[pl->count].c = -(s[2] == '<');
760 }
761 pl = 0;
762 }
763 if (done) break;
764 s = 0;
765
766
767 for (;;) {
768 if (isspace(*start)) ++start;
769 else if (*start=='#') while (*start && *start != '\n') ++start;
770 else break;
771 }
772
773
774 if ((end = parse_word(start)) == (void *)1)
775 goto flush;
776
777
778 if (!pl) {
779 pl = xzalloc(sizeof(struct sh_pipeline));
780 arg = pl->arg;
781 dlist_add_nomalloc((void *)&sp->pipeline, (void *)pl);
782 }
783 argxtend(arg);
784
785
786 if (!end) {
787
788 arg->v[arg->c] = xstrndup(start, strlen(start));
789 arg->c = -(arg->c+1);
790 free(delete);
791
792 return 1;
793 }
794
795
796
797
798
799 if (end == start || (arg->c && *start == ')' && pl->type!='f')) {
800 arg->v[arg->c] = 0;
801
802 if (pl->type == 'f' && arg->c<3) {
803 s = "function()";
804 goto flush;
805 }
806
807
808 if (arg->c == 1 && ex && !memcmp(ex, "do\0A", 4)) {
809 s = "newline";
810 goto flush;
811 }
812
813
814 if (!arg->c) free_pipeline(dlist_lpop(&sp->pipeline));
815
816
817 if (end == start) done++;
818 pl->count = -1;
819 last = 0;
820
821 continue;
822 }
823
824
825 s = arg->v[arg->c] = xstrndup(start, end-start);
826 start = end;
827 if (strchr(";|&", *s)) {
828
829
830 if (!arg->c) goto flush;
831
832
833 if (!strcmp(s, ";")) {
834 arg->v[arg->c] = 0;
835 free(s);
836 s = 0;
837 }
838 last = s;
839 pl->count = -1;
840
841 continue;
842 } else arg->v[++arg->c] = 0;
843
844
845 if (arg->c>1 && !strcmp(s, "(")) pl->type = 'f';
846 if (pl->type=='f') {
847 if (arg->c == 2 && strcmp(s, "(")) goto flush;
848 if (arg->c == 3) {
849 if (strcmp(s, ")")) goto flush;
850
851
852 pl->count = -1;
853 last = 0;
854 dlist_add(&sp->expect, "}");
855 dlist_add(&sp->expect, 0);
856 dlist_add(&sp->expect, "{");
857
858 continue;
859 }
860
861
862 } else if (ex && !memcmp(ex, "do\0A", 4)) {
863
864
865 if (strncmp(s, "((", 2) && strchr(s, '=')) goto flush;
866 pl->count = -1;
867 sp->expect->prev->data = "do\0C";
868
869 continue;
870
871
872 } else if (arg->c>1) continue;
873
874
875 if (ex) {
876
877 if (!strcmp(ex, "{")) {
878 if (strcmp(s, "{")) goto flush;
879 free(arg->v[--arg->c]);
880 free(dlist_lpop(&sp->expect));
881
882 continue;
883
884
885
886 } else if (!memcmp(ex, "do\0C", 4)) {
887 if (strcmp(s, "do")) {
888
889 if (!pl->prev->type) goto flush;
890 if (!strncmp(pl->prev->arg->v[1], "((", 2)) goto flush;
891 else if (strcmp(s, "in")) goto flush;
892
893 continue;
894 }
895 }
896 }
897
898
899
900
901 if (!strcmp(s, "for") || !strcmp(s, "select")) {
902 if (!pl->type) pl->type = 1;
903 dlist_add(&sp->expect, "do\0A");
904
905 continue;
906 }
907
908 end = 0;
909 if (!strcmp(s, "if")) end = "then";
910 else if (!strcmp(s, "while") || !strcmp(s, "until")) end = "do\0B";
911 else if (!strcmp(s, "case")) end = "esac";
912 else if (!strcmp(s, "{")) end = "}";
913 else if (!strcmp(s, "[[")) end = "]]";
914 else if (!strcmp(s, "(")) end = ")";
915
916
917 else if (sp->expect && !ex) {
918 free(dlist_lpop(&sp->expect));
919 continue;
920 } else if (!ex) goto check;
921
922
923 if (end) {
924 pl->type = 1;
925
926
927 if (sp->expect && !sp->expect->prev->data) free(dlist_lpop(&sp->expect));
928
929
930 } else if (!strcmp(s, ex)) {
931
932 if (last && (strcmp(ex, "then") || strcmp(last, "&"))) {
933 s = end;
934 goto flush;
935 }
936
937 free(dlist_lpop(&sp->expect));
938 pl->type = anystr(s, (char *[]){"fi", "done", "esac", "}", "]]", ")", 0})
939 ? 3 : 2;
940
941
942 if (!strcmp(s, "do")) end = "done";
943 else if (!strcmp(s, "then")) end = "fi\0A";
944
945
946 } else if (!strcmp(ex, "fi")) {
947 if (!strcmp(s, "elif")) {
948 free(dlist_lpop(&sp->expect));
949 end = "then";
950
951 } else if (!strcmp(s, "else")) {
952 if (ex[3] != 'A') {
953 s = "2 else";
954 goto flush;
955 }
956 free(dlist_lpop(&sp->expect));
957 end = "fi\0B";
958 }
959 }
960
961
962 if (end) {
963 if (!pl->type) pl->type = 2;
964 dlist_add(&sp->expect, end);
965 dlist_add(&sp->expect, 0);
966 pl->count = -1;
967 }
968
969check:
970
971 if (!pl->type && anystr(s, (char *[]){"then", "do", "esac", "}", "]]", ")",
972 "done", "fi", "elif", "else", 0})) goto flush;
973 }
974 free(delete);
975
976
977 pl = sp->pipeline->prev;
978 while (pl->count<pl->here && pl->arg[pl->count].c<0)
979 pl->arg[pl->count++].c = 0;
980
981
982 if (sp->expect) return 1;
983 if (sp->pipeline && pl->count != pl->here) return 1;
984 dlist_terminate(sp->pipeline);
985
986
987
988 return 0;
989
990flush:
991 if (s) syntax_err("bad %s", s);
992 free_function(sp);
993
994 return 0-!!s;
995}
996
997static void dump_state(struct sh_function *sp)
998{
999 struct sh_pipeline *pl;
1000 int q = 0;
1001 long i;
1002
1003 if (sp->expect) {
1004 struct double_list *dl;
1005
1006 for (dl = sp->expect; dl; dl = (dl->next == sp->expect) ? 0 : dl->next)
1007 dprintf(2, "expecting %s\n", dl->data);
1008 if (sp->pipeline)
1009 dprintf(2, "pipeline count=%d here=%d\n", sp->pipeline->prev->count,
1010 sp->pipeline->prev->here);
1011 }
1012
1013 for (pl = sp->pipeline; pl ; pl = (pl->next == sp->pipeline) ? 0 : pl->next) {
1014 for (i = 0; i<pl->arg->c; i++)
1015 printf("arg[%d][%ld]=%s\n", q, i, pl->arg->v[i]);
1016 printf("type=%d term[%d]=%s\n", pl->type, q++, pl->arg->v[pl->arg->c]);
1017 }
1018}
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029static void run_function(struct sh_function *sp)
1030{
1031 struct sh_pipeline *pl = sp->pipeline, *end;
1032 struct blockstack {
1033 struct blockstack *next;
1034 struct sh_pipeline *start, *end;
1035 int run, loop, *redir;
1036
1037 struct sh_arg farg;
1038 struct string_list *fdelete;
1039 char *fvar;
1040 } *blk = 0, *new;
1041 long i;
1042
1043
1044 while (pl) {
1045 char *s = *pl->arg->v, *ss = pl->arg->v[1];
1046
1047
1048 if (!pl->type) {
1049
1050
1051 if (!strcmp(s, "break") || !strcmp(s, "continue")) {
1052
1053
1054 i = ss ? atol(ss) : 0;
1055 if (i<1) i = 1;
1056 if (!blk || pl->arg->c>2 || ss[strspn(ss, "0123456789")]) {
1057 syntax_err("bad %s", s);
1058 break;
1059 }
1060 i = atol(ss);
1061 if (!i) i++;
1062 while (i && blk) {
1063 if (--i && *s == 'c') {
1064 pl = blk->start;
1065 break;
1066 }
1067 pl = blk->end;
1068 llist_traverse(blk->fdelete, free);
1069 free(llist_pop(&blk));
1070 }
1071 pl = pl->next;
1072
1073 continue;
1074 }
1075
1076
1077
1078 if (!blk) toys.exitval = run_pipeline(&pl, 0);
1079 else if (blk->run) toys.exitval = run_pipeline(&pl, blk->redir);
1080 else while (pl->next && !pl->next->type) pl = pl->next;
1081
1082
1083 } else if (pl->type == 1) {
1084
1085
1086 if (!blk || blk->start != pl) {
1087
1088
1089 end = block_end(pl->next);
1090 if (blk && !blk->run) {
1091 pl = end;
1092 if (pl) pl = pl->next;
1093 continue;
1094 }
1095
1096
1097 new = xzalloc(sizeof(*blk));
1098 new->next = blk;
1099 blk = new;
1100 blk->start = pl;
1101 blk->end = end;
1102 blk->run = 1;
1103
1104 }
1105
1106
1107
1108
1109
1110
1111 if (!strcmp(s, "for") || !strcmp(s, "select")) {
1112 if (blk->loop);
1113 else if (!strncmp(blk->fvar = ss, "((", 2)) {
1114 blk->loop = 1;
1115dprintf(2, "TODO skipped init for((;;)), need math parser\n");
1116 } else {
1117
1118
1119 if (!pl->next->type) {
1120 for (i = 1; i<pl->next->arg->c; i++)
1121 expand_arg(&blk->farg, pl->next->arg->v[i], 0, &blk->fdelete);
1122 } else expand_arg(&blk->farg, "\"$@\"", 0, &blk->fdelete);
1123 }
1124 pl = pl->next;
1125 }
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137 } else if (pl->type == 2) {
1138
1139
1140 if (!strcmp(s, "then")) blk->run = blk->run && !toys.exitval;
1141 else if (!strcmp(s, "else") || !strcmp(s, "elif")) blk->run = !blk->run;
1142 else if (!strcmp(s, "do")) {
1143 ss = *blk->start->arg->v;
1144 if (!strcmp(ss, "while")) blk->run = blk->run && !toys.exitval;
1145 else if (!strcmp(ss, "until")) blk->run = blk->run && toys.exitval;
1146 else if (blk->loop >= blk->farg.c) {
1147 blk->run = 0;
1148 pl = block_end(pl);
1149 continue;
1150 } else if (!strncmp(blk->fvar, "((", 2)) {
1151dprintf(2, "TODO skipped running for((;;)), need math parser\n");
1152 } else setvar(xmprintf("%s=%s", blk->fvar, blk->farg.v[blk->loop++]),
1153 TAKE_MEM);
1154 }
1155
1156
1157 } else if (pl->type == 3) {
1158
1159
1160 if (blk->run && !strcmp(s, "done")) {
1161 pl = blk->start;
1162 continue;
1163 }
1164
1165
1166 llist_traverse(blk->fdelete, free);
1167 free(llist_pop(&blk));
1168
1169
1170
1171 } else if (pl->type == 'f') pl = add_function(s, pl);
1172
1173 pl = pl->next;
1174 }
1175
1176
1177 while (blk) {
1178 llist_traverse(blk->fdelete, free);
1179 free(llist_pop(&blk));
1180 }
1181
1182 return;
1183}
1184
1185void subshell_imports(void)
1186{
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236}
1237
1238void sh_main(void)
1239{
1240 FILE *f;
1241 char *new;
1242 struct sh_function scratch;
1243 int prompt = 0;
1244
1245
1246
1247
1248 subshell_imports();
1249
1250 memset(&scratch, 0, sizeof(scratch));
1251 if (TT.command) f = fmemopen(TT.command, strlen(TT.command), "r");
1252 else if (*toys.optargs) f = xfopen(*toys.optargs, "r");
1253 else {
1254 f = stdin;
1255 if (isatty(0)) toys.optflags |= FLAG_i;
1256 }
1257
1258 for (;;) {
1259
1260
1261 if (f == stdin) {
1262 char *s = getenv(prompt ? "PS2" : "PS1");
1263
1264 if (!s) s = prompt ? "> " : (getpid() ? "\\$ " : "# ");
1265 do_prompt(s);
1266 } else TT.lineno++;
1267 if (!(new = xgetline(f ? f : stdin, 0))) break;
1268
1269
1270
1271
1272 prompt = parse_line(new, &scratch);
1273if (0) dump_state(&scratch);
1274 if (prompt != 1) {
1275
1276 if (!prompt) run_function(&scratch);
1277 free_function(&scratch);
1278 prompt = 0;
1279 }
1280 free(new);
1281 }
1282
1283 if (prompt) error_exit("%ld:unfinished line"+4*!TT.lineno, TT.lineno);
1284 toys.exitval = f && ferror(f);
1285}
1286