Porting to linux

This commit is contained in:
2025-08-10 18:44:10 +02:00
parent 720fdd9f34
commit 4b55faa41e
11 changed files with 298 additions and 21 deletions

View File

@@ -4,6 +4,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <linux/limits.h>
#include <unistd.h>
@@ -11,6 +12,9 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <spawn.h>
#include <poll.h>
void (*Error)(const char *, ...);
@@ -212,28 +216,204 @@ FileIter IterateFiles(Allocator alo, String path) {
return it;
}
// struct Process {
// bool is_valid;
// int exit_code;
// char platform[6 * 8];
//
// int64_t view_id; // text editor view
// bool scroll_to_end;
// };
struct UnixProcess {
pid_t pid;
int child_stdout_read;
int stdin_write;
};
Array<char *> SplitCommand(Allocator allocator, String command_line) {
Array<char *> cmd = {allocator};
String curr = {};
for (int i = 0; i < command_line.len; i += 1) {
if (command_line.data[i] == ' ') {
if (curr.len > 0) {
Add(&cmd, Copy(allocator, curr).data);
curr = {};
}
continue;
}
if (curr.len == 0) {
curr.data = command_line.data + i;
}
curr.len += 1;
}
if (curr.len > 0) {
Add(&cmd, Copy(allocator, curr).data);
}
return cmd;
}
Process SpawnProcess(String command_line, String working_dir, String write_stdin, Array<String> enviroment) {
return {};
const int PIPE_READ = 0;
const int PIPE_WRITE = 1;
bool error = false;
Scratch scratch;
Process process = {};
UnixProcess *plat = (UnixProcess *)&process.platform;
Array<char *> args = SplitCommand(scratch, command_line);
Array<char *> env = {scratch};
For (enviroment) {
Add(&env, Copy(scratch, it).data);
}
int stdout_desc[2] = {};
int stdin_desc[2] = {};
posix_spawn_file_actions_t actions = {};
if (posix_spawn_file_actions_init(&actions) != 0) {
perror("posix_spawn_file_actions_init");
return process;
}
defer {
posix_spawn_file_actions_destroy(&actions);
};
if (pipe(stdout_desc) == -1) {
perror("pipe");
return process;
}
defer {
if (error) {
close(stdout_desc[PIPE_READ]);
close(stdout_desc[PIPE_WRITE]);
} else {
close(stdout_desc[PIPE_WRITE]);
}
};
if (pipe(stdin_desc) == -1) {
perror("pipe");
return process;
}
defer {
if (error) {
close(stdin_desc[PIPE_READ]);
close(stdin_desc[PIPE_WRITE]);
} else {
close(stdin_desc[PIPE_READ]);
}
};
error = posix_spawn_file_actions_addclose(&actions, stdout_desc[PIPE_READ]) != 0;
if (error) {
perror("posix_spawn_file_actions_addclose");
return process;
}
error = posix_spawn_file_actions_adddup2(&actions, stdout_desc[PIPE_WRITE], STDOUT_FILENO) != 0;
if (error) {
perror("posix_spawn_file_actions_adddup2 STDOUT_FILENO");
return process;
}
error = posix_spawn_file_actions_adddup2(&actions, stdout_desc[PIPE_WRITE], STDERR_FILENO) != 0;
if (error) {
perror("posix_spawn_file_actions_adddup2 STDERR_FILENO");
return process;
}
error = posix_spawn_file_actions_addclose(&actions, stdin_desc[PIPE_WRITE]) != 0;
if (error) {
perror("posix_spawn_file_actions_addclose");
return process;
}
error = posix_spawn_file_actions_adddup2(&actions, stdin_desc[PIPE_READ], STDIN_FILENO) != 0;
if (error) {
perror("posix_spawn_file_actions_adddup2 STDIN_FILENO");
return process;
}
pid_t process_pid = 0;
error = posix_spawnp(&process_pid, args[0], &actions, NULL, args.data, env.data) != 0;
if (error) {
perror("failed to create process\n");
return process;
}
process.is_valid = true;
plat->child_stdout_read = stdout_desc[PIPE_READ];
plat->stdin_write = stdin_desc[PIPE_WRITE];
if (write_stdin.len) {
WriteStdin(&process, write_stdin);
CloseStdin(&process);
}
return process;
}
bool IsValid(Process *process) {
return false;
UnixProcess *plat = (UnixProcess *)&process->platform;
if (process->is_valid == false) {
return false;
}
int status = 0;
pid_t result = waitpid(plat->pid, &status, WNOHANG);
if (result >= 0) {
if (WIFSIGNALED(status) || WIFEXITED(status)) {
process->exit_code = WEXITSTATUS(status);
return false;
}
}
return true;
}
void KillProcess(Process *process) {
Assert(process->is_valid);
UnixProcess *plat = (UnixProcess *)process->platform;
kill(plat->pid, SIGKILL);
process->exit_code = -1;
}
String PollStdout(Allocator allocator, Process *process) {
return "";
String PollStdout(Allocator allocator, Process *process, bool force_read) {
Assert(process->is_valid);
UnixProcess *plat = (UnixProcess *)process->platform;
String result = {};
result.data = AllocArray(allocator, char, 16 * 4096);
pollfd p = {};
p.fd = plat->child_stdout_read;
p.events = POLLIN;
int res = poll(&p, 1, 0);
if (res == 1 || force_read) {
result.len = read(plat->child_stdout_read, result.data, 4 * 4096);
}
return result;
}
void WriteStdin(Process *process, String string) {
if (string.len == 0) return;
Assert(process->is_valid);
UnixProcess *plat = (UnixProcess *)process->platform;
ssize_t size = write(plat->stdin_write, string.data, string.len);
Assert(size == string.len);
}
void CloseStdin(Process *process) {
UnixProcess *plat = (UnixProcess *)process->platform;
close(plat->stdin_write);
}