execvp.c 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <errno.h>
  5. #include <limits.h>
  6. #include "libc.h"
  7. extern char **__environ;
  8. int __execvpe(const char *file, char *const argv[], char *const envp[])
  9. {
  10. const char *p, *z, *path = getenv("PATH");
  11. size_t l, k;
  12. int seen_eacces = 0;
  13. errno = ENOENT;
  14. if (!*file) return -1;
  15. if (strchr(file, '/'))
  16. return execve(file, argv, envp);
  17. if (!path) path = "/usr/local/bin:/bin:/usr/bin";
  18. k = strnlen(file, NAME_MAX+1);
  19. if (k > NAME_MAX) {
  20. errno = ENAMETOOLONG;
  21. return -1;
  22. }
  23. l = strnlen(path, PATH_MAX-1)+1;
  24. for(p=path; ; p=z) {
  25. char b[l+k+1];
  26. z = strchr(p, ':');
  27. if (!z) z = p+strlen(p);
  28. if (z-p >= l) {
  29. if (!*z++) break;
  30. continue;
  31. }
  32. memcpy(b, p, z-p);
  33. b[z-p] = '/';
  34. memcpy(b+(z-p)+(z>p), file, k+1);
  35. execve(b, argv, envp);
  36. switch (errno) {
  37. case EACCES:
  38. seen_eacces = 1;
  39. case ENOENT:
  40. case ENOTDIR:
  41. break;
  42. default:
  43. return -1;
  44. }
  45. if (!*z++) break;
  46. }
  47. if (seen_eacces) errno = EACCES;
  48. return -1;
  49. }
  50. int execvp(const char *file, char *const argv[])
  51. {
  52. return __execvpe(file, argv, __environ);
  53. }
  54. weak_alias(__execvpe, execvpe);