process.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include "common.h"
  2. /* make a stream to a child process */
  3. extern stream *
  4. instream(void)
  5. {
  6. stream *rv;
  7. int pfd[2];
  8. if ((rv = (stream *)malloc(sizeof(stream))) == 0)
  9. return 0;
  10. memset(rv, 0, sizeof(stream));
  11. if (pipe(pfd) < 0)
  12. return 0;
  13. if(Binit(&rv->bb, pfd[1], OWRITE) < 0){
  14. close(pfd[0]);
  15. close(pfd[1]);
  16. return 0;
  17. }
  18. rv->fp = &rv->bb;
  19. rv->fd = pfd[0];
  20. return rv;
  21. }
  22. /* make a stream from a child process */
  23. extern stream *
  24. outstream(void)
  25. {
  26. stream *rv;
  27. int pfd[2];
  28. if ((rv = (stream *)malloc(sizeof(stream))) == 0)
  29. return 0;
  30. memset(rv, 0, sizeof(stream));
  31. if (pipe(pfd) < 0)
  32. return 0;
  33. if (Binit(&rv->bb, pfd[0], OREAD) < 0){
  34. close(pfd[0]);
  35. close(pfd[1]);
  36. return 0;
  37. }
  38. rv->fp = &rv->bb;
  39. rv->fd = pfd[1];
  40. return rv;
  41. }
  42. extern void
  43. stream_free(stream *sp)
  44. {
  45. int fd;
  46. close(sp->fd);
  47. fd = Bfildes(sp->fp);
  48. Bterm(sp->fp);
  49. close(fd);
  50. free((char *)sp);
  51. }
  52. /* start a new process */
  53. extern process *
  54. noshell_proc_start(char **av, stream *inp, stream *outp, stream *errp, int newpg, char *who)
  55. {
  56. process *pp;
  57. int i, n;
  58. if ((pp = (process *)malloc(sizeof(process))) == 0) {
  59. if (inp != 0)
  60. stream_free(inp);
  61. if (outp != 0)
  62. stream_free(outp);
  63. if (errp != 0)
  64. stream_free(errp);
  65. return 0;
  66. }
  67. pp->std[0] = inp;
  68. pp->std[1] = outp;
  69. pp->std[2] = errp;
  70. switch (pp->pid = fork()) {
  71. case -1:
  72. proc_free(pp);
  73. return 0;
  74. case 0:
  75. if(newpg)
  76. sysdetach();
  77. for (i=0; i<3; i++)
  78. if (pp->std[i] != 0){
  79. close(Bfildes(pp->std[i]->fp));
  80. while(pp->std[i]->fd < 3)
  81. pp->std[i]->fd = dup(pp->std[i]->fd, -1);
  82. }
  83. for (i=0; i<3; i++)
  84. if (pp->std[i] != 0)
  85. dup(pp->std[i]->fd, i);
  86. for (n = sysfiles(); i < n; i++)
  87. close(i);
  88. if(who)
  89. become(av, who);
  90. exec(av[0], av);
  91. perror("proc_start");
  92. exits("proc_start");
  93. default:
  94. for (i=0; i<3; i++)
  95. if (pp->std[i] != 0) {
  96. close(pp->std[i]->fd);
  97. pp->std[i]->fd = -1;
  98. }
  99. return pp;
  100. }
  101. }
  102. /* start a new process under a shell */
  103. extern process *
  104. proc_start(char *cmd, stream *inp, stream *outp, stream *errp, int newpg, char *who)
  105. {
  106. char *av[4];
  107. av[0] = SHELL;
  108. av[1] = "-c";
  109. av[2] = cmd;
  110. av[3] = 0;
  111. return noshell_proc_start(av, inp, outp, errp, newpg, who);
  112. }
  113. /* wait for a process to stop */
  114. extern int
  115. proc_wait(process *pp)
  116. {
  117. Waitmsg *status;
  118. char err[Errlen];
  119. for(;;){
  120. status = wait();
  121. if(status == nil){
  122. errstr(err, sizeof(err));
  123. if(strstr(err, "interrupt") == 0)
  124. break;
  125. }
  126. if (status->pid==pp->pid)
  127. break;
  128. }
  129. pp->pid = -1;
  130. if(status == nil)
  131. pp->status = -1;
  132. else
  133. pp->status = status->msg[0];
  134. pp->waitmsg = status;
  135. return pp->status;
  136. }
  137. /* free a process */
  138. extern int
  139. proc_free(process *pp)
  140. {
  141. int i;
  142. if(pp->std[1] == pp->std[2])
  143. pp->std[2] = 0; /* avoid freeing it twice */
  144. for (i = 0; i < 3; i++)
  145. if (pp->std[i])
  146. stream_free(pp->std[i]);
  147. if (pp->pid >= 0)
  148. proc_wait(pp);
  149. free(pp->waitmsg);
  150. free((char *)pp);
  151. return 0;
  152. }
  153. /* kill a process */
  154. extern int
  155. proc_kill(process *pp)
  156. {
  157. return syskill(pp->pid);
  158. }