server.c (6986B)
1 #define FD_SET_MAX(fd, set, maxfd) do { \ 2 FD_SET(fd, set); \ 3 if (fd > maxfd) \ 4 maxfd = fd; \ 5 } while (0) 6 7 static Client *client_malloc(int socket) { 8 Client *c = calloc(1, sizeof(Client)); 9 if (!c) 10 return NULL; 11 c->socket = socket; 12 return c; 13 } 14 15 static void client_free(Client *c) { 16 if (c && c->socket > 0) 17 close(c->socket); 18 free(c); 19 } 20 21 static void server_sink_client() { 22 if (!server.clients || !server.clients->next) 23 return; 24 Client *target = server.clients; 25 server.clients = target->next; 26 Client *dst = server.clients; 27 while (dst->next) 28 dst = dst->next; 29 target->next = NULL; 30 dst->next = target; 31 } 32 33 static void server_mark_socket_exec(bool exec, bool usr) { 34 struct stat sb; 35 if (stat(sockaddr.sun_path, &sb) == -1) 36 return; 37 mode_t mode = sb.st_mode; 38 mode_t flag = usr ? S_IXUSR : S_IXGRP; 39 if (exec) 40 mode |= flag; 41 else 42 mode &= ~flag; 43 chmod(sockaddr.sun_path, mode); 44 } 45 46 static int server_create_socket(const char *name) { 47 if (!set_socket_name(&sockaddr, name)) 48 return -1; 49 int fd = socket(AF_UNIX, SOCK_STREAM, 0); 50 if (fd == -1) 51 return -1; 52 socklen_t socklen = offsetof(struct sockaddr_un, sun_path) + strlen(sockaddr.sun_path) + 1; 53 mode_t mask = umask(S_IXUSR|S_IRWXG|S_IRWXO); 54 int r = bind(fd, (struct sockaddr*)&sockaddr, socklen); 55 umask(mask); 56 57 if (r == -1) { 58 close(fd); 59 return -1; 60 } 61 62 if (listen(fd, 5) == -1) { 63 unlink(sockaddr.sun_path); 64 close(fd); 65 return -1; 66 } 67 68 return fd; 69 } 70 71 static int server_set_socket_non_blocking(int sock) { 72 int flags; 73 if ((flags = fcntl(sock, F_GETFL, 0)) == -1) 74 flags = 0; 75 return fcntl(sock, F_SETFL, flags | O_NONBLOCK); 76 } 77 78 static bool server_read_pty(Packet *pkt) { 79 pkt->type = MSG_CONTENT; 80 ssize_t len = read(server.pty, pkt->u.msg, sizeof(pkt->u.msg)); 81 if (len > 0) 82 pkt->len = len; 83 else if (len == 0) 84 server.running = false; 85 else if (len == -1 && errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) 86 server.running = false; 87 print_packet("server-read-pty:", pkt); 88 return len > 0; 89 } 90 91 static bool server_write_pty(Packet *pkt) { 92 print_packet("server-write-pty:", pkt); 93 size_t size = pkt->len; 94 if (write_all(server.pty, pkt->u.msg, size) == size) 95 return true; 96 debug("FAILED\n"); 97 server.running = false; 98 return false; 99 } 100 101 static bool server_recv_packet(Client *c, Packet *pkt) { 102 if (recv_packet(c->socket, pkt)) { 103 print_packet("server-recv:", pkt); 104 return true; 105 } 106 debug("server-recv: FAILED\n"); 107 c->state = STATE_DISCONNECTED; 108 return false; 109 } 110 111 static bool server_send_packet(Client *c, Packet *pkt) { 112 print_packet("server-send:", pkt); 113 if (send_packet(c->socket, pkt)) 114 return true; 115 debug("FAILED\n"); 116 c->state = STATE_DISCONNECTED; 117 return false; 118 } 119 120 static void server_pty_died_handler(int sig) { 121 int errsv = errno; 122 pid_t pid; 123 124 while ((pid = waitpid(-1, &server.exit_status, WNOHANG)) != 0) { 125 if (pid == -1) 126 break; 127 server.exit_status = WEXITSTATUS(server.exit_status); 128 server_mark_socket_exec(true, false); 129 } 130 131 debug("server pty died: %d\n", server.exit_status); 132 errno = errsv; 133 } 134 135 static void server_sigterm_handler(int sig) { 136 exit(EXIT_FAILURE); /* invoke atexit handler */ 137 } 138 139 static Client *server_accept_client(void) { 140 int newfd = accept(server.socket, NULL, NULL); 141 if (newfd == -1 || server_set_socket_non_blocking(newfd) == -1) 142 goto error; 143 Client *c = client_malloc(newfd); 144 if (!c) 145 goto error; 146 if (!server.clients) 147 server_mark_socket_exec(true, true); 148 c->socket = newfd; 149 c->state = STATE_CONNECTED; 150 c->next = server.clients; 151 server.clients = c; 152 server.read_pty = true; 153 154 Packet pkt = { 155 .type = MSG_PID, 156 .len = sizeof pkt.u.l, 157 .u.l = getpid(), 158 }; 159 server_send_packet(c, &pkt); 160 161 return c; 162 error: 163 if (newfd != -1) 164 close(newfd); 165 return NULL; 166 } 167 168 static void server_sigusr1_handler(int sig) { 169 int socket = server_create_socket(server.session_name); 170 if (socket != -1) { 171 if (server.socket) 172 close(server.socket); 173 server.socket = socket; 174 } 175 } 176 177 static void server_atexit_handler(void) { 178 unlink(sockaddr.sun_path); 179 } 180 181 static void server_mainloop(void) { 182 atexit(server_atexit_handler); 183 fd_set new_readfds, new_writefds; 184 FD_ZERO(&new_readfds); 185 FD_ZERO(&new_writefds); 186 FD_SET(server.socket, &new_readfds); 187 int new_fdmax = server.socket; 188 bool exit_packet_delivered = false; 189 190 if (server.read_pty) 191 FD_SET_MAX(server.pty, &new_readfds, new_fdmax); 192 193 while (server.clients || !exit_packet_delivered) { 194 int fdmax = new_fdmax; 195 fd_set readfds = new_readfds; 196 fd_set writefds = new_writefds; 197 FD_SET_MAX(server.socket, &readfds, fdmax); 198 199 if (select(fdmax+1, &readfds, &writefds, NULL, NULL) == -1) { 200 if (errno == EINTR) 201 continue; 202 die("server-mainloop"); 203 } 204 205 FD_ZERO(&new_readfds); 206 FD_ZERO(&new_writefds); 207 new_fdmax = server.socket; 208 209 bool pty_data = false; 210 211 Packet server_packet, client_packet; 212 213 if (FD_ISSET(server.socket, &readfds)) 214 server_accept_client(); 215 216 if (FD_ISSET(server.pty, &readfds)) 217 pty_data = server_read_pty(&server_packet); 218 219 for (Client **prev_next = &server.clients, *c = server.clients; c;) { 220 if (FD_ISSET(c->socket, &readfds) && server_recv_packet(c, &client_packet)) { 221 switch (client_packet.type) { 222 case MSG_CONTENT: 223 server_write_pty(&client_packet); 224 break; 225 case MSG_ATTACH: 226 c->flags = client_packet.u.i; 227 if (c->flags & CLIENT_LOWPRIORITY) 228 server_sink_client(); 229 break; 230 case MSG_RESIZE: 231 c->state = STATE_ATTACHED; 232 if (!(c->flags & CLIENT_READONLY) && c == server.clients) { 233 debug("server-ioct: TIOCSWINSZ\n"); 234 struct winsize ws = { 0 }; 235 ws.ws_row = client_packet.u.ws.rows; 236 ws.ws_col = client_packet.u.ws.cols; 237 ioctl(server.pty, TIOCSWINSZ, &ws); 238 } 239 kill(-server.pid, SIGWINCH); 240 break; 241 case MSG_EXIT: 242 exit_packet_delivered = true; 243 /* fall through */ 244 case MSG_DETACH: 245 c->state = STATE_DISCONNECTED; 246 break; 247 default: /* ignore package */ 248 break; 249 } 250 } 251 252 if (c->state == STATE_DISCONNECTED) { 253 bool first = (c == server.clients); 254 Client *t = c->next; 255 client_free(c); 256 *prev_next = c = t; 257 if (first && server.clients) { 258 Packet pkt = { 259 .type = MSG_RESIZE, 260 .len = 0, 261 }; 262 server_send_packet(server.clients, &pkt); 263 } else if (!server.clients) { 264 server_mark_socket_exec(false, true); 265 } 266 continue; 267 } 268 269 FD_SET_MAX(c->socket, &new_readfds, new_fdmax); 270 271 if (pty_data) 272 server_send_packet(c, &server_packet); 273 if (!server.running) { 274 if (server.exit_status != -1) { 275 Packet pkt = { 276 .type = MSG_EXIT, 277 .u.i = server.exit_status, 278 .len = sizeof(pkt.u.i), 279 }; 280 if (!server_send_packet(c, &pkt)) 281 FD_SET_MAX(c->socket, &new_writefds, new_fdmax); 282 } else { 283 FD_SET_MAX(c->socket, &new_writefds, new_fdmax); 284 } 285 } 286 prev_next = &c->next; 287 c = c->next; 288 } 289 290 if (server.running && server.read_pty) 291 FD_SET_MAX(server.pty, &new_readfds, new_fdmax); 292 } 293 294 exit(EXIT_SUCCESS); 295 }