Skip to content

Instantly share code, notes, and snippets.

@HotelCalifornia
Created February 5, 2020 19:31
Show Gist options
  • Save HotelCalifornia/a34e4c26a6c0855b6d8d349e2f9f9c31 to your computer and use it in GitHub Desktop.
Save HotelCalifornia/a34e4c26a6c0855b6d8d349e2f9f9c31 to your computer and use it in GitHub Desktop.
automate xinu console tools for great workflow good
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define READ 0
#define WRITE 1
int main() {
printf("start\n");
int writer[2];
int reader[2];
if (pipe(writer) < 0) {
fprintf(stderr, "error: writer pipe: %s\n", strerror(errno));
return EXIT_FAILURE;
}
if (pipe(reader) < 0) {
close(writer[READ]); close(writer[WRITE]);
fprintf(stderr, "error: reader pipe: %s\n", strerror(errno));
return EXIT_FAILURE;
}
printf("pipes made\n");
pid_t pid = fork();
if (pid == 0) {
// child proc
// duplicate read end of the writer pipe onto stdin (so parent can write to child's stdin)
if (dup2(writer[READ], STDIN_FILENO) < 0) {
fprintf(stderr, "error: writer dup2: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
// duplicate write end of the reader pipe onto stdout and stderr (so parent can read child's stdout/err)
if (dup2(reader[WRITE], STDOUT_FILENO) < 0) {
fprintf(stderr, "error: reader dup2 (stdin): %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (dup2(reader[WRITE], STDERR_FILENO) < 0) {
fprintf(stderr, "error: reader dup2 (stderr): %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
// close unused pipes (dup2 silently closes some of these so we have a couple no-ops. nbd)
close(writer[READ]); close(writer[WRITE]);
close(reader[READ]); close(writer[WRITE]);
//
char* args[] = {"/p/xinu/bin/cs-console", "-c", "quark", NULL};
char* env[] = {"CS_FILENAME=/homes/brookea/cs/cs354/xinu-spring2020/compile/xinu.xbin", NULL};
exit(execve(args[0], args, env));
} else if (pid > 0) {
printf("parent\n");
// parent proc
// close unneeded pipe ends
close(writer[READ]);
close(reader[WRITE]);
// send our cursed input to the child
dprintf(writer[WRITE], "%cd", '\0');
sleep(1);
dprintf(writer[WRITE], "\n");
sleep(1);
dprintf(writer[WRITE], "%cp", '\0');
int wstatus;
while (waitpid(pid, &wstatus, WNOHANG)) {
printf("loop\n");
// echo child's output in parent
char c;
while (read(reader[READ], &c, 1) == 1) {
write(STDOUT_FILENO, &c, 1);
}
// pass parent's stdin to child
while (read(STDIN_FILENO, &c, 1) == 1) {
write(writer[WRITE], &c, 1);
}
}
printf("loop done\n");
if (WIFEXITED(wstatus)) {
printf("child exited normally with code %d\n", WEXITSTATUS(wstatus));
}
// wait for child proc to finish
// waitpid(pid, NULL, 0);
close(writer[WRITE]);
close(reader[READ]);
} else {
// failure
close(writer[READ]); close(writer[WRITE]);
close(reader[READ]); close(reader[WRITE]);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment