2026-01-28 19:34:39 +01:00
|
|
|
// retoor <retoor@molodetz.nl>
|
|
|
|
|
|
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
|
#include "bash_executor.h"
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
|
|
char *r_bash_execute(const char *command, bool interactive) {
|
|
|
|
|
if (!command) {
|
|
|
|
|
return strdup("Error: null command");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t len = strlen(command);
|
|
|
|
|
char *cmd_with_nl = malloc(len + 2);
|
|
|
|
|
if (!cmd_with_nl) {
|
|
|
|
|
return strdup("Error: memory allocation failed");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
strcpy(cmd_with_nl, command);
|
|
|
|
|
if (len > 0 && cmd_with_nl[len - 1] != '\n') {
|
|
|
|
|
cmd_with_nl[len] = '\n';
|
|
|
|
|
cmd_with_nl[len + 1] = '\0';
|
|
|
|
|
} else if (len == 0) {
|
|
|
|
|
cmd_with_nl[0] = '\n';
|
|
|
|
|
cmd_with_nl[1] = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char tmp_script[] = "/tmp/r_bash_XXXXXX.sh";
|
|
|
|
|
int fd = mkstemps(tmp_script, 3);
|
|
|
|
|
if (fd == -1) {
|
|
|
|
|
free(cmd_with_nl);
|
|
|
|
|
perror("mkstemps");
|
|
|
|
|
return strdup("Error: failed to create temp script");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (write(fd, cmd_with_nl, strlen(cmd_with_nl)) == -1) {
|
|
|
|
|
close(fd);
|
|
|
|
|
free(cmd_with_nl);
|
|
|
|
|
unlink(tmp_script);
|
|
|
|
|
return strdup("Error: failed to write to temp script");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
|
free(cmd_with_nl);
|
|
|
|
|
|
|
|
|
|
char *output = NULL;
|
|
|
|
|
|
|
|
|
|
if (interactive) {
|
|
|
|
|
char *run_cmd = NULL;
|
|
|
|
|
if (asprintf(&run_cmd, "bash %s", tmp_script) == -1) {
|
|
|
|
|
unlink(tmp_script);
|
|
|
|
|
return strdup("Error: asprintf failed");
|
|
|
|
|
}
|
|
|
|
|
int status = system(run_cmd);
|
|
|
|
|
free(run_cmd);
|
|
|
|
|
|
|
|
|
|
if (asprintf(&output, "Command exited with status %d", status) == -1) {
|
|
|
|
|
output = strdup("Command completed (asprintf failed for status).");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
char *run_cmd = NULL;
|
|
|
|
|
if (asprintf(&run_cmd, "bash %s 2>&1", tmp_script) == -1) {
|
|
|
|
|
unlink(tmp_script);
|
|
|
|
|
return strdup("Error: asprintf failed");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FILE *fp = popen(run_cmd, "r");
|
|
|
|
|
free(run_cmd);
|
|
|
|
|
|
|
|
|
|
if (!fp) {
|
|
|
|
|
unlink(tmp_script);
|
|
|
|
|
return strdup("Error: popen failed");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char buffer[1024];
|
|
|
|
|
size_t total_size = 0;
|
|
|
|
|
|
|
|
|
|
while (fgets(buffer, sizeof(buffer), fp)) {
|
2026-01-28 19:50:07 +01:00
|
|
|
// Print to stderr for the user in a subtle dim/gray color
|
|
|
|
|
fprintf(stderr, "\033[2m%s\033[0m", buffer);
|
2026-01-28 19:34:39 +01:00
|
|
|
|
|
|
|
|
size_t chunk_len = strlen(buffer);
|
|
|
|
|
char *new_output = realloc(output, total_size + chunk_len + 1);
|
|
|
|
|
if (!new_output) {
|
|
|
|
|
free(output);
|
|
|
|
|
pclose(fp);
|
|
|
|
|
unlink(tmp_script);
|
|
|
|
|
return strdup("Error: memory allocation failed");
|
|
|
|
|
}
|
|
|
|
|
output = new_output;
|
|
|
|
|
strcpy(output + total_size, buffer);
|
|
|
|
|
total_size += chunk_len;
|
|
|
|
|
}
|
|
|
|
|
pclose(fp);
|
|
|
|
|
|
|
|
|
|
if (!output) {
|
|
|
|
|
output = strdup("");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unlink(tmp_script);
|
|
|
|
|
return output;
|
|
|
|
|
}
|