havefork.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #include "rc.h"
  2. #include "getflags.h"
  3. #include "exec.h"
  4. #include "io.h"
  5. #include "fns.h"
  6. int havefork = 1;
  7. void
  8. Xasync(void)
  9. {
  10. int null = open("/dev/null", 0);
  11. int pid;
  12. char npid[10];
  13. if(null<0){
  14. Xerror("Can't open /dev/null\n");
  15. return;
  16. }
  17. switch(pid = rfork(RFFDG|RFPROC|RFNOTEG|RFNOWAIT)){
  18. case -1:
  19. close(null);
  20. Xerror("try again");
  21. break;
  22. case 0:
  23. pushredir(ROPEN, null, 0);
  24. start(runq->code, runq->pc+1, runq->local);
  25. runq->ret = 0;
  26. break;
  27. default:
  28. close(null);
  29. runq->pc = runq->code[runq->pc].i;
  30. inttoascii(npid, pid);
  31. setvar("apid", newword(npid, (word *)0));
  32. break;
  33. }
  34. }
  35. void
  36. Xpipe(void)
  37. {
  38. struct thread *p = runq;
  39. int pc = p->pc, forkid;
  40. int lfd = p->code[pc++].i;
  41. int rfd = p->code[pc++].i;
  42. int pfd[2];
  43. if(pipe(pfd)<0){
  44. Xerror("can't get pipe");
  45. return;
  46. }
  47. switch(forkid = fork()){
  48. case -1:
  49. Xerror("try again");
  50. break;
  51. case 0:
  52. start(p->code, pc+2, runq->local);
  53. runq->ret = 0;
  54. close(pfd[PRD]);
  55. pushredir(ROPEN, pfd[PWR], lfd);
  56. break;
  57. default:
  58. start(p->code, p->code[pc].i, runq->local);
  59. close(pfd[PWR]);
  60. pushredir(ROPEN, pfd[PRD], rfd);
  61. p->pc = p->code[pc+1].i;
  62. p->pid = forkid;
  63. break;
  64. }
  65. }
  66. /*
  67. * Who should wait for the exit from the fork?
  68. */
  69. void
  70. Xbackq(void)
  71. {
  72. char wd[8193];
  73. int c;
  74. char *s, *ewd=&wd[8192], *stop;
  75. struct io *f;
  76. var *ifs = vlook("ifs");
  77. word *v, *nextv;
  78. int pfd[2];
  79. int pid;
  80. stop = ifs->val?ifs->val->word:"";
  81. if(pipe(pfd)<0){
  82. Xerror("can't make pipe");
  83. return;
  84. }
  85. switch(pid = fork()){
  86. case -1:
  87. Xerror("try again");
  88. close(pfd[PRD]);
  89. close(pfd[PWR]);
  90. return;
  91. case 0:
  92. close(pfd[PRD]);
  93. start(runq->code, runq->pc+1, runq->local);
  94. pushredir(ROPEN, pfd[PWR], 1);
  95. return;
  96. default:
  97. close(pfd[PWR]);
  98. f = openfd(pfd[PRD]);
  99. s = wd;
  100. v = 0;
  101. while((c = rchr(f))!=EOF){
  102. if(strchr(stop, c) || s==ewd){
  103. if(s!=wd){
  104. *s='\0';
  105. v = newword(wd, v);
  106. s = wd;
  107. }
  108. }
  109. else *s++=c;
  110. }
  111. if(s!=wd){
  112. *s='\0';
  113. v = newword(wd, v);
  114. }
  115. closeio(f);
  116. Waitfor(pid, 0);
  117. /* v points to reversed arglist -- reverse it onto argv */
  118. while(v){
  119. nextv = v->next;
  120. v->next = runq->argv->words;
  121. runq->argv->words = v;
  122. v = nextv;
  123. }
  124. runq->pc = runq->code[runq->pc].i;
  125. return;
  126. }
  127. }
  128. void
  129. Xpipefd(void)
  130. {
  131. struct thread *p = runq;
  132. int pc = p->pc;
  133. char name[40];
  134. int pfd[2];
  135. int sidefd, mainfd;
  136. if(pipe(pfd)<0){
  137. Xerror("can't get pipe");
  138. return;
  139. }
  140. if(p->code[pc].i==READ){
  141. sidefd = pfd[PWR];
  142. mainfd = pfd[PRD];
  143. }
  144. else{
  145. sidefd = pfd[PRD];
  146. mainfd = pfd[PWR];
  147. }
  148. switch(fork()){
  149. case -1:
  150. Xerror("try again");
  151. break;
  152. case 0:
  153. start(p->code, pc+2, runq->local);
  154. close(mainfd);
  155. pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);
  156. runq->ret = 0;
  157. break;
  158. default:
  159. close(sidefd);
  160. pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */
  161. strcpy(name, Fdprefix);
  162. inttoascii(name+strlen(name), mainfd);
  163. pushword(name);
  164. p->pc = p->code[pc+1].i;
  165. break;
  166. }
  167. }
  168. void
  169. Xsubshell(void)
  170. {
  171. int pid;
  172. switch(pid = fork()){
  173. case -1:
  174. Xerror("try again");
  175. break;
  176. case 0:
  177. start(runq->code, runq->pc+1, runq->local);
  178. runq->ret = 0;
  179. break;
  180. default:
  181. Waitfor(pid, 1);
  182. runq->pc = runq->code[runq->pc].i;
  183. break;
  184. }
  185. }
  186. int
  187. execforkexec(void)
  188. {
  189. int pid;
  190. int n;
  191. char buf[ERRMAX];
  192. switch(pid = fork()){
  193. case -1:
  194. return -1;
  195. case 0:
  196. pushword("exec");
  197. execexec();
  198. strcpy(buf, "can't exec: ");
  199. n = strlen(buf);
  200. errstr(buf+n, ERRMAX-n);
  201. Exit(buf);
  202. }
  203. return pid;
  204. }