exec.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <thread.h>
  4. #include "threadimpl.h"
  5. #define PIPEMNT "/mnt/temp"
  6. void
  7. procexec(Channel *pidc, char *prog, char *args[])
  8. {
  9. int n;
  10. Proc *p;
  11. Thread *t;
  12. _threaddebug(DBGEXEC, "procexec %s", prog);
  13. /* must be only thread in proc */
  14. p = _threadgetproc();
  15. t = p->thread;
  16. if(p->threads.head != t || p->threads.head->nextt != nil){
  17. werrstr("not only thread in proc");
  18. Bad:
  19. if(pidc)
  20. sendul(pidc, ~0);
  21. return;
  22. }
  23. /*
  24. * We want procexec to behave like exec; if exec succeeds,
  25. * never return, and if it fails, return with errstr set.
  26. * Unfortunately, the exec happens in another proc since
  27. * we have to wait for the exec'ed process to finish.
  28. * To provide the semantics, we open a pipe with the
  29. * write end close-on-exec and hand it to the proc that
  30. * is doing the exec. If the exec succeeds, the pipe will
  31. * close so that our read below fails. If the exec fails,
  32. * then the proc doing the exec sends the errstr down the
  33. * pipe to us.
  34. */
  35. if(bind("#|", PIPEMNT, MREPL) < 0)
  36. goto Bad;
  37. if((p->exec.fd[0] = open(PIPEMNT "/data", OREAD)) < 0){
  38. unmount(nil, PIPEMNT);
  39. goto Bad;
  40. }
  41. if((p->exec.fd[1] = open(PIPEMNT "/data1", OWRITE|OCEXEC)) < 0){
  42. close(p->exec.fd[0]);
  43. unmount(nil, PIPEMNT);
  44. goto Bad;
  45. }
  46. unmount(nil, PIPEMNT);
  47. /* exec in parallel via the scheduler */
  48. assert(p->needexec==0);
  49. p->exec.prog = prog;
  50. p->exec.args = args;
  51. p->needexec = 1;
  52. _sched();
  53. close(p->exec.fd[1]);
  54. if((n = read(p->exec.fd[0], p->exitstr, ERRMAX-1)) > 0){ /* exec failed */
  55. p->exitstr[n] = '\0';
  56. errstr(p->exitstr, ERRMAX);
  57. close(p->exec.fd[0]);
  58. goto Bad;
  59. }
  60. close(p->exec.fd[0]);
  61. if(pidc)
  62. sendul(pidc, t->ret);
  63. /* wait for exec'ed program, then exit */
  64. _schedexecwait();
  65. }
  66. void
  67. procexecl(Channel *pidc, char *f, ...)
  68. {
  69. procexec(pidc, f, &f+1);
  70. }