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