1 /* $OpenBSD: client.c,v 1.149 2020/09/22 05:23:34 nicm Exp $ */ 2 3 /* 4 * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/socket.h> 21 #include <sys/uio.h> 22 #include <sys/un.h> 23 #include <sys/wait.h> 24 25 #include <errno.h> 26 #include <event.h> 27 #include <fcntl.h> 28 #include <imsg.h> 29 #include <signal.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <unistd.h> 33 34 #include "tmux.h" 35 36 static struct tmuxproc *client_proc; 37 static struct tmuxpeer *client_peer; 38 static uint64_t client_flags; 39 static enum { 40 CLIENT_EXIT_NONE, 41 CLIENT_EXIT_DETACHED, 42 CLIENT_EXIT_DETACHED_HUP, 43 CLIENT_EXIT_LOST_TTY, 44 CLIENT_EXIT_TERMINATED, 45 CLIENT_EXIT_LOST_SERVER, 46 CLIENT_EXIT_EXITED, 47 CLIENT_EXIT_SERVER_EXITED, 48 CLIENT_EXIT_MESSAGE_PROVIDED 49 } client_exitreason = CLIENT_EXIT_NONE; 50 static int client_exitflag; 51 static int client_exitval; 52 static enum msgtype client_exittype; 53 static const char *client_exitsession; 54 static char *client_exitmessage; 55 static const char *client_execshell; 56 static const char *client_execcmd; 57 static int client_attached; 58 static struct client_files client_files = RB_INITIALIZER(&client_files); 59 60 static __dead void client_exec(const char *,const char *); 61 static int client_get_lock(char *); 62 static int client_connect(struct event_base *, const char *, 63 uint64_t); 64 static void client_send_identify(const char *, const char *, int); 65 static void client_signal(int); 66 static void client_dispatch(struct imsg *, void *); 67 static void client_dispatch_attached(struct imsg *); 68 static void client_dispatch_wait(struct imsg *); 69 static const char *client_exit_message(void); 70 71 /* 72 * Get server create lock. If already held then server start is happening in 73 * another client, so block until the lock is released and return -2 to 74 * retry. Return -1 on failure to continue and start the server anyway. 75 */ 76 static int 77 client_get_lock(char *lockfile) 78 { 79 int lockfd; 80 81 log_debug("lock file is %s", lockfile); 82 83 if ((lockfd = open(lockfile, O_WRONLY|O_CREAT, 0600)) == -1) { 84 log_debug("open failed: %s", strerror(errno)); 85 return (-1); 86 } 87 88 if (flock(lockfd, LOCK_EX|LOCK_NB) == -1) { 89 log_debug("flock failed: %s", strerror(errno)); 90 if (errno != EAGAIN) 91 return (lockfd); 92 while (flock(lockfd, LOCK_EX) == -1 && errno == EINTR) 93 /* nothing */; 94 close(lockfd); 95 return (-2); 96 } 97 log_debug("flock succeeded"); 98 99 return (lockfd); 100 } 101 102 /* Connect client to server. */ 103 static int 104 client_connect(struct event_base *base, const char *path, uint64_t flags) 105 { 106 struct sockaddr_un sa; 107 size_t size; 108 int fd, lockfd = -1, locked = 0; 109 char *lockfile = NULL; 110 111 memset(&sa, 0, sizeof sa); 112 sa.sun_family = AF_UNIX; 113 size = strlcpy(sa.sun_path, path, sizeof sa.sun_path); 114 if (size >= sizeof sa.sun_path) { 115 errno = ENAMETOOLONG; 116 return (-1); 117 } 118 log_debug("socket is %s", path); 119 120 retry: 121 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 122 return (-1); 123 124 log_debug("trying connect"); 125 if (connect(fd, (struct sockaddr *)&sa, sizeof sa) == -1) { 126 log_debug("connect failed: %s", strerror(errno)); 127 if (errno != ECONNREFUSED && errno != ENOENT) 128 goto failed; 129 if (~flags & CLIENT_STARTSERVER) 130 goto failed; 131 close(fd); 132 133 if (!locked) { 134 xasprintf(&lockfile, "%s.lock", path); 135 if ((lockfd = client_get_lock(lockfile)) < 0) { 136 log_debug("didn't get lock (%d)", lockfd); 137 138 free(lockfile); 139 lockfile = NULL; 140 141 if (lockfd == -2) 142 goto retry; 143 } 144 log_debug("got lock (%d)", lockfd); 145 146 /* 147 * Always retry at least once, even if we got the lock, 148 * because another client could have taken the lock, 149 * started the server and released the lock between our 150 * connect() and flock(). 151 */ 152 locked = 1; 153 goto retry; 154 } 155 156 if (lockfd >= 0 && unlink(path) != 0 && errno != ENOENT) { 157 free(lockfile); 158 close(lockfd); 159 return (-1); 160 } 161 fd = server_start(client_proc, flags, base, lockfd, lockfile); 162 } 163 164 if (locked && lockfd >= 0) { 165 free(lockfile); 166 close(lockfd); 167 } 168 setblocking(fd, 0); 169 return (fd); 170 171 failed: 172 if (locked) { 173 free(lockfile); 174 close(lockfd); 175 } 176 close(fd); 177 return (-1); 178 } 179 180 /* Get exit string from reason number. */ 181 const char * 182 client_exit_message(void) 183 { 184 static char msg[256]; 185 186 switch (client_exitreason) { 187 case CLIENT_EXIT_NONE: 188 break; 189 case CLIENT_EXIT_DETACHED: 190 if (client_exitsession != NULL) { 191 xsnprintf(msg, sizeof msg, "detached " 192 "(from session %s)", client_exitsession); 193 return (msg); 194 } 195 return ("detached"); 196 case CLIENT_EXIT_DETACHED_HUP: 197 if (client_exitsession != NULL) { 198 xsnprintf(msg, sizeof msg, "detached and SIGHUP " 199 "(from session %s)", client_exitsession); 200 return (msg); 201 } 202 return ("detached and SIGHUP"); 203 case CLIENT_EXIT_LOST_TTY: 204 return ("lost tty"); 205 case CLIENT_EXIT_TERMINATED: 206 return ("terminated"); 207 case CLIENT_EXIT_LOST_SERVER: 208 return ("server exited unexpectedly"); 209 case CLIENT_EXIT_EXITED: 210 return ("exited"); 211 case CLIENT_EXIT_SERVER_EXITED: 212 return ("server exited"); 213 case CLIENT_EXIT_MESSAGE_PROVIDED: 214 return (client_exitmessage); 215 } 216 return ("unknown reason"); 217 } 218 219 /* Exit if all streams flushed. */ 220 static void 221 client_exit(void) 222 { 223 struct client_file *cf; 224 size_t left; 225 int waiting = 0; 226 227 RB_FOREACH (cf, client_files, &client_files) { 228 if (cf->event == NULL) 229 continue; 230 left = EVBUFFER_LENGTH(cf->event->output); 231 if (left != 0) { 232 waiting++; 233 log_debug("file %u %zu bytes left", cf->stream, left); 234 } 235 } 236 if (waiting == 0) 237 proc_exit(client_proc); 238 } 239 240 /* Client main loop. */ 241 int 242 client_main(struct event_base *base, int argc, char **argv, uint64_t flags, 243 int feat) 244 { 245 struct cmd_parse_result *pr; 246 struct msg_command *data; 247 int fd, i; 248 const char *ttynam, *cwd; 249 pid_t ppid; 250 enum msgtype msg; 251 struct termios tio, saved_tio; 252 size_t size, linesize = 0; 253 ssize_t linelen; 254 char *line = NULL; 255 256 /* Ignore SIGCHLD now or daemon() in the server will leave a zombie. */ 257 signal(SIGCHLD, SIG_IGN); 258 259 /* Set up the initial command. */ 260 if (shell_command != NULL) { 261 msg = MSG_SHELL; 262 flags |= CLIENT_STARTSERVER; 263 } else if (argc == 0) { 264 msg = MSG_COMMAND; 265 flags |= CLIENT_STARTSERVER; 266 } else { 267 msg = MSG_COMMAND; 268 269 /* 270 * It sucks parsing the command string twice (in client and 271 * later in server) but it is necessary to get the start server 272 * flag. 273 */ 274 pr = cmd_parse_from_arguments(argc, argv, NULL); 275 if (pr->status == CMD_PARSE_SUCCESS) { 276 if (cmd_list_any_have(pr->cmdlist, CMD_STARTSERVER)) 277 flags |= CLIENT_STARTSERVER; 278 cmd_list_free(pr->cmdlist); 279 } else 280 free(pr->error); 281 } 282 283 /* Create client process structure (starts logging). */ 284 client_proc = proc_start("client"); 285 proc_set_signals(client_proc, client_signal); 286 287 /* Save the flags. */ 288 client_flags = flags; 289 log_debug("flags are %#llx", (unsigned long long)client_flags); 290 291 /* Initialize the client socket and start the server. */ 292 fd = client_connect(base, socket_path, client_flags); 293 if (fd == -1) { 294 if (errno == ECONNREFUSED) { 295 fprintf(stderr, "no server running on %s\n", 296 socket_path); 297 } else { 298 fprintf(stderr, "error connecting to %s (%s)\n", 299 socket_path, strerror(errno)); 300 } 301 return (1); 302 } 303 client_peer = proc_add_peer(client_proc, fd, client_dispatch, NULL); 304 305 /* Save these before pledge(). */ 306 if ((cwd = find_cwd()) == NULL && (cwd = find_home()) == NULL) 307 cwd = "/"; 308 if ((ttynam = ttyname(STDIN_FILENO)) == NULL) 309 ttynam = ""; 310 311 /* 312 * Drop privileges for client. "proc exec" is needed for -c and for 313 * locking (which uses system(3)). 314 * 315 * "tty" is needed to restore termios(4) and also for some reason -CC 316 * does not work properly without it (input is not recognised). 317 * 318 * "sendfd" is dropped later in client_dispatch_wait(). 319 */ 320 if (pledge( 321 "stdio rpath wpath cpath unix sendfd proc exec tty", 322 NULL) != 0) 323 fatal("pledge failed"); 324 325 /* Free stuff that is not used in the client. */ 326 if (ptm_fd != -1) 327 close(ptm_fd); 328 options_free(global_options); 329 options_free(global_s_options); 330 options_free(global_w_options); 331 environ_free(global_environ); 332 333 /* Set up control mode. */ 334 if (client_flags & CLIENT_CONTROLCONTROL) { 335 if (tcgetattr(STDIN_FILENO, &saved_tio) != 0) { 336 fprintf(stderr, "tcgetattr failed: %s\n", 337 strerror(errno)); 338 return (1); 339 } 340 cfmakeraw(&tio); 341 tio.c_iflag = ICRNL|IXANY; 342 tio.c_oflag = OPOST|ONLCR; 343 tio.c_lflag = NOKERNINFO; 344 tio.c_cflag = CREAD|CS8|HUPCL; 345 tio.c_cc[VMIN] = 1; 346 tio.c_cc[VTIME] = 0; 347 cfsetispeed(&tio, cfgetispeed(&saved_tio)); 348 cfsetospeed(&tio, cfgetospeed(&saved_tio)); 349 tcsetattr(STDIN_FILENO, TCSANOW, &tio); 350 } 351 352 /* Send identify messages. */ 353 client_send_identify(ttynam, cwd, feat); 354 355 /* Send first command. */ 356 if (msg == MSG_COMMAND) { 357 /* How big is the command? */ 358 size = 0; 359 for (i = 0; i < argc; i++) 360 size += strlen(argv[i]) + 1; 361 if (size > MAX_IMSGSIZE - (sizeof *data)) { 362 fprintf(stderr, "command too long\n"); 363 return (1); 364 } 365 data = xmalloc((sizeof *data) + size); 366 367 /* Prepare command for server. */ 368 data->argc = argc; 369 if (cmd_pack_argv(argc, argv, (char *)(data + 1), size) != 0) { 370 fprintf(stderr, "command too long\n"); 371 free(data); 372 return (1); 373 } 374 size += sizeof *data; 375 376 /* Send the command. */ 377 if (proc_send(client_peer, msg, -1, data, size) != 0) { 378 fprintf(stderr, "failed to send command\n"); 379 free(data); 380 return (1); 381 } 382 free(data); 383 } else if (msg == MSG_SHELL) 384 proc_send(client_peer, msg, -1, NULL, 0); 385 386 /* Start main loop. */ 387 proc_loop(client_proc, NULL); 388 389 /* Run command if user requested exec, instead of exiting. */ 390 if (client_exittype == MSG_EXEC) { 391 if (client_flags & CLIENT_CONTROLCONTROL) 392 tcsetattr(STDOUT_FILENO, TCSAFLUSH, &saved_tio); 393 client_exec(client_execshell, client_execcmd); 394 } 395 396 /* Restore streams to blocking. */ 397 setblocking(STDIN_FILENO, 1); 398 setblocking(STDOUT_FILENO, 1); 399 setblocking(STDERR_FILENO, 1); 400 401 /* Print the exit message, if any, and exit. */ 402 if (client_attached) { 403 if (client_exitreason != CLIENT_EXIT_NONE) 404 printf("[%s]\n", client_exit_message()); 405 406 ppid = getppid(); 407 if (client_exittype == MSG_DETACHKILL && ppid > 1) 408 kill(ppid, SIGHUP); 409 } else if (client_flags & CLIENT_CONTROL) { 410 if (client_exitreason != CLIENT_EXIT_NONE) 411 printf("%%exit %s\n", client_exit_message()); 412 else 413 printf("%%exit\n"); 414 fflush(stdout); 415 if (client_flags & CLIENT_CONTROL_WAITEXIT) { 416 setvbuf(stdin, NULL, _IOLBF, 0); 417 for (;;) { 418 linelen = getline(&line, &linesize, stdin); 419 if (linelen <= 1) 420 break; 421 } 422 free(line); 423 } 424 if (client_flags & CLIENT_CONTROLCONTROL) { 425 printf("\033\\"); 426 fflush(stdout); 427 tcsetattr(STDOUT_FILENO, TCSAFLUSH, &saved_tio); 428 } 429 } else if (client_exitreason != CLIENT_EXIT_NONE) 430 fprintf(stderr, "%s\n", client_exit_message()); 431 return (client_exitval); 432 } 433 434 /* Send identify messages to server. */ 435 static void 436 client_send_identify(const char *ttynam, const char *cwd, int feat) 437 { 438 const char *s; 439 char **ss; 440 size_t sslen; 441 int fd, flags = client_flags; 442 pid_t pid; 443 444 proc_send(client_peer, MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags); 445 proc_send(client_peer, MSG_IDENTIFY_LONGFLAGS, -1, &client_flags, 446 sizeof client_flags); 447 448 if ((s = getenv("TERM")) == NULL) 449 s = ""; 450 proc_send(client_peer, MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1); 451 proc_send(client_peer, MSG_IDENTIFY_FEATURES, -1, &feat, sizeof feat); 452 453 proc_send(client_peer, MSG_IDENTIFY_TTYNAME, -1, ttynam, 454 strlen(ttynam) + 1); 455 proc_send(client_peer, MSG_IDENTIFY_CWD, -1, cwd, strlen(cwd) + 1); 456 457 if ((fd = dup(STDIN_FILENO)) == -1) 458 fatal("dup failed"); 459 proc_send(client_peer, MSG_IDENTIFY_STDIN, fd, NULL, 0); 460 if ((fd = dup(STDOUT_FILENO)) == -1) 461 fatal("dup failed"); 462 proc_send(client_peer, MSG_IDENTIFY_STDOUT, fd, NULL, 0); 463 464 pid = getpid(); 465 proc_send(client_peer, MSG_IDENTIFY_CLIENTPID, -1, &pid, sizeof pid); 466 467 for (ss = environ; *ss != NULL; ss++) { 468 sslen = strlen(*ss) + 1; 469 if (sslen > MAX_IMSGSIZE - IMSG_HEADER_SIZE) 470 continue; 471 proc_send(client_peer, MSG_IDENTIFY_ENVIRON, -1, *ss, sslen); 472 } 473 474 proc_send(client_peer, MSG_IDENTIFY_DONE, -1, NULL, 0); 475 } 476 477 /* File write error callback. */ 478 static void 479 client_write_error_callback(__unused struct bufferevent *bev, 480 __unused short what, void *arg) 481 { 482 struct client_file *cf = arg; 483 484 log_debug("write error file %d", cf->stream); 485 486 bufferevent_free(cf->event); 487 cf->event = NULL; 488 489 close(cf->fd); 490 cf->fd = -1; 491 492 if (client_exitflag) 493 client_exit(); 494 } 495 496 /* File write callback. */ 497 static void 498 client_write_callback(__unused struct bufferevent *bev, void *arg) 499 { 500 struct client_file *cf = arg; 501 502 if (cf->closed && EVBUFFER_LENGTH(cf->event->output) == 0) { 503 bufferevent_free(cf->event); 504 close(cf->fd); 505 RB_REMOVE(client_files, &client_files, cf); 506 file_free(cf); 507 } 508 509 if (client_exitflag) 510 client_exit(); 511 } 512 513 /* Open write file. */ 514 static void 515 client_write_open(void *data, size_t datalen) 516 { 517 struct msg_write_open *msg = data; 518 const char *path; 519 struct msg_write_ready reply; 520 struct client_file find, *cf; 521 const int flags = O_NONBLOCK|O_WRONLY|O_CREAT; 522 int error = 0; 523 524 if (datalen < sizeof *msg) 525 fatalx("bad MSG_WRITE_OPEN size"); 526 if (datalen == sizeof *msg) 527 path = "-"; 528 else 529 path = (const char *)(msg + 1); 530 log_debug("open write file %d %s", msg->stream, path); 531 532 find.stream = msg->stream; 533 if ((cf = RB_FIND(client_files, &client_files, &find)) == NULL) { 534 cf = file_create(NULL, msg->stream, NULL, NULL); 535 RB_INSERT(client_files, &client_files, cf); 536 } else { 537 error = EBADF; 538 goto reply; 539 } 540 if (cf->closed) { 541 error = EBADF; 542 goto reply; 543 } 544 545 cf->fd = -1; 546 if (msg->fd == -1) 547 cf->fd = open(path, msg->flags|flags, 0644); 548 else { 549 if (msg->fd != STDOUT_FILENO && msg->fd != STDERR_FILENO) 550 errno = EBADF; 551 else { 552 cf->fd = dup(msg->fd); 553 if (~client_flags & CLIENT_CONTROL) 554 close(msg->fd); /* can only be used once */ 555 } 556 } 557 if (cf->fd == -1) { 558 error = errno; 559 goto reply; 560 } 561 562 cf->event = bufferevent_new(cf->fd, NULL, client_write_callback, 563 client_write_error_callback, cf); 564 bufferevent_enable(cf->event, EV_WRITE); 565 goto reply; 566 567 reply: 568 reply.stream = msg->stream; 569 reply.error = error; 570 proc_send(client_peer, MSG_WRITE_READY, -1, &reply, sizeof reply); 571 } 572 573 /* Write to client file. */ 574 static void 575 client_write_data(void *data, size_t datalen) 576 { 577 struct msg_write_data *msg = data; 578 struct client_file find, *cf; 579 size_t size = datalen - sizeof *msg; 580 581 if (datalen < sizeof *msg) 582 fatalx("bad MSG_WRITE size"); 583 find.stream = msg->stream; 584 if ((cf = RB_FIND(client_files, &client_files, &find)) == NULL) 585 fatalx("unknown stream number"); 586 log_debug("write %zu to file %d", size, cf->stream); 587 588 if (cf->event != NULL) 589 bufferevent_write(cf->event, msg + 1, size); 590 } 591 592 /* Close client file. */ 593 static void 594 client_write_close(void *data, size_t datalen) 595 { 596 struct msg_write_close *msg = data; 597 struct client_file find, *cf; 598 599 if (datalen != sizeof *msg) 600 fatalx("bad MSG_WRITE_CLOSE size"); 601 find.stream = msg->stream; 602 if ((cf = RB_FIND(client_files, &client_files, &find)) == NULL) 603 fatalx("unknown stream number"); 604 log_debug("close file %d", cf->stream); 605 606 if (cf->event == NULL || EVBUFFER_LENGTH(cf->event->output) == 0) { 607 if (cf->event != NULL) 608 bufferevent_free(cf->event); 609 if (cf->fd != -1) 610 close(cf->fd); 611 RB_REMOVE(client_files, &client_files, cf); 612 file_free(cf); 613 } 614 } 615 616 /* File read callback. */ 617 static void 618 client_read_callback(__unused struct bufferevent *bev, void *arg) 619 { 620 struct client_file *cf = arg; 621 void *bdata; 622 size_t bsize; 623 struct msg_read_data *msg; 624 size_t msglen; 625 626 msg = xmalloc(sizeof *msg); 627 for (;;) { 628 bdata = EVBUFFER_DATA(cf->event->input); 629 bsize = EVBUFFER_LENGTH(cf->event->input); 630 631 if (bsize == 0) 632 break; 633 if (bsize > MAX_IMSGSIZE - IMSG_HEADER_SIZE - sizeof *msg) 634 bsize = MAX_IMSGSIZE - IMSG_HEADER_SIZE - sizeof *msg; 635 log_debug("read %zu from file %d", bsize, cf->stream); 636 637 msglen = (sizeof *msg) + bsize; 638 msg = xrealloc(msg, msglen); 639 msg->stream = cf->stream; 640 memcpy(msg + 1, bdata, bsize); 641 proc_send(client_peer, MSG_READ, -1, msg, msglen); 642 643 evbuffer_drain(cf->event->input, bsize); 644 } 645 free(msg); 646 } 647 648 /* File read error callback. */ 649 static void 650 client_read_error_callback(__unused struct bufferevent *bev, 651 __unused short what, void *arg) 652 { 653 struct client_file *cf = arg; 654 struct msg_read_done msg; 655 656 log_debug("read error file %d", cf->stream); 657 658 msg.stream = cf->stream; 659 msg.error = 0; 660 proc_send(client_peer, MSG_READ_DONE, -1, &msg, sizeof msg); 661 662 bufferevent_free(cf->event); 663 close(cf->fd); 664 RB_REMOVE(client_files, &client_files, cf); 665 file_free(cf); 666 } 667 668 /* Open read file. */ 669 static void 670 client_read_open(void *data, size_t datalen) 671 { 672 struct msg_read_open *msg = data; 673 const char *path; 674 struct msg_read_done reply; 675 struct client_file find, *cf; 676 const int flags = O_NONBLOCK|O_RDONLY; 677 int error; 678 679 if (datalen < sizeof *msg) 680 fatalx("bad MSG_READ_OPEN size"); 681 if (datalen == sizeof *msg) 682 path = "-"; 683 else 684 path = (const char *)(msg + 1); 685 log_debug("open read file %d %s", msg->stream, path); 686 687 find.stream = msg->stream; 688 if ((cf = RB_FIND(client_files, &client_files, &find)) == NULL) { 689 cf = file_create(NULL, msg->stream, NULL, NULL); 690 RB_INSERT(client_files, &client_files, cf); 691 } else { 692 error = EBADF; 693 goto reply; 694 } 695 if (cf->closed) { 696 error = EBADF; 697 goto reply; 698 } 699 700 cf->fd = -1; 701 if (msg->fd == -1) 702 cf->fd = open(path, flags); 703 else { 704 if (msg->fd != STDIN_FILENO) 705 errno = EBADF; 706 else { 707 cf->fd = dup(msg->fd); 708 if (~client_flags & CLIENT_CONTROL) 709 close(msg->fd); /* can only be used once */ 710 } 711 } 712 if (cf->fd == -1) { 713 error = errno; 714 goto reply; 715 } 716 717 cf->event = bufferevent_new(cf->fd, client_read_callback, NULL, 718 client_read_error_callback, cf); 719 bufferevent_enable(cf->event, EV_READ); 720 return; 721 722 reply: 723 reply.stream = msg->stream; 724 reply.error = error; 725 proc_send(client_peer, MSG_READ_DONE, -1, &reply, sizeof reply); 726 } 727 728 /* Run command in shell; used for -c. */ 729 static __dead void 730 client_exec(const char *shell, const char *shellcmd) 731 { 732 const char *name, *ptr; 733 char *argv0; 734 735 log_debug("shell %s, command %s", shell, shellcmd); 736 737 ptr = strrchr(shell, '/'); 738 if (ptr != NULL && *(ptr + 1) != '\0') 739 name = ptr + 1; 740 else 741 name = shell; 742 if (client_flags & CLIENT_LOGIN) 743 xasprintf(&argv0, "-%s", name); 744 else 745 xasprintf(&argv0, "%s", name); 746 setenv("SHELL", shell, 1); 747 748 proc_clear_signals(client_proc, 1); 749 750 setblocking(STDIN_FILENO, 1); 751 setblocking(STDOUT_FILENO, 1); 752 setblocking(STDERR_FILENO, 1); 753 closefrom(STDERR_FILENO + 1); 754 755 execl(shell, argv0, "-c", shellcmd, (char *) NULL); 756 fatal("execl failed"); 757 } 758 759 /* Callback to handle signals in the client. */ 760 static void 761 client_signal(int sig) 762 { 763 struct sigaction sigact; 764 int status; 765 766 if (sig == SIGCHLD) 767 waitpid(WAIT_ANY, &status, WNOHANG); 768 else if (!client_attached) { 769 if (sig == SIGTERM) 770 proc_exit(client_proc); 771 } else { 772 switch (sig) { 773 case SIGHUP: 774 client_exitreason = CLIENT_EXIT_LOST_TTY; 775 client_exitval = 1; 776 proc_send(client_peer, MSG_EXITING, -1, NULL, 0); 777 break; 778 case SIGTERM: 779 client_exitreason = CLIENT_EXIT_TERMINATED; 780 client_exitval = 1; 781 proc_send(client_peer, MSG_EXITING, -1, NULL, 0); 782 break; 783 case SIGWINCH: 784 proc_send(client_peer, MSG_RESIZE, -1, NULL, 0); 785 break; 786 case SIGCONT: 787 memset(&sigact, 0, sizeof sigact); 788 sigemptyset(&sigact.sa_mask); 789 sigact.sa_flags = SA_RESTART; 790 sigact.sa_handler = SIG_IGN; 791 if (sigaction(SIGTSTP, &sigact, NULL) != 0) 792 fatal("sigaction failed"); 793 proc_send(client_peer, MSG_WAKEUP, -1, NULL, 0); 794 break; 795 } 796 } 797 } 798 799 /* Callback for client read events. */ 800 static void 801 client_dispatch(struct imsg *imsg, __unused void *arg) 802 { 803 if (imsg == NULL) { 804 client_exitreason = CLIENT_EXIT_LOST_SERVER; 805 client_exitval = 1; 806 proc_exit(client_proc); 807 return; 808 } 809 810 if (client_attached) 811 client_dispatch_attached(imsg); 812 else 813 client_dispatch_wait(imsg); 814 } 815 816 /* Process an exit message. */ 817 static void 818 client_dispatch_exit_message(char *data, size_t datalen) 819 { 820 int retval; 821 822 if (datalen < sizeof retval && datalen != 0) 823 fatalx("bad MSG_EXIT size"); 824 825 if (datalen >= sizeof retval) { 826 memcpy(&retval, data, sizeof retval); 827 client_exitval = retval; 828 } 829 830 if (datalen > sizeof retval) { 831 datalen -= sizeof retval; 832 data += sizeof retval; 833 834 client_exitmessage = xmalloc(datalen); 835 memcpy(client_exitmessage, data, datalen); 836 client_exitmessage[datalen - 1] = '\0'; 837 838 client_exitreason = CLIENT_EXIT_MESSAGE_PROVIDED; 839 } 840 } 841 842 /* Dispatch imsgs when in wait state (before MSG_READY). */ 843 static void 844 client_dispatch_wait(struct imsg *imsg) 845 { 846 char *data; 847 ssize_t datalen; 848 static int pledge_applied; 849 850 /* 851 * "sendfd" is no longer required once all of the identify messages 852 * have been sent. We know the server won't send us anything until that 853 * point (because we don't ask it to), so we can drop "sendfd" once we 854 * get the first message from the server. 855 */ 856 if (!pledge_applied) { 857 if (pledge( 858 "stdio rpath wpath cpath unix proc exec tty", 859 NULL) != 0) 860 fatal("pledge failed"); 861 pledge_applied = 1; 862 } 863 864 data = imsg->data; 865 datalen = imsg->hdr.len - IMSG_HEADER_SIZE; 866 867 switch (imsg->hdr.type) { 868 case MSG_EXIT: 869 case MSG_SHUTDOWN: 870 client_dispatch_exit_message(data, datalen); 871 client_exitflag = 1; 872 client_exit(); 873 break; 874 case MSG_READY: 875 if (datalen != 0) 876 fatalx("bad MSG_READY size"); 877 878 client_attached = 1; 879 proc_send(client_peer, MSG_RESIZE, -1, NULL, 0); 880 break; 881 case MSG_VERSION: 882 if (datalen != 0) 883 fatalx("bad MSG_VERSION size"); 884 885 fprintf(stderr, "protocol version mismatch " 886 "(client %d, server %u)\n", PROTOCOL_VERSION, 887 imsg->hdr.peerid & 0xff); 888 client_exitval = 1; 889 proc_exit(client_proc); 890 break; 891 case MSG_FLAGS: 892 if (datalen != sizeof client_flags) 893 fatalx("bad MSG_FLAGS string"); 894 895 memcpy(&client_flags, data, sizeof client_flags); 896 log_debug("new flags are %#llx", 897 (unsigned long long)client_flags); 898 break; 899 case MSG_SHELL: 900 if (datalen == 0 || data[datalen - 1] != '\0') 901 fatalx("bad MSG_SHELL string"); 902 903 client_exec(data, shell_command); 904 /* NOTREACHED */ 905 case MSG_DETACH: 906 case MSG_DETACHKILL: 907 proc_send(client_peer, MSG_EXITING, -1, NULL, 0); 908 break; 909 case MSG_EXITED: 910 proc_exit(client_proc); 911 break; 912 case MSG_READ_OPEN: 913 client_read_open(data, datalen); 914 break; 915 case MSG_WRITE_OPEN: 916 client_write_open(data, datalen); 917 break; 918 case MSG_WRITE: 919 client_write_data(data, datalen); 920 break; 921 case MSG_WRITE_CLOSE: 922 client_write_close(data, datalen); 923 break; 924 case MSG_OLDSTDERR: 925 case MSG_OLDSTDIN: 926 case MSG_OLDSTDOUT: 927 fprintf(stderr, "server version is too old for client\n"); 928 proc_exit(client_proc); 929 break; 930 } 931 } 932 933 /* Dispatch imsgs in attached state (after MSG_READY). */ 934 static void 935 client_dispatch_attached(struct imsg *imsg) 936 { 937 struct sigaction sigact; 938 char *data; 939 ssize_t datalen; 940 941 data = imsg->data; 942 datalen = imsg->hdr.len - IMSG_HEADER_SIZE; 943 944 switch (imsg->hdr.type) { 945 case MSG_FLAGS: 946 if (datalen != sizeof client_flags) 947 fatalx("bad MSG_FLAGS string"); 948 949 memcpy(&client_flags, data, sizeof client_flags); 950 log_debug("new flags are %#llx", 951 (unsigned long long)client_flags); 952 break; 953 case MSG_DETACH: 954 case MSG_DETACHKILL: 955 if (datalen == 0 || data[datalen - 1] != '\0') 956 fatalx("bad MSG_DETACH string"); 957 958 client_exitsession = xstrdup(data); 959 client_exittype = imsg->hdr.type; 960 if (imsg->hdr.type == MSG_DETACHKILL) 961 client_exitreason = CLIENT_EXIT_DETACHED_HUP; 962 else 963 client_exitreason = CLIENT_EXIT_DETACHED; 964 proc_send(client_peer, MSG_EXITING, -1, NULL, 0); 965 break; 966 case MSG_EXEC: 967 if (datalen == 0 || data[datalen - 1] != '\0' || 968 strlen(data) + 1 == (size_t)datalen) 969 fatalx("bad MSG_EXEC string"); 970 client_execcmd = xstrdup(data); 971 client_execshell = xstrdup(data + strlen(data) + 1); 972 973 client_exittype = imsg->hdr.type; 974 proc_send(client_peer, MSG_EXITING, -1, NULL, 0); 975 break; 976 case MSG_EXIT: 977 client_dispatch_exit_message(data, datalen); 978 if (client_exitreason == CLIENT_EXIT_NONE) 979 client_exitreason = CLIENT_EXIT_EXITED; 980 proc_send(client_peer, MSG_EXITING, -1, NULL, 0); 981 break; 982 case MSG_EXITED: 983 if (datalen != 0) 984 fatalx("bad MSG_EXITED size"); 985 986 proc_exit(client_proc); 987 break; 988 case MSG_SHUTDOWN: 989 if (datalen != 0) 990 fatalx("bad MSG_SHUTDOWN size"); 991 992 proc_send(client_peer, MSG_EXITING, -1, NULL, 0); 993 client_exitreason = CLIENT_EXIT_SERVER_EXITED; 994 client_exitval = 1; 995 break; 996 case MSG_SUSPEND: 997 if (datalen != 0) 998 fatalx("bad MSG_SUSPEND size"); 999 1000 memset(&sigact, 0, sizeof sigact); 1001 sigemptyset(&sigact.sa_mask); 1002 sigact.sa_flags = SA_RESTART; 1003 sigact.sa_handler = SIG_DFL; 1004 if (sigaction(SIGTSTP, &sigact, NULL) != 0) 1005 fatal("sigaction failed"); 1006 kill(getpid(), SIGTSTP); 1007 break; 1008 case MSG_LOCK: 1009 if (datalen == 0 || data[datalen - 1] != '\0') 1010 fatalx("bad MSG_LOCK string"); 1011 1012 system(data); 1013 proc_send(client_peer, MSG_UNLOCK, -1, NULL, 0); 1014 break; 1015 } 1016 } 1017