#include "commander.h" #include "aliases.h" #include "shell_utils.h" #include #include #include #include #include #define CMD_BUF_LEN 8192 #define OUT_BUF_LEN 4096 internal inline CMDError build_command_from_args(char *cmd, u64 buf_len, va_list args); internal inline CMDResult execute_command(const char *cmd, CMDOutHandling out_handling, char *out_buf, u64 buf_size); internal inline CMDError get_command_output(FILE *fp, CMDOutHandling out_handling, char *out_buf, u64 buf_size); extern CMDError get_output_status(FILE *fp, i32 *status_out); CMDResult run_command(CMDOutHandling out_handling, char *out_buf, u64 buf_size, ...) { va_list args; va_start(args, buf_size); char cmd[CMD_BUF_LEN] = {0}; CMDError err = build_command_from_args(cmd, CMD_BUF_LEN, args); if (err > SHELL_ERR_NO_ERROR) { va_end(args); return CMD_NO_EXIT(err); } va_end(args); return execute_command(cmd, out_handling, out_buf, buf_size); } internal inline CMDError build_command_from_args(char *cmd, u64 buf_len, va_list args) { u64 size = 0; u64 arg_len = 0; const char *arg = va_arg(args, const char *); while (arg) { arg_len = strlen(arg); if (arg_len >= buf_len - size) { return SHELL_ERR_CMD_BUF_FULL; } strcat(cmd, arg); cmd[size + arg_len] = ' '; size += arg_len + 1; arg = va_arg(args, const char *); } return SHELL_ERR_NO_ERROR; } internal inline CMDResult execute_command(const char *cmd, CMDOutHandling out_handling, char *out_buf, u64 buf_size) { FILE *fp = wapp_shell_utils_popen(cmd, "r"); if (!fp) { return CMD_NO_EXIT(SHELL_ERR_PROC_START_FAIL); } CMDResult output; CMDError err = get_command_output(fp, out_handling, out_buf, buf_size); if (err > SHELL_ERR_NO_ERROR) { output = CMD_NO_EXIT(err); goto EXECUTE_COMMAND_CLOSE; } i32 st = EXIT_SUCCESS; err = get_output_status(fp, &st); if (err > SHELL_ERR_NO_ERROR) { output = CMD_NO_EXIT(err); goto EXECUTE_COMMAND_CLOSE; } // Process is already closed in get_output_status fp = NULL; output = (CMDResult){ .exited = true, .exit_code = st, .error = SHELL_ERR_NO_ERROR, }; EXECUTE_COMMAND_CLOSE: if (fp) { wapp_shell_utils_pclose(fp); } return output; } internal inline CMDError get_command_output(FILE *fp, CMDOutHandling out_handling, char *out_buf, u64 buf_size) { char out[OUT_BUF_LEN] = {0}; u64 max_out_length = OUT_BUF_LEN - 1; u64 buf_filled = 0; while (fgets(out, (i32)max_out_length, fp)) { if (out_handling == SHELL_OUTPUT_CAPTURE && out_buf != NULL) { buf_filled += strlen(out); if (buf_filled >= buf_size) { return SHELL_ERR_OUT_BUF_FULL; } strcat(out_buf, out); } else if (out_handling == SHELL_OUTPUT_PRINT) { printf("%s", out); } } return SHELL_ERR_NO_ERROR; }