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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297#define FOR_sh
298#include "toys.h"
299
300GLOBALS(
301 union {
302 struct {
303 char *c;
304 } sh;
305 struct {
306 char *a;
307 } exec;
308 };
309
310
311 long long SECONDS;
312 char *isexec, *wcpat;
313 unsigned options, jobcnt, LINENO;
314 int hfd, pid, bangpid, srclvl, recursion;
315
316
317 struct sh_function {
318 char *name;
319 struct sh_pipeline {
320 struct sh_pipeline *next, *prev, *end;
321 int count, here, type, lineno;
322 struct sh_arg {
323 char **v;
324 int c;
325 } arg[1];
326 } *pipeline;
327 unsigned long refcount;
328 } **functions;
329 long funcslen;
330
331
332 struct sh_fcall {
333 struct sh_fcall *next, *prev;
334
335
336 struct sh_vars {
337 long flags;
338 char *str;
339 } *vars;
340 long varslen, varscap, shift, oldlineno;
341
342 struct sh_function *func;
343 struct sh_pipeline *pl;
344 char *ifs, *omnom;
345 struct sh_arg arg;
346 struct arg_list *delete;
347
348
349 struct sh_blockstack {
350 struct sh_blockstack *next;
351 struct sh_pipeline *start, *middle;
352 struct sh_process *pp;
353 int run, loop, *urd, pout, pipe;
354 struct sh_arg farg;
355 struct arg_list *fdelete;
356 char *fvar;
357 } *blk;
358 } *ff;
359
360
361 struct sh_process {
362 struct sh_process *next, *prev;
363 struct arg_list *delete;
364
365 int *urd, envlen, pid, exit, flags, job, dash;
366 long long when;
367 struct sh_arg *raw, arg;
368 } *pp;
369
370
371 struct sh_arg jobs, *wcdeck;
372)
373
374
375int do_source(char *name, FILE *ff);
376
377static void free_pipeline(void *pipeline);
378
379static struct sh_vars *setvar(char *str);
380
381
382
383
384static const char *redirectors[] = {"<<<", "<<-", "<<", "<&", "<>", "<", ">>",
385 ">&", ">|", ">", "&>>", "&>", 0};
386
387
388#define OPT_B 0x100
389#define OPT_C 0x200
390#define OPT_x 0x400
391
392
393#define OPT_cd 0x80000000
394
395
396#define PFLAG_NOT 1
397
398static void syntax_err(char *s)
399{
400 struct sh_fcall *ff = TT.ff;
401
402 for (ff = TT.ff; ff != TT.ff->prev; ff = ff->next) if (ff->omnom) break;
403 error_msg("syntax error '%s'@%u: %s", ff->omnom ? : "-c", TT.LINENO, s);
404 toys.exitval = 2;
405 if (!(TT.options&FLAG_i)) xexit();
406}
407
408void debug_show_fds()
409{
410 int x = 0, fd = open("/proc/self/fd", O_RDONLY);
411 DIR *X = fdopendir(fd);
412 struct dirent *DE;
413 char *s, *ss = 0, buf[4096], *sss = buf;
414
415 if (!X) return;
416 for (; (DE = readdir(X));) {
417 if (atoi(DE->d_name) == fd) continue;
418 s = xreadlink(ss = xmprintf("/proc/self/fd/%s", DE->d_name));
419 if (s && *s != '.') sss += sprintf(sss, ", %s=%s"+2*!x++, DE->d_name, s);
420 free(s); free(ss);
421 }
422 *sss = 0;
423 dprintf(2, "%d fd:%s\n", getpid(), buf);
424 closedir(X);
425}
426
427static char **nospace(char **ss)
428{
429 while (isspace(**ss)) ++*ss;
430
431 return ss;
432}
433
434
435static void arg_add(struct sh_arg *arg, char *data)
436{
437
438 if (!(arg->c&31) && (arg->c || !arg->v))
439 arg->v = xrealloc(arg->v, sizeof(char *)*(arg->c+33));
440 arg->v[arg->c++] = data;
441 arg->v[arg->c] = 0;
442}
443
444
445static void *push_arg(struct arg_list **list, void *arg)
446{
447 struct arg_list *al;
448
449 if (list) {
450 al = xmalloc(sizeof(struct arg_list));
451 al->next = *list;
452 al->arg = arg;
453 *list = al;
454 }
455
456 return arg;
457}
458
459static void arg_add_del(struct sh_arg *arg, char *data,struct arg_list **delete)
460{
461 arg_add(arg, push_arg(delete, data));
462}
463
464
465
466#define VAR_NOFREE (1<<10)
467#define VAR_WHITEOUT (1<<9)
468#define VAR_DICT (1<<8)
469#define VAR_ARRAY (1<<7)
470#define VAR_INT (1<<6)
471#define VAR_TOLOWER (1<<5)
472#define VAR_TOUPPER (1<<4)
473#define VAR_NAMEREF (1<<3)
474#define VAR_EXPORT (1<<2)
475#define VAR_READONLY (1<<1)
476#define VAR_MAGIC (1<<0)
477
478
479static char *varend(char *s)
480{
481 if (isdigit(*s)) return s;
482 while (*s>' ' && (*s=='_' || !ispunct(*s))) s++;
483
484 return s;
485}
486
487
488
489
490
491static struct sh_vars *findvar(char *name, struct sh_fcall **pff)
492{
493 int len = varend(name)-name;
494 struct sh_fcall *ff = TT.ff;
495
496
497 if (len) do {
498 struct sh_vars *var = ff->vars+ff->varslen;
499
500 if (var) while (var--!=ff->vars) {
501 if (strncmp(var->str, name, len) || var->str[len]!='=') continue;
502 if (pff) *pff = ff;
503 else if (var->flags&VAR_WHITEOUT) return 0;
504
505 return var;
506 }
507 } while ((ff = ff->next)!=TT.ff);
508
509 return 0;
510}
511
512
513static char *getvar(char *s)
514{
515 struct sh_vars *var = findvar(s, 0);
516
517 if (!var) return 0;
518
519 if (var->flags & VAR_MAGIC) {
520 char c = *var->str;
521
522 if (c == 'S') sprintf(toybuf, "%lld", (millitime()-TT.SECONDS)/1000);
523 else if (c == 'R') sprintf(toybuf, "%ld", random()&((1<<16)-1));
524 else if (c == 'L') sprintf(toybuf, "%u", TT.ff->pl->lineno);
525 else if (c == 'G') sprintf(toybuf, "TODO: GROUPS");
526 else if (c == 'B') sprintf(toybuf, "%d", getpid());
527 else if (c == 'E') {
528 struct timespec ts;
529
530 clock_gettime(CLOCK_REALTIME, &ts);
531 sprintf(toybuf, "%lld%c%06ld", (long long)ts.tv_sec, (s[5]=='R')*'.',
532 ts.tv_nsec/1000);
533 }
534
535 return toybuf;
536 }
537
538 return varend(var->str)+1;
539}
540
541
542static struct sh_vars *addvar(char *s, struct sh_fcall *ff)
543{
544 if (ff->varslen == ff->varscap && !(ff->varslen&31)) {
545 ff->varscap += 32;
546 ff->vars = xrealloc(ff->vars, (ff->varscap)*sizeof(*ff->vars));
547 }
548 if (!s) return ff->vars;
549 ff->vars[ff->varslen].flags = 0;
550 ff->vars[ff->varslen].str = s;
551
552 return ff->vars+ff->varslen++;
553}
554
555
556
557
558static int recalculate(long long *dd, char **ss, int lvl)
559{
560 long long ee, ff;
561 char *var = 0, *val, cc = **nospace(ss);
562 int ii, assign = 1;
563
564 if (lvl>99) {
565 lvl -= 100;
566 assign = 0;
567 }
568
569
570 if (cc=='!' || cc=='~') {
571 ++*ss;
572 if (!recalculate(dd, ss, 15)) return 0;
573 *dd = (cc=='!') ? !*dd : ~*dd;
574 } else if (cc=='+' || cc=='-') {
575
576 if (*++*ss==cc) {
577 val = (*ss)++;
578 nospace(ss);
579 if (*ss==(var = varend(*ss))) {
580 *ss = val;
581 var = 0;
582 }
583 }
584 if (!var) {
585 if (!recalculate(dd, ss, 15)) return 0;
586 if (cc=='-') *dd = -*dd;
587 }
588 } else if (cc=='(') {
589 ++*ss;
590 if (!recalculate(dd, ss, 1)) return 0;
591 if (**ss!=')') return 0;
592 else ++*ss;
593 } else if (isdigit(cc)) {
594 *dd = strtoll(*ss, ss, 0);
595 if (**ss=='#') {
596 if (!*++*ss || isspace(**ss) || ispunct(**ss)) return 0;
597 *dd = strtoll(val = *ss, ss, *dd);
598 if (val == *ss) return 0;
599 }
600 } else if ((var = varend(*ss))==*ss) {
601
602 if (lvl || (cc && cc!=')')) return 0;
603 *dd = 0;
604 return 1;
605 }
606
607
608 if (var) {
609
610 if (TT.recursion++ == 50+200*CFG_TOYBOX_FORK) {
611 perror_msg("recursive occlusion");
612 --TT.recursion;
613
614 return 0;
615 }
616 val = getvar(var = *ss) ? : "";
617 ii = recalculate(dd, &val, 0);
618 TT.recursion--;
619 if (!ii) return 0;
620 if (*val) {
621 perror_msg("bad math: %s @ %d", var, (int)(val-var));
622
623 return 0;
624 }
625 val = *ss = varend(var);
626
627
628
629
630 if (cc=='+' || cc=='-') {
631 if (cc=='+') ee = ++*dd;
632 else ee = --*dd;
633 } else cc = 0;
634
635
636 if ((**nospace(ss)=='+' || **ss=='-') && (*ss)[1]==**ss) {
637 ee = ((cc = **ss)=='+') ? 1+*dd : -1+*dd;
638 *ss += 2;
639
640
641 } else if (lvl<=2 && (*ss)[ii = !!strchr("*/%+-", **ss)
642 +2*!memcmp(*ss, "<<", 2)+2*!memcmp(*ss, ">>", 2)]=='=')
643 {
644
645
646 cc = **ss;
647 *ss += ii+1;
648 if (!recalculate(&ee, ss, 1)) return 0;
649 if (cc=='*') *dd *= ee;
650 else if (cc=='/') *dd /= ee;
651 else if (cc=='%') *dd %= ee;
652 else if (cc=='+') *dd += ee;
653 else if (cc=='-') *dd -= ee;
654 else if (cc=='<') *dd <<= ee;
655 else if (cc=='>') *dd >>= ee;
656 else if (cc=='&') *dd &= ee;
657 else if (cc=='^') *dd ^= ee;
658 else if (cc=='|') *dd |= ee;
659 else *dd = ee;
660 ee = *dd;
661 }
662 if (cc && assign) setvar(xmprintf("%.*s=%lld", (int)(val-var), var, ee));
663 }
664
665
666 if (lvl<=13) while (strstart(nospace(ss), "**")) {
667 if (!recalculate(&ee, ss, 14)) return 0;
668 if (ee<0) perror_msg("** < 0");
669 for (ff = *dd, *dd = 1; ee; ee--) *dd *= ff;
670 }
671
672
673 if (lvl<=12) while ((cc = **nospace(ss)) && strchr("*/%", cc)) {
674 ++*ss;
675 if (!recalculate(&ee, ss, 13)) return 0;
676 if (cc=='*') *dd *= ee;
677 else if (cc=='%') *dd %= ee;
678 else if (!ee) {
679 perror_msg("/0");
680 return 0;
681 } else *dd /= ee;
682 }
683
684
685 if (lvl<=11) while ((cc = **nospace(ss)) && strchr("+-", cc)) {
686 ++*ss;
687 if (!recalculate(&ee, ss, 12)) return 0;
688 if (cc=='+') *dd += ee;
689 else *dd -= ee;
690 }
691
692
693
694 if (lvl<=10) while ((cc = **nospace(ss)) && strchr("<>", cc) && cc==(*ss)[1]){
695 *ss += 2;
696 if (!recalculate(&ee, ss, 11)) return 0;
697 if (cc == '<') *dd <<= ee;
698 else *dd >>= ee;
699 }
700
701
702 if (lvl<=9) while ((cc = **nospace(ss)) && strchr("<>", cc)) {
703 if ((ii = *++*ss=='=')) ++*ss;
704 if (!recalculate(&ee, ss, 10)) return 0;
705 if (cc=='<') *dd = ii ? (*dd<=ee) : (*dd<ee);
706 else *dd = ii ? (*dd>=ee) : (*dd>ee);
707 }
708
709 if (lvl<=8) while ((cc = **nospace(ss)) && strchr("=!", cc) && (*ss)[1]=='='){
710 *ss += 2;
711 if (!recalculate(&ee, ss, 9)) return 0;
712 *dd = (cc=='!') ? *dd != ee : *dd == ee;
713 }
714
715 if (lvl<=7) while (**nospace(ss)=='&') {
716 ++*ss;
717 if (!recalculate(&ee, ss, 8)) return 0;
718 *dd &= ee;
719 }
720
721 if (lvl<=6) while (**nospace(ss)=='^') {
722 ++*ss;
723 if (!recalculate(&ee, ss, 7)) return 0;
724 *dd ^= ee;
725 }
726
727 if (lvl<=5) while (**nospace(ss)=='|') {
728 ++*ss;
729 if (!recalculate(&ee, ss, 6)) return 0;
730 *dd |= ee;
731 }
732
733 if (lvl<=5) while (strstart(nospace(ss), "&&")) {
734 if (!recalculate(&ee, ss, 6+100*!!*dd)) return 0;
735 *dd = *dd && ee;
736 }
737
738 if (lvl<=4) while (strstart(nospace(ss), "||")) {
739 if (!recalculate(&ee, ss, 5+100*!*dd)) return 0;
740 *dd = *dd || ee;
741 }
742
743
744
745 if (lvl<=3) if (**nospace(ss)=='?') {
746 ++*ss;
747 if (**nospace(ss)==':' && *dd) ee = *dd;
748 else if (!recalculate(&ee, ss, 1+100*!*dd) || **nospace(ss)!=':')
749 return 0;
750 ++*ss;
751 if (!recalculate(&ff, ss, 1+100*!!*dd)) return 0;
752 *dd = *dd ? ee : ff;
753 }
754
755
756
757
758 if (lvl<=1) while ((cc = **nospace(ss)) && cc==',') {
759 ++*ss;
760 if (!recalculate(dd, ss, 2)) return 0;
761 }
762
763 return 1;
764}
765
766
767static int getutf8(char *s, int len, int *cc)
768{
769 unsigned wc;
770
771 if (len<0) wc = len = 0;
772 else if (1>(len = utf8towc(&wc, s, len))) wc = *s, len = 1;
773 if (cc) *cc = wc;
774
775 return len;
776}
777
778
779
780static int utf8chr(char *wc, char *chrs, int *len)
781{
782 unsigned wc1, wc2;
783 int ll;
784
785 if (len) *len = 1;
786 if (!*wc) return 0;
787 if (0<(ll = utf8towc(&wc1, wc, 99))) {
788 if (len) *len = ll;
789 while (*chrs) {
790 if(1>(ll = utf8towc(&wc2, chrs, 99))) chrs++;
791 else {
792 if (wc1 == wc2) return wc1;
793 chrs += ll;
794 }
795 }
796 }
797
798 return 0;
799}
800
801
802static int anystart(char *s, char **try)
803{
804 char *ss = s;
805
806 while (*try) if (strstart(&s, *try++)) return s-ss;
807
808 return 0;
809}
810
811
812static int anystr(char *s, char **try)
813{
814 while (*try) if (!strcmp(s, *try++)) return 1;
815
816 return 0;
817}
818
819
820static void cache_ifs(char *s, struct sh_fcall *ff)
821{
822 if (!strncmp(s, "IFS=", 4))
823 do ff->ifs = s+4; while ((ff = ff->next) != TT.ff->prev);
824}
825
826
827
828
829
830
831static struct sh_vars *setvar_found(char *s, int freeable, struct sh_vars *var)
832{
833 char *ss, *sss, *sd, buf[24];
834 long ii, jj, kk, flags = var->flags&~VAR_WHITEOUT;
835 long long ll;
836 int cc, vlen = varend(s)-s;
837
838 if (flags&VAR_READONLY) {
839 error_msg("%.*s: read only", vlen, s);
840 goto bad;
841 }
842
843
844 if (s[vlen]=='+' && (var->str==s || !strchr(var->str, '=')[1])) {
845 ss = xmprintf("%.*s%s", vlen, s, s+vlen+1);
846 if (var->str==s) {
847 if (!freeable++) var->flags |= VAR_NOFREE;
848 } else if (freeable++) free(s);
849 s = ss;
850 }
851
852
853 if (strncmp(var->str, s, vlen)) {
854 ss = s+vlen+(s[vlen]=='+')+1;
855 ss = xmprintf("%.*s%s", (vlen = varend(var->str)-var->str)+1, var->str, ss);
856 if (freeable++) free(s);
857 s = ss;
858 }
859
860
861
862
863 if (flags&(VAR_TOUPPER|VAR_TOLOWER)) {
864 for (jj = kk = 0, sss = 0; jj<2; jj++, sss = sd = xmalloc(vlen+kk+2)) {
865 sd = jj ? stpncpy(sss, s, vlen+1) : (void *)&sss;
866 for (ss = s+vlen+1; (ii = getutf8(ss, 4, &cc)); ss += ii) {
867 kk += wctoutf8(sd, (flags&VAR_TOUPPER) ? towupper(cc) : towlower(cc));
868 if (jj) {
869 sd += kk;
870 kk = 0;
871 }
872 }
873 }
874 *sd = 0;
875 if (freeable++) free(s);
876 s = sss;
877 }
878
879
880 ss = s+vlen+(s[vlen]=='+')+1;
881 if (flags&VAR_INT) {
882 sd = ss;
883 if (!recalculate(&ll, &sd, 0) || *sd) {
884 perror_msg("bad math: %s @ %d", ss, (int)(sd-ss));
885
886 goto bad;
887 }
888
889 sprintf(buf, "%lld", ll);
890 if (flags&VAR_MAGIC) {
891 if (*s == 'S') {
892 ll *= 1000;
893 TT.SECONDS = (s[vlen]=='+') ? TT.SECONDS+ll : millitime()-ll;
894 } else if (*s == 'R') srandom(ll);
895 if (freeable) free(s);
896
897
898 return var;
899 } else if (s[vlen]=='+' || strcmp(buf, ss)) {
900 if (s[vlen]=='+') ll += atoll(strchr(var->str, '=')+1);
901 ss = xmprintf("%.*s=%lld", vlen, s, ll);
902 if (freeable++) free(s);
903 s = ss;
904 }
905 } else if (s[vlen]=='+' && !(flags&VAR_MAGIC)) {
906 ss = xmprintf("%s%s", var->str, ss);
907 if (freeable++) free(s);
908 s = ss;
909 }
910
911
912 if (flags&VAR_NOFREE) flags ^= VAR_NOFREE;
913 else free(var->str);
914 if (!freeable) flags |= VAR_NOFREE;
915 var->str = s;
916 var->flags = flags;
917
918 return var;
919bad:
920 if (freeable) free(s);
921
922 return 0;
923}
924
925
926
927static struct sh_vars *setvar_long(char *s, int freeable, struct sh_fcall *ff)
928{
929 struct sh_vars *vv = 0, *was;
930 char *ss;
931
932 if (!s) return 0;
933 ss = varend(s);
934 if (ss[*ss=='+']!='=') {
935 error_msg("bad setvar %s\n", s);
936 if (freeable) free(s);
937
938 return 0;
939 }
940
941
942 if (!(was = vv = findvar(s, &ff))) (vv = addvar(s, ff))->flags = VAR_NOFREE;
943 if (!setvar_found(s, freeable, vv)) {
944 if (!was) memmove(vv, vv+1, sizeof(ff->vars)*(--ff->varslen-(vv-ff->vars)));
945
946 return 0;
947 }
948 cache_ifs(vv->str, ff);
949
950 return vv;
951}
952
953
954
955static struct sh_vars *setvar(char *str)
956{
957 return setvar_long(str, 0, TT.ff->prev);
958}
959
960
961
962static int unsetvar(char *name)
963{
964 struct sh_fcall *ff;
965 struct sh_vars *var = findvar(name, &ff);
966 int len = varend(name)-name;
967
968 if (!var || (var->flags&VAR_WHITEOUT)) return 0;
969 if (var->flags&VAR_READONLY) error_msg("readonly %.*s", len, name);
970 else {
971
972 if (ff != TT.ff->prev) {
973 var->flags = VAR_WHITEOUT;
974 if (!(var->flags&VAR_NOFREE))
975 (var->str = xrealloc(var->str, len+2))[len+1] = 0;
976
977 } else {
978 if (!(var->flags&VAR_NOFREE)) free(var->str);
979 memmove(var, var+1, sizeof(ff->vars)*(ff->varslen-(var-ff->vars)));
980 }
981 if (!strcmp(name, "IFS"))
982 do ff->ifs = " \t\n"; while ((ff = ff->next) != TT.ff->prev);
983 }
984
985 return 1;
986}
987
988static struct sh_vars *setvarval(char *name, char *val)
989{
990 return setvar(xmprintf("%s=%s", name, val));
991}
992
993
994
995
996static struct sh_vars **visible_vars(void)
997{
998 struct sh_arg arg;
999 struct sh_fcall *ff;
1000 struct sh_vars *vv;
1001 unsigned ii, jj, len;
1002
1003 arg.c = 0;
1004 arg.v = 0;
1005
1006
1007 for (ff = TT.ff; ; ff = ff->next) {
1008 if (ff->vars) for (ii = ff->varslen; ii--;) {
1009 vv = ff->vars+ii;
1010 len = 1+(varend(vv->str)-vv->str);
1011 for (jj = 0; ;jj++) {
1012 if (jj == arg.c) arg_add(&arg, (void *)vv);
1013 else if (strncmp(arg.v[jj], vv->str, len)) continue;
1014
1015 break;
1016 }
1017 }
1018 if (ff->next == TT.ff) break;
1019 }
1020
1021 return (void *)arg.v;
1022}
1023
1024
1025static char *declarep(struct sh_vars *var)
1026{
1027 char *types = "rxnuliaA", *esc = "$\"\\`", *in, flags[16], *out = flags, *ss;
1028 int len;
1029
1030 for (len = 0; types[len]; len++) if (var->flags&(2<<len)) *out++ = types[len];
1031 if (out==flags) *out++ = '-';
1032 *out = 0;
1033 len = out-flags;
1034
1035 for (in = var->str; *in; in++) len += !!strchr(esc, *in);
1036 len += in-var->str;
1037 ss = xmalloc(len+15);
1038
1039 len = varend(var->str)-var->str;
1040 out = ss + sprintf(ss, "declare -%s %.*s", flags, len, var->str);
1041 if (var->flags != VAR_MAGIC) {
1042 out = stpcpy(out, "=\"");
1043 for (in = var->str+len+1; *in; *out++ = *in++)
1044 if (strchr(esc, *in)) *out++ = '\\';
1045 *out++ = '"';
1046 }
1047 *out = 0;
1048
1049 return ss;
1050}
1051
1052
1053static char *skip_redir_prefix(char *word)
1054{
1055 char *s = word;
1056
1057 if (*s == '{') {
1058 if (*(s = varend(s+1)) == '}' && s != word+1) s++;
1059 else s = word;
1060 } else while (isdigit(*s)) s++;
1061
1062 return s;
1063}
1064
1065
1066
1067
1068static char *parse_word(char *start, int early, int quote)
1069{
1070 int ii, qq, qc = 0;
1071 char *end = start, *ss;
1072
1073
1074 ss = skip_redir_prefix(end);
1075 if (strstart(&ss, "<(") || strstart(&ss, ">(")) {
1076 toybuf[quote++]=')';
1077 end = ss;
1078 } else if ((ii = anystart(ss, (void *)redirectors))) return ss+ii;
1079 if (strstart(&end, "((")) toybuf[quote++] = 254;
1080
1081
1082 while (*end) {
1083
1084 if (early && end!=start && !quote) break;
1085
1086
1087 if (quote>4000) {
1088 syntax_err("bad quote depth");
1089 return (void *)1;
1090 }
1091
1092
1093 if ((qq = quote ? toybuf[quote-1] : 0)) {
1094 ii = *end++;
1095 if ((qq==')' || qq>=254) && (ii=='(' || ii==')')) {
1096 if (ii=='(') qc++;
1097 else if (qc) qc--;
1098 else if (qq>=254) {
1099
1100 if (ii==')' && *end==')') quote--, end++;
1101 else if (qq==254) return start+1;
1102 else if (qq==255) toybuf[quote-1] = ')';
1103 } else if (ii==')') quote--;
1104 } else if (ii==qq) quote--;
1105 else if (qq!='\'') end--, ii = 0;
1106 if (ii) continue;
1107
1108
1109 } else {
1110 if (isspace(*end)) break;
1111 ss = end + anystart(end, (char *[]){";;&", ";;", ";&", ";", "||",
1112 "|&", "|", "&&", "&", "(", ")", 0});
1113 if (ss!=end) return (end==start) ? ss : end;
1114 }
1115
1116
1117 if (strchr("'\"`"+(qq=='"'), ii = *end++)) toybuf[quote++] = ii;
1118
1119
1120 else {
1121 if (ii=='\\') {
1122 if (!*end || (*end=='\n' && !end[1])) return early ? end : 0;
1123 } else if (ii=='$' && -1!=(qq = stridx("({[", *end))) {
1124 if (strstart(&end, "((")) {
1125 end--;
1126 toybuf[quote++] = 255;
1127 } else toybuf[quote++] = ")}]"[qq];
1128 } else if (*end=='(' && strchr("?*+@!", ii)) toybuf[quote++] = ')';
1129 else {
1130 end--;
1131 if (early && !quote) return end;
1132 }
1133 end++;
1134 }
1135 }
1136
1137 return (quote && !early) ? 0 : end;
1138}
1139
1140
1141static int next_hfd()
1142{
1143 int hfd;
1144
1145 for (; TT.hfd<=99999; TT.hfd++) if (-1 == fcntl(TT.hfd, F_GETFL)) break;
1146 hfd = TT.hfd;
1147 if (TT.hfd>99999) {
1148 hfd = -1;
1149 if (!errno) errno = EMFILE;
1150 }
1151
1152 return hfd;
1153}
1154
1155
1156
1157
1158
1159static int save_redirect(int **rd, int from, int to)
1160{
1161 int cnt, hfd, *rr;
1162
1163
1164 if (from == to) return 0;
1165
1166
1167 if (from>-2) {
1168 if ((hfd = next_hfd())==-1) return 1;
1169 if (hfd != dup2(to, hfd)) hfd = -1;
1170 else fcntl(hfd, F_SETFD, FD_CLOEXEC);
1171
1172
1173 if (from >= 0 && to != dup2(from, to)) {
1174 if (hfd >= 0) close(hfd);
1175
1176 return 1;
1177 }
1178 } else {
1179 hfd = to;
1180 to = -1;
1181 }
1182
1183
1184 if (!((cnt = *rd ? **rd : 0)&31)) *rd = xrealloc(*rd, (cnt+33)*2*sizeof(int));
1185 *(rr = *rd) = ++cnt;
1186 rr[2*cnt-1] = hfd;
1187 rr[2*cnt] = to;
1188
1189 return 0;
1190}
1191
1192
1193static void unredirect(int *urd)
1194{
1195 int *rr = urd+1, i;
1196
1197 if (!urd) return;
1198
1199 for (i = 0; i<*urd; i++, rr += 2) if (rr[0] != -1) {
1200
1201 dup2(rr[0], rr[1]);
1202 close(rr[0]);
1203 }
1204 free(urd);
1205}
1206
1207
1208static void subshell_callback(char **argv)
1209{
1210
1211 environ[1] = xmprintf("@%d,%d", getpid(), getppid());
1212 environ[2] = xmprintf("$=%d", TT.pid);
1213
1214}
1215
1216
1217
1218static char *pl2str(struct sh_pipeline *pl, int one)
1219{
1220 struct sh_pipeline *end = 0, *pp;
1221 int len QUIET, i;
1222 char *ss;
1223
1224
1225 if (one) end = pl->next;
1226 else for (end = pl, len = 0; end; end = end->next)
1227 if (end->type == 1) len++;
1228 else if (end->type == 3 && --len<0) break;
1229
1230
1231 for (ss = 0;; ss = xmalloc(len+1)) {
1232 for (pp = pl; pp != end; pp = pp->next) {
1233 if (pp->type == 'F') continue;
1234 for (i = len = 0; i<=pp->arg->c; i++)
1235 len += snprintf(ss+len, ss ? INT_MAX : 0, " %s"+!i,
1236 pp->arg->v[i] ? : ";"+(pp->next==end));
1237 }
1238 if (ss) return ss;
1239 }
1240
1241
1242
1243
1244}
1245
1246static struct sh_blockstack *clear_block(struct sh_blockstack *blk)
1247{
1248 memset(blk, 0, sizeof(*blk));
1249 blk->start = TT.ff->pl;
1250 blk->run = 1;
1251 blk->pout = -1;
1252
1253 return blk;
1254}
1255
1256
1257static struct sh_pipeline *pop_block(void)
1258{
1259 struct sh_pipeline *pl = 0;
1260 struct sh_blockstack *blk = TT.ff->blk;
1261
1262
1263 if (blk->pout != -1) close(blk->pout);
1264 unredirect(blk->urd);
1265 llist_traverse(blk->fdelete, llist_free_arg);
1266 free(blk->farg.v);
1267 if (TT.ff->blk->next) {
1268 pl = blk->start->end;
1269 free(llist_pop(&TT.ff->blk));
1270 } else clear_block(blk);
1271
1272 return pl;
1273}
1274
1275
1276static void add_block(void)
1277{
1278 struct sh_blockstack *blk = clear_block(xmalloc(sizeof(*blk)));
1279
1280 blk->next = TT.ff->blk;
1281 TT.ff->blk = blk;
1282}
1283
1284
1285static void call_function(void)
1286{
1287
1288 dlist_add_nomalloc((void *)&TT.ff, xzalloc(sizeof(struct sh_fcall)));
1289 TT.ff = TT.ff->prev;
1290 add_block();
1291
1292
1293
1294 TT.ff->arg.v = TT.ff->next->arg.v;
1295 TT.ff->arg.c = TT.ff->next->arg.c;
1296 TT.ff->ifs = TT.ff->next->ifs;
1297}
1298
1299static void free_function(struct sh_function *funky)
1300{
1301 if (--funky->refcount) return;
1302
1303 free(funky->name);
1304 llist_traverse(funky->pipeline, free_pipeline);
1305 free(funky);
1306}
1307
1308
1309
1310static int end_function(int funconly)
1311{
1312 struct sh_fcall *ff = TT.ff;
1313 int func = ff->next!=ff && ff->vars;
1314
1315 if (!func && funconly) return 0;
1316 llist_traverse(ff->delete, llist_free_arg);
1317 ff->delete = 0;
1318 while (TT.ff->blk->next) pop_block();
1319 pop_block();
1320
1321
1322 if (!func) return 0;
1323 while (ff->varslen)
1324 if (!(ff->vars[--ff->varslen].flags&VAR_NOFREE))
1325 free(ff->vars[ff->varslen].str);
1326 free(ff->vars);
1327 free(TT.ff->blk);
1328 if (ff->func) free_function(ff->func);
1329 free(dlist_pop(&TT.ff));
1330
1331 return 1;
1332}
1333
1334
1335
1336
1337
1338
1339
1340static int run_subshell(char *str, int len)
1341{
1342 pid_t pid;
1343
1344
1345 if (CFG_TOYBOX_FORK) {
1346 if ((pid = fork())<0) perror_msg("fork");
1347 else if (!pid) {
1348 call_function();
1349 if (str) {
1350 do_source(0, fmemopen(str, len, "r"));
1351 _exit(toys.exitval);
1352 }
1353 }
1354
1355
1356 } else {
1357 int pipes[2];
1358 unsigned i;
1359 char **oldenv = environ, *ss = str ? : pl2str(TT.ff->pl->next, 0);
1360 struct sh_vars **vv;
1361
1362
1363 if (pipe(pipes) || 254 != dup2(pipes[0], 254)) return 1;
1364 close(pipes[0]);
1365 fcntl(pipes[1], F_SETFD, FD_CLOEXEC);
1366
1367
1368 environ = xzalloc(4*sizeof(char *));
1369 *environ = getvar("PATH") ? : "PATH=";
1370 pid = xpopen_setup(0, 0, subshell_callback);
1371
1372
1373 free(environ[1]);
1374 free(environ[2]);
1375 free(environ);
1376 environ = oldenv;
1377
1378
1379 close(254);
1380 dprintf(pipes[1], "%lld %u %u %u %u\n", TT.SECONDS,
1381 TT.options, TT.LINENO, TT.pid, TT.bangpid);
1382
1383 for (i = 0, vv = visible_vars(); vv[i]; i++)
1384 dprintf(pipes[1], "%u %lu\n%.*s", (unsigned)strlen(vv[i]->str),
1385 vv[i]->flags, (int)strlen(vv[i]->str), vv[i]->str);
1386 free(vv);
1387
1388
1389 dprintf(pipes[1], "0 0\n%.*s\n", len, ss);
1390 if (!str) free(ss);
1391 close(pipes[1]);
1392 }
1393
1394 return pid;
1395}
1396
1397
1398static int pipe_subshell(char *s, int len, int out)
1399{
1400 int pipes[2], *uu = 0, in = !out;
1401
1402
1403 if (pipe(pipes)) {
1404 perror_msg("%.*s", len, s);
1405
1406 return -1;
1407 }
1408
1409
1410 save_redirect(&uu, pipes[in], in);
1411 close(pipes[in]);
1412 fcntl(pipes[!in], F_SETFD, FD_CLOEXEC);
1413 run_subshell(s, len);
1414 fcntl(pipes[!in], F_SETFD, 0);
1415 unredirect(uu);
1416
1417 return pipes[out];
1418}
1419
1420
1421
1422char *getvar_special(char *str, int len, int *used, struct arg_list **delete)
1423{
1424 char *s = 0, *ss, cc = *str;
1425 unsigned uu;
1426
1427 *used = 1;
1428 if (cc == '-') {
1429 s = ss = xmalloc(8);
1430 if (TT.options&FLAG_i) *ss++ = 'i';
1431 if (TT.options&OPT_B) *ss++ = 'B';
1432 if (TT.options&FLAG_s) *ss++ = 's';
1433 if (TT.options&FLAG_c) *ss++ = 'c';
1434 *ss = 0;
1435 } else if (cc == '?') s = xmprintf("%d", toys.exitval);
1436 else if (cc == '$') s = xmprintf("%d", TT.pid);
1437 else if (cc == '#') s = xmprintf("%d", TT.ff->arg.c ? TT.ff->arg.c-1 : 0);
1438 else if (cc == '!') s = xmprintf("%d"+2*!TT.bangpid, TT.bangpid);
1439 else {
1440 delete = 0;
1441 for (*used = uu = 0; *used<len && isdigit(str[*used]); ++*used)
1442 uu = (10*uu)+str[*used]-'0';
1443 if (*used) {
1444 if (uu) uu += TT.ff->shift;
1445 if (uu<TT.ff->arg.c) s = TT.ff->arg.v[uu];
1446 } else if ((*used = varend(str)-str)) return getvar(str);
1447 }
1448 if (s) push_arg(delete, s);
1449
1450 return s;
1451}
1452
1453#define WILD_SHORT 1
1454#define WILD_CASE 2
1455#define WILD_ANY 4
1456
1457static int wildcard_matchlen(char *str, int len, char *pattern, int plen,
1458 struct sh_arg *deck, int flags)
1459{
1460 struct sh_arg ant = {0};
1461 long ss, pp, dd, best = -1;
1462 int i, j, c, not;
1463
1464
1465 for (ss = pp = dd = 0; ;) {
1466 if ((flags&WILD_ANY) && best!=-1) break;
1467
1468
1469 if (pp==plen) {
1470 if (ss>best) best = ss;
1471 if (ss==len || (flags&WILD_SHORT)) break;
1472
1473 } else if (dd>=deck->c || pp!=(long)deck->v[dd]) {
1474 if (ss<len) {
1475 if (flags&WILD_CASE) {
1476 ss += getutf8(str+ss, len-ss, &c);
1477 c = towupper(c);
1478 pp += getutf8(pattern+pp, pp-plen, &i);
1479 i = towupper(i);
1480 } else c = str[ss++], i = pattern[pp++];
1481 if (c==i) continue;
1482 }
1483
1484
1485 } else {
1486 c = pattern[pp++];
1487 dd++;
1488 if (c=='?' || ((flags&WILD_ANY) && c=='*')) {
1489 ss += (i = getutf8(str+ss, len-ss, 0));
1490 if (i) continue;
1491 } else if (c=='*') {
1492
1493
1494 if (dd==1 || pp-2!=(long)deck->v[dd-1] || pattern[pp-2]!='*') {
1495 arg_add(&ant, (void *)ss);
1496 arg_add(&ant, 0);
1497 }
1498
1499 continue;
1500 } else if (c == '[') {
1501 pp += (not = !!strchr("!^", pattern[pp]));
1502 ss += getutf8(str+ss, len-ss, &c);
1503 for (i = 0; pp<(long)deck->v[dd]; i = 0) {
1504 pp += getutf8(pattern+pp, plen-pp, &i);
1505 if (pattern[pp]=='-') {
1506 ++pp;
1507 pp += getutf8(pattern+pp, plen-pp, &j);
1508 if (not^(i<=c && j>=c)) break;
1509 } else if (not^(i==c)) break;
1510 }
1511 if (i) {
1512 pp = 1+(long)deck->v[dd++];
1513
1514 continue;
1515 }
1516
1517
1518
1519 } else {
1520 dd++;
1521 continue;
1522 }
1523 }
1524
1525
1526 if (flags&WILD_ANY) {
1527 ss = 0;
1528 if (plen==pp) break;
1529 continue;
1530 }
1531
1532
1533 while (ant.c) {
1534 if ((c = pattern[(long)deck->v[--dd]])=='*') {
1535 if (len<(ss = (long)ant.v[ant.c-2]+(long)++ant.v[ant.c-1])) ant.c -= 2;
1536 else {
1537 pp = (long)deck->v[dd++]+1;
1538 break;
1539 }
1540 } else if (c == '(') dprintf(2, "TODO: (");
1541 }
1542
1543 if (!ant.c) break;
1544 }
1545 free (ant.v);
1546
1547 return best;
1548}
1549
1550static int wildcard_match(char *s, char *p, struct sh_arg *deck, int flags)
1551{
1552 return wildcard_matchlen(s, strlen(s), p, strlen(p), deck, flags);
1553}
1554
1555
1556
1557
1558
1559
1560char *wildcard_path(char *pattern, int off, struct sh_arg *deck, int *idx,
1561 int count)
1562{
1563 char *p, *old;
1564 int i = 0, j = 0;
1565
1566
1567 for (p = old = pattern+off;; p++) {
1568 if (!*p) return p;
1569 while (*p=='/') {
1570 old = p++;
1571 if (j && !count) return old;
1572 j = 0;
1573 }
1574
1575
1576 if (*idx<deck->c && p-pattern == (long)deck->v[*idx]) {
1577 if (!j++ && !count--) return old;
1578 ++*idx;
1579 if (*p=='[') p = pattern+(long)deck->v[(*idx)++];
1580 else if (*p=='(') while (*++p) if (p-pattern == (long)deck->v[*idx]) {
1581 ++*idx;
1582 if (*p == ')') {
1583 if (!i) break;
1584 i--;
1585 } else if (*p == '(') i++;
1586 }
1587 }
1588 }
1589}
1590
1591
1592
1593
1594
1595
1596int do_wildcard_files(struct dirtree *node)
1597{
1598 struct dirtree *nn;
1599 char *pattern, *patend;
1600 int lvl, ll = 0, ii = 0, rc;
1601 struct sh_arg ant;
1602
1603
1604 if (!node->parent) return DIRTREE_RECURSE;
1605
1606
1607 for (nn = node->parent; nn; nn = nn->parent) if (nn->parent) ii++;
1608 pattern = wildcard_path(TT.wcpat, 0, TT.wcdeck, &ll, ii);
1609 while (*pattern=='/') pattern++;
1610 lvl = ll;
1611 patend = wildcard_path(TT.wcpat, pattern-TT.wcpat, TT.wcdeck, &ll, 1);
1612
1613
1614 if (*node->name=='.' && *pattern!='.') return 0;
1615
1616
1617 if (*patend && !S_ISDIR(node->st.st_mode) && *node->name) return 0;
1618
1619
1620 ant.c = ll-lvl;
1621 ant.v = TT.wcdeck->v+lvl;
1622 for (ii = 0; ii<ant.c; ii++) TT.wcdeck->v[lvl+ii] -= pattern-TT.wcpat;
1623 rc = wildcard_matchlen(node->name, strlen(node->name), pattern,
1624 patend-pattern, &ant, 0);
1625 for (ii = 0; ii<ant.c; ii++) TT.wcdeck->v[lvl+ii] += pattern-TT.wcpat;
1626
1627
1628 if (rc<0 || node->name[rc]) return 0;
1629 if (!*patend) return DIRTREE_SAVE;
1630
1631
1632 if (TT.wcdeck->c!=ll) return DIRTREE_RECURSE;
1633
1634
1635 pattern = xmprintf("%s%s", node->name, patend);
1636 rc = faccessat(dirtree_parentfd(node), pattern, F_OK, AT_SYMLINK_NOFOLLOW);
1637 free(pattern);
1638 if (rc) return 0;
1639
1640
1641 while (*patend=='/' && patend[1]) patend++;
1642 node->child = xzalloc(sizeof(struct dirtree)+1+strlen(patend));
1643 node->child->parent = node;
1644 strcpy(node->child->name, patend);
1645
1646 return DIRTREE_SAVE;
1647}
1648
1649
1650
1651static void collect_wildcards(char *new, long oo, struct sh_arg *deck)
1652{
1653 long bracket, *vv;
1654 char cc = new[oo];
1655
1656
1657
1658 if (!deck->c) arg_add(deck, 0);
1659 vv = (long *)deck->v;
1660
1661
1662
1663
1664 if (!cc) {
1665 long ii = 0, jj = 65535&*vv, kk;
1666
1667 for (kk = deck->c; jj;) {
1668 if (')' == (cc = new[vv[--kk]])) ii++;
1669 else if ('(' == cc) {
1670 if (ii) ii--;
1671 else {
1672 memmove(vv+kk, vv+kk+1, sizeof(long)*(deck->c-- -kk));
1673 jj--;
1674 }
1675 }
1676 }
1677 if (deck->c) memmove(vv, vv+1, sizeof(long)*deck->c--);
1678
1679 return;
1680 }
1681
1682
1683 if (deck->c>1 && vv[deck->c-1] == oo-1 && strchr("+@!*?", new[oo-1])) {
1684 if (cc == '(') {
1685 vv[deck->c-1] = oo;
1686 return;
1687 } else if (!strchr("*?", new[oo-1])) deck->c--;
1688 }
1689
1690
1691 if (strchr("|+@!*?", cc));
1692 else if (cc == ')' && (65535&*vv)) --*vv;
1693
1694
1695 else if (cc == ']' && (bracket = *vv>>16)) {
1696
1697
1698 if (bracket+1 == oo || (bracket+2 == oo && strchr("!^", new[oo-1]))) return;
1699 while (deck->c>1 && vv[deck->c-1]>=bracket) deck->c--;
1700 *vv &= 65535;
1701 arg_add(deck, (void *)bracket);
1702
1703
1704 } else {
1705
1706 if (cc == '[' && !(*vv>>16)) *vv = (oo<<16)+(65535&*vv);
1707 return;
1708 }
1709
1710
1711 arg_add(deck, (void *)oo);
1712}
1713
1714
1715
1716static void wildcard_add_files(struct sh_arg *arg, char *pattern,
1717 struct sh_arg *deck, struct arg_list **delete)
1718{
1719 struct dirtree *dt;
1720 char *pp;
1721 int ll = 0;
1722
1723
1724 collect_wildcards("", 0, deck);
1725 if (!deck->c) return arg_add(arg, pattern);
1726
1727
1728 pp = wildcard_path(TT.wcpat = pattern, 0, TT.wcdeck = deck, &ll, 0);
1729 pp = (pp==pattern) ? 0 : xstrndup(pattern, pp-pattern);
1730 dt = dirtree_flagread(pp, DIRTREE_STATLESS|DIRTREE_SYMFOLLOW,
1731 do_wildcard_files);
1732 free(pp);
1733 deck->c = 0;
1734
1735
1736 if (!dt) return arg_add(arg, pattern);
1737 while (dt) {
1738 while (dt->child) dt = dt->child;
1739 arg_add(arg, push_arg(delete, dirtree_path(dt, 0)));
1740 do {
1741 pp = (void *)dt;
1742 if ((dt = dt->parent)) dt->child = dt->child->next;
1743 free(pp);
1744 } while (dt && !dt->child);
1745 }
1746
1747}
1748
1749
1750
1751char *slashcopy(char *s, char *c, struct sh_arg *deck)
1752{
1753 char *ss;
1754 long ii, jj;
1755
1756 for (ii = 0; !strchr(c, s[ii]); ii++) if (s[ii] == '\\') ii++;
1757 ss = xmalloc(ii+1);
1758 for (ii = jj = 0; !strchr(c, s[jj]); ii++)
1759 if ('\\'==(ss[ii] = s[jj++])) ss[ii] = s[jj++];
1760 else if (deck) collect_wildcards(ss, ii, deck);
1761 ss[ii] = 0;
1762 if (deck) {
1763 arg_add(deck, 0);
1764 deck->v[--deck->c] = (void *)jj;
1765 collect_wildcards("", 0, deck);
1766 }
1767
1768 return ss;
1769}
1770
1771#define NO_QUOTE (1<<0)
1772#define NO_PATH (1<<1)
1773#define NO_SPLIT (1<<2)
1774#define NO_BRACE (1<<3)
1775#define NO_TILDE (1<<4)
1776#define NO_NULL (1<<5)
1777#define SEMI_IFS (1<<6)
1778
1779
1780
1781static int expand_arg_nobrace(struct sh_arg *arg, char *str, unsigned flags,
1782 struct arg_list **delete, struct sh_arg *ant, long *measure)
1783{
1784 char cc, qq = flags&NO_QUOTE, sep[6], *new = str, *s, *ss = ss, *ifs, *slice;
1785 int ii = 0, oo = 0, xx, yy, dd, jj, kk, ll, mm;
1786 struct sh_arg deck = {0};
1787
1788
1789 if (!(flags&NO_TILDE) && *str == '~') {
1790 struct passwd *pw = 0;
1791
1792 ss = 0;
1793 while (str[ii] && str[ii]!=':' && str[ii]!='/') ii++;
1794 if (ii==1) {
1795 if (!(ss = getvar("HOME")) || !*ss) pw = bufgetpwuid(getuid());
1796 } else {
1797
1798 pw = getpwnam(s = xstrndup(str+1, ii-1));
1799 free(s);
1800 }
1801 if (pw) {
1802 ss = pw->pw_dir;
1803 if (!ss || !*ss) ss = "/";
1804 }
1805 if (ss) {
1806 oo = strlen(ss);
1807 s = xmprintf("%s%s", ss, str+ii);
1808 if (str != new) free(new);
1809 new = s;
1810 }
1811 }
1812
1813
1814 if (!ant) ant = &deck;
1815 for (; (cc = str[ii++]); str!=new && (new[oo] = 0)) {
1816 struct sh_arg aa = {0};
1817 int nosplit = 0;
1818
1819 if (measure && cc==*measure) break;
1820
1821
1822 if (!strchr("'\"\\$`"+2*(flags&NO_QUOTE), cc)) {
1823 if (str != new) new[oo] = cc;
1824 if (!(flags&NO_PATH) && !(qq&1)) collect_wildcards(new, oo, ant);
1825 oo++;
1826 continue;
1827 }
1828
1829
1830 if (str == new) {
1831 new = xstrdup(new);
1832 new[oo] = 0;
1833 }
1834 ifs = slice = 0;
1835
1836
1837 if (cc == '\\') {
1838 if (!(qq&1) || (str[ii] && strchr("\"\\$`", str[ii])))
1839 new[oo++] = str[ii] ? str[ii++] : cc;
1840 } else if (cc == '"') qq++;
1841 else if (cc == '\'') {
1842 if (qq&1) new[oo++] = cc;
1843 else {
1844 qq += 2;
1845 while ((cc = str[ii++]) != '\'') new[oo++] = cc;
1846 }
1847
1848
1849
1850 } else if (cc == '`' || (cc == '$' && str[ii] && strchr("([", str[ii]))) {
1851 off_t pp = 0;
1852
1853 s = str+ii-1;
1854 kk = parse_word(s, 1, 0)-s;
1855 if (str[ii] == '[' || *toybuf == 255) {
1856 struct sh_arg aa = {0};
1857 long long ll;
1858
1859
1860 ss = str+ii+1+(str[ii]=='(');
1861 push_arg(delete, ss = xstrndup(ss, kk - (3+2*(str[ii]!='['))));
1862 expand_arg_nobrace(&aa, ss, NO_PATH|NO_SPLIT, delete, 0, 0);
1863 s = ss = (aa.v && *aa.v) ? *aa.v : "";
1864 free(aa.v);
1865
1866
1867 if (!recalculate(&ll, &s, 0) || *s) {
1868 error_msg("bad math: %s @ %ld", ss, (long)(s-ss)+1);
1869 goto fail;
1870 }
1871 ii += kk-1;
1872 push_arg(delete, ifs = xmprintf("%lld", ll));
1873 } else {
1874
1875 s += (jj = 1+(cc == '$'));
1876 ii += --kk;
1877 kk -= jj;
1878
1879
1880 for (ss = s; isspace(*ss); ss++);
1881 if (*ss != '<') ss = 0;
1882 else {
1883 while (isspace(*++ss));
1884 if (!(ll = parse_word(ss, 0, 0)-ss)) ss = 0;
1885 else {
1886 jj = ll+(ss-s);
1887 while (isspace(s[jj])) jj++;
1888 if (jj != kk) ss = 0;
1889 else {
1890 jj = xcreate_stdio(ss = xstrndup(ss, ll), O_RDONLY|WARN_ONLY, 0);
1891 free(ss);
1892 }
1893 }
1894 }
1895
1896
1897
1898 if (!ss) jj = pipe_subshell(s, kk, 0);
1899 if ((ifs = readfd(jj, 0, &pp)))
1900 for (kk = strlen(ifs); kk && ifs[kk-1]=='\n'; ifs[--kk] = 0);
1901 close(jj);
1902 }
1903
1904
1905
1906 } else if (cc == '$') {
1907 cc = *(ss = str+ii++);
1908 if (cc=='\'') {
1909 for (s = str+ii; *s != '\''; oo += wcrtomb(new+oo, unescape2(&s, 0),0));
1910 ii = s-str+1;
1911
1912 continue;
1913 } else if (cc=='"' && !(qq&1)) {
1914 qq++;
1915
1916 continue;
1917 } else if (cc == '{') {
1918
1919
1920 for (cc = *++ss; str[ii] != '}'; ii++) if (str[ii]=='\\') ii++;
1921 ii++;
1922
1923 if (cc == '}') ifs = (void *)1;
1924 else if (strchr("#!", cc)) ss++;
1925 if (!(jj = varend(ss)-ss)) while (isdigit(ss[jj])) jj++;
1926 if (!jj && strchr("#$_*", *ss)) jj++;
1927
1928 if (!jj && strchr("-?@", *ss)) if (ss[++jj]!='}' && ss[-1]!='{') ss--;
1929 slice = ss+jj;
1930
1931 if (!jj) {
1932
1933 if (strchr("#!", cc)) ifs = getvar_special(--ss, 1, &kk, delete);
1934 else ifs = (void *)1;
1935 } else if (ss[-1]=='{');
1936 else if (cc == '#') {
1937 dd = !!strchr("@*", *ss);
1938 ifs = getvar_special(ss-dd, jj, &kk, delete) ? : "";
1939 if (!dd) push_arg(delete, ifs = xmprintf("%zu", strlen(ifs)));
1940
1941 } else if (cc == '!') {
1942
1943
1944 if (ss[jj] == '*' || (ss[jj] == '@' && !isalpha(ss[jj+1]))) {
1945 struct sh_vars **vv = visible_vars();
1946
1947 for (slice++, kk = 0; vv[kk]; kk++) {
1948 if (vv[kk]->flags&VAR_WHITEOUT) continue;
1949 if (!strncmp(s = vv[kk]->str, ss, jj))
1950 arg_add(&aa, push_arg(delete, s = xstrndup(s, stridx(s, '='))));
1951 }
1952 if (aa.c) push_arg(delete, aa.v);
1953 free(vv);
1954
1955
1956 } else {
1957
1958 if (strchr("@*", *ss)) {
1959 expand_arg_nobrace(&aa, "\"$*\"", NO_PATH|NO_SPLIT, delete, 0, 0);
1960 ifs = *aa.v;
1961 free(aa.v);
1962 memset(&aa, 0, sizeof(aa));
1963 jj = 1;
1964 } else ifs = getvar_special(ss, jj, &jj, delete);
1965 slice = ss+jj;
1966
1967
1968 if (!jj) ifs = (void *)1;
1969 else if (ifs && *(ss = ifs)) {
1970 if (strchr("@*", cc)) {
1971 aa.c = TT.ff->arg.c-1;
1972 aa.v = TT.ff->arg.v+1;
1973 jj = 1;
1974 } else ifs = getvar_special(ifs, strlen(ifs), &jj, delete);
1975 if (ss && ss[jj]) {
1976 ifs = (void *)1;
1977 slice = ss+strlen(ss);
1978 }
1979 }
1980 }
1981 }
1982
1983
1984 if (ifs == (void *)1) {
1985barf:
1986 if (!(((unsigned long)ifs)>>1)) ifs = "bad substitution";
1987 error_msg("%.*s: %s", (int)(slice-ss), ss, ifs);
1988 goto fail;
1989 }
1990 } else jj = 1;
1991
1992
1993 if (strchr("{$", ss[-1])) {
1994 if (strchr("@*", cc)) {
1995 aa.c = TT.ff->arg.c-1;
1996 aa.v = TT.ff->arg.v+1;
1997 } else {
1998 ifs = getvar_special(ss, jj, &jj, delete);
1999 if (!jj) {
2000 if (ss[-1] == '{') goto barf;
2001 new[oo++] = '$';
2002 ii--;
2003 continue;
2004 } else if (ss[-1] != '{') ii += jj-1;
2005 }
2006 }
2007 }
2008
2009
2010
2011
2012
2013
2014
2015 *sep = 0;
2016 if (((qq&1) && cc=='*') || (flags&NO_SPLIT)) {
2017 unsigned wc;
2018
2019 nosplit++;
2020 if (flags&SEMI_IFS) strcpy(sep, " ");
2021
2022 else if (0<(dd = utf8towc(&wc, TT.ff->ifs, 4)))
2023 sprintf(sep, "%.*s", dd, TT.ff->ifs);
2024 }
2025
2026
2027 mm = yy = 0;
2028 do {
2029
2030 if (aa.c) ifs = aa.v[mm++] ? : "";
2031
2032
2033 if (slice && *slice != '}') {
2034 dd = slice[xx = (*slice == ':')];
2035 if (!ifs || (xx && !*ifs)) {
2036 if (strchr("-?=", dd)) {
2037 push_arg(delete, ifs = slashcopy(slice+xx+1, "}", 0));
2038 if (dd == '?' || (dd == '=' &&
2039 !(setvar(s = xmprintf("%.*s=%s", (int)(slice-ss), ss, ifs)))))
2040 goto barf;
2041 }
2042 } else if (dd == '-');
2043
2044 else if (dd == '+')
2045 push_arg(delete, ifs = slashcopy(slice+xx+1, "}", 0));
2046 else if (xx) {
2047 long long la = 0, lb = LLONG_MAX, lc = 1;
2048
2049 ss = ++slice;
2050 if ((lc = recalculate(&la, &ss, 0)) && *ss == ':') {
2051 ss++;
2052 lc = recalculate(&lb, &ss, 0);
2053 }
2054 if (!lc || *ss != '}') {
2055 for (s = ss; *s != '}' && *s != ':'; s++);
2056 error_msg("bad %.*s @ %ld", (int)(s-slice), slice,(long)(ss-slice));
2057
2058 goto fail;
2059 }
2060
2061
2062 if (!(lc = aa.c)) lc = strlen(ifs);
2063 else if (!la && !yy && strchr("@*", *slice)) {
2064 aa.v--;
2065 aa.c++;
2066 yy++;
2067 }
2068 if (la<0 && (la += lc)<0) continue;
2069 if (lb<0) lb = lc+lb-la;
2070 if (aa.c) {
2071 if (mm<la || mm>=la+lb) continue;
2072 } else if (la>=lc || lb<0) ifs = "";
2073 else if (la+lb>=lc) ifs += la;
2074 else if (!*delete || ifs != (*delete)->arg)
2075 push_arg(delete, ifs = xmprintf("%.*s", (int)lb, ifs+la));
2076 else {
2077 for (dd = 0; dd<lb ; dd++) if (!(ifs[dd] = ifs[dd+la])) break;
2078 ifs[dd] = 0;
2079 }
2080 } else if (strchr("#%^,", *slice)) {
2081 struct sh_arg wild = {0};
2082 char buf[8];
2083
2084 s = slashcopy(slice+(xx = slice[1]==*slice)+1, "}", &wild);
2085
2086
2087 if (strchr("^,", *slice)) {
2088 for (ss = ifs; *ss; ss += dd) {
2089 dd = getutf8(ss, 4, &jj);
2090 if (!*s || 0<wildcard_match(ss, s, &wild, WILD_ANY)) {
2091 ll = ((*slice=='^') ? towupper : towlower)(jj);
2092
2093
2094
2095
2096 if (ll != jj) {
2097 yy = ss-ifs;
2098 if (!*delete || (*delete)->arg!=ifs)
2099 push_arg(delete, ifs = xstrdup(ifs));
2100 if (dd != (ll = wctoutf8(buf, ll))) {
2101 if (dd<ll)
2102 ifs = (*delete)->arg = xrealloc(ifs, strlen(ifs)+1+dd-ll);
2103 memmove(ifs+yy+dd-ll, ifs+yy+ll, strlen(ifs+yy+ll)+1);
2104 }
2105 memcpy(ss = ifs+yy, buf, dd = ll);
2106 }
2107 }
2108 if (!xx) break;
2109 }
2110
2111 } else if (*slice=='#') {
2112 if (0<(dd = wildcard_match(ifs, s, &wild, WILD_SHORT*!xx)))
2113 ifs += dd;
2114
2115 } else if (*slice=='%') {
2116 for (ss = ifs+strlen(ifs), yy = -1; ss>=ifs; ss--) {
2117 if (0<(dd = wildcard_match(ss, s, &wild, WILD_SHORT*xx))&&!ss[dd])
2118 {
2119 yy = ss-ifs;
2120 if (!xx) break;
2121 }
2122 }
2123
2124 if (yy != -1) {
2125 if (*delete && (*delete)->arg==ifs) ifs[yy] = 0;
2126 else push_arg(delete, ifs = xstrndup(ifs, yy));
2127 }
2128 }
2129 free(s);
2130 free(wild.v);
2131
2132
2133
2134 } else if (*slice=='/') {
2135 struct sh_arg wild = {0};
2136
2137 s = slashcopy(ss = slice+(xx = !!strchr("/#%", slice[1]))+1, "/}",
2138 &wild);
2139 ss += (long)wild.v[wild.c];
2140 ss = (*ss == '/') ? slashcopy(ss+1, "}", 0) : 0;
2141 jj = ss ? strlen(ss) : 0;
2142 ll = 0;
2143 for (ll = 0; ifs[ll];) {
2144
2145 if (0<(dd = wildcard_match(ifs+ll, s, &wild, 0))) {
2146 char *bird = 0;
2147
2148 if (slice[1]=='%' && ifs[ll+dd]) {
2149 ll++;
2150 continue;
2151 }
2152 if (*delete && (*delete)->arg==ifs) {
2153 if (jj==dd) memcpy(ifs+ll, ss, jj);
2154 else if (jj<dd) sprintf(ifs+ll, "%s%s", ss, ifs+ll+dd);
2155 else bird = ifs;
2156 } else bird = (void *)1;
2157 if (bird) {
2158 ifs = xmprintf("%.*s%s%s", ll, ifs, ss ? : "", ifs+ll+dd);
2159 if (bird != (void *)1) {
2160 free(bird);
2161 (*delete)->arg = ifs;
2162 } else push_arg(delete, ifs);
2163 }
2164 if (slice[1]!='/') break;
2165 } else ll++;
2166 if (slice[1]=='#') break;
2167 }
2168
2169
2170
2171
2172
2173
2174
2175 } else {
2176
2177 ifs = slice;
2178 goto barf;
2179 }
2180
2181
2182
2183
2184 }
2185
2186
2187 if (!ifs) break;
2188 if (!*ifs && !qq) continue;
2189
2190
2191 do {
2192
2193
2194 if ((qq&1) || nosplit) ss = ifs+strlen(ifs);
2195 else for (ss = ifs; *ss; ss += kk)
2196 if (utf8chr(ss, TT.ff->ifs, &kk)) break;
2197
2198
2199 if (!oo && !*ss && !((mm==aa.c) ? str[ii] : nosplit)) {
2200 if (qq || ss!=ifs) {
2201 if (!(flags&NO_PATH))
2202 for (jj = 0; ifs[jj]; jj++) collect_wildcards(ifs, jj, ant);
2203 wildcard_add_files(arg, ifs, &deck, delete);
2204 }
2205 continue;
2206 }
2207
2208
2209 jj = (mm == aa.c) && !*ss;
2210 new = xrealloc(new, oo + (ss-ifs) + ((nosplit&!jj) ? strlen(sep) : 0) +
2211 (jj ? strlen(str+ii) : 0) + 1);
2212 dd = sprintf(new + oo, "%.*s%s", (int)(ss-ifs), ifs,
2213 (nosplit&!jj) ? sep : "");
2214 if (flags&NO_PATH) oo += dd;
2215 else while (dd--) collect_wildcards(new, oo++, ant);
2216 if (jj) break;
2217
2218
2219 if (!nosplit) {
2220 if (qq || *new || *ss) {
2221 push_arg(delete, new = xrealloc(new, strlen(new)+1));
2222 wildcard_add_files(arg, new, &deck, delete);
2223 new = xstrdup(str+ii);
2224 }
2225 qq &= 1;
2226 oo = 0;
2227 }
2228
2229
2230 kk = 0;
2231 while ((jj = utf8chr(ss, TT.ff->ifs, &ll))) {
2232 if (!iswspace(jj) && kk++) break;
2233 ss += ll;
2234 }
2235 } while (*(ifs = ss));
2236 } while (!(mm == aa.c));
2237 }
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247 if (*new || qq) {
2248 if (str != new) push_arg(delete, new);
2249 wildcard_add_files(arg, new, &deck, delete);
2250 new = 0;
2251 }
2252
2253
2254 arg = 0;
2255
2256fail:
2257 if (str != new) free(new);
2258 free(deck.v);
2259 if (ant!=&deck && ant->v) collect_wildcards("", 0, ant);
2260 if (measure) *measure = --ii;
2261
2262 return !!arg;
2263}
2264
2265struct sh_brace {
2266 struct sh_brace *next, *prev, *stack;
2267 int active, cnt, idx, commas[];
2268};
2269
2270static int brace_end(struct sh_brace *bb)
2271{
2272 return bb->commas[(bb->cnt<0 ? 0 : bb->cnt)+1];
2273}
2274
2275
2276static int expand_arg(struct sh_arg *arg, char *old, unsigned flags,
2277 struct arg_list **delete)
2278{
2279 struct sh_brace *bb = 0, *blist = 0, *bstk, *bnext;
2280 int i, j, k, x;
2281 char *s, *ss;
2282
2283
2284 if ((TT.options&OPT_B) && !(flags&NO_BRACE)) for (i = 0; ; i++) {
2285
2286 while ((s = parse_word(old+i, 1, 0)) != old+i) i += s-(old+i);
2287
2288 if (!bb && !old[i]) break;
2289
2290 if (bb && (!old[i] || old[i] == '}')) {
2291 bb->active = bb->commas[bb->cnt+1] = i;
2292
2293 for (bnext = bb; bb && bb->active; bb = (bb==blist) ? 0 : bb->prev);
2294
2295 j = 1+*bnext->commas;
2296 if (old[i] && !bnext->cnt && i-j>=4) {
2297
2298 if (old[j+1]=='.' && old[j+2]=='.') {
2299 bnext->commas[2] = old[j];
2300 bnext->commas[3] = old[j+3];
2301 k = 0;
2302 if (old[j+4]=='}' ||
2303 (sscanf(old+j+4, "..%u}%n", bnext->commas+4, &k) && k))
2304 bnext->cnt = -1;
2305 }
2306
2307 if (!bnext->cnt) {
2308 for (k=0, j = 1+*bnext->commas; k<3; k++, j += x)
2309 if (!sscanf(old+j, "..%u%n"+2*!k, bnext->commas+2+k, &x)) break;
2310 if (old[j] == '}') bnext->cnt = -2;
2311 }
2312
2313 if (bnext->cnt) {
2314 if (!bnext->commas[4]) bnext->commas[4] = 1;
2315 if ((bnext->commas[3]-bnext->commas[2]>0) != (bnext->commas[4]>0))
2316 bnext->commas[4] *= -1;
2317 }
2318 }
2319
2320 if (!old[i] || !bnext->cnt)
2321 free(dlist_pop((blist == bnext) ? &blist : &bnext));
2322
2323 } else if (old[i] == '{') {
2324 dlist_add_nomalloc((void *)&blist,
2325 (void *)(bb = xzalloc(sizeof(struct sh_brace)+34*4)));
2326 bb->commas[0] = i;
2327
2328 } else if (!bb) continue;
2329
2330 else if (bb && old[i] == ',') {
2331 if (bb->cnt && !(bb->cnt&31)) {
2332 dlist_lpop(&blist);
2333 dlist_add_nomalloc((void *)&blist,
2334 (void *)(bb = xrealloc(bb, sizeof(struct sh_brace)+(bb->cnt+34)*4)));
2335 }
2336 bb->commas[++bb->cnt] = i;
2337 }
2338 }
2339
2340
2341
2342 if (!blist) return expand_arg_nobrace(arg, old, flags, delete, 0, 0);
2343
2344
2345 (bstk = xzalloc(sizeof(struct sh_brace)+8))->commas[1] = strlen(old)+1;
2346 bstk->commas[0] = -1;
2347
2348
2349 for (;;) {
2350
2351
2352 s = ss = xmalloc(bstk->commas[1]);
2353
2354
2355 for (bb = blist; bb; bb = (bnext == blist) ? 0 : bnext) {
2356
2357
2358 if (bstk == bb) bstk = bstk->stack;
2359
2360 if (brace_end(bstk)>bb->commas[0]) {
2361 i = bstk->commas[bstk->idx]+1;
2362 s = stpncpy(s, old+i, bb->commas[0]-i);
2363 }
2364 else bstk = bstk->stack;
2365
2366 bb->stack = bstk;
2367 bb->active = 1;
2368 bstk = bnext = bb;
2369
2370
2371 while ((bnext = (bnext->next==blist) ? 0 : bnext->next)) {
2372
2373
2374 if ((i = bnext->commas[0])>brace_end(bb)) break;
2375
2376
2377 if (i<bb->commas[bb->idx] || i>bb->commas[bb->idx+1]) {
2378 bnext->active = 0;
2379 bnext->stack = 0;
2380
2381
2382 } else break;
2383 }
2384
2385
2386 if (!bnext || bb->cnt<0 || bnext->commas[0]>bb->commas[bb->idx+1]) {
2387
2388
2389 if (bb->cnt<0) {
2390 k = bb->commas[2]+bb->commas[4]*bb->idx;
2391 s += sprintf(s, (bb->cnt==-1) ? "\\%c"+!ispunct(k) : "%d", k);
2392 } else {
2393 i = bb->commas[bstk->idx]+1;
2394 s = stpncpy(s, old+i, bb->commas[bb->idx+1]-i);
2395 }
2396
2397
2398 while (!bnext || bnext->commas[0]>brace_end(bstk)) {
2399 if (!(bb = bstk->stack)) break;
2400 i = brace_end(bstk)+1;
2401 j = bb->commas[bb->idx+1];
2402
2403 while (bnext) {
2404 if (bnext->commas[0]<j) {
2405 j = bnext->commas[0];
2406 break;
2407 } else if (brace_end(bb)>bnext->commas[0])
2408 bnext = (bnext->next == blist) ? 0 : bnext->next;
2409 else break;
2410 }
2411 s = stpncpy(s, old+i, j-i);
2412
2413
2414 if (bnext && bnext->commas[0]<brace_end(bb)) break;
2415 bstk = bb;
2416 }
2417 }
2418 }
2419
2420
2421 if (expand_arg_nobrace(arg, push_arg(delete, ss), flags, delete, 0, 0)) {
2422 llist_traverse(blist, free);
2423
2424 return 1;
2425 }
2426
2427
2428 for (bb = blist->prev; bb; bb = (bb == blist) ? 0 : bb->prev) {
2429 if (!bb->stack) continue;
2430 else if (bb->cnt<0) {
2431 if (abs(bb->commas[2]-bb->commas[3]) < abs(++bb->idx*bb->commas[4]))
2432 bb->idx = 0;
2433 else break;
2434 } else if (++bb->idx > bb->cnt) bb->idx = 0;
2435 else break;
2436 }
2437
2438
2439 if (!bb) break;
2440 }
2441 llist_traverse(blist, free);
2442
2443 return 0;
2444}
2445
2446
2447static char *expand_one_arg(char *new, unsigned flags, struct arg_list **del)
2448{
2449 struct sh_arg arg = {0};
2450 char *s = 0;
2451
2452
2453 if (!expand_arg(&arg, new, flags|NO_PATH|NO_SPLIT, del))
2454 if (!(s = *arg.v) && (flags&(SEMI_IFS|NO_NULL))) s = "";
2455 free(arg.v);
2456
2457 return s;
2458}
2459
2460
2461
2462
2463
2464static struct sh_process *expand_redir(struct sh_arg *arg, int skip, int *urd)
2465{
2466 struct sh_process *pp;
2467 char *s = s, *ss, *sss, *cv = 0;
2468 int j, to, from, here = 0;
2469
2470 TT.hfd = 10;
2471 pp = xzalloc(sizeof(struct sh_process));
2472 pp->urd = urd;
2473 pp->raw = arg;
2474
2475
2476
2477
2478 for (j = skip; j<arg->c; j++) {
2479 int saveclose = 0, bad = 0;
2480
2481 if (!strcmp(s = arg->v[j], "!")) {
2482 pp->flags ^= PFLAG_NOT;
2483
2484 continue;
2485 }
2486
2487
2488 if ((*s == '<' || *s == '>') && s[1] == '(') {
2489 int new = pipe_subshell(s+2, strlen(s+2)-1, *s == '>');
2490
2491
2492 if (new == -1) {
2493 pp->exit = 1;
2494
2495 return pp;
2496 }
2497 save_redirect(&pp->urd, -2, new);
2498
2499
2500
2501 arg_add_del(&pp->arg, ss = xmprintf("/proc/self/fd/%d", new),&pp->delete);
2502
2503 continue;
2504 }
2505
2506
2507 ss = skip_redir_prefix(s);
2508 sss = ss + anystart(ss, (void *)redirectors);
2509 if (ss == sss) {
2510
2511 if (expand_arg(&pp->arg, s, 0, &pp->delete)) {
2512 pp->exit = 1;
2513
2514 return pp;
2515 }
2516 continue;
2517 } else if (j+1 >= arg->c) {
2518
2519 s = "\\n";
2520 break;
2521 }
2522 sss = arg->v[++j];
2523
2524
2525 if (isdigit(*s) && ss-s>5) break;
2526
2527
2528 if (strncmp(ss, "<<", 2)) {
2529 struct sh_arg tmp = {0};
2530
2531 if (!expand_arg(&tmp, sss, 0, &pp->delete) && tmp.c == 1) sss = *tmp.v;
2532 else {
2533 if (tmp.c > 1) error_msg("%s: ambiguous redirect", sss);
2534 s = 0;
2535 }
2536 free(tmp.v);
2537 if (!s) break;
2538 }
2539
2540
2541 to = *ss != '<';
2542 if (isdigit(*s)) to = atoi(s);
2543 else if (*s == '{') {
2544 if (*varend(s+1) != '}') break;
2545
2546 if ((!strcmp(ss, "<&") || !strcmp(ss, ">&")) && !strcmp(sss, "-")) {
2547 if (!(ss = getvar(s+1))) break;
2548 to = atoi(ss);
2549 if (save_redirect(&pp->urd, -1, to)) break;
2550 close(to);
2551
2552 continue;
2553
2554 } else {
2555
2556 if (-1 == (to = next_hfd())) break;
2557 cv = xmprintf("%.*s=%d", (int)(ss-s-2), s+1, to);
2558 }
2559 }
2560
2561
2562 if (!strncmp(ss, "<<", 2)) {
2563 char *tmp = xmprintf("%s/sh-XXXXXX", getvar("TMPDIR") ? : "/tmp");
2564 int i, len, zap = (ss[2] == '-'), x = !ss[strcspn(ss, "\"'")];
2565
2566
2567 if ((from = mkstemp(tmp))>=0) {
2568 if (unlink(tmp)) bad++;
2569 else if (ss[2] == '<') {
2570 if (!(ss = expand_one_arg(sss, 0, 0))) {
2571 s = 0;
2572 break;
2573 }
2574 len = strlen(ss);
2575 if (len != writeall(from, ss, len)) bad++;
2576 if (ss != sss) free(ss);
2577 } else {
2578 struct sh_arg *hh = arg+here++;
2579
2580 for (i = 0; i<hh->c; i++) {
2581 ss = hh->v[i];
2582 sss = 0;
2583
2584
2585 if (x && !(sss = expand_one_arg(ss, ~SEMI_IFS, 0))) {
2586 s = 0;
2587 break;
2588 }
2589
2590 while (zap && *ss == '\t') ss++;
2591 x = writeall(from, ss, len = strlen(ss));
2592 if (ss != sss) free(sss);
2593 if (len != x) break;
2594 }
2595 if (i != hh->c) bad++;
2596 }
2597 if (!bad && lseek(from, 0, SEEK_SET)) bad++;
2598 if (bad) close(from);
2599 } else bad++;
2600 free(tmp);
2601 if (bad) break;
2602
2603
2604
2605
2606
2607
2608
2609 } else if (*ss == '&' || ss[1] == '&') {
2610
2611
2612 for (ss = sss; isdigit(*ss); ss++);
2613 if (ss-sss>5 || (*ss && (*ss != '-' || ss[1]))) {
2614 if (*ss=='&') ss++;
2615 saveclose = 4;
2616 goto notfd;
2617 }
2618
2619 from = (ss==sss) ? to : atoi(sss);
2620 saveclose = 2-(*ss == '-');
2621 } else {
2622notfd:
2623
2624 if (!strcmp(ss, "<>")) from = O_CREAT|O_RDWR;
2625 else if (strstr(ss, ">>")) from = O_CREAT|O_APPEND|O_WRONLY;
2626 else {
2627 from = (*ss == '<') ? O_RDONLY : O_CREAT|O_WRONLY|O_TRUNC;
2628 if (!strcmp(ss, ">") && (TT.options&OPT_C)) {
2629 struct stat st;
2630
2631
2632 if (stat(sss, &st) || !S_ISREG(st.st_mode)) from |= O_EXCL;
2633 }
2634 }
2635
2636
2637
2638
2639
2640
2641 if (-1 == (from = xcreate_stdio(sss, from|WARN_ONLY, 0666))) {
2642 s = 0;
2643
2644 break;
2645 }
2646 }
2647
2648
2649 if (save_redirect(&pp->urd, from, to)) bad++;
2650
2651 if (cv) {
2652 --*pp->urd;
2653 if (!setvar(cv)) bad++;
2654 cv = 0;
2655 }
2656 if ((saveclose&1) && save_redirect(&pp->urd, -1, from)) bad++;
2657 if ((saveclose&4) && save_redirect(&pp->urd, from, 2)) bad++;
2658 if (!(saveclose&2)) close(from);
2659 if (bad) break;
2660 }
2661
2662
2663 if (j != arg->c) {
2664 if (s) syntax_err(s);
2665 if (!pp->exit) pp->exit = 1;
2666 free(cv);
2667 }
2668
2669 return pp;
2670}
2671
2672
2673static void sh_exec(char **argv)
2674{
2675 char *pp = getvar("PATH" ? : _PATH_DEFPATH), *cc = TT.isexec ? : *argv, *ss,
2676 **sss = 0, **oldenv = environ, **argv2;
2677 struct string_list *sl;
2678
2679 if (getpid() != TT.pid) signal(SIGINT, SIG_DFL);
2680 errno = ENOENT;
2681 if (strchr(ss = cc, '/')) {
2682 if (access(ss, X_OK)) ss = 0;
2683 } else for (sl = find_in_path(pp, cc); sl || (ss = 0); free(llist_pop(&sl)))
2684 if (!access(ss = sl->str, X_OK)) break;
2685
2686 if (ss) {
2687 struct sh_vars **vv = visible_vars();
2688 struct sh_arg aa;
2689 unsigned uu, argc;
2690
2691
2692 aa.v = environ = (void *)vv;
2693 for (aa.c = uu = 0; vv[uu]; uu++) {
2694 if ((vv[uu]->flags&(VAR_WHITEOUT|VAR_EXPORT))==VAR_EXPORT) {
2695 if (*(pp = vv[uu]->str)=='_' && pp[1]=='=') sss = aa.v+aa.c;
2696 aa.v[aa.c++] = pp;
2697 }
2698 }
2699 aa.v[aa.c] = 0;
2700 if (!sss) {
2701 arg_add(&aa, 0);
2702 sss = aa.v+aa.c-1;
2703 }
2704 *sss = xmprintf("_=%s", ss);
2705
2706
2707 execve(ss, argv, environ);
2708 if (errno == ENOEXEC) {
2709 for (argc = 0; argv[argc]; argc++);
2710 argv2 = xmalloc((argc+3)*sizeof(char *));
2711 memcpy(argv2+3, argv+1, argc*sizeof(char *));
2712 argv2[0] = "sh";
2713 argv2[1] = "--";
2714 argv2[2] = ss;
2715 xexec(argv2);
2716 free(argv2);
2717 }
2718 environ = oldenv;
2719 free(*sss);
2720 free(aa.v);
2721 }
2722
2723 perror_msg("%s", *argv);
2724 if (!TT.isexec) _exit(127);
2725 llist_traverse(sl, free);
2726}
2727
2728
2729static struct sh_process *run_command(void)
2730{
2731 char *s, *ss, *sss;
2732 struct sh_arg *arg = TT.ff->pl->arg;
2733 int envlen, skiplen, funk = TT.funcslen, ii, jj = 0, prefix = 0;
2734 struct sh_process *pp;
2735
2736
2737 for (envlen = skiplen = 0; envlen<arg->c; envlen++)
2738 if ((ss = varend(arg->v[envlen]))==arg->v[envlen] || ss[*ss=='+']!='=')
2739 break;
2740
2741
2742 if ((s = arg->v[envlen])) {
2743 if (!memcmp(s, "((", 2)) skiplen = 1;
2744 else if (!strcmp(s, "[[")) while (strcmp(arg->v[envlen+skiplen++], "]]"));
2745 }
2746 pp = expand_redir(arg, envlen+skiplen, 0);
2747
2748
2749
2750 if (skiplen) {
2751
2752 if (pp->arg.c) {
2753 syntax_err(*pp->arg.v);
2754 pp->exit = 1;
2755 }
2756 if (!pp->exit) {
2757 for (ii = 0; ii<skiplen; ii++)
2758
2759 if (expand_arg(&pp->arg, arg->v[envlen+ii], NO_PATH|NO_SPLIT, &pp->delete))
2760 break;
2761 if (ii != skiplen) pp->exit = toys.exitval = 1;
2762 }
2763 if (pp->exit) return pp;
2764 }
2765
2766
2767 if (pp->arg.c)
2768 if (!strchr(s, '/')) for (funk = 0; funk<TT.funcslen; funk++)
2769 if (!strcmp(s, TT.functions[funk]->name)) break;
2770
2771
2772 if (funk != TT.funcslen || (envlen && pp->arg.c) || TT.ff->blk->pipe) {
2773 call_function();
2774
2775 if (funk != TT.funcslen) {
2776 TT.ff->delete = pp->delete;
2777 pp->delete = 0;
2778 }
2779 addvar(0, TT.ff);
2780 prefix = 1;
2781 }
2782
2783
2784 if (envlen) for (; jj<envlen && !pp->exit; jj++) {
2785 struct sh_vars *vv;
2786
2787 if ((sss = expand_one_arg(ss = arg->v[jj], SEMI_IFS, 0))) {
2788 if (!prefix && sss==ss) sss = xstrdup(sss);
2789 if ((vv = setvar_long(sss, sss!=ss, prefix ? TT.ff : TT.ff->prev))) {
2790 if (prefix) vv->flags |= VAR_EXPORT;
2791 continue;
2792 }
2793 }
2794 pp->exit = 1;
2795 break;
2796 }
2797
2798
2799 if (pp->exit || envlen==arg->c) s = 0;
2800 else if (!pp->arg.c) s = "";
2801
2802
2803
2804
2805
2806
2807 else if (!memcmp(s = *pp->arg.v, "((", 2)) {
2808 char *ss = s+2;
2809 long long ll;
2810
2811 funk = TT.funcslen;
2812 ii = strlen(s)-2;
2813 if (!recalculate(&ll, &ss, 0) || ss!=s+ii)
2814 perror_msg("bad math: %.*s @ %ld", ii-2, s+2, (long)(ss-s)-2);
2815 else toys.exitval = !ll;
2816 pp->exit = toys.exitval;
2817 s = 0;
2818
2819
2820 } else if (funk != TT.funcslen) {
2821 s = 0;
2822 (TT.ff->func = TT.functions[funk])->refcount++;
2823 TT.ff->pl = TT.ff->func->pipeline;
2824 TT.ff->arg = pp->arg;
2825
2826 } else {
2827 struct toy_list *tl = toy_find(*pp->arg.v);
2828
2829 jj = tl ? tl->flags : 0;
2830 TT.pp = pp;
2831 s = pp->arg.v[pp->arg.c-1];
2832 sss = pp->arg.v[pp->arg.c];
2833
2834
2835
2836
2837 if ((jj&TOYFLAG_NOFORK) || ((jj&TOYFLAG_MAYFORK) && !prefix)) {
2838 sigjmp_buf rebound;
2839 char temp[jj = offsetof(struct toy_context, rebound)];
2840
2841
2842 memcpy(&temp, &toys, jj);
2843 memset(&toys, 0, jj);
2844
2845
2846
2847
2848 memset(&TT, 0, offsetof(struct sh_data, SECONDS));
2849 if (!sigsetjmp(rebound, 1)) {
2850 toys.rebound = &rebound;
2851
2852 toy_singleinit(tl, pp->arg.v);
2853 tl->toy_main();
2854 xflush(0);
2855 }
2856 toys.rebound = 0;
2857 pp->exit = toys.exitval;
2858 if (toys.optargs != toys.argv+1) free(toys.optargs);
2859 if (toys.old_umask) umask(toys.old_umask);
2860 memcpy(&toys, &temp, jj);
2861 } else if (-1==(pp->pid = xpopen_setup(pp->arg.v, 0, sh_exec)))
2862 perror_msg("%s: vfork", *pp->arg.v);
2863 }
2864
2865
2866 unredirect(pp->urd);
2867 pp->urd = 0;
2868 if (prefix && funk == TT.funcslen) end_function(0);
2869 if (s) setvarval("_", s);
2870
2871 return pp;
2872}
2873
2874static int free_process(struct sh_process *pp)
2875{
2876 int rc;
2877
2878 if (!pp) return 127;
2879 rc = pp->exit;
2880 llist_traverse(pp->delete, llist_free_arg);
2881 free(pp);
2882
2883 return rc;
2884}
2885
2886
2887
2888
2889static void free_pipeline(void *pipeline)
2890{
2891 struct sh_pipeline *pl = pipeline;
2892 int i, j;
2893
2894 if (!pl) return;
2895
2896
2897 if (pl->type == 'F') {
2898 free_function((void *)*pl->arg->v);
2899 *pl->arg->v = 0;
2900 }
2901 for (j=0; j<=pl->count; j++) {
2902 if (!pl->arg[j].v) continue;
2903 for (i = 0; i<=pl->arg[j].c; i++) free(pl->arg[j].v[i]);
2904 free(pl->arg[j].v);
2905 }
2906 free(pl);
2907}
2908
2909
2910static struct sh_pipeline *add_pl(struct sh_pipeline **ppl, struct sh_arg **arg)
2911{
2912 struct sh_pipeline *pl = xzalloc(sizeof(struct sh_pipeline));
2913
2914 if (arg) *arg = pl->arg;
2915 pl->lineno = TT.LINENO;
2916 dlist_add_nomalloc((void *)ppl, (void *)pl);
2917
2918 return pl->end = pl;
2919}
2920
2921
2922
2923static int parse_line(char *line, struct sh_pipeline **ppl,
2924 struct double_list **expect)
2925{
2926 char *start = line, *delete = 0, *end, *s, *ex, done = 0,
2927 *tails[] = {"fi", "done", "esac", "}", "]]", ")", 0};
2928 struct sh_pipeline *pl = *ppl ? (*ppl)->prev : 0, *pl2, *pl3;
2929 struct sh_arg *arg = 0;
2930 long i;
2931
2932
2933 if (pl) {
2934 arg = pl->arg;
2935
2936
2937 if (arg->c<0) {
2938 delete = start = xmprintf("%s%s", arg->v[arg->c = (-arg->c)-1], start);
2939 free(arg->v[arg->c]);
2940 arg->v[arg->c] = 0;
2941
2942
2943 } else if (pl->count != pl->here) {
2944
2945 while (pl != *ppl && pl->prev->count != pl->prev->here) pl = pl->prev;
2946 arg = pl->arg+1+pl->here;
2947
2948
2949 for (s = line, end = arg->v[arg->c]; *end; s++) {
2950 s += strspn(s, "\\\"'");
2951 if (!*s || *s != *end) break;
2952 }
2953
2954 if (*s || *end) {
2955 end = arg->v[arg->c];
2956 arg_add(arg, xstrdup(line));
2957 arg->v[arg->c] = end;
2958 } else {
2959
2960 arg->v[arg->c] = 0;
2961 if (pl->count == ++pl->here)
2962 while (pl->next != *ppl && (pl = pl->next)->here == -1)
2963 pl->here = pl->count;
2964 }
2965 if (pl->here != pl->count) return 1;
2966 start = 0;
2967
2968
2969 } else if (pl->type < 128) pl = 0;
2970 }
2971
2972
2973 if (start) for (;;) {
2974 ex = *expect ? (*expect)->prev->data : 0;
2975
2976
2977 if (pl && pl->count == -1) {
2978
2979 for (arg = pl->arg, pl->count = i = 0; i<arg->c; i++) {
2980 s = skip_redir_prefix(arg->v[i]);
2981 if (strncmp(s, "<<", 2) || s[2]=='<') continue;
2982 if (i+1 == arg->c) goto flush;
2983
2984
2985
2986 dlist_lpop(ppl);
2987 pl = xrealloc(pl, sizeof(*pl)+(++pl->count+1)*sizeof(struct sh_arg));
2988 arg = pl->arg;
2989 dlist_add_nomalloc((void *)ppl, (void *)pl);
2990
2991
2992 *(arg[pl->count].v = xzalloc(2*sizeof(void *))) = arg->v[++i];
2993 arg[pl->count].c = 0;
2994 }
2995
2996 if (!pl->count && pl->prev->count != pl->prev->here) pl->prev->here = -1;
2997 pl = 0;
2998 }
2999 if (done) break;
3000 s = 0;
3001
3002
3003 while (isspace(*start)) ++start;
3004 if (*start=='#') while (*start && *start != '\n') ++start;
3005
3006
3007 if ((end = parse_word(start, 0, 0)) == (void *)1) goto flush;
3008
3009
3010
3011 if (pl && pl->type == 'f' && arg->c == 1 && (end-start!=1 || *start!='(')) {
3012
3013 dlist_add(expect, 0);
3014 pl = 0;
3015
3016 continue;
3017 }
3018
3019
3020 if (!pl) pl = add_pl(ppl, &arg);
3021
3022
3023 if (!end) {
3024
3025 arg_add(arg, xstrndup(start, strlen(start)));
3026 arg->c = -arg->c;
3027 free(delete);
3028
3029 return 1;
3030 }
3031
3032
3033
3034
3035 i = ex && !strcmp(ex, "esac") &&
3036 ((pl->type && pl->type != 3) || (*start==';' && end-start>1));
3037 if (i) {
3038
3039
3040 if (end == start) {
3041 if (pl->type==128 && arg->c==2) break;
3042 if (pl->type==129 && (!arg->c || (arg->c==1 && **arg->v==';'))) break;
3043 s = "newline";
3044 goto flush;
3045 }
3046
3047
3048 if (!pl->type || pl->type==3) {
3049
3050 if (arg->v && arg->v[arg->c] && strcmp(arg->v[arg->c], "&")) goto flush;
3051 if (!arg->c) {
3052 if (pl->prev->type == 2) {
3053
3054 arg_add(arg, xstrdup(":"));
3055 pl = add_pl(ppl, &arg);
3056 }
3057 pl->type = 129;
3058 } else {
3059
3060 pl->count = -1;
3061 continue;
3062 }
3063 }
3064
3065
3066
3067 } else if (end == start || (arg->c && *start == ')' && pl->type!='f')) {
3068
3069
3070 if (pl->type == 'f' && arg->c != 1 && arg->c != 3) {
3071 s = "function(";
3072 goto flush;
3073 }
3074
3075
3076 if (arg->c == 1 && ex && !memcmp(ex, "do\0A", 4)) {
3077 s = "newline";
3078 goto flush;
3079 }
3080
3081
3082 if (end == start) done++;
3083 if (!pl->type && !arg->c) {
3084 free_pipeline(dlist_lpop(ppl));
3085 pl = *ppl ? (*ppl)->prev : 0;
3086 } else pl->count = -1;
3087
3088 continue;
3089 }
3090
3091
3092 arg_add(arg, s = xstrndup(start, end-start));
3093 start = end;
3094
3095
3096 if (i) {
3097
3098 if (pl->type==128) {
3099 if (arg->c==2 && strchr("()|;&", *s)) goto flush;
3100 if (arg->c==3) {
3101 if (strcmp(s, "in")) goto flush;
3102 pl->type = 1;
3103 (pl = add_pl(ppl, &arg))->type = 129;
3104 }
3105
3106 continue;
3107
3108
3109 } else {
3110
3111
3112 if (*s==';') {
3113 if (arg->c>1 || (arg->c==1 && pl->prev->type==1)) goto flush;
3114 } else pl->type = 2;
3115 i = arg->c - (**arg->v==';' && arg->v[0][1]);
3116 if (i==1 && !strcmp(s, "esac")) {
3117
3118 if (arg->c>1) {
3119 arg->v[1] = 0;
3120 pl = add_pl(ppl, &arg);
3121 arg_add(arg, s);
3122 } else pl->type = 0;
3123 } else {
3124 if (arg->c>1) i -= *arg->v[1]=='(';
3125 if (i>0 && ((i&1)==!!strchr("|)", *s) || strchr(";(", *s)))
3126 goto flush;
3127 if (*s=='&' || !strcmp(s, "||")) goto flush;
3128 if (*s==')') pl = add_pl(ppl, &arg);
3129
3130 continue;
3131 }
3132 }
3133 }
3134
3135
3136 if (!pl->type || pl->type=='f') {
3137 if (!pl->type && arg->c==1 && !strcmp(s, "function")) {
3138 free(arg->v[--arg->c]);
3139 arg->v[arg->c] = 0;
3140 pl->type = 'f';
3141 continue;
3142 } else if (arg->c==2 && !strcmp(s, "(")) pl->type = 'f';
3143 }
3144
3145
3146 if (pl->type=='f') {
3147 if (arg->v[0][strcspn(*arg->v, "\"'`><;|&$")]) {
3148 s = *arg->v;
3149 goto flush;
3150 }
3151 if (arg->c == 2 && strcmp(s, "(")) goto flush;
3152 if (arg->c == 3) {
3153 if (strcmp(s, ")")) goto flush;
3154 dlist_add(expect, 0);
3155 pl = 0;
3156 }
3157
3158 continue;
3159
3160
3161 } else if (strchr(";|&", *s) && strncmp(s, "&>", 2)) {
3162 arg->c--;
3163
3164
3165 if (!strcmp(s, ";")) {
3166 arg->v[arg->c] = 0;
3167 free(s);
3168 s = 0;
3169
3170 if (!arg->c && ex && !memcmp(ex, "do\0C", 4)) continue;
3171
3172
3173 } else if (*s == ';') goto flush;
3174
3175
3176 if (!arg->c) goto flush;
3177 pl->count = -1;
3178
3179 continue;
3180
3181
3182 } else if (ex && !memcmp(ex, "do\0A", 4)) {
3183
3184
3185 if (strncmp(s, "((", 2) && *varend(s)) goto flush;
3186 pl->count = -1;
3187 (*expect)->prev->data = "do\0C";
3188
3189 continue;
3190
3191
3192 } else if (arg->c>1) {
3193
3194 if (ex && *ex==']' && !strcmp(s, ex)) free(dlist_lpop(expect));
3195
3196 continue;
3197 }
3198
3199
3200
3201 if (ex && !memcmp(ex, "do\0C", 4)) {
3202 if (strcmp(s, "do")) {
3203
3204 if (pl->prev->type == 's') goto flush;
3205 if (!strncmp(pl->prev->arg->v[1], "((", 2)) goto flush;
3206 else if (strcmp(s, "in")) goto flush;
3207 pl->type = 's';
3208
3209 continue;
3210 }
3211 }
3212
3213
3214
3215
3216 if (!strcmp(s, "for") || !strcmp(s, "select") || !strcmp(s, "case")) {
3217
3218 if (!pl->type) pl->type = (*s == 'c') ? 128 : 1;
3219 dlist_add(expect, (*s == 'c') ? "esac" : "do\0A");
3220
3221 continue;
3222 }
3223
3224 end = 0;
3225 if (!strcmp(s, "if")) end = "then";
3226 else if (!strcmp(s, "while") || !strcmp(s, "until")) end = "do\0B";
3227 else if (!strcmp(s, "{")) end = "}";
3228 else if (!strcmp(s, "(")) end = ")";
3229 else if (!strcmp(s, "[[")) end = "]]";
3230
3231
3232 if (!ex && *expect) {
3233 if (pl->prev->type == 'f' && !end && memcmp(s, "((", 2)) goto flush;
3234 free(dlist_lpop(expect));
3235 }
3236
3237
3238 if (end) {
3239 if (*end!=']') pl->type = 1;
3240 else {
3241
3242 dlist_add(expect, end);
3243 continue;
3244 }
3245
3246
3247 if (*expect && !(*expect)->prev->data) free(dlist_lpop(expect));
3248
3249
3250 } else if (!ex);
3251
3252
3253 else if (!strcmp(s, ex)) {
3254
3255 if (strcmp(pl->prev->arg->v[pl->prev->arg->c] ? : "&", "&")) goto flush;
3256
3257
3258 free(dlist_lpop(expect));
3259 if (3 == (pl->type = anystr(s, tails) ? 3 : 2)) {
3260 for (i = 0, pl2 = pl3 = pl; (pl2 = pl2->prev);) {
3261 if (pl2->type == 3) i++;
3262 else if (pl2->type) {
3263 if (!i) {
3264 if (pl2->type == 2) {
3265 pl2->end = pl3;
3266 pl3 = pl2;
3267 } else pl2->end = pl;
3268 }
3269 if (pl2->type == 1 && --i<0) break;
3270 }
3271 }
3272 }
3273
3274
3275 if (!strcmp(s, "do")) end = "done";
3276 else if (!strcmp(s, "then")) end = "fi\0A";
3277
3278
3279 } else if (!strcmp(ex, "fi")) {
3280 if (!strcmp(s, "elif")) {
3281 free(dlist_lpop(expect));
3282 end = "then";
3283
3284 } else if (!strcmp(s, "else")) {
3285 if (ex[3] != 'A') {
3286 s = "2 else";
3287 goto flush;
3288 }
3289 free(dlist_lpop(expect));
3290 end = "fi\0B";
3291 }
3292 }
3293
3294
3295 if (end) {
3296 if (!pl->type) pl->type = 2;
3297
3298 dlist_add(expect, end);
3299 if (!anystr(end, tails)) dlist_add(expect, 0);
3300 pl->count = -1;
3301 }
3302
3303
3304 if (!pl->type && anystr(s, (char *[]){"then", "do", "esac", "}", "]]", ")",
3305 "done", "fi", "elif", "else", 0})) goto flush;
3306 }
3307 free(delete);
3308
3309
3310 if (!*ppl) return 0;
3311 pl = (*ppl)->prev;
3312
3313
3314 if (pl->count != pl->here) return 1;
3315 if (*expect) return 1;
3316 if (pl->arg->v[pl->arg->c] && strcmp(pl->arg->v[pl->arg->c], "&")) return 1;
3317
3318
3319 for (;;) {
3320 if (pl->type=='f') {
3321 struct sh_function *funky;
3322
3323
3324 funky = xmalloc(sizeof(struct sh_function));
3325 funky->refcount = 1;
3326 funky->name = *pl->arg->v;
3327 *pl->arg->v = (void *)funky;
3328 pl->type = 'F';
3329
3330
3331 pl2 = pl->next;
3332
3333 (funky->pipeline = add_pl(&pl2, 0))->type = 'f';
3334
3335 for (i = 0, pl3 = pl2->next;;pl3 = pl3->next)
3336 if (pl3->type == 1) i++;
3337 else if (pl3->type == 3 && --i<0) break;
3338
3339 pl3->next->prev = pl;
3340 pl->next = pl3->next;
3341
3342 pl2->prev = 0;
3343 pl3->next = 0;
3344 }
3345 if (pl == *ppl) break;
3346 pl = pl->prev;
3347 }
3348
3349
3350
3351 dlist_terminate(*ppl);
3352 return 0;
3353
3354flush:
3355 if (s) syntax_err(s);
3356 llist_traverse(*ppl, free_pipeline);
3357 *ppl = 0;
3358 llist_traverse(*expect, free);
3359 *expect = 0;
3360
3361 return 0-!!s;
3362}
3363
3364
3365int find_plus_minus(int *minus)
3366{
3367 long long when, then;
3368 int i, plus;
3369
3370 if (minus) *minus = 0;
3371 for (then = i = plus = 0; i<TT.jobs.c; i++) {
3372 if ((when = ((struct sh_process *)TT.jobs.v[i])->when) > then) {
3373 then = when;
3374 if (minus) *minus = plus;
3375 plus = i;
3376 }
3377 }
3378
3379 return plus;
3380}
3381
3382char is_plus_minus(int i, int plus, int minus)
3383{
3384 return (i == plus) ? '+' : (i == minus) ? '-' : ' ';
3385}
3386
3387
3388
3389char *show_job(struct sh_process *pp, char dash)
3390{
3391 char *s = "Run", *buf = 0;
3392 int i, j, len, len2;
3393
3394
3395 if (pp->exit<0) s = "Stop";
3396 else if (pp->exit>126) s = "Kill";
3397 else if (pp->exit>0) s = "Done";
3398 for (i = len = len2 = 0;; i++) {
3399 len += snprintf(buf, len2, "[%d]%c %-6s", pp->job, dash, s);
3400 for (j = 0; j<pp->raw->c; j++)
3401 len += snprintf(buf, len2, " %s"+!j, pp->raw->v[j]);
3402 if (!i) buf = xmalloc(len2 = len+1);
3403 else break;
3404 }
3405
3406 return buf;
3407}
3408
3409
3410struct sh_process *wait_job(int pid, int nohang)
3411{
3412 struct sh_process *pp = pp;
3413 int ii, status, minus, plus;
3414
3415 if (TT.jobs.c<1) return 0;
3416 for (;;) {
3417 errno = 0;
3418 if (1>(pid = waitpid(pid, &status, nohang ? WNOHANG : 0))) {
3419 if (!nohang && errno==EINTR && !toys.signal) continue;
3420 return 0;
3421 }
3422 for (ii = 0; ii<TT.jobs.c; ii++) {
3423 pp = (void *)TT.jobs.v[ii];
3424 if (pp->pid == pid) break;
3425 }
3426 if (ii == TT.jobs.c) continue;
3427 if (pid<1) return 0;
3428 if (!WIFSTOPPED(status) && !WIFCONTINUED(status)) break;
3429 }
3430 plus = find_plus_minus(&minus);
3431 memmove(TT.jobs.v+ii, TT.jobs.v+ii+1, (TT.jobs.c--)-ii);
3432 pp->exit = WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status)+128;
3433 pp->dash = is_plus_minus(ii, plus, minus);
3434
3435 return pp;
3436}
3437
3438
3439static int wait_pipeline(struct sh_process *pp)
3440{
3441 int rc = 0;
3442
3443 for (dlist_terminate(pp); pp; pp = pp->next) {
3444 if (pp->pid) {
3445
3446 pp->exit = xwaitpid(pp->pid);
3447 pp->pid = 0;
3448 }
3449
3450 rc = (pp->flags&PFLAG_NOT) ? !pp->exit : pp->exit;
3451 }
3452
3453 while ((pp = wait_job(-1, 1)) && (TT.options&FLAG_i)) {
3454 char *s = show_job(pp, pp->dash);
3455
3456 dprintf(2, "%s\n", s);
3457 free(s);
3458 }
3459
3460 return rc;
3461}
3462
3463
3464
3465static void do_prompt(char *prompt)
3466{
3467 char *s, *ss, c, cc, *pp = toybuf;
3468 int len, ll;
3469
3470 if (!prompt) return;
3471 while ((len = sizeof(toybuf)-(pp-toybuf))>0 && *prompt) {
3472 c = *(prompt++);
3473
3474 if (c=='!') {
3475 if (*prompt=='!') prompt++;
3476 else {
3477 pp += snprintf(pp, len, "%u", TT.LINENO);
3478 continue;
3479 }
3480 } else if (c=='\\') {
3481 cc = *(prompt++);
3482 if (!cc) {
3483 *pp++ = c;
3484 break;
3485 }
3486
3487
3488
3489 if (cc=='[' || cc==']') continue;
3490 else if (cc=='$') *pp++ = getuid() ? '$' : '#';
3491 else if (cc=='h' || cc=='H') {
3492 *pp = 0;
3493 gethostname(pp, len);
3494 pp[len-1] = 0;
3495 if (cc=='h' && (s = strchr(pp, '.'))) *s = 0;
3496 pp += strlen(pp);
3497 } else if (cc=='s') {
3498 s = getbasename(*toys.argv);
3499 while (*s && len--) *pp++ = *s++;
3500 } else if (cc=='w') {
3501 if ((s = getvar("PWD"))) {
3502 if ((ss = getvar("HOME")) && strstart(&s, ss)) {
3503 *pp++ = '~';
3504 if (--len && *s!='/') *pp++ = '/';
3505 len--;
3506 }
3507 if (len>0) {
3508 ll = strlen(s);
3509 pp = stpncpy(pp, s, ll>len ? len : ll);
3510 }
3511 }
3512 } else if (!(c = unescape(cc))) {
3513 *pp++ = '\\';
3514 if (--len) *pp++ = c;
3515 } else *pp++ = c;
3516 } else *pp++ = c;
3517 }
3518 len = pp-toybuf;
3519 if (len>=sizeof(toybuf)) len = sizeof(toybuf);
3520 writeall(2, toybuf, len);
3521}
3522
3523
3524static char *get_next_line(FILE *ff, int prompt)
3525{
3526 char *new;
3527 int len, cc;
3528
3529 if (!ff) {
3530 char ps[16];
3531
3532 sprintf(ps, "PS%d", prompt);
3533 do_prompt(getvar(ps));
3534 }
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544 for (new = 0, len = 0;;) {
3545 errno = 0;
3546 if (!(cc = getc(ff ? : stdin))) {
3547 if (TT.LINENO) continue;
3548 free(new);
3549 return (char *)1;
3550 }
3551 if (cc<0) {
3552 if (errno == EINTR) continue;
3553 break;
3554 }
3555 if (!(len&63)) new = xrealloc(new, len+65);
3556 if (cc == '\n') break;
3557 new[len++] = cc;
3558 }
3559 if (new) new[len] = 0;
3560
3561 return new;
3562}
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582static void run_lines(void)
3583{
3584 char *ctl, *s, *ss, **vv;
3585 struct sh_process *pp, *pplist = 0;
3586 long i, j, k;
3587
3588
3589 for (;;) {
3590 if (!TT.ff->pl) {
3591 if (!end_function(1)) break;
3592 goto advance;
3593 }
3594
3595 ctl = TT.ff->pl->end->arg->v[TT.ff->pl->end->arg->c];
3596 s = *TT.ff->pl->arg->v;
3597 ss = TT.ff->pl->arg->v[1];
3598
3599 if (!pplist) TT.hfd = 10;
3600
3601
3602 if (TT.ff->pl->type<2) {
3603 if (!TT.ff->blk->run) {
3604 TT.ff->pl = TT.ff->pl->end->next;
3605
3606 continue;
3607 }
3608
3609 if (TT.options&OPT_x) {
3610 unsigned lineno;
3611 char *ss, *ps4 = getvar("PS4");
3612
3613
3614 if (ps4 && *ps4) {
3615 j = getutf8(ps4, k = strlen(ps4), 0);
3616 ss = xmalloc(TT.srclvl*j+k+1);
3617 for (k = 0; k<TT.srclvl; k++) memcpy(ss+k*j, ps4, j);
3618 strcpy(ss+k*j, ps4+j);
3619
3620 lineno = TT.LINENO;
3621 TT.LINENO = TT.ff->pl->lineno;
3622 do_prompt(ss);
3623 TT.LINENO = lineno;
3624 free(ss);
3625
3626
3627 ss = pl2str(TT.ff->pl, 1);
3628 dprintf(2, "%s\n", ss);
3629 free(ss);
3630 }
3631 }
3632
3633
3634 unredirect(TT.ff->blk->urd);
3635 TT.ff->blk->urd = 0;
3636 TT.ff->blk->pipe = 0;
3637
3638
3639 if (TT.ff->blk->pout != -1) {
3640 TT.ff->blk->pipe++;
3641 if (save_redirect(&TT.ff->blk->urd, TT.ff->blk->pout, 0)) break;
3642 close(TT.ff->blk->pout);
3643 TT.ff->blk->pout = -1;
3644 }
3645
3646
3647 if (ctl && *ctl == '|' && ctl[1] != '|') {
3648 int pipes[2] = {-1, -1};
3649
3650 TT.ff->blk->pipe++;
3651 if (pipe(pipes)) {
3652 perror_msg("pipe");
3653
3654 break;
3655 }
3656 if (save_redirect(&TT.ff->blk->urd, pipes[1], 1)) {
3657 close(pipes[0]);
3658 close(pipes[1]);
3659
3660 break;
3661 }
3662 if (pipes[1] != 1) close(pipes[1]);
3663 fcntl(TT.ff->blk->pout = *pipes, F_SETFD, FD_CLOEXEC);
3664 if (ctl[1] == '&') save_redirect(&TT.ff->blk->urd, 1, 2);
3665 }
3666 }
3667
3668
3669 if (!TT.ff->pl->type) {
3670
3671
3672 if (!strcmp(s, "break") || !strcmp(s, "continue")) {
3673
3674
3675 i = ss ? atol(ss) : 0;
3676 if (i<1) i = 1;
3677 if (TT.ff->blk->next && TT.ff->pl->arg->c<3
3678 && (!ss || !ss[strspn(ss,"0123456789")]))
3679 {
3680 while (i && TT.ff->blk->next)
3681 if (TT.ff->blk->middle && !strcmp(*TT.ff->blk->middle->arg->v, "do")
3682 && !--i && *s=='c') TT.ff->pl = TT.ff->blk->start;
3683 else TT.ff->pl = pop_block();
3684 }
3685 if (i) {
3686 syntax_err(s);
3687 break;
3688 }
3689
3690 } else dlist_add_nomalloc((void *)&pplist, (void *)run_command());
3691
3692
3693 } else if (TT.ff->pl->type == 1) {
3694
3695
3696
3697
3698 pp = expand_redir(TT.ff->pl->end->arg, 1, TT.ff->blk->urd);
3699 TT.ff->blk->urd = pp->urd;
3700 pp->urd = 0;
3701 if (pp->arg.c) syntax_err(*pp->arg.v);
3702 llist_traverse(pp->delete, llist_free_arg);
3703 pp->delete = 0;
3704 if (pp->exit || pp->arg.c) {
3705 free(pp);
3706 toys.exitval = 1;
3707
3708 break;
3709 }
3710 add_block();
3711
3712
3713
3714
3715 if (TT.ff->blk->pipe || !strcmp(s, "(") || (ctl && !strcmp(ctl, "&"))) {
3716 if (!(pp->pid = run_subshell(0, -1))) {
3717
3718
3719 pplist = 0;
3720 while (TT.ff->blk->next) TT.ff->blk = TT.ff->blk->next;
3721 TT.ff->blk->pout = -1;
3722 TT.ff->blk->urd = 0;
3723 TT.ff->pl = TT.ff->next->pl->next;
3724
3725 continue;
3726 }
3727 TT.ff->pl = TT.ff->pl->end;
3728 pop_block();
3729 dlist_add_nomalloc((void *)&pplist, (void *)pp);
3730
3731
3732 } else {
3733 free(pp);
3734
3735
3736
3737
3738
3739
3740 if (!strcmp(s, "for") || !strcmp(s, "select")) {
3741 if (TT.ff->blk->loop);
3742
3743
3744 else if (!strncmp(TT.ff->blk->fvar = ss, "((", 2)) {
3745 char *in = ss+2, *out;
3746 long long ll;
3747
3748 TT.ff->blk->loop = 1;
3749 for (i = 0; i<3; i++) {
3750 if (i==2) k = strlen(in)-2;
3751 else {
3752
3753 k = ';';
3754 pp = xzalloc(sizeof(*pp));
3755 if (expand_arg_nobrace(&pp->arg, ss+2, NO_PATH|NO_SPLIT,
3756 &pp->delete, 0, &k)) break;
3757 free_process(pp);
3758 if (in[k] != ';') break;
3759 }
3760 (out = xmalloc(k+1))[k] = 0;
3761 memcpy(out, in, k);
3762 arg_add(&TT.ff->blk->farg, push_arg(&TT.ff->blk->fdelete, out));
3763 in += k+1;
3764 }
3765 if (i!=3) {
3766 syntax_err(ss);
3767 break;
3768 }
3769 in = out = *TT.ff->blk->farg.v;
3770 if (!recalculate(&ll, &in, 0) || *in) {
3771 perror_msg("bad math: %s @ %ld", in, (long)(in-out));
3772 break;
3773 }
3774
3775
3776 } else if (TT.ff->pl->next->type == 's') {
3777 for (i = 1; i<TT.ff->pl->next->arg->c; i++)
3778 if (expand_arg(&TT.ff->blk->farg, TT.ff->pl->next->arg->v[i],
3779 0, &TT.ff->blk->fdelete)) break;
3780 if (i != TT.ff->pl->next->arg->c) TT.ff->pl = pop_block();
3781
3782
3783 } else expand_arg(&TT.ff->blk->farg, "\"$@\"", 0,
3784 &TT.ff->blk->fdelete);
3785
3786
3787 if (*s == 's') for (i = 0; i<TT.ff->blk->farg.c; i++)
3788 dprintf(2, "%ld) %s\n", i+1, TT.ff->blk->farg.v[i]);
3789
3790
3791 } else if (!strcmp(s, "case")) {
3792 TT.ff->blk->fvar = expand_one_arg(ss, NO_NULL, &TT.ff->blk->fdelete);
3793 if (!TT.ff->blk->fvar) break;
3794 }
3795
3796
3797 }
3798
3799
3800 } else if (TT.ff->pl->type == 2) {
3801 int match, err;
3802
3803 TT.ff->blk->middle = TT.ff->pl;
3804
3805
3806 if (!strcmp(*TT.ff->blk->start->arg->v, "case")) {
3807 if (!strcmp(s, ";;")) {
3808 while (TT.ff->pl->type!=3) TT.ff->pl = TT.ff->pl->end;
3809 continue;
3810 } else if (strcmp(s, ";&")) {
3811 struct sh_arg arg = {0}, arg2 = {0};
3812
3813 for (err = 0, vv = 0;;) {
3814 if (!vv) {
3815 vv = TT.ff->pl->arg->v + (**TT.ff->pl->arg->v == ';');
3816 if (!*vv) {
3817
3818 TT.ff->pl = TT.ff->pl->next;
3819 break;
3820 } else vv += **vv == '(';
3821 }
3822 arg.c = arg2.c = 0;
3823 if ((err = expand_arg_nobrace(&arg, *vv++, NO_SPLIT,
3824 &TT.ff->blk->fdelete, &arg2, 0))) break;
3825 s = arg.c ? *arg.v : "";
3826 match = wildcard_match(TT.ff->blk->fvar, s, &arg2, 0);
3827 if (match>=0 && !s[match]) break;
3828 else if (**vv++ == ')') {
3829 vv = 0;
3830 if ((TT.ff->pl = TT.ff->pl->end)->type!=2) break;
3831 }
3832 }
3833 free(arg.v);
3834 free(arg2.v);
3835 if (err) break;
3836 if (TT.ff->pl->type==3) continue;
3837 }
3838
3839
3840 } else if (!strcmp(s, "then"))
3841 TT.ff->blk->run = TT.ff->blk->run && !toys.exitval;
3842 else if (!strcmp(s, "else") || !strcmp(s, "elif"))
3843 TT.ff->blk->run = !TT.ff->blk->run;
3844
3845
3846 else if (!strcmp(s, "do")) {
3847 struct sh_blockstack *blk = TT.ff->blk;
3848
3849 ss = *blk->start->arg->v;
3850 if (!strcmp(ss, "while")) blk->run = blk->run && !toys.exitval;
3851 else if (!strcmp(ss, "until")) blk->run = blk->run && toys.exitval;
3852 else if (!strcmp(ss, "select")) {
3853 if (!(ss = get_next_line(0, 3)) || ss==(void *)1) {
3854 TT.ff->pl = pop_block();
3855 printf("\n");
3856 } else {
3857 match = atoi(ss);
3858 free(ss);
3859 if (!*ss) {
3860 TT.ff->pl = blk->start;
3861 continue;
3862 } else setvarval(blk->fvar, (match<1 || match>blk->farg.c)
3863 ? "" : blk->farg.v[match-1]);
3864 }
3865 } else if (blk->loop >= blk->farg.c) TT.ff->pl = pop_block();
3866 else if (!strncmp(blk->fvar, "((", 2)) {
3867 char *aa, *bb;
3868 long long ll;
3869
3870 for (i = 2; i; i--) {
3871 if (TT.ff->blk->loop == 1) {
3872 TT.ff->blk->loop++;
3873 i--;
3874 }
3875 aa = bb = TT.ff->blk->farg.v[i];
3876 if (!recalculate(&ll, &aa, 0) || *aa) {
3877 perror_msg("bad math: %s @ %ld", aa, (long)(aa-bb));
3878 break;
3879 }
3880 if (i==1 && !ll) TT.ff->pl = pop_block();
3881 }
3882 } else setvarval(blk->fvar, blk->farg.v[blk->loop++]);
3883 }
3884
3885
3886 } else if (TT.ff->pl->type == 3) {
3887
3888 if (!TT.ff->blk->next) xexit();
3889
3890
3891 if (TT.ff->blk->run && !strcmp(s, "done")) {
3892 TT.ff->pl = TT.ff->blk->middle;
3893 continue;
3894 }
3895
3896
3897 pop_block();
3898
3899
3900 } else if (TT.ff->pl->type == 'F') {
3901 struct sh_function *funky = (void *)*TT.ff->pl->arg->v;
3902
3903
3904 for (i = 0; i<TT.funcslen; i++)
3905 if (!strcmp(TT.functions[i]->name, funky->name)) break;
3906 if (i == TT.funcslen) {
3907 struct sh_arg arg = {(void *)TT.functions, TT.funcslen};
3908
3909 arg_add(&arg, (void *)funky);
3910 TT.functions = (void *)arg.v;
3911 TT.funcslen++;
3912 } else {
3913 free_function(TT.functions[i]);
3914 TT.functions[i] = funky;
3915 }
3916 TT.functions[i]->refcount++;
3917 }
3918
3919
3920
3921 if (pplist && TT.ff->blk->pout == -1) {
3922 if (ctl && !strcmp(ctl, "&")) {
3923 if (!TT.jobs.c) TT.jobcnt = 0;
3924 pplist->job = ++TT.jobcnt;
3925 arg_add(&TT.jobs, (void *)pplist);
3926 if (TT.options&FLAG_i) dprintf(2, "[%u] %u\n", pplist->job,pplist->pid);
3927 } else {
3928 toys.exitval = wait_pipeline(pplist);
3929 llist_traverse(pplist, (void *)free_process);
3930 }
3931 pplist = 0;
3932 }
3933advance:
3934
3935 if (!TT.ff->pl->type || TT.ff->pl->type == 3) {
3936 for (;;) {
3937 ctl = TT.ff->pl->arg->v[TT.ff->pl->arg->c];
3938 if (!ctl || strcmp(ctl, toys.exitval ? "&&" : "||")) break;
3939 if ((TT.ff->pl = TT.ff->pl->next)->type) TT.ff->pl = TT.ff->pl->end;
3940 }
3941 }
3942 TT.ff->pl = TT.ff->pl->next;
3943 }
3944
3945
3946 if (pplist) {
3947 toys.exitval = wait_pipeline(pplist);
3948 llist_traverse(pplist, (void *)free_process);
3949 }
3950
3951
3952 while (end_function(0));
3953}
3954
3955
3956static struct sh_vars *initvar(char *name, char *val)
3957{
3958 return addvar(xmprintf("%s=%s", name, val ? val : ""), TT.ff);
3959}
3960
3961static struct sh_vars *initvardef(char *name, char *val, char *def)
3962{
3963 return initvar(name, (!val || !*val) ? def : val);
3964}
3965
3966
3967static void set_varflags(char *str, unsigned set_flags, unsigned unset_flags)
3968{
3969 struct sh_vars *shv = 0;
3970 struct sh_fcall *ff;
3971 char *s;
3972
3973
3974 if (strchr(str, '=')) shv = setvar(xstrdup(str));
3975 else if (!(shv = findvar(str, &ff))) {
3976 if (!set_flags) return;
3977 shv = addvar(str = xmprintf("%s=", str), TT.ff->prev);
3978 shv->flags = VAR_WHITEOUT;
3979 } else if (shv->flags&VAR_WHITEOUT) shv->flags |= VAR_EXPORT;
3980 if (!shv || (shv->flags&VAR_EXPORT)) return;
3981
3982
3983 if (shv->flags&VAR_MAGIC) {
3984 s = shv->str;
3985 shv->str = xmprintf("%.*s=%s", (int)(varend(str)-str), str, getvar(str));
3986 if (!(shv->flags&VAR_NOFREE)) free(s);
3987 else shv->flags ^= VAR_NOFREE;
3988 }
3989 shv->flags |= set_flags;
3990 shv->flags &= ~unset_flags;
3991}
3992
3993static void export(char *str)
3994{
3995 set_varflags(str, VAR_EXPORT, 0);
3996}
3997
3998FILE *fpathopen(char *name)
3999{
4000 struct string_list *sl = 0;
4001 FILE *f = fopen(name, "r");
4002 char *pp = getvar("PATH") ? : _PATH_DEFPATH;
4003
4004 if (!f) {
4005 for (sl = find_in_path(pp, name); sl; free(llist_pop(&sl)))
4006 if ((f = fopen(sl->str, "r"))) break;
4007 if (sl) llist_traverse(sl, free);
4008 }
4009
4010 return f;
4011}
4012
4013
4014int do_source(char *name, FILE *ff)
4015{
4016 struct sh_pipeline *pl = 0;
4017 struct double_list *expect = 0;
4018 unsigned lineno = TT.LINENO, more = 0, wc;
4019 int cc, ii;
4020 char *new;
4021
4022 if (++TT.recursion>(50+200*CFG_TOYBOX_FORK)) {
4023 error_msg("recursive occlusion");
4024
4025 goto end;
4026 }
4027
4028 if (name) TT.ff->omnom = name;
4029
4030
4031
4032
4033 if (!name) TT.LINENO = 0;
4034
4035 do {
4036 if ((void *)1 == (new = get_next_line(ff, more+1))) goto is_binary;
4037
4038
4039 if (!TT.LINENO++ && name && new) {
4040
4041 for (ii = 0; new[ii]>6 && 0<(cc = utf8towc(&wc, new+ii, 4)); ii += cc);
4042 if (new[ii]) {
4043is_binary:
4044 if (name) error_msg("'%s' is binary", name);
4045 if (new != (void *)1) free(new);
4046 new = 0;
4047 }
4048 }
4049
4050
4051
4052
4053
4054 more = parse_line(new ? : " ", &pl, &expect);
4055 free(new);
4056 if (more==1) {
4057 if (!new) syntax_err("unexpected end of file");
4058 else continue;
4059 } else if (!more && pl) {
4060 TT.ff->pl = pl;
4061 run_lines();
4062 } else more = 0;
4063
4064 llist_traverse(pl, free_pipeline);
4065 pl = 0;
4066 llist_traverse(expect, free);
4067 expect = 0;
4068 } while (new);
4069
4070 if (ff) fclose(ff);
4071
4072 if (!name) TT.LINENO = lineno;
4073
4074end:
4075 TT.recursion--;
4076
4077 return more;
4078}
4079
4080
4081static void nommu_reentry(void)
4082{
4083 struct stat st;
4084 int ii, pid, ppid, len;
4085 unsigned long ll;
4086 char *s = 0;
4087 FILE *fp;
4088
4089
4090 if (!fstat(254, &st) && S_ISFIFO(st.st_mode)) {
4091 for (ii = len = 0; (s = environ[ii]); ii++) {
4092 if (*s!='@') continue;
4093 sscanf(s, "@%u,%u%n", &pid, &ppid, &len);
4094 break;
4095 }
4096 }
4097 if (!s || s[len] || pid!=getpid() || ppid!=getppid()) error_exit(0);
4098
4099
4100
4101
4102 if (5!=fscanf(fp = fdopen(254, "r"), "%lld %u %u %u %u%*[^\n]", &TT.SECONDS,
4103 &TT.options, &TT.LINENO, &TT.pid, &TT.bangpid)) error_exit(0);
4104
4105
4106 for (;;) {
4107 len = ll = 0;
4108 (void)fscanf(fp, "%u %lu%*[^\n]", &len, &ll);
4109 fgetc(fp);
4110 if (!len) break;
4111 (s = xmalloc(len+1))[len] = 0;
4112 for (ii = 0; ii<len; ii += pid)
4113 if (1>(pid = fread(s+ii, 1, len-ii, fp))) error_exit(0);
4114 set_varflags(s, ll, 0);
4115 }
4116
4117
4118 do_source(0, fp);
4119 xexit();
4120}
4121
4122
4123static void subshell_setup(void)
4124{
4125 int ii, from, uid = getuid();
4126 struct passwd *pw = getpwuid(uid);
4127 char *s, *ss, *magic[] = {"SECONDS", "RANDOM", "LINENO", "GROUPS", "BASHPID",
4128 "EPOCHREALTIME", "EPOCHSECONDS"},
4129 *readonly[] = {xmprintf("EUID=%d", geteuid()), xmprintf("UID=%d", uid),
4130 xmprintf("PPID=%d", getppid())};
4131 struct sh_vars *shv;
4132 struct utsname uu;
4133
4134
4135 for (ii = 0; ii<ARRAY_LEN(magic) && (s = magic[ii]); ii++)
4136 initvar(s, "")->flags = VAR_MAGIC+VAR_INT*('G'!=*s)+VAR_READONLY*('B'==*s);
4137 for (ii = 0; ii<ARRAY_LEN(readonly); ii++)
4138 addvar(readonly[ii], TT.ff)->flags = VAR_READONLY|VAR_INT;
4139
4140
4141 initvar("PATH", _PATH_DEFPATH);
4142 if (!pw) pw = (void *)toybuf;
4143 sprintf(toybuf+1024, "%u", uid);
4144 initvardef("HOME", pw->pw_dir, "/");
4145 initvardef("SHELL", pw->pw_shell, "/bin/sh");
4146 initvardef("USER", pw->pw_name, toybuf+1024);
4147 initvardef("LOGNAME", pw->pw_name, toybuf+1024);
4148 gethostname(toybuf, sizeof(toybuf)-1);
4149 initvar("HOSTNAME", toybuf);
4150 uname(&uu);
4151 initvar("HOSTTYPE", uu.machine);
4152 sprintf(toybuf, "%s-unknown-linux", uu.machine);
4153 initvar("MACHTYPE", toybuf);
4154 initvar("OSTYPE", uu.sysname);
4155
4156
4157 initvar("OPTERR", "1");
4158 if (readlink0("/proc/self/exe", s = toybuf, sizeof(toybuf))||(s=getenv("_")))
4159 initvar("BASH", s);
4160 initvar("PS2", "> ");
4161 initvar("PS3", "#? ");
4162 initvar("PS4", "+ ");
4163
4164
4165 for (from = 0; (s = environ[from]); from++) {
4166 if (*varend(s) != '=') continue;
4167 if (!(shv = findvar(s, 0))) addvar(s, TT.ff)->flags = VAR_EXPORT|VAR_NOFREE;
4168 else if (shv->flags&VAR_READONLY) continue;
4169 else {
4170 if (!(shv->flags&VAR_NOFREE)) {
4171 free(shv->str);
4172 shv->flags ^= VAR_NOFREE;
4173 }
4174 shv->flags |= VAR_EXPORT;
4175 shv->str = s;
4176 }
4177 cache_ifs(s, TT.ff);
4178 }
4179
4180
4181 do_source(0, fmemopen("cd .", 4, "r"));
4182
4183
4184 s = toys.argv[0];
4185 ss = 0;
4186 if (!strchr(s, '/')) {
4187 if ((ss = getcwd(0, 0))) {
4188 s = xmprintf("%s/%s", ss, s);
4189 free(ss);
4190 ss = s;
4191 } else if (*toybuf) s = toybuf;
4192 }
4193 setvarval("_", s)->flags |= VAR_EXPORT;
4194 free(ss);
4195
4196
4197 if (!(ss = getvar("SHLVL"))) export("SHLVL=1");
4198 else {
4199 char buf[16];
4200
4201 sprintf(buf, "%u", atoi(ss+6)+1);
4202 setvarval("SHLVL", buf)->flags |= VAR_EXPORT;
4203 }
4204}
4205
4206void sh_main(void)
4207{
4208 char *cc = 0;
4209 FILE *ff;
4210
4211
4212
4213 signal(SIGPIPE, SIG_IGN);
4214 TT.options = OPT_B;
4215 TT.pid = getpid();
4216 srandom(TT.SECONDS = millitime());
4217
4218
4219
4220
4221
4222
4223
4224
4225 if (toys.stacktop) {
4226 cc = TT.sh.c;
4227 if (!FLAG(c)) {
4228 if (toys.optc==1) toys.optflags |= FLAG_s;
4229 if (FLAG(s) && isatty(0)) toys.optflags |= FLAG_i;
4230 }
4231 if (toys.optc>1) {
4232 toys.optargs++;
4233 toys.optc--;
4234 }
4235 TT.options |= toys.optflags&0xff;
4236 }
4237
4238
4239 call_function();
4240 TT.ff->arg.v = toys.optargs;
4241 TT.ff->arg.c = toys.optc;
4242 TT.ff->ifs = " \t\n";
4243
4244
4245
4246
4247 if (CFG_TOYBOX_FORK || toys.stacktop) subshell_setup();
4248 else nommu_reentry();
4249
4250 if (TT.options&FLAG_i) {
4251 if (!getvar("PS1")) setvarval("PS1", getpid() ? "\\$ " : "# ");
4252
4253
4254
4255 xsignal(SIGINT, SIG_IGN);
4256 }
4257
4258 if (cc) ff = fmemopen(cc, strlen(cc), "r");
4259 else if (TT.options&FLAG_s) ff = (TT.options&FLAG_i) ? 0 : stdin;
4260 else if (!(ff = fpathopen(*toys.optargs))) perror_exit_raw(*toys.optargs);
4261
4262
4263 if (do_source(cc ? : *toys.optargs, ff))
4264 error_exit("%u:unfinished line"+3*!TT.LINENO, TT.LINENO);
4265}
4266
4267
4268
4269
4270
4271#define FOR_cd
4272#include "generated/flags.h"
4273void cd_main(void)
4274{
4275 char *from, *to = 0, *dd = *toys.optargs ? : (getvar("HOME") ? : "/"),
4276 *pwd = FLAG(P) ? 0 : getvar("PWD"), *zap = 0;
4277 struct stat st1, st2;
4278
4279
4280
4281
4282 if (!strcmp(dd, "-") && (!(dd = getvar("OLDPWD")) || !*dd))
4283 return perror_msg("No $OLDPWD");
4284
4285 if (*dd == '/') pwd = 0;
4286
4287
4288 if (pwd && !stat(".", &st1))
4289 if (stat(pwd, &st2) || st1.st_dev!=st2.st_dev || st1.st_ino!=st2.st_ino)
4290 pwd = 0;
4291
4292
4293 if (pwd) {
4294 zap = xmprintf("%s/%s", pwd, dd);
4295
4296
4297 for (from = to = zap; *from;) {
4298 if (*from=='/' && from[1]=='/') from++;
4299 else if (*from!='/' || from[1]!='.') *to++ = *from++;
4300 else if (!from[2] || from[2]=='/') from += 2;
4301 else if (from[2]=='.' && (!from[3] || from[3]=='/')) {
4302 from += 3;
4303 while (to>zap && *--to != '/');
4304 } else *to++ = *from++;
4305 }
4306 if (to == zap) to++;
4307 if (to-zap>1 && to[-1]=='/') to--;
4308 *to = 0;
4309 }
4310
4311
4312 if (!zap || chdir(zap)) {
4313 free(zap);
4314 if (chdir(dd)) return perror_msg("%s", dd);
4315 if (!(dd = getcwd(0, 0))) dd = xstrdup("(nowhere)");
4316 } else dd = zap;
4317
4318 if ((pwd = getvar("PWD"))) setvarval("OLDPWD", pwd);
4319 setvarval("PWD", dd);
4320 free(dd);
4321
4322 if (!(TT.options&OPT_cd)) {
4323 export("OLDPWD");
4324 export("PWD");
4325 TT.options |= OPT_cd;
4326 }
4327}
4328
4329void exit_main(void)
4330{
4331 exit(*toys.optargs ? atoi(*toys.optargs) : 0);
4332}
4333
4334
4335void set_main(void)
4336{
4337 char *cc, *ostr[] = {"braceexpand", "noclobber", "xtrace"};
4338 int ii, jj, kk, oo = 0, dd = 0;
4339
4340
4341 if (!*toys.optargs) {
4342 struct sh_vars **vv = visible_vars();
4343
4344
4345 for (ii = 0; vv[ii]; ii++)
4346 if (!(vv[ii]->flags&VAR_WHITEOUT)) printf("%s\n", vv[ii]->str);
4347 free(vv);
4348
4349 return;
4350 }
4351
4352
4353 for (ii = 0;; ii++) {
4354 if ((cc = toys.optargs[ii]) && !(dd = stridx("-+", *cc)+1) && oo--) {
4355 for (jj = 0; jj<ARRAY_LEN(ostr); jj++) if (!strcmp(cc, ostr[jj])) break;
4356 if (jj != ARRAY_LEN(ostr)) {
4357 if (dd==1) TT.options |= OPT_B<<kk;
4358 else TT.options &= ~(OPT_B<<kk);
4359
4360 continue;
4361 }
4362 error_exit("bad -o %s", cc);
4363 }
4364 if (oo>0) for (jj = 0; jj<ARRAY_LEN(ostr); jj++)
4365 printf("%s\t%s\n", ostr[jj], TT.options&(OPT_B<<jj) ? "on" : "off");
4366 oo = 0;
4367 if (!cc || !dd) break;
4368 for (jj = 1; cc[jj]; jj++) {
4369 if (cc[jj] == 'o') oo++;
4370 else if (-1 != (kk = stridx("BCx", cc[jj]))) {
4371 if (*cc == '-') TT.options |= OPT_B<<kk;
4372 else TT.options &= ~(OPT_B<<kk);
4373 } else error_exit("bad -%c", toys.optargs[ii][1]);
4374 }
4375 }
4376
4377
4378 if (cc) {
4379 struct arg_list *al, **head;
4380 struct sh_arg *arg = &TT.ff->arg;
4381
4382
4383 for (al = *(head = &TT.ff->delete); al; al = *(head = &al->next))
4384 if (al->arg == (void *)arg->v) break;
4385
4386
4387 if (al) for (jj = arg->c+1; jj; jj--) {
4388 *head = al->next;
4389 free(al->arg);
4390 free(al);
4391 }
4392
4393 while (toys.optargs[ii])
4394 arg_add(arg, push_arg(&TT.ff->delete, strdup(toys.optargs[ii++])));
4395 push_arg(&TT.ff->delete, arg->v);
4396 }
4397}
4398
4399
4400#define FOR_unset
4401#include "generated/flags.h"
4402
4403void unset_main(void)
4404{
4405 char **arg, *s;
4406 int ii;
4407
4408 for (arg = toys.optargs; *arg; arg++) {
4409 s = varend(*arg);
4410 if (s == *arg || *s) {
4411 error_msg("bad '%s'", *arg);
4412 continue;
4413 }
4414
4415
4416
4417 if (!FLAG(f) && unsetvar(*arg)) continue;
4418
4419 for (ii = 0; ii<TT.funcslen; ii++)
4420 if (!strcmp(*arg, TT.functions[ii]->name)) break;
4421 if (ii != TT.funcslen) {
4422 free_function(TT.functions[ii]);
4423 memmove(TT.functions+ii, TT.functions+ii+1, TT.funcslen+1-ii);
4424 }
4425 }
4426}
4427
4428#define FOR_export
4429#include "generated/flags.h"
4430
4431void export_main(void)
4432{
4433 char **arg, *eq;
4434
4435
4436 if (!toys.optc) {
4437 struct sh_vars **vv = visible_vars();
4438 unsigned uu;
4439
4440 for (uu = 0; vv[uu]; uu++) {
4441 if ((vv[uu]->flags&(VAR_WHITEOUT|VAR_EXPORT))==VAR_EXPORT) {
4442 xputs(eq = declarep(vv[uu]));
4443 free(eq);
4444 }
4445 }
4446 free(vv);
4447
4448 return;
4449 }
4450
4451
4452 for (arg = toys.optargs; *arg; arg++) {
4453 eq = varend(*arg);
4454 if (eq == *arg || (*eq && eq[*eq=='+'] != '=')) {
4455 error_msg("bad %s", *arg);
4456 continue;
4457 }
4458
4459 if (FLAG(n)) set_varflags(*arg, 0, VAR_EXPORT);
4460 else export(*arg);
4461 }
4462}
4463
4464#define FOR_declare
4465#include "generated/flags.h"
4466
4467void declare_main(void)
4468{
4469 unsigned uu, fl = toys.optflags&(FLAG(p)-1);
4470 char *ss, **arg;
4471
4472
4473
4474 if (!toys.optc) {
4475 struct sh_vars **vv = visible_vars();
4476
4477 for (uu = 0; vv[uu]; uu++) {
4478 if ((vv[uu]->flags&VAR_WHITEOUT) || (fl && !(vv[uu]->flags&fl))) continue;
4479 xputs(ss = declarep(vv[uu]));
4480 free(ss);
4481 }
4482 free(vv);
4483 } else if (FLAG(p)) for (arg = toys.optargs; *arg; arg++) {
4484 struct sh_vars *vv = *varend(ss = *arg) ? 0 : findvar(ss, 0);
4485
4486 if (!vv) perror_msg("%s: not found", ss);
4487 else {
4488 xputs(ss = declarep(vv));
4489 free(ss);
4490 }
4491 } else for (arg = toys.optargs; *arg; arg++) {
4492 ss = varend(*arg);
4493 if (ss == *arg || (*ss && ss[*ss=='+'] != '=')) {
4494 error_msg("bad %s", *arg);
4495 continue;
4496 }
4497 set_varflags(*arg, toys.optflags<<1, 0);
4498 }
4499}
4500
4501void eval_main(void)
4502{
4503 char *s;
4504
4505
4506 call_function();
4507 TT.ff->arg.v = toys.argv;
4508 TT.ff->arg.c = toys.optc+1;
4509 s = expand_one_arg("\"$*\"", SEMI_IFS, 0);
4510 TT.ff->arg.v = TT.ff->next->arg.v;
4511 TT.ff->arg.c = TT.ff->next->arg.c;
4512 do_source(0, fmemopen(s, strlen(s), "r"));
4513 free(dlist_pop(&TT.ff));
4514 free(s);
4515}
4516
4517#define FOR_exec
4518#include "generated/flags.h"
4519
4520void exec_main(void)
4521{
4522 char *ee[1] = {0}, **old = environ;
4523
4524
4525 free(TT.pp->urd);
4526 TT.pp->urd = 0;
4527 if (!toys.optc) return;
4528
4529
4530 TT.isexec = *toys.optargs;
4531 if (FLAG(c)) environ = ee;
4532 if (TT.exec.a || FLAG(l))
4533 *toys.optargs = xmprintf("%s%s", FLAG(l) ? "-" : "", TT.exec.a?:TT.isexec);
4534 sh_exec(toys.optargs);
4535
4536
4537 perror_msg("%s", TT.isexec);
4538 if (*toys.optargs != TT.isexec) free(*toys.optargs);
4539 TT.isexec = 0;
4540 toys.exitval = 127;
4541 environ = old;
4542}
4543
4544
4545
4546
4547int find_job(char *s)
4548{
4549 char *ss;
4550 long ll = strtol(s, &ss, 10);
4551 int i, j;
4552
4553 if (!TT.jobs.c) return -1;
4554 if (!*s || (!s[1] && strchr("%+-", *s))) {
4555 int minus, plus = find_plus_minus(&minus);
4556
4557 return (*s == '-') ? minus : plus;
4558 }
4559
4560
4561 if (s != ss && !*ss)
4562 for (i = 0; i<TT.jobs.c; i++)
4563 if (((struct sh_process *)TT.jobs.v[i])->job == ll) return i;
4564
4565
4566 for (i = 0; i<TT.jobs.c; i++) {
4567 struct sh_process *pp = (void *)TT.jobs.v[i];
4568
4569 if (strstart(&s, *pp->arg.v)) return i;
4570 if (*s != '?' || !s[1]) continue;
4571 for (j = 0; j<pp->arg.c; j++) if (strstr(pp->arg.v[j], s+1)) return i;
4572 }
4573
4574 return -1;
4575}
4576
4577void jobs_main(void)
4578{
4579 int i, j, minus, plus = find_plus_minus(&minus);
4580 char *s;
4581
4582
4583
4584 for (i = 0;;i++) {
4585 if (toys.optc) {
4586 if (!(s = toys.optargs[i])) break;
4587 if ((j = find_job(s+('%' == *s))) == -1) {
4588 perror_msg("%s: no such job", s);
4589
4590 continue;
4591 }
4592 } else if ((j = i) >= TT.jobs.c) break;
4593
4594 s = show_job((void *)TT.jobs.v[i], is_plus_minus(i, plus, minus));
4595 printf("%s\n", s);
4596 free(s);
4597 }
4598}
4599
4600#define FOR_local
4601#include "generated/flags.h"
4602
4603void local_main(void)
4604{
4605 struct sh_fcall *ff, *ff2;
4606 struct sh_vars *var;
4607 char **arg, *eq;
4608
4609
4610 for (ff = TT.ff;; ff = ff->next) {
4611 if (ff == TT.ff->prev) return error_msg("not in function");
4612 if (ff->vars) break;
4613 }
4614
4615
4616 if (!toys.optc) {
4617 for (var = ff->vars; var; var++) xputs(var->str);
4618 return;
4619 }
4620
4621
4622 for (arg = toys.optargs; *arg; arg++) {
4623 if ((eq = varend(*arg)) == *arg || (*eq && *eq != '=')) {
4624 error_msg("bad %s", *arg);
4625 continue;
4626 }
4627
4628 if ((var = findvar(*arg, &ff2)) && ff == ff2 && !*eq) continue;
4629 if (var && (var->flags&VAR_READONLY)) {
4630 error_msg("%.*s: readonly variable", (int)(varend(*arg)-*arg), *arg);
4631 continue;
4632 }
4633
4634
4635 if (!var || ff!=ff2) {
4636 int flags = var ? var->flags&VAR_EXPORT : 0;
4637
4638 var = addvar(xmprintf("%s%s", *arg, *eq ? "" : "="), ff);
4639 var->flags = flags|(VAR_WHITEOUT*!*eq);
4640 }
4641
4642
4643
4644 }
4645}
4646
4647void shift_main(void)
4648{
4649 long long by = 1;
4650
4651 if (toys.optc) by = atolx(*toys.optargs);
4652 by += TT.ff->shift;
4653 if (by<0 || by>=TT.ff->arg.c) toys.exitval++;
4654 else TT.ff->shift = by;
4655}
4656
4657void source_main(void)
4658{
4659 char *name = *toys.optargs;
4660 FILE *ff = fpathopen(name);
4661
4662 if (!ff) return perror_msg_raw(name);
4663
4664
4665 *toys.optargs = *toys.argv;
4666 ++TT.srclvl;
4667 call_function();
4668 TT.ff->arg.v = toys.optargs;
4669 TT.ff->arg.c = toys.optc;
4670 TT.ff->oldlineno = TT.LINENO;
4671 TT.LINENO = 0;
4672 do_source(name, ff);
4673 TT.LINENO = TT.ff->oldlineno;
4674 free(dlist_pop(&TT.ff));
4675 --TT.srclvl;
4676}
4677
4678#define FOR_wait
4679#include "generated/flags.h"
4680
4681void wait_main(void)
4682{
4683 struct sh_process *pp;
4684 int ii, jj;
4685 long long ll;
4686 char *s;
4687
4688
4689 if (FLAG(n)) toys.exitval = free_process(wait_job(-1, 0));
4690 else if (!toys.optc) while (TT.jobs.c) {
4691 if (!(pp = wait_job(-1, 0))) break;
4692 } else for (ii = 0; ii<toys.optc; ii++) {
4693 ll = estrtol(toys.optargs[ii], &s, 10);
4694 if (errno || *s) {
4695 if (-1 == (jj = find_job(toys.optargs[ii]))) {
4696 error_msg("%s: bad pid/job", toys.optargs[ii]);
4697 continue;
4698 }
4699 ll = ((struct sh_process *)TT.jobs.v[jj])->pid;
4700 }
4701 if (!(pp = wait_job(ll, 0))) {
4702 if (toys.signal) toys.exitval = 128+toys.signal;
4703 break;
4704 }
4705 toys.exitval = free_process(pp);
4706 }
4707}
4708