abduco

Fork of abduco for persistent terminal sessions
git clone git://git.laack.co/abduco.git
Log | Files | Refs | README | LICENSE

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 }