havefork.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "rc.h"
  10. #include "getflags.h"
  11. #include "exec.h"
  12. #include "io.h"
  13. #include "fns.h"
  14. #include <String.h>
  15. int havefork = 1;
  16. void
  17. Xasync(void)
  18. {
  19. int null = open("/dev/null", 0);
  20. int pid;
  21. char npid[10];
  22. if(null<0){
  23. Xerror("Can't open /dev/null\n");
  24. return;
  25. }
  26. switch(pid = rfork(RFFDG|RFPROC|RFNOTEG)){
  27. case -1:
  28. close(null);
  29. Xerror("try again");
  30. break;
  31. case 0:
  32. clearwaitpids();
  33. pushredir(ROPEN, null, 0);
  34. start(runq->code, runq->pc+1, runq->local);
  35. runq->ret = 0;
  36. break;
  37. default:
  38. addwaitpid(pid);
  39. close(null);
  40. runq->pc = runq->code[runq->pc].i;
  41. inttoascii(npid, pid);
  42. setvar("apid", newword(npid, (word *)0));
  43. break;
  44. }
  45. }
  46. void
  47. Xpipe(void)
  48. {
  49. struct thread *p = runq;
  50. int pc = p->pc, forkid;
  51. int lfd = p->code[pc++].i;
  52. int rfd = p->code[pc++].i;
  53. int pfd[2];
  54. if(pipe(pfd)<0){
  55. Xerror("can't get pipe");
  56. return;
  57. }
  58. switch(forkid = fork()){
  59. case -1:
  60. Xerror("try again");
  61. break;
  62. case 0:
  63. clearwaitpids();
  64. start(p->code, pc+2, runq->local);
  65. runq->ret = 0;
  66. close(pfd[PRD]);
  67. pushredir(ROPEN, pfd[PWR], lfd);
  68. break;
  69. default:
  70. addwaitpid(forkid);
  71. start(p->code, p->code[pc].i, runq->local);
  72. close(pfd[PWR]);
  73. pushredir(ROPEN, pfd[PRD], rfd);
  74. p->pc = p->code[pc+1].i;
  75. p->pid = forkid;
  76. break;
  77. }
  78. }
  79. /*
  80. * Who should wait for the exit from the fork?
  81. */
  82. void
  83. Xbackq(void)
  84. {
  85. int n, pid;
  86. int pfd[2];
  87. char *stop;
  88. char utf[UTFmax+1];
  89. struct io *f;
  90. var *ifs = vlook("ifs");
  91. word *v, *nextv;
  92. Rune r;
  93. String *word;
  94. stop = ifs->val? ifs->val->word: "";
  95. if(pipe(pfd)<0){
  96. Xerror("can't make pipe");
  97. return;
  98. }
  99. switch(pid = fork()){
  100. case -1:
  101. Xerror("try again");
  102. close(pfd[PRD]);
  103. close(pfd[PWR]);
  104. return;
  105. case 0:
  106. clearwaitpids();
  107. close(pfd[PRD]);
  108. start(runq->code, runq->pc+1, runq->local);
  109. pushredir(ROPEN, pfd[PWR], 1);
  110. return;
  111. default:
  112. addwaitpid(pid);
  113. close(pfd[PWR]);
  114. f = openfd(pfd[PRD]);
  115. word = s_new();
  116. v = nil;
  117. /* rutf requires at least UTFmax+1 bytes in utf */
  118. while((n = rutf(f, utf, &r)) != EOF){
  119. utf[n] = '\0';
  120. if(utfutf(stop, utf) == nil)
  121. s_nappend(word, utf, n);
  122. else
  123. /*
  124. * utf/r is an ifs rune (e.g., \t, \n), thus
  125. * ends the current word, if any.
  126. */
  127. if(s_len(word) > 0){
  128. v = newword(s_to_c(word), v);
  129. s_reset(word);
  130. }
  131. }
  132. if(s_len(word) > 0)
  133. v = newword(s_to_c(word), v);
  134. s_free(word);
  135. closeio(f);
  136. Waitfor(pid, 0);
  137. /* v points to reversed arglist -- reverse it onto argv */
  138. while(v){
  139. nextv = v->next;
  140. v->next = runq->argv->words;
  141. runq->argv->words = v;
  142. v = nextv;
  143. }
  144. runq->pc = runq->code[runq->pc].i;
  145. return;
  146. }
  147. }
  148. void
  149. Xpipefd(void)
  150. {
  151. struct thread *p = runq;
  152. int pc = p->pc, pid;
  153. char name[40];
  154. int pfd[2];
  155. int sidefd, mainfd;
  156. if(pipe(pfd)<0){
  157. Xerror("can't get pipe");
  158. return;
  159. }
  160. if(p->code[pc].i==READ){
  161. sidefd = pfd[PWR];
  162. mainfd = pfd[PRD];
  163. }
  164. else{
  165. sidefd = pfd[PRD];
  166. mainfd = pfd[PWR];
  167. }
  168. switch(pid = fork()){
  169. case -1:
  170. Xerror("try again");
  171. break;
  172. case 0:
  173. clearwaitpids();
  174. start(p->code, pc+2, runq->local);
  175. close(mainfd);
  176. pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);
  177. runq->ret = 0;
  178. break;
  179. default:
  180. addwaitpid(pid);
  181. close(sidefd);
  182. pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */
  183. strcpy(name, Fdprefix);
  184. inttoascii(name+strlen(name), mainfd);
  185. pushword(name);
  186. p->pc = p->code[pc+1].i;
  187. break;
  188. }
  189. }
  190. void
  191. Xsubshell(void)
  192. {
  193. int pid;
  194. switch(pid = fork()){
  195. case -1:
  196. Xerror("try again");
  197. break;
  198. case 0:
  199. clearwaitpids();
  200. start(runq->code, runq->pc+1, runq->local);
  201. runq->ret = 0;
  202. break;
  203. default:
  204. addwaitpid(pid);
  205. Waitfor(pid, 1);
  206. runq->pc = runq->code[runq->pc].i;
  207. break;
  208. }
  209. }
  210. int
  211. execforkexec(void)
  212. {
  213. int pid;
  214. int n;
  215. char buf[ERRMAX];
  216. switch(pid = fork()){
  217. case -1:
  218. return -1;
  219. case 0:
  220. clearwaitpids();
  221. pushword("exec");
  222. execexec();
  223. strcpy(buf, "can't exec: ");
  224. n = strlen(buf);
  225. errstr(buf+n, ERRMAX-n);
  226. Exit(buf);
  227. }
  228. addwaitpid(pid);
  229. return pid;
  230. }