commit 5026e5f

uint  ·  2026-06-23 15:17:06 +0000 UTC
parent 60b3c6f
Spawn pty on multiplex start
1 files changed,  +71, -7
M tmtm.c
M tmtm.c
+71, -7
  1@@ -2,16 +2,28 @@
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 #include <string.h>
  5+#include <sys/ioctl.h>
  6+#include <sys/poll.h>
  7 #include <termios.h>
  8 #include <unistd.h>
  9 
 10+#ifdef __linux__
 11+#include <pty.h>
 12+#else /* BSD and macOS */
 13+#include <util.h>
 14+#endif
 15+
 16 #define TMTM_VER "26.6"
 17 
 18 static void die(int ln, int ec, const char* fmt, ...);
 19+static void getwinsize(void);
 20 static void rawon(void);
 21 static void rawoff(void);
 22 
 23 static struct termios orig_termios;
 24+static int scrrows = 0;
 25+static int scrcols = 0;
 26+static int masterfd = -1;
 27 
 28 static void die(int ln, int ec, const char* fmt, ...)
 29 {
 30@@ -49,6 +61,14 @@ static void rawoff(void)
 31 	tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios);
 32 }
 33 
 34+static void getwinsize(void)
 35+{
 36+	struct winsize ws;
 37+	if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0)
 38+		die(__LINE__, EXIT_FAILURE, "failed to get window size");
 39+	scrrows = ws.ws_row;
 40+	scrcols = ws.ws_col;
 41+}
 42 
 43 int main(int argc, char* argv[])
 44 {
 45@@ -59,16 +79,60 @@ int main(int argc, char* argv[])
 46 		}
 47 	}
 48 
 49+	pid_t pid = forkpty(&masterfd, NULL, NULL, NULL);
 50+	if (pid < 0)
 51+		die(__LINE__, EXIT_FAILURE, "forkpty failed");
 52+	if (pid == 0) {
 53+		char* shell = getenv("SHELL");
 54+		if (!shell)
 55+			shell = "sh";
 56+		execlp(shell, shell, NULL);
 57+		fprintf(stderr, "ln:%d execlp failed", __LINE__);
 58+		_exit(EXIT_FAILURE);
 59+	}
 60+
 61 	rawon();
 62-	char c;
 63-	while ((read(STDIN_FILENO, &c, 1) == 1 && c != 'q')) {
 64-		if (c >= '!' && c <= '~')
 65-			printf("%c", c);
 66-		else
 67-			printf("%d", c);
 68-		fflush(stdout);
 69+	getwinsize();
 70+
 71+	struct pollfd fds[2]; /* stdin, shell */
 72+	fds[0].fd = STDIN_FILENO;
 73+	fds[0].events = POLLIN;
 74+	fds[1].fd = masterfd;
 75+	fds[1].events = POLLIN;
 76+	char buf[256];
 77+
 78+	printf("\r\nin pty\r\n");
 79+	for (;;) {
 80+		if (poll(fds, 2, -1) < 0)
 81+			break;
 82+
 83+		/* input->shell */
 84+		if (fds[0].revents & POLLIN) {
 85+			int n = read(STDIN_FILENO, buf, sizeof(buf));
 86+			if (n <= 0)
 87+				break;
 88+			if (n == 1 && buf[0] == 0x11) /* ctrl-q */
 89+				break;
 90+			if (write(masterfd, buf, n) < 0)
 91+				break;
 92+		}
 93+
 94+		/* shell->screen */
 95+		if (fds[1].revents & POLLIN) {
 96+			int n = read(masterfd, buf, sizeof(buf));
 97+			if (n <= 0)
 98+				break;
 99+			if (write(STDOUT_FILENO, buf, n) < 0)
100+				break;
101+		}
102+
103+		/* either descriptor closes */
104+		if ((fds[0].revents | fds[1].revents) & (POLLHUP | POLLERR))
105+			break;
106 	}
107 
108+	printf("\r\nexited pty\r\n");
109+
110 	return EXIT_SUCCESS;
111 }
112