_exec.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #include <lib.h>
  2. #include <unistd.h>
  3. #define execl _execl
  4. #define execle _execle
  5. #define execv _execv
  6. #define execve _execve
  7. extern char **environ; /* environment pointer */
  8. #define PTRSIZE (sizeof(char *))
  9. _PROTOTYPE( char *_sbrk, (int _incr) );
  10. #if _ANSI
  11. #include <stdarg.h>
  12. PUBLIC int execl(char *name, ...)
  13. {
  14. int retval;
  15. va_list ap;
  16. va_start(ap, name);
  17. retval = execve(name, (char **)ap, environ);
  18. va_end(ap);
  19. return retval;
  20. }
  21. #else
  22. PUBLIC int execl(name, arg0)
  23. char *name;
  24. char *arg0;
  25. {
  26. return(execve(name, &arg0, environ));
  27. }
  28. #endif
  29. #if _ANSI
  30. PUBLIC int execle(char *name, ...)
  31. {
  32. int retval;
  33. va_list ap;
  34. char *p;
  35. va_start(ap, name);
  36. do {
  37. p = va_arg(ap, char *);
  38. } while(p);
  39. p = (char *)va_arg(ap, char **);
  40. va_end(ap);
  41. va_start(ap, name);
  42. retval = execve(name, (char **)ap, (char **) p);
  43. va_end(ap);
  44. return retval;
  45. }
  46. #else
  47. PUBLIC int execle(name, argv)
  48. char *name, *argv;
  49. {
  50. char **p;
  51. p = (char **) &argv;
  52. while (*p++) /* null statement */
  53. ;
  54. return(execve(name, &argv, (char **) *p));
  55. }
  56. #endif
  57. PUBLIC int execv(name, argv)
  58. char *name, *argv[];
  59. {
  60. return(execve(name, argv, environ));
  61. }
  62. PUBLIC int execve(path, argv, envp)
  63. char *path; /* pointer to name of file to be executed */
  64. char *argv[]; /* pointer to argument array */
  65. char *envp[]; /* pointer to environment */
  66. {
  67. register char **argtop;
  68. register char **envtop;
  69. /* Count the argument pointers and environment pointers. */
  70. for (argtop = argv; *argtop != (char *) NULL; ) argtop++;
  71. for (envtop = envp; *envtop != (char *) NULL; ) envtop++;
  72. return(__execve(path, argv, envp, (int)(argtop - argv), (int)(envtop - envp)));
  73. }
  74. PUBLIC int __execve(path, argv, envp, nargs, nenvps)
  75. char *path; /* pointer to name of file to be executed */
  76. char *argv[]; /* pointer to argument array */
  77. char *envp[]; /* pointer to environment */
  78. int nargs; /* number of args */
  79. int nenvps; /* number of environment strings */
  80. {
  81. /* This is split off from execve to be called from execvp, so execvp does not
  82. * have to allocate up to ARG_MAX bytes just to prepend "sh" to the arg array.
  83. */
  84. char *hp, **ap, *p;
  85. int i, stackbytes, npointers, overflow, temp;
  86. char *stack;
  87. /* Decide how big a stack is needed. Be paranoid about overflow. */
  88. #if ARG_MAX > INT_MAX
  89. #error /* overflow checks and sbrk depend on sizes being ints */
  90. #endif
  91. overflow = FALSE;
  92. npointers = 1 + nargs + 1 + nenvps + 1; /* 1's for argc and NULLs */
  93. stackbytes = 0; /* changed because _len is used now */
  94. if (nargs < 0 || nenvps < 0 || nargs+nenvps < 0 || npointers < 0)
  95. overflow = TRUE;
  96. for (i = PTRSIZE; i != 0; i--) {
  97. temp = stackbytes + npointers;
  98. if (temp < stackbytes) overflow = TRUE;
  99. stackbytes = temp;
  100. }
  101. for (i = 0, ap = argv; i < nargs; i++) {
  102. temp = stackbytes + _len(*ap++);
  103. if (temp < stackbytes) overflow = TRUE;
  104. stackbytes = temp;
  105. }
  106. for (i = 0, ap = envp; i < nenvps; i++) {
  107. temp = stackbytes + _len(*ap++);
  108. if (temp < stackbytes) overflow = TRUE;
  109. stackbytes = temp;
  110. }
  111. temp = stackbytes + PTRSIZE - 1;
  112. if (temp < stackbytes) overflow = TRUE;
  113. stackbytes = (temp / PTRSIZE) * PTRSIZE;
  114. /* Check for overflow before committing sbrk. */
  115. if (overflow || stackbytes > ARG_MAX) {
  116. errno = E2BIG;
  117. return(-1);
  118. }
  119. /* Allocate the stack. */
  120. stack = _sbrk(stackbytes);
  121. if (stack == (char *) -1) {
  122. errno = E2BIG;
  123. return(-1);
  124. }
  125. /* Prepare the stack vector and argc. */
  126. ap = (char **) stack;
  127. hp = &stack[npointers * PTRSIZE];
  128. *ap++ = (char *) nargs;
  129. /* Prepare the argument pointers and strings. */
  130. for (i = 0; i < nargs; i++) {
  131. *ap++ = (char *) (hp - stack);
  132. p = *argv++;
  133. while ((*hp++ = *p++) != 0)
  134. ;
  135. }
  136. *ap++ = (char *) NULL;
  137. /* Prepare the environment pointers and strings. */
  138. for (i = 0; i < nenvps; i++) {
  139. *ap++ = (char *) (hp - stack);
  140. p = *envp++;
  141. while ((*hp++ = *p++) != 0)
  142. ;
  143. }
  144. *ap++ = (char *) NULL;
  145. /* Do the real work. */
  146. temp = _callm1(MM, EXEC, _len(path), stackbytes, 0, path, stack, NIL_PTR);
  147. _sbrk(-stackbytes);
  148. return(temp);
  149. }