aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2009-04-23 00:05:31 +1000
committerNguyễn Thái Ngọc Duy <pclouds@gmail.com>2009-04-23 04:44:41 +1000
commit560c665526a24446df2d5c3f069574d2b4d432d6 (patch)
treeab6abff54c82a287487e4bf4ec76e840b30ffc78 /shell
parent1e0286a58015a0b39b61984edd1ae409f74d4fff (diff)
downloadbusybox-w32-560c665526a24446df2d5c3f069574d2b4d432d6.tar.gz
busybox-w32-560c665526a24446df2d5c3f069574d2b4d432d6.tar.bz2
busybox-w32-560c665526a24446df2d5c3f069574d2b4d432d6.zip
shell/ash: add basic code for transferring internal data
Because there is no such thing like fork() on Windows, we somehow need a way to "clone" a shell process. This code streamlines important information that a subshell will need, make it ready for sending to the subshell.
Diffstat (limited to 'shell')
-rw-r--r--shell/ash_mingw.c783
1 files changed, 783 insertions, 0 deletions
diff --git a/shell/ash_mingw.c b/shell/ash_mingw.c
new file mode 100644
index 000000000..c52d8b45c
--- /dev/null
+++ b/shell/ash_mingw.c
@@ -0,0 +1,783 @@
1extern void trace_printf(const char *format, ...);
2extern void trace_argv_printf(const char **argv, const char *format, ...);
3
4#define SER_TBLENTRY -100
5#define SER_VARTAB -102
6#define SER_LOCALVARS -103
7#define SER_OPTLIST -104
8#define SER_FORK -105
9#define SER_DONE -106
10#define SER_MISC -107
11
12/* * * * * serialization routines * * * * */
13static void node_send(int fd, union node *n);
14static union node *node_recv(int fd);
15
16#define SERDES_DEBUG 0
17
18static inline void
19ser_read(int fd, void *buf, size_t len)
20{
21 if (xread(fd, buf, len) != len)
22 die("Corrupted");
23}
24
25static void
26str_send(int fd, const char *s)
27{
28 int size = s ? strlen(s)+1 : -1;
29 if (SERDES_DEBUG) fprintf(stderr," --> String(%d:%d %s)", size, s ? (int)(unsigned char)*s : 0,s ? s+1 : 0);
30 write(fd, &size, sizeof(int));
31 if (s)
32 write(fd, s, size);
33}
34
35static char*
36str_recv(int fd)
37{
38 int size;
39 char *s;
40 ser_read(fd, &size, sizeof(int));
41 if (size == -1)
42 s = NULL;
43 else {
44 s = ckmalloc(size);
45 ser_read(fd, s, size);
46 }
47 if (SERDES_DEBUG) fprintf(stderr," <-- String(%d:%s)", size, s);
48 return s;
49}
50
51static void
52int_send(int fd, int n)
53{
54 write(fd, &n, sizeof(int));
55 if (SERDES_DEBUG) fprintf(stderr," --> Int(%d)", n);
56}
57
58static int
59int_recv(int fd)
60{
61 int n;
62 ser_read(fd, &n, sizeof(int));
63 if (SERDES_DEBUG) fprintf(stderr," <-- Int(%d)", n);
64 return n;
65}
66
67static void
68guard_send(int fd, int n)
69{
70 write(fd, &n, sizeof(int));
71 if (SERDES_DEBUG) fprintf(stderr,"\n--> Guard(%d)\n", n);
72}
73
74static void
75guard_recv1(int fd, int n1)
76{
77 int n;
78 ser_read(fd, &n, sizeof(int));
79 if (SERDES_DEBUG) fprintf(stderr,"\n<-- Guard1(%d,%d)\n", n, n1);
80 if (n != n1)
81 die("Corrupted");
82}
83
84static int
85guard_recv2(int fd, int n1, int n2)
86{
87 int n;
88 ser_read(fd, &n, sizeof(int));
89 if (SERDES_DEBUG) fprintf(stderr,"\n<-- Guard2(%d,%d,%d)\n", n, n1,n2);
90 if (n != n1 && n != n2)
91 die("Corrupted");
92 return n;
93}
94
95static void
96buf_send(int fd, void *buf, int size)
97{
98 write(fd, buf, size);
99 if (SERDES_DEBUG) fprintf(stderr," --> Buf(%d) ", size);
100}
101
102static void
103buf_recv(int fd, void *buf, int size)
104{
105 ser_read(fd, buf, size);
106 if (SERDES_DEBUG) fprintf(stderr," <-- Buf(%d) ", size);
107}
108
109static void
110nodelist_send(int fd, struct nodelist *nl)
111{
112 int id;
113 for (id = 0;nl;nl = nl->next) {
114 guard_send(fd, id++);
115 node_send(fd, nl->n);
116 }
117 guard_send(fd, -1);
118}
119
120static struct nodelist *
121nodelist_recv(int fd)
122{
123 int id = 0;
124 struct nodelist *head = NULL, *tail = NULL;
125 union node *n;
126 do {
127 if (guard_recv2(fd, id++, -1) == -1)
128 break;
129 n = node_recv(fd);
130 if (tail) {
131 tail->next = ckmalloc(sizeof(struct nodelist));
132 tail->next->next = NULL;
133 tail->next->n = n;
134 tail = tail->next;
135 } else {
136 head = tail = ckmalloc(sizeof(struct nodelist));
137 tail->next = NULL;
138 tail->n = n;
139 }
140 } while (1);
141 return head;
142}
143
144static void
145node_send(int fd, union node *n)
146{
147 int type = n ? n->type : -2;
148 int size;
149
150 int_send(fd, type);
151 if (!n)
152 return;
153
154 switch (type) {
155 case NCMD:
156 size = sizeof(struct ncmd);
157 break;
158 case NPIPE:
159 size = sizeof(struct npipe);
160 break;
161 case NREDIR:
162 case NBACKGND:
163 case NSUBSHELL:
164 size = sizeof(struct nredir);
165 break;
166 case NAND:
167 case NOR:
168 case NSEMI:
169 case NWHILE:
170 case NUNTIL:
171 size = sizeof(struct nbinary);
172 break;
173 case NIF:
174 size = sizeof(struct nif);
175 break;
176 case NFOR:
177 size = sizeof(struct nfor);
178 break;
179 case NCASE:
180 size = sizeof(struct ncase);
181 break;
182 case NCLIST:
183 size = sizeof(struct nclist);
184 break;
185 case NDEFUN:
186 case NARG:
187 size = sizeof(struct narg);
188 break;
189 case NTO:
190 case NCLOBBER:
191 case NFROM:
192 case NFROMTO:
193 case NAPPEND:
194 size = sizeof(struct nfile);
195 break;
196 case NTOFD:
197 case NFROMFD:
198 size = sizeof(struct ndup);
199 break;
200 case NXHERE:
201 case NHERE:
202 size = sizeof(struct nhere);
203 break;
204 case NNOT:
205 size = sizeof(struct nnot);
206 break;
207 default:
208 die("Unknown construct type");
209 }
210 int_send(fd, size);
211
212 switch (type) {
213 case NCMD:
214 node_send(fd, n->ncmd.assign);
215 node_send(fd, n->ncmd.args);
216 node_send(fd, n->ncmd.redirect);
217 break;
218
219 case NPIPE:
220 int_send(fd, n->npipe.backgnd);
221 nodelist_send(fd, n->npipe.cmdlist);
222 break;
223
224 case NREDIR:
225 case NBACKGND:
226 case NSUBSHELL:
227 node_send(fd, n->nredir.n);
228 node_send(fd, n->nredir.redirect);
229 break;
230
231 case NAND:
232 case NOR:
233 case NSEMI:
234 case NWHILE:
235 case NUNTIL:
236 node_send(fd, n->nbinary.ch1);
237 node_send(fd, n->nbinary.ch2);
238 break;
239
240 case NIF:
241 node_send(fd, n->nif.test);
242 node_send(fd, n->nif.ifpart);
243 node_send(fd, n->nif.elsepart);
244 break;
245
246 case NFOR:
247 node_send(fd, n->nfor.args);
248 node_send(fd, n->nfor.body);
249 str_send(fd, n->nfor.var);
250 break;
251
252 case NCASE:
253 node_send(fd, n->ncase.expr);
254 node_send(fd, n->ncase.cases);
255 break;
256
257 case NCLIST:
258 node_send(fd, n->nclist.next);
259 node_send(fd, n->nclist.pattern);
260 node_send(fd, n->nclist.body);
261 break;
262
263 case NDEFUN:
264 case NARG:
265 node_send(fd, n->narg.next);
266 str_send(fd, n->narg.text);
267 nodelist_send(fd, n->narg.backquote);
268 break;
269
270 case NTO:
271 case NCLOBBER:
272 case NFROM:
273 case NFROMTO:
274 case NAPPEND:
275 node_send(fd, n->nfile.next);
276 int_send(fd, n->nfile.fd);
277 node_send(fd, n->nfile.fname);
278 //str_send(fd, n->nfile.expfname);
279 break;
280
281 case NTOFD:
282 case NFROMFD:
283 node_send(fd, n->ndup.next);
284 int_send(fd, n->ndup.fd);
285 int_send(fd, n->ndup.dupfd);
286 node_send(fd, n->ndup.vname);
287 break;
288
289 case NXHERE:
290 case NHERE:
291 node_send(fd, n->nhere.next);
292 int_send(fd, n->nhere.fd);
293 node_send(fd, n->nhere.doc);
294 break;
295
296 case NNOT:
297 node_send(fd, n->nnot.com);
298 break;
299
300 default:
301 die("Unknown construct type");
302 }
303 guard_send(fd, -1);
304}
305
306static union node*
307node_recv(int fd)
308{
309 int type;
310 int size;
311 union node *n;
312
313 type = int_recv(fd);
314 if (type == -2)
315 return NULL;
316 size = int_recv(fd);
317 n = ckmalloc(size);
318 n->type = type;
319
320 switch (type) {
321 case NCMD:
322 n->ncmd.assign = node_recv(fd);
323 n->ncmd.args = node_recv(fd);
324 n->ncmd.redirect = node_recv(fd);
325 break;
326
327 case NPIPE:
328 n->npipe.backgnd = int_recv(fd);
329 n->npipe.cmdlist = nodelist_recv(fd);
330 break;
331
332 case NREDIR:
333 case NBACKGND:
334 case NSUBSHELL:
335 n->nredir.n = node_recv(fd);
336 n->nredir.redirect = node_recv(fd);
337 break;
338
339 case NAND:
340 case NOR:
341 case NSEMI:
342 case NWHILE:
343 case NUNTIL:
344 n->nbinary.ch1 = node_recv(fd);
345 n->nbinary.ch2 = node_recv(fd);
346 break;
347
348 case NIF:
349 n->nif.test = node_recv(fd);
350 n->nif.ifpart = node_recv(fd);
351 n->nif.elsepart = node_recv(fd);
352 break;
353
354 case NFOR:
355 n->nfor.args = node_recv(fd);
356 n->nfor.body = node_recv(fd);
357 n->nfor.var = str_recv(fd);
358 break;
359
360 case NCASE:
361 n->ncase.expr = node_recv(fd);
362 n->ncase.cases = node_recv(fd);
363 break;
364
365 case NCLIST:
366 n->nclist.next = node_recv(fd);
367 n->nclist.pattern = node_recv(fd);
368 n->nclist.body = node_recv(fd);
369 break;
370
371 case NDEFUN:
372 case NARG:
373 n->narg.next = node_recv(fd);
374 n->narg.text = str_recv(fd);
375 n->narg.backquote = nodelist_recv(fd);
376 break;
377
378 case NTO:
379 case NCLOBBER:
380 case NFROM:
381 case NFROMTO:
382 case NAPPEND:
383 n->nfile.next = node_recv(fd);
384 n->nfile.fd = int_recv(fd);
385 n->nfile.fname = node_recv(fd);
386 //n->nfile.expfname = str_recv(fd);
387 break;
388
389 case NTOFD:
390 case NFROMFD:
391 n->ndup.next = node_recv(fd);
392 n->ndup.fd = int_recv(fd);
393 n->ndup.dupfd = int_recv(fd);
394 n->ndup.vname = node_recv(fd);
395 break;
396
397 case NXHERE:
398 case NHERE:
399 n->nhere.next = node_recv(fd);
400 n->nhere.fd = int_recv(fd);
401 n->nhere.doc = node_recv(fd);
402 break;
403
404 case NNOT:
405 n->nnot.com = node_recv(fd);
406 break;
407
408 default:
409 die("Unknown construct type");
410 }
411
412 guard_recv1(fd, -1);
413 return n;
414}
415
416static void
417funcnode_send(int fd, struct funcnode *n)
418{
419 int_send(fd, n->count);
420 node_send(fd, &n->n);
421 guard_send(fd, -1);
422}
423
424static struct funcnode*
425funcnode_recv(int fd)
426{
427 struct funcnode *fn;
428 union node *n;
429
430 fn = ckmalloc(sizeof(struct funcnode));
431 fn->count = int_recv(fd);
432 n = node_recv(fd);
433 memcpy(&fn->n, n, sizeof(union node));
434 free(n);
435 guard_recv1(fd, -1);
436 return fn;
437}
438
439static void
440tblentry_send(int fd)
441{
442 int i, id = 0;
443 struct tblentry *e;
444 int size;
445
446 guard_send(fd, SER_TBLENTRY);
447 for (i = 0;i < CMDTABLESIZE;i ++) {
448 for (e = cmdtable[i];e;e = e->next) {
449 guard_send(fd, id++);
450 int_send(fd, i);
451 size = sizeof(struct tblentry) - ARB + strlen(e->cmdname) + 1;
452 int_send(fd, size);
453 buf_send(fd, e, size);
454 switch (e->cmdtype) {
455 case CMDUNKNOWN:
456 case CMDNORMAL:
457 break;
458
459 case CMDBUILTIN:
460 int_send(fd, e->param.cmd - builtintab);
461 break;
462
463 case CMDFUNCTION:
464 funcnode_send(fd, e->param.func);
465 break;
466 }
467 }
468 }
469 guard_send(fd, -1);
470}
471
472static void
473tblentry_recv(int fd)
474{
475 int i = 0;
476 int size;
477 struct tblentry *e;
478 int id = 0;
479
480 guard_recv1(fd, SER_TBLENTRY);
481
482 do {
483 if (guard_recv2(fd, id++, -1) == -1)
484 break;
485 i = int_recv(fd);
486 size = int_recv(fd);
487 e = ckmalloc(size);
488 buf_recv(fd, e, size);
489 switch (e->cmdtype) {
490 case CMDUNKNOWN:
491 case CMDNORMAL:
492 break;
493
494 case CMDBUILTIN:
495 e->param.cmd = &builtintab[int_recv(fd)];
496 break;
497
498 case CMDFUNCTION:
499 e->param.func = funcnode_recv(fd);
500 break;
501 }
502 e->next = cmdtable[i];
503 cmdtable[i] = e;
504 } while (1);
505}
506
507static void
508var_send(int fd, struct var *v)
509{
510 int_send(fd, v->flags);
511 str_send(fd, v->text);
512}
513
514static struct var*
515var_recv(int fd)
516{
517 struct var *v = ckmalloc(sizeof(struct var));
518 memset(v, 0, sizeof(struct var));
519 v->flags = int_recv(fd);
520 v->text = str_recv(fd);
521 return v;
522}
523
524static void
525vartab_send(int fd)
526{
527 int i;
528 struct var *v;
529 int id = 0;
530
531 guard_send(fd, SER_VARTAB);
532 for (i = 0;i < VTABSIZE;i++)
533 for (v = vartab[i];v;v = v->next) {
534 guard_send(fd, id++);
535 int_send(fd, i);
536 var_send(fd, v);
537 }
538 guard_send(fd, -1);
539}
540
541static void
542vartab_recv(int fd)
543{
544 int i;
545 struct var *v;
546 int id = 0;
547
548 guard_recv1(fd, SER_VARTAB);
549 do {
550 if (guard_recv2(fd, id++, -1) == -1)
551 break;
552 i = int_recv(fd);
553 v = var_recv(fd);
554 v->next = vartab[i];
555 vartab[i] = v;
556 } while (1);
557}
558
559static void
560localvar_send(int fd, struct localvar *lv)
561{
562 var_send(fd,lv->vp);
563 int_send(fd, lv->flags);
564 str_send(fd, lv->text);
565}
566
567static struct localvar*
568localvar_recv(int fd)
569{
570 int i;
571 struct var *v;
572 struct localvar *lv;
573 lv = ckmalloc(sizeof(struct localvar));
574 memset(lv, 0, sizeof(struct localvar));
575 lv->vp = var_recv(fd);
576 for (i = 0, v = vartab[0];i < VTABSIZE;v = v && v->next ? v->next : vartab[i++])
577 if (v && !strcmp(v->text, lv->vp->text)) {
578 free((char*)lv->vp->text);
579 free(lv->vp);
580 lv->vp = v;
581 break;
582 }
583
584 if (i == VTABSIZE) {
585 struct var **vp;
586 vp = hashvar(lv->vp->text);
587 *vp = lv->vp;
588 lv->vp->next = *vp;
589 }
590
591 lv->flags = int_recv(fd);
592 lv->text = str_recv(fd);
593 return lv;
594}
595
596static void
597localvars_send(int fd)
598{
599 struct localvar *lv;
600 int id = 0;
601
602 guard_send(fd, SER_LOCALVARS);
603 for (lv = localvars;lv;lv = lv->next) {
604 guard_send(fd, id++);
605 localvar_send(fd, lv);
606 }
607 guard_send(fd, -1);
608}
609
610static void
611localvars_recv(int fd)
612{
613 struct localvar *lv;
614 int id = 0;
615
616 guard_recv1(fd, SER_LOCALVARS);
617 do {
618 if (guard_recv2(fd, id++, -1) == -1)
619 break;
620 lv = localvar_recv(fd);
621 lv->next = localvars;
622 localvars = lv;
623 } while (1);
624}
625
626static void
627optlist_send(int fd)
628{
629 guard_send(fd, SER_OPTLIST);
630 buf_send(fd, optlist, sizeof(optlist));
631 guard_send(fd, -1);
632}
633
634static void
635optlist_recv(int fd)
636{
637 guard_recv1(fd, SER_OPTLIST);
638 buf_recv(fd, optlist, sizeof(optlist));
639 guard_recv1(fd, -1);
640}
641
642static void
643sig_send(int fd)
644{
645 int i;
646 for (i = 0;i < NSIG;i++) {
647 guard_send(fd, i);
648 /* str_send(fd, trap[i]); */
649 int_send(fd, sigmode[i]);
650 int_send(fd, gotsig[i]);
651 }
652 guard_send(fd, -1);
653}
654
655static void
656sig_recv(int fd)
657{
658 int i;
659 for (i = 0;i < NSIG;i++) {
660 guard_recv1(fd, i);
661 /* trap[i] = str_recv(fd); */
662 sigmode[i] = int_recv(fd);
663 gotsig[i] = int_recv(fd);
664 }
665 guard_recv1(fd, -1);
666}
667
668static void
669redir_send(int fd)
670{
671 int i;
672 struct redirtab *rd;
673 for (rd = redirlist, i = 0;rd;rd = rd->next) {
674 guard_send(fd, i++);
675 buf_send(fd, rd->renamed, 10*sizeof(int));
676 int_send(fd, rd->nullredirs);
677 }
678 guard_send(fd, -1);
679 int_send(fd, nullredirs);
680 int_send(fd, preverrout_fd);
681 guard_send(fd, -1);
682}
683
684static void
685redir_recv(int fd)
686{
687 int i = 0;
688 struct redirtab *rd = NULL;
689 while (1) {
690 if (guard_recv2(fd, i++, -1) == -1)
691 break;
692 if (rd) {
693 rd->next = ckmalloc(sizeof(struct redirtab));
694 rd = rd->next;
695 } else
696 redirlist = rd = ckmalloc(sizeof(struct redirtab));
697 rd->next = NULL;
698 buf_recv(fd, rd->renamed, 10*sizeof(int));
699 rd->nullredirs = int_recv(fd);
700 }
701 nullredirs = int_recv(fd);
702 preverrout_fd = int_recv(fd);
703 guard_recv1(fd, -1);
704}
705
706static void
707shparam_send(int fd)
708{
709 int i;
710 int_send(fd, shellparam.nparam);
711#if ENABLE_ASH_GETOPTS
712 int_send(fd, shellparam.optind);
713 int_send(fd, shellparam.optoff);
714#endif
715 for (i = 0;i < shellparam.nparam;i ++) {
716 guard_send(fd, i);
717 str_send(fd, shellparam.p[i]);
718 }
719 guard_send(fd, -1);
720}
721
722static void
723shparam_recv(int fd)
724{
725 int i;
726 shellparam.nparam = int_recv(fd);
727 shellparam.malloc = 1;
728#if ENABLE_ASH_GETOPTS
729 shellparam.optind = int_recv(fd);
730 shellparam.optoff = int_recv(fd);
731#endif
732 if (shellparam.nparam) {
733 shellparam.p = ckmalloc((shellparam.nparam+1)*sizeof(char *));
734 for (i = 0;i < shellparam.nparam;i ++) {
735 guard_recv1(fd, i);
736 shellparam.p[i] = str_recv(fd);
737 }
738 shellparam.p[i] = NULL;
739 } else
740 shellparam.p = NULL;
741 guard_recv1(fd, -1);
742}
743
744static void
745misc_send(int fd)
746{
747 guard_send(fd, SER_MISC);
748 int_send(fd, rootpid); /* used in varvalue */
749 /* backgndpid ($!) is unsupported */
750 int_send(fd, shlvl + 1);
751 int_send(fd, exitstatus);
752 int_send(fd, startlinno);
753 str_send(fd, commandname);
754 str_send(fd, arg0);
755 str_send(fd, curdir == nullstr ? NULL : curdir);
756 str_send(fd, physdir == nullstr ? NULL : physdir);
757 sig_send(fd);
758 redir_send(fd);
759 shparam_send(fd);
760 /* stackbase... */
761 guard_send(fd, -1);
762}
763
764static void
765misc_recv(int fd)
766{
767 guard_recv1(fd, SER_MISC);
768 rootpid = int_recv(fd); /* used in varvalue */
769 shlvl = int_recv(fd);
770 exitstatus = int_recv(fd);
771 startlinno = int_recv(fd);
772 commandname = str_recv(fd);
773 arg0 = str_recv(fd);
774 curdir = str_recv(fd);
775 if (!curdir) curdir = nullstr;
776 physdir = str_recv(fd);
777 if (!physdir) physdir = nullstr;
778 sig_recv(fd);
779 redir_recv(fd);
780 shparam_recv(fd);
781 /* stackbase... */
782 guard_recv1(fd, -1);
783}