execvpe is not available on non GNU systems */
| 3500 | |
| 3501 | /* execvpe is not available on non GNU systems */ |
| 3502 | static int my_execvpe(const char *filename, char **argv, char **envp) |
| 3503 | { |
| 3504 | char *path, *p, *p_next, *p1; |
| 3505 | char buf[JS__PATH_MAX]; |
| 3506 | size_t filename_len, path_len; |
| 3507 | bool eacces_error; |
| 3508 | |
| 3509 | filename_len = strlen(filename); |
| 3510 | if (filename_len == 0) { |
| 3511 | errno = ENOENT; |
| 3512 | return -1; |
| 3513 | } |
| 3514 | if (strchr(filename, '/')) |
| 3515 | return execve(filename, argv, envp); |
| 3516 | |
| 3517 | path = getenv("PATH"); |
| 3518 | if (!path) |
| 3519 | path = (char *)"/bin:/usr/bin"; |
| 3520 | eacces_error = false; |
| 3521 | p = path; |
| 3522 | for(p = path; p != NULL; p = p_next) { |
| 3523 | p1 = strchr(p, ':'); |
| 3524 | if (!p1) { |
| 3525 | p_next = NULL; |
| 3526 | path_len = strlen(p); |
| 3527 | } else { |
| 3528 | p_next = p1 + 1; |
| 3529 | path_len = p1 - p; |
| 3530 | } |
| 3531 | /* path too long */ |
| 3532 | if ((path_len + 1 + filename_len + 1) > JS__PATH_MAX) |
| 3533 | continue; |
| 3534 | memcpy(buf, p, path_len); |
| 3535 | buf[path_len] = '/'; |
| 3536 | memcpy(buf + path_len + 1, filename, filename_len); |
| 3537 | buf[path_len + 1 + filename_len] = '\0'; |
| 3538 | |
| 3539 | execve(buf, argv, envp); |
| 3540 | |
| 3541 | switch(errno) { |
| 3542 | case EACCES: |
| 3543 | eacces_error = true; |
| 3544 | break; |
| 3545 | case ENOENT: |
| 3546 | case ENOTDIR: |
| 3547 | break; |
| 3548 | default: |
| 3549 | return -1; |
| 3550 | } |
| 3551 | } |
| 3552 | if (eacces_error) |
| 3553 | errno = EACCES; |
| 3554 | return -1; |
| 3555 | } |
| 3556 | |
| 3557 | static void (*js_os_exec_closefrom)(int); |
| 3558 |