execvp.c (1407B)
1 /* 2 * execvp.c - execute a file, searching PATH 3 * Copyright (C) 2026. All rights reserved. 4 */ 5 6 #include "libc.h" 7 8 char **environ; 9 10 int execvp(const char *file, char *const argv[]) { 11 static char *empty_env[] = { NULL }; 12 char **env = (environ != NULL) ? environ : empty_env; 13 14 if (strchr(file, '/') != 0) { 15 return execve(file, argv, env); 16 } 17 18 const char *path_env = NULL; 19 if (env != NULL) { 20 for (char **ep = env; *ep != NULL; ++ep) { 21 if (ep[0][0] == 'P' && ep[0][1] == 'A' && 22 ep[0][2] == 'T' && ep[0][3] == 'H' && ep[0][4] == '=') { 23 path_env = *ep + 5; 24 break; 25 } 26 } 27 } 28 29 if (path_env == NULL || *path_env == '\0') { 30 path_env = "/bin"; 31 } 32 33 char path_buf[1024]; 34 size_t file_len = strlen(file); 35 36 const char *p = path_env; 37 while (*p != '\0') { 38 const char *start = p; 39 while (*p != '\0' && *p != ':') { 40 p++; 41 } 42 43 size_t dir_len = p - start; 44 45 if (dir_len == 0) { 46 if (file_len + 1 < sizeof(path_buf)) { 47 memcpy(path_buf, file, file_len + 1); 48 execve(path_buf, argv, env); 49 } 50 } else { 51 if (dir_len + 1 + file_len + 1 < sizeof(path_buf)) { 52 memcpy(path_buf, start, dir_len); 53 path_buf[dir_len] = '/'; 54 memcpy(path_buf + dir_len + 1, file, file_len + 1); 55 execve(path_buf, argv, env); 56 } 57 } 58 59 if (*p == ':') { 60 p++; 61 } 62 } 63 64 return -1; 65 }