summaryrefslogtreecommitdiffstats
path: root/linux/main.c
diff options
context:
space:
mode:
authorLibravatar bigfoot547 <bigfoot@figboot.dev>2026-06-29 03:00:12 -0500
committerLibravatar bigfoot547 <bigfoot@figboot.dev>2026-06-29 03:00:12 -0500
commit6bb84fe005fc151df1a67259242da9c0eaf3fe93 (patch)
tree683d6e160bf48fd0c235635be874a8fef697402c /linux/main.c
parentadd new tests (diff)
begin work on pc side
Diffstat (limited to 'linux/main.c')
-rw-r--r--linux/main.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/linux/main.c b/linux/main.c
new file mode 100644
index 0000000..bd208f2
--- /dev/null
+++ b/linux/main.c
@@ -0,0 +1,132 @@
+#include <stdio.h>
+#include <termios.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <poll.h>
+
+#ifdef DEBUG_MESSAGE
+#define DEBUG(_s, ...) fprintf(stderr, _s, ## __VA_ARGS__)
+#else
+#define DEBUG(_s, ...)
+#endif
+
+#define elt0(_exp) ((_exp) < 0)
+#define check(_x, _cond, ...) do { if (_cond(_x)) { fatal_error(__VA_ARGS__); } } while (0)
+#define fatal_error(...) do { fprintf(stderr, __VA_ARGS__); exit(1); } while (0)
+
+#define GECKO_BAUD B115200
+
+static int setup_term(const char *name) {
+ int fd;
+ int flags;
+ struct termios tio;
+
+#define O(_ex, _m) check(_ex, elt0, "error " _m " %s: %s\n", name, strerror(errno))
+
+ O(fd = openat(AT_FDCWD, name, O_RDWR | O_NOCTTY), "opening");
+ O(tcgetattr(fd, &tio), "getting tio attrs for");
+ O(cfsetispeed(&tio, GECKO_BAUD), "setting ispeed of");
+ O(cfsetospeed(&tio, GECKO_BAUD), "setting ospeed of");
+
+ tio.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
+ tio.c_oflag &= ~OPOST;
+ tio.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+ tio.c_cflag &= ~(CSIZE | PARENB);
+ tio.c_cflag |= CS8;
+
+ O(tcsetattr(fd, TCSANOW, &tio), "setting tio attrs for");
+
+ O(flags = fcntl(fd, F_GETFL), "getting stream status for");
+ flags |= O_NONBLOCK;
+ O(fcntl(fd, F_SETFL, flags), "setting stream status for");
+
+#undef O
+
+ return fd;
+}
+
+static void handle_command(const char *cmd) {
+
+}
+
+int main(int argc, char **argv) {
+ struct termios tio;
+ int tfd;
+ unsigned char buf[1024];
+ char cmdbuf[1024];
+ struct pollfd fds[2];
+ int infd;
+ int flags;
+ int can_write = 0;
+ size_t partialcmd_sz = 0;
+
+ int test_mode = 0;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <term>\n", argv[0]);
+ return 1;
+ }
+
+ tfd = setup_term(argv[1]);
+
+ check(infd = dup(STDIN_FILENO), elt0, "error duplicating stdin: %s\n", strerror(errno));
+ check(flags = fcntl(infd, F_GETFL), elt0, "error getting stream status for stdin: %s\n", strerror(errno));
+ flags |= O_NONBLOCK;
+ check(fcntl(infd, F_SETFL, flags), elt0, "setting stream status for stdin: %s\n", strerror(errno));
+
+ fds[0].fd = tfd;
+ fds[0].events = POLLIN | POLLOUT;
+
+ fds[1].fd = STDIN_FILENO;
+ fds[1].events = POLLIN;
+
+ while (1) {
+ int nready;
+ check(nready = poll(fds, 2, -1), elt0, "poll()ing: %s\n", strerror(errno));
+
+ if (nready == 0) continue;
+
+ for (nfds_t i = 0; i < 2; ++i) {
+ if (fds[i].revents & (POLLERR | POLLHUP)) {
+ fatal_error("stream error or hangup condition on %d\n", fds[i].fd);
+ }
+
+ if (fds[i].revents & POLLIN) {
+ ssize_t nread;
+ while ((nread = read(fds[i].fd, buf, 1024)) > 0) {
+ if (fds[i].fd == infd) {
+ /* command */
+ for (ssize_t cidx = 0; cidx < nread; ++i) {
+ /* TODO: split command by lines */
+ }
+ } else {
+ /* gecko */
+
+ }
+ check(write(STDOUT_FILENO, buf, nread), elt0, "write(%d) failed: %s\n", STDOUT_FILENO, strerror(errno));
+ }
+
+ if (nread == 0 && fds[i].fd == tfd) {
+ fatal_error("EOF reached on terminal.\n");
+ }
+
+ if (nread < 0 && errno != EAGAIN) {
+ fatal_error("io error on fd %d: %s\n", fds[i].fd, strerror(errno));
+ }
+ }
+
+ if (fds[i].revents & POLLOUT) {
+ fds[i].events &= ~POLLOUT;
+ can_write = 1;
+ }
+ }
+ }
+
+ close(tfd);
+ close(infd);
+
+ return 0;
+}