havefork.c 3.6 KB

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