If stdin is not a terminal pass-through its data to the session
[abduco.git] / client.c
blob3d6d82b146eb90c78332be91f4732e940222d94d
1 static void client_sigwinch_handler(int sig) {
2 client.need_resize = true;
5 static bool client_send_packet(Packet *pkt) {
6 print_packet("client-send:", pkt);
7 if (send_packet(server.socket, pkt))
8 return true;
9 debug("FAILED\n");
10 server.running = false;
11 return false;
14 static bool client_recv_packet(Packet *pkt) {
15 if (recv_packet(server.socket, pkt)) {
16 print_packet("client-recv:", pkt);
17 return true;
19 debug("client-recv: FAILED\n");
20 server.running = false;
21 return false;
24 static void client_restore_terminal(void) {
25 if (!has_term)
26 return;
27 tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_term);
28 if (alternate_buffer) {
29 printf("\033[?25h\033[?1049l");
30 fflush(stdout);
31 alternate_buffer = false;
35 static void client_setup_terminal(void) {
36 if (!has_term)
37 return;
38 atexit(client_restore_terminal);
40 cur_term = orig_term;
41 cur_term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXOFF);
42 cur_term.c_oflag &= ~(OPOST);
43 cur_term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
44 cur_term.c_cflag &= ~(CSIZE|PARENB);
45 cur_term.c_cflag |= CS8;
46 cur_term.c_cc[VLNEXT] = _POSIX_VDISABLE;
47 cur_term.c_cc[VMIN] = 1;
48 cur_term.c_cc[VTIME] = 0;
49 tcsetattr(STDIN_FILENO, TCSANOW, &cur_term);
51 if (!alternate_buffer) {
52 printf("\033[?1049h\033[H");
53 fflush(stdout);
54 alternate_buffer = true;
58 static int client_mainloop(void) {
59 sigset_t emptyset, blockset;
60 sigemptyset(&emptyset);
61 sigemptyset(&blockset);
62 sigaddset(&blockset, SIGWINCH);
63 sigprocmask(SIG_BLOCK, &blockset, NULL);
65 client.need_resize = true;
66 Packet pkt = {
67 .type = MSG_ATTACH,
68 .u.i = client.flags,
69 .len = sizeof(pkt.u.i),
71 client_send_packet(&pkt);
73 while (server.running) {
74 fd_set fds;
75 FD_ZERO(&fds);
76 FD_SET(STDIN_FILENO, &fds);
77 FD_SET(server.socket, &fds);
79 if (client.need_resize) {
80 struct winsize ws;
81 if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) != -1) {
82 Packet pkt = {
83 .type = MSG_RESIZE,
84 .u = { .ws = { .rows = ws.ws_row, .cols = ws.ws_col } },
85 .len = sizeof(pkt.u.ws),
87 if (client_send_packet(&pkt))
88 client.need_resize = false;
92 if (pselect(server.socket+1, &fds, NULL, NULL, NULL, &emptyset) == -1) {
93 if (errno == EINTR)
94 continue;
95 die("client-mainloop");
98 if (FD_ISSET(server.socket, &fds)) {
99 Packet pkt;
100 if (client_recv_packet(&pkt)) {
101 switch (pkt.type) {
102 case MSG_CONTENT:
103 if (!passthrough)
104 write_all(STDOUT_FILENO, pkt.u.msg, pkt.len);
105 break;
106 case MSG_RESIZE:
107 client.need_resize = true;
108 break;
109 case MSG_EXIT:
110 client_send_packet(&pkt);
111 close(server.socket);
112 return pkt.u.i;
117 if (FD_ISSET(STDIN_FILENO, &fds)) {
118 Packet pkt = { .type = MSG_CONTENT };
119 ssize_t len = read(STDIN_FILENO, pkt.u.msg, sizeof(pkt.u.msg));
120 if (len == -1 && errno != EAGAIN && errno != EINTR)
121 die("client-stdin");
122 if (len > 0) {
123 debug("client-stdin: %c\n", pkt.u.msg[0]);
124 pkt.len = len;
125 if (KEY_REDRAW && pkt.u.msg[0] == KEY_REDRAW) {
126 client.need_resize = true;
127 } else if (pkt.u.msg[0] == KEY_DETACH) {
128 pkt.type = MSG_DETACH;
129 pkt.len = 0;
130 client_send_packet(&pkt);
131 close(server.socket);
132 return -1;
133 } else if (!(client.flags & CLIENT_READONLY)) {
134 client_send_packet(&pkt);
136 } else if (len == 0) {
137 debug("client-stdin: EOF\n");
138 return -1;
143 return -EIO;