aboutsummaryrefslogtreecommitdiffstats
path: root/taketty.c
diff options
context:
space:
mode:
authorLouis Burda <dev@sinitax.com>2026-01-30 22:49:06 +0100
committerLouis Burda <dev@sinitax.com>2026-01-30 22:51:59 +0100
commit0ff1fafa09eb0af827233d3e0906cf64282d096f (patch)
tree3729dbad9023c155115d408a779a5b0210a6e4f9 /taketty.c
downloadtaketty-master.tar.gz
taketty-master.zip
Add initial versionHEADmastermain
Diffstat (limited to 'taketty.c')
-rw-r--r--taketty.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/taketty.c b/taketty.c
new file mode 100644
index 0000000..31fb25e
--- /dev/null
+++ b/taketty.c
@@ -0,0 +1,119 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <sys/select.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <string.h>
+
+static void set_raw_mode(int fd) {
+ struct termios tios;
+
+ if (tcgetattr(fd, &tios) < 0) {
+ perror("tcgetattr");
+ exit(1);
+ }
+
+ tios.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO);
+ tios.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+ tios.c_cflag &= ~(CSIZE | PARENB);
+ tios.c_cflag |= CS8;
+ tios.c_oflag &= ~(OPOST);
+
+ tios.c_cc[VMIN] = 1;
+ tios.c_cc[VTIME] = 0;
+
+ if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
+ perror("tcsetattr");
+ exit(1);
+ }
+}
+
+static void forward_io(int master_fd) {
+ fd_set rfds;
+ char buf[4096];
+ ssize_t n;
+
+ while (1) {
+ FD_ZERO(&rfds);
+ FD_SET(STDIN_FILENO, &rfds);
+ FD_SET(master_fd, &rfds);
+
+ int maxfd = (master_fd > STDIN_FILENO) ? master_fd : STDIN_FILENO;
+
+ if (select(maxfd + 1, &rfds, NULL, NULL, NULL) < 0) {
+ if (errno == EINTR) continue;
+ perror("select");
+ exit(1);
+ }
+
+ if (FD_ISSET(STDIN_FILENO, &rfds)) {
+ n = read(STDIN_FILENO, buf, sizeof(buf));
+ if (n <= 0) {
+ if (n < 0) perror("read stdin");
+ break;
+ }
+ if (write(master_fd, buf, n) != n) {
+ perror("write to master");
+ exit(1);
+ }
+ }
+
+ if (FD_ISSET(master_fd, &rfds)) {
+ n = read(master_fd, buf, sizeof(buf));
+ if (n <= 0) {
+ if (n < 0 && errno != EIO) perror("read master");
+ break;
+ }
+ if (write(STDOUT_FILENO, buf, n) != n) {
+ perror("write to stdout");
+ exit(1);
+ }
+ }
+ }
+}
+
+int main(int argc, char *argv[]) {
+ int master_fd;
+ char *slave_name;
+ struct winsize ws;
+
+ master_fd = posix_openpt(O_RDWR | O_NOCTTY);
+ if (master_fd < 0) {
+ perror("posix_openpt");
+ exit(1);
+ }
+
+ if (grantpt(master_fd) < 0) {
+ perror("grantpt");
+ exit(1);
+ }
+
+ if (unlockpt(master_fd) < 0) {
+ perror("unlockpt");
+ exit(1);
+ }
+
+ slave_name = ptsname(master_fd);
+ if (!slave_name) {
+ perror("ptsname");
+ exit(1);
+ }
+
+ if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0) {
+ ioctl(master_fd, TIOCSWINSZ, &ws);
+ }
+
+ fprintf(stderr, "TAKETTY_PTY=%s\n", slave_name);
+ fflush(stderr);
+
+ set_raw_mode(STDIN_FILENO);
+
+ forward_io(master_fd);
+
+ close(master_fd);
+ return 0;
+}