execvp.c 1.1 KB

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