Send info messages to stderr
[abduco.git] / client.c
blob8ace58f97c1405b7441758ba506e439d8783e86b
1 static Client client;
3 static void client_sigwinch_handler(int sig) {
4 client.need_resize = true;
7 static ssize_t write_all(int fd, const char *buf, size_t len) {
8 ssize_t ret = len;
9 while (len > 0) {
10 ssize_t res = write(fd, buf, len);
11 if (res < 0) {
12 if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
13 continue;
14 return -1;
16 if (res == 0)
17 return ret - len;
18 buf += res;
19 len -= res;
21 return ret;
24 static ssize_t read_all(int fd, char *buf, size_t len) {
25 ssize_t ret = len;
26 while (len > 0) {
27 ssize_t res = read(fd, buf, len);
28 if (res < 0) {
29 if (errno == EWOULDBLOCK)
30 return ret - len;
31 if (errno == EAGAIN || errno == EINTR)
32 continue;
33 return -1;
35 if (res == 0)
36 return ret - len;
37 buf += res;
38 len -= res;
40 return ret;
43 static bool client_send_packet(Packet *pkt) {
44 print_packet("client-send:", pkt);
45 size_t size = packet_size(pkt);
46 if (write_all(server.socket, (char *)pkt, size) != size) {
47 debug("FAILED\n");
48 server.running = false;
49 return false;
51 return true;
54 static bool client_recv_packet(Packet *pkt) {
55 ssize_t len = read_all(server.socket, (char*)pkt, packet_header_size());
56 if (len <= 0 || len != packet_header_size() || pkt->len == 0)
57 goto error;
58 len = read_all(server.socket, pkt->u.msg, pkt->len);
59 print_packet("client-recv:", pkt);
60 if (len <= 0 || len != pkt->len)
61 goto error;
62 return true;
63 error:
64 debug("FAILED here\n");
65 server.running = false;
66 return false;
69 static void client_clear_screen() {
70 printf("\e[H\e[J");
71 fflush(stdout);
74 static void client_show_cursor() {
75 printf("\e[?25h");
76 fflush(stdout);
79 static void client_restore_terminal() {
80 if (has_term)
81 tcsetattr(0, TCSADRAIN, &orig_term);
82 client_show_cursor();
85 static int client_mainloop() {
86 client.need_resize = true;
87 while (server.running) {
88 fd_set fds;
89 FD_ZERO(&fds);
90 FD_SET(STDIN_FILENO, &fds);
91 FD_SET(server.socket, &fds);
93 if (client.need_resize) {
94 struct winsize ws;
95 if (ioctl(0, TIOCGWINSZ, &ws) != -1) {
96 Packet pkt = {
97 .type = MSG_RESIZE,
98 .u = { .ws = ws },
99 .len = sizeof(ws),
101 if (client_send_packet(&pkt))
102 client.need_resize = false;
106 if (select(server.socket + 1, &fds, NULL, NULL, NULL) == -1) {
107 if (errno == EINTR)
108 continue;
109 die("client-mainloop");
112 if (FD_ISSET(server.socket, &fds)) {
113 Packet pkt;
114 if (client_recv_packet(&pkt)) {
115 switch (pkt.type) {
116 case MSG_CONTENT:
117 write_all(STDOUT_FILENO, pkt.u.msg, pkt.len);
118 break;
119 case MSG_EXIT:
120 return pkt.u.i;
125 if (FD_ISSET(STDIN_FILENO, &fds)) {
126 Packet pkt = { .type = MSG_CONTENT };
127 ssize_t len = read(STDIN_FILENO, pkt.u.msg, sizeof(pkt.u.msg));
128 if (len == -1 && errno != EAGAIN && errno != EINTR)
129 die("client-stdin");
130 if (len > 0) {
131 debug("client-stdin: %c", pkt.u.msg[0]);
132 pkt.len = len;
133 if (pkt.u.msg[0] == KEY_REDRAW) {
134 client.need_resize = true;
135 } else if (pkt.u.msg[0] == KEY_DETACH) {
136 pkt.type = MSG_DETACH;
137 pkt.len = 0;
138 client_send_packet(&pkt);
139 return -1;
140 } else {
141 client_send_packet(&pkt);
147 return -EIO;