exec.c 2.2 KB

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