codecrafters-shell-c

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit c83d3ad2215baa5da4309224a33cdb9d7029a2d8
parent 9d332950dd77f13f48c8bff595208b70c1139d9d
Author: 5hif7y <[email protected]>
Date:   Fri,  3 Jan 2025 01:44:20 -0300

9 run a program

Diffstat:
Mapp/main.c | 101++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 90 insertions(+), 11 deletions(-)

diff --git a/app/main.c b/app/main.c @@ -4,13 +4,17 @@ #include <stdlib.h> #ifdef _WIN32 + #define WIN32_LEAN_AND_MEAN + #include <windows.h> #define F_OK 0 #else + #include <sys/wait.h> #include <unistd.h> #endif void parse_input(const char *input, char *cmd, char **args, int *argc); bool find_executable(const char *cmd, char *result_path); +void run_executable(const char *cmd, char **args); int main() { @@ -65,7 +69,12 @@ int main() { printf("Usage: type [command]\n"); } } else { - printf("%s: command not found\n", cmd); + char path[512]; + if (find_executable(cmd, path)){ + run_executable(path, args); + } else { + printf("%s: command not found\n", cmd); + } } //free mem @@ -101,6 +110,33 @@ void parse_input(const char *input, char *cmd, char **args, int *argc){ } bool find_executable(const char *cmd, char *result_path){ + + // First, search in current folder + #ifdef _WIN32 + const char *extensions[] = {".exe", NULL}; // Extension support list + // ------------ + if (strchr(cmd, '.')){ + snprintf(result_path, 512, ".\\%s", cmd); + if (access(result_path, F_OK) == 0){ + return true; + } + } else { + for (const char **ext = extensions; *ext != NULL; ext++){ + snprintf(result_path, 512, ".\\%s%s", cmd, *ext); + if (access(result_path, F_OK) == 0){ + return true; + } + } + + #else + // In POSIX systems, simply search in current folder + snprintf(result_path, 512, "./%s", cmd); + if (access(result_path, F_OK) == 0){ + return true; + } + #endif + + // Second, search in PATH char *path_env = getenv("PATH"); if(!path_env){ return false; @@ -111,32 +147,75 @@ bool find_executable(const char *cmd, char *result_path){ path_copy[sizeof(path_copy) - 1] = '\0'; char separator = ':'; -#ifdef _WIN32 - separator = ';'; -#endif + #ifdef _WIN32 + separator = ';'; + #endif char *dir = strtok(path_copy, &separator); while (dir != NULL){ - snprintf(result_path, 512, "%s/%s", dir, cmd); -#ifdef _WIN32 - const char *extensions[] = {".exe", NULL}; // Extension support list - for (const char **ext = extensions; *ext != NULL; ext++){ - snprintf(result_path, 512, "%s\\%s%s", dir, cmd, *ext); + if (strlen(dir) > 0) { + #ifdef _WIN32 + if (strchr(cmd, '.')){ + snprintf(result_path, 512, "%s\\%s", dir, cmd); if (access(result_path, F_OK) == 0){ return true; } + } else { + for (const char **ext = extensions; *ext != NULL; ext++){ + snprintf(result_path, 512, "%s\\%s%s", dir, cmd, *ext); + if (access(result_path, F_OK) == 0){ + return true; + } + } } -#else + #else + snprintf(result_path, 512, "%s/%s", dir, cmd); if(access(result_path, X_OK) == 0){ return true; } -#endif + #endif + } dir = strtok(NULL, &separator); } return false; } +void run_executable(const char *cmd, char **args){ + #ifdef _WIN32 + // 1. Build command line + char command_line[1024] = {0}; + snprintf(command_line, sizeof(command_line), "\"%s\"", cmd); + + for (int i = 0; args[i] != NULL; i++){ + strncat(command_line, " ", sizeof(command_line) - strlen(command_line) - 1); + strncat(command_line, args[i], sizeof(command_line) - strlen(command_line) - 1); + } + // 2. Setup structures for 'CreateProcess' + STARTUPINFO si = {0}; + PROCESS_INFORMATION pi = {0}; + si.cb = sizeof(STARTUPINFO); + + // 3. Try to create process + if (!CreateProcess(NULL, command_line, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)){ + fprintf(stderr, "Error: error executing command %s\n", cmd); + } else { + WaitForSingleObject(pi.hProcess, INFINITE); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } + + #else + // Use 'execvp' in POSIX systems + if (fork() == 0){ + execvp(cmd, args); + perror("Error executing command"); + exit(EXIT_FAILURE); + } else { + wait(NULL); + } + #endif +}