client.c (3409B)
1 static void client_sigwinch_handler(int sig) { 2 client.need_resize = true; 3 } 4 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; 12 } 13 14 static bool client_recv_packet(Packet *pkt) { 15 if (recv_packet(server.socket, pkt)) { 16 print_packet("client-recv:", pkt); 17 return true; 18 } 19 debug("client-recv: FAILED\n"); 20 server.running = false; 21 return false; 22 } 23 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; 32 } 33 } 34 35 static void client_setup_terminal(void) { 36 if (!has_term) 37 return; 38 atexit(client_restore_terminal); 39 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); 50 51 if (!alternate_buffer) { 52 printf("\033[?1049h\033[H"); 53 fflush(stdout); 54 alternate_buffer = true; 55 } 56 } 57 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); 64 65 client.need_resize = true; 66 Packet pkt = { 67 .type = MSG_ATTACH, 68 .u.i = client.flags, 69 .len = sizeof(pkt.u.i), 70 }; 71 client_send_packet(&pkt); 72 73 while (server.running) { 74 fd_set fds; 75 FD_ZERO(&fds); 76 FD_SET(STDIN_FILENO, &fds); 77 FD_SET(server.socket, &fds); 78 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), 86 }; 87 if (client_send_packet(&pkt)) 88 client.need_resize = false; 89 } 90 } 91 92 if (pselect(server.socket+1, &fds, NULL, NULL, NULL, &emptyset) == -1) { 93 if (errno == EINTR) 94 continue; 95 die("client-mainloop"); 96 } 97 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; 113 } 114 } 115 } 116 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); 135 } 136 } else if (len == 0) { 137 debug("client-stdin: EOF\n"); 138 return -1; 139 } 140 } 141 } 142 143 return -EIO; 144 }