1 /* $OpenBSD$ */ 2 3 /* 4 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> 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/file.h> 21 #include <sys/socket.h> 22 #include <sys/stat.h> 23 #include <sys/un.h> 24 #include <sys/wait.h> 25 26 #include <errno.h> 27 #include <event.h> 28 #include <fcntl.h> 29 #include <signal.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <unistd.h> 33 34 #include "tmux.h" 35 36 int client_flags; 37 struct imsgbuf client_ibuf; 38 struct event client_event; 39 struct event client_stdin; 40 enum { 41 CLIENT_EXIT_NONE, 42 CLIENT_EXIT_DETACHED, 43 CLIENT_EXIT_DETACHED_HUP, 44 CLIENT_EXIT_LOST_TTY, 45 CLIENT_EXIT_TERMINATED, 46 CLIENT_EXIT_LOST_SERVER, 47 CLIENT_EXIT_EXITED, 48 CLIENT_EXIT_SERVER_EXITED, 49 } client_exitreason = CLIENT_EXIT_NONE; 50 int client_exitval; 51 enum msgtype client_exittype; 52 const char *client_exitsession; 53 int client_attached; 54 55 __dead void client_exec(const char *); 56 int client_get_lock(char *); 57 int client_connect(struct event_base *, char *, int); 58 void client_send_identify(const char *, int); 59 int client_write_one(enum msgtype, int, const void *, size_t); 60 int client_write_server(enum msgtype, const void *, size_t); 61 void client_update_event(void); 62 void client_signal(int, short, void *); 63 void client_stdin_callback(int, short, void *); 64 void client_write(int, const char *, size_t); 65 void client_callback(int, short, void *); 66 int client_dispatch_attached(void); 67 int client_dispatch_wait(void); 68 const char *client_exit_message(void); 69 70 /* 71 * Get server create lock. If already held then server start is happening in 72 * another client, so block until the lock is released and return -1 to 73 * retry. Ignore other errors - just continue and start the server without the 74 * lock. 75 */ 76 int 77 client_get_lock(char *lockfile) 78 { 79 int lockfd; 80 81 if ((lockfd = open(lockfile, O_WRONLY|O_CREAT, 0600)) == -1) 82 fatal("open failed"); 83 log_debug("lock file is %s", lockfile); 84 85 if (flock(lockfd, LOCK_EX|LOCK_NB) == -1) { 86 log_debug("flock failed: %s", strerror(errno)); 87 if (errno != EAGAIN) 88 return (lockfd); 89 while (flock(lockfd, LOCK_EX) == -1 && errno == EINTR) 90 /* nothing */; 91 close(lockfd); 92 return (-1); 93 } 94 log_debug("flock succeeded"); 95 96 return (lockfd); 97 } 98 99 /* Connect client to server. */ 100 int 101 client_connect(struct event_base *base, char *path, int start_server) 102 { 103 struct sockaddr_un sa; 104 size_t size; 105 int fd, lockfd = -1, locked = 0; 106 char *lockfile = NULL; 107 108 memset(&sa, 0, sizeof sa); 109 sa.sun_family = AF_UNIX; 110 size = strlcpy(sa.sun_path, path, sizeof sa.sun_path); 111 if (size >= sizeof sa.sun_path) { 112 errno = ENAMETOOLONG; 113 return (-1); 114 } 115 log_debug("socket is %s", path); 116 117 retry: 118 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 119 fatal("socket failed"); 120 121 log_debug("trying connect"); 122 if (connect(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) { 123 log_debug("connect failed: %s", strerror(errno)); 124 if (errno != ECONNREFUSED && errno != ENOENT) 125 goto failed; 126 if (!start_server) 127 goto failed; 128 close(fd); 129 130 if (!locked) { 131 xasprintf(&lockfile, "%s.lock", path); 132 if ((lockfd = client_get_lock(lockfile)) == -1) { 133 log_debug("didn't get lock"); 134 free(lockfile); 135 goto retry; 136 } 137 log_debug("got lock"); 138 139 /* 140 * Always retry at least once, even if we got the lock, 141 * because another client could have taken the lock, 142 * started the server and released the lock between our 143 * connect() and flock(). 144 */ 145 locked = 1; 146 goto retry; 147 } 148 149 if (unlink(path) != 0 && errno != ENOENT) { 150 free(lockfile); 151 close(lockfd); 152 return (-1); 153 } 154 fd = server_start(base, lockfd, lockfile); 155 } 156 157 if (locked) { 158 free(lockfile); 159 close(lockfd); 160 } 161 setblocking(fd, 0); 162 return (fd); 163 164 failed: 165 if (locked) { 166 free(lockfile); 167 close(lockfd); 168 } 169 close(fd); 170 return (-1); 171 } 172 173 /* Get exit string from reason number. */ 174 const char * 175 client_exit_message(void) 176 { 177 static char msg[256]; 178 179 switch (client_exitreason) { 180 case CLIENT_EXIT_NONE: 181 break; 182 case CLIENT_EXIT_DETACHED: 183 if (client_exitsession != NULL) { 184 xsnprintf(msg, sizeof msg, "detached " 185 "(from session %s)", client_exitsession); 186 return (msg); 187 } 188 return ("detached"); 189 case CLIENT_EXIT_DETACHED_HUP: 190 if (client_exitsession != NULL) { 191 xsnprintf(msg, sizeof msg, "detached and SIGHUP " 192 "(from session %s)", client_exitsession); 193 return (msg); 194 } 195 return ("detached and SIGHUP"); 196 case CLIENT_EXIT_LOST_TTY: 197 return ("lost tty"); 198 case CLIENT_EXIT_TERMINATED: 199 return ("terminated"); 200 case CLIENT_EXIT_LOST_SERVER: 201 return ("lost server"); 202 case CLIENT_EXIT_EXITED: 203 return ("exited"); 204 case CLIENT_EXIT_SERVER_EXITED: 205 return ("server exited"); 206 } 207 return ("unknown reason"); 208 } 209 210 /* Client main loop. */ 211 int 212 client_main(struct event_base *base, int argc, char **argv, int flags) 213 { 214 struct cmd *cmd; 215 struct cmd_list *cmdlist; 216 struct msg_command_data *data; 217 int cmdflags, fd, i, cwd; 218 const char* ttynam; 219 pid_t ppid; 220 enum msgtype msg; 221 char *cause; 222 struct termios tio, saved_tio; 223 size_t size; 224 225 /* Save the flags. */ 226 client_flags = flags; 227 228 /* Set up the initial command. */ 229 cmdflags = 0; 230 if (shell_cmd != NULL) { 231 msg = MSG_SHELL; 232 cmdflags = CMD_STARTSERVER; 233 } else if (argc == 0) { 234 msg = MSG_COMMAND; 235 cmdflags = CMD_STARTSERVER; 236 } else { 237 msg = MSG_COMMAND; 238 239 /* 240 * It sucks parsing the command string twice (in client and 241 * later in server) but it is necessary to get the start server 242 * flag. 243 */ 244 cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause); 245 if (cmdlist == NULL) { 246 fprintf(stderr, "%s\n", cause); 247 return (1); 248 } 249 cmdflags &= ~CMD_STARTSERVER; 250 TAILQ_FOREACH(cmd, &cmdlist->list, qentry) { 251 if (cmd->entry->flags & CMD_STARTSERVER) 252 cmdflags |= CMD_STARTSERVER; 253 } 254 cmd_list_free(cmdlist); 255 } 256 257 /* Establish signal handlers. */ 258 set_signals(client_signal); 259 260 /* Initialize the client socket and start the server. */ 261 fd = client_connect(base, socket_path, cmdflags & CMD_STARTSERVER); 262 if (fd == -1) { 263 if (errno == ECONNREFUSED) { 264 fprintf(stderr, "no server running on %s\n", 265 socket_path); 266 } else { 267 fprintf(stderr, "error connecting to %s (%s)\n", 268 socket_path, strerror(errno)); 269 } 270 return (1); 271 } 272 273 /* Save these before pledge(). */ 274 if ((cwd = open(".", O_RDONLY)) == -1) 275 cwd = open("/", O_RDONLY); 276 if ((ttynam = ttyname(STDIN_FILENO)) == NULL) 277 ttynam = ""; 278 279 #ifdef __OpenBSD__ 280 /* 281 * Drop privileges for client. "proc exec" is needed for -c and for 282 * locking (which uses system(3)). 283 * 284 * "tty" is needed to restore termios(4) and also for some reason -CC 285 * does not work properly without it (input is not recognised). 286 * 287 * "sendfd" is dropped later in client_dispatch_wait(). 288 */ 289 if (pledge("stdio unix sendfd proc exec tty", NULL) != 0) 290 fatal("pledge failed"); 291 #endif 292 293 /* Free stuff that is not used in the client. */ 294 options_free(&global_options); 295 options_free(&global_s_options); 296 options_free(&global_w_options); 297 environ_free(&global_environ); 298 299 /* Set process title, log and signals now this is the client. */ 300 #ifdef HAVE_SETPROCTITLE 301 setproctitle("client (%s)", socket_path); 302 #endif 303 logfile("client"); 304 305 /* Create imsg. */ 306 imsg_init(&client_ibuf, fd); 307 event_set(&client_event, fd, EV_READ, client_callback, NULL); 308 309 /* Create stdin handler. */ 310 setblocking(STDIN_FILENO, 0); 311 event_set(&client_stdin, STDIN_FILENO, EV_READ|EV_PERSIST, 312 client_stdin_callback, NULL); 313 if (client_flags & CLIENT_CONTROLCONTROL) { 314 if (tcgetattr(STDIN_FILENO, &saved_tio) != 0) { 315 fprintf(stderr, "tcgetattr failed: %s\n", 316 strerror(errno)); 317 return (1); 318 } 319 cfmakeraw(&tio); 320 tio.c_iflag = ICRNL|IXANY; 321 tio.c_oflag = OPOST|ONLCR; 322 #ifdef NOKERNINFO 323 tio.c_lflag = NOKERNINFO; 324 #endif 325 tio.c_cflag = CREAD|CS8|HUPCL; 326 tio.c_cc[VMIN] = 1; 327 tio.c_cc[VTIME] = 0; 328 cfsetispeed(&tio, cfgetispeed(&saved_tio)); 329 cfsetospeed(&tio, cfgetospeed(&saved_tio)); 330 tcsetattr(STDIN_FILENO, TCSANOW, &tio); 331 } 332 333 /* Send identify messages. */ 334 client_send_identify(ttynam, cwd); /* closes cwd */ 335 336 /* Send first command. */ 337 if (msg == MSG_COMMAND) { 338 /* How big is the command? */ 339 size = 0; 340 for (i = 0; i < argc; i++) 341 size += strlen(argv[i]) + 1; 342 data = xmalloc((sizeof *data) + size); 343 344 /* Prepare command for server. */ 345 data->argc = argc; 346 if (cmd_pack_argv(argc, argv, (char *)(data + 1), size) != 0) { 347 fprintf(stderr, "command too long\n"); 348 free(data); 349 return (1); 350 } 351 size += sizeof *data; 352 353 /* Send the command. */ 354 if (client_write_server(msg, data, size) != 0) { 355 fprintf(stderr, "failed to send command\n"); 356 free(data); 357 return (1); 358 } 359 free(data); 360 } else if (msg == MSG_SHELL) 361 client_write_server(msg, NULL, 0); 362 363 /* Set the event and dispatch. */ 364 client_update_event(); 365 event_dispatch(); 366 367 /* Print the exit message, if any, and exit. */ 368 if (client_attached) { 369 if (client_exitreason != CLIENT_EXIT_NONE) 370 printf("[%s]\n", client_exit_message()); 371 372 ppid = getppid(); 373 if (client_exittype == MSG_DETACHKILL && ppid > 1) 374 kill(ppid, SIGHUP); 375 } else if (client_flags & CLIENT_CONTROLCONTROL) { 376 if (client_exitreason != CLIENT_EXIT_NONE) 377 printf("%%exit %s\n", client_exit_message()); 378 else 379 printf("%%exit\n"); 380 printf("\033\\"); 381 tcsetattr(STDOUT_FILENO, TCSAFLUSH, &saved_tio); 382 } 383 setblocking(STDIN_FILENO, 1); 384 return (client_exitval); 385 } 386 387 /* Send identify messages to server. */ 388 void 389 client_send_identify(const char *ttynam, int cwd) 390 { 391 const char *s; 392 char **ss; 393 size_t sslen; 394 int fd, flags = client_flags; 395 pid_t pid; 396 397 client_write_one(MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags); 398 399 if ((s = getenv("TERM")) == NULL) 400 s = ""; 401 client_write_one(MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1); 402 403 client_write_one(MSG_IDENTIFY_TTYNAME, -1, ttynam, strlen(ttynam) + 1); 404 client_write_one(MSG_IDENTIFY_CWD, cwd, NULL, 0); 405 406 if ((fd = dup(STDIN_FILENO)) == -1) 407 fatal("dup failed"); 408 client_write_one(MSG_IDENTIFY_STDIN, fd, NULL, 0); 409 410 pid = getpid(); 411 client_write_one(MSG_IDENTIFY_CLIENTPID, -1, &pid, sizeof pid); 412 413 for (ss = environ; *ss != NULL; ss++) { 414 sslen = strlen(*ss) + 1; 415 if (sslen <= MAX_IMSGSIZE - IMSG_HEADER_SIZE) 416 client_write_one(MSG_IDENTIFY_ENVIRON, -1, *ss, sslen); 417 } 418 419 client_write_one(MSG_IDENTIFY_DONE, -1, NULL, 0); 420 } 421 422 /* Helper to send one message. */ 423 int 424 client_write_one(enum msgtype type, int fd, const void *buf, size_t len) 425 { 426 int retval; 427 428 retval = imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, fd, 429 __UNCONST(buf), len); 430 if (retval != 1) 431 return (-1); 432 return (0); 433 } 434 435 /* Write a message to the server without a file descriptor. */ 436 int 437 client_write_server(enum msgtype type, const void *buf, size_t len) 438 { 439 int retval; 440 441 retval = client_write_one(type, -1, buf, len); 442 if (retval == 0) 443 client_update_event(); 444 return (retval); 445 } 446 447 /* Update client event based on whether it needs to read or read and write. */ 448 void 449 client_update_event(void) 450 { 451 short events; 452 453 event_del(&client_event); 454 events = EV_READ; 455 if (client_ibuf.w.queued > 0) 456 events |= EV_WRITE; 457 event_set(&client_event, client_ibuf.fd, events, client_callback, NULL); 458 event_add(&client_event, NULL); 459 } 460 461 /* Callback to handle signals in the client. */ 462 void 463 client_signal(int sig, unused short events, unused void *arg) 464 { 465 struct sigaction sigact; 466 int status; 467 468 if (sig == SIGCHLD) 469 waitpid(WAIT_ANY, &status, WNOHANG); 470 else if (!client_attached) { 471 if (sig == SIGTERM) 472 event_loopexit(NULL); 473 } else { 474 switch (sig) { 475 case SIGHUP: 476 client_exitreason = CLIENT_EXIT_LOST_TTY; 477 client_exitval = 1; 478 client_write_server(MSG_EXITING, NULL, 0); 479 break; 480 case SIGTERM: 481 client_exitreason = CLIENT_EXIT_TERMINATED; 482 client_exitval = 1; 483 client_write_server(MSG_EXITING, NULL, 0); 484 break; 485 case SIGWINCH: 486 client_write_server(MSG_RESIZE, NULL, 0); 487 break; 488 case SIGCONT: 489 memset(&sigact, 0, sizeof sigact); 490 sigemptyset(&sigact.sa_mask); 491 sigact.sa_flags = SA_RESTART; 492 sigact.sa_handler = SIG_IGN; 493 if (sigaction(SIGTSTP, &sigact, NULL) != 0) 494 fatal("sigaction failed"); 495 client_write_server(MSG_WAKEUP, NULL, 0); 496 break; 497 } 498 } 499 500 client_update_event(); 501 } 502 503 /* Callback for client imsg read events. */ 504 void 505 client_callback(unused int fd, short events, unused void *arg) 506 { 507 ssize_t n; 508 int retval; 509 510 if (events & EV_READ) { 511 if ((n = imsg_read(&client_ibuf)) == -1 || n == 0) 512 goto lost_server; 513 if (client_attached) 514 retval = client_dispatch_attached(); 515 else 516 retval = client_dispatch_wait(); 517 if (retval != 0) { 518 event_loopexit(NULL); 519 return; 520 } 521 } 522 523 if (events & EV_WRITE) { 524 if (msgbuf_write(&client_ibuf.w) <= 0 && errno != EAGAIN) 525 goto lost_server; 526 } 527 528 client_update_event(); 529 return; 530 531 lost_server: 532 client_exitreason = CLIENT_EXIT_LOST_SERVER; 533 client_exitval = 1; 534 event_loopexit(NULL); 535 } 536 537 /* Callback for client stdin read events. */ 538 void 539 client_stdin_callback(unused int fd, unused short events, unused void *arg) 540 { 541 struct msg_stdin_data data; 542 543 data.size = read(STDIN_FILENO, data.data, sizeof data.data); 544 if (data.size < 0 && (errno == EINTR || errno == EAGAIN)) 545 return; 546 547 client_write_server(MSG_STDIN, &data, sizeof data); 548 if (data.size <= 0) 549 event_del(&client_stdin); 550 client_update_event(); 551 } 552 553 /* Force write to file descriptor. */ 554 void 555 client_write(int fd, const char *data, size_t size) 556 { 557 ssize_t used; 558 559 while (size != 0) { 560 used = write(fd, data, size); 561 if (used == -1) { 562 if (errno == EINTR || errno == EAGAIN) 563 continue; 564 break; 565 } 566 data += used; 567 size -= used; 568 } 569 } 570 571 /* Run command in shell; used for -c. */ 572 __dead void 573 client_exec(const char *shell) 574 { 575 const char *name, *ptr; 576 char *argv0; 577 578 log_debug("shell %s, command %s", shell, shell_cmd); 579 580 ptr = strrchr(shell, '/'); 581 if (ptr != NULL && *(ptr + 1) != '\0') 582 name = ptr + 1; 583 else 584 name = shell; 585 if (client_flags & CLIENT_LOGIN) 586 xasprintf(&argv0, "-%s", name); 587 else 588 xasprintf(&argv0, "%s", name); 589 setenv("SHELL", shell, 1); 590 591 setblocking(STDIN_FILENO, 1); 592 setblocking(STDOUT_FILENO, 1); 593 setblocking(STDERR_FILENO, 1); 594 closefrom(STDERR_FILENO + 1); 595 596 execl(shell, argv0, "-c", shell_cmd, (char *) NULL); 597 fatal("execl failed"); 598 } 599 600 /* Dispatch imsgs when in wait state (before MSG_READY). */ 601 int 602 client_dispatch_wait(void) 603 { 604 struct imsg imsg; 605 char *data; 606 ssize_t n, datalen; 607 struct msg_stdout_data stdoutdata; 608 struct msg_stderr_data stderrdata; 609 int retval; 610 #ifdef __OpenBSD__ 611 static int pledge_applied; 612 613 /* 614 * "sendfd" is no longer required once all of the identify messages 615 * have been sent. We know the server won't send us anything until that 616 * point (because we don't ask it to), so we can drop "sendfd" once we 617 * get the first message from the server. 618 */ 619 if (!pledge_applied) { 620 if (pledge("stdio unix proc exec tty", NULL) != 0) 621 fatal("pledge failed"); 622 pledge_applied = 1; 623 }; 624 #endif 625 626 for (;;) { 627 if ((n = imsg_get(&client_ibuf, &imsg)) == -1) 628 fatalx("imsg_get failed"); 629 if (n == 0) 630 return (0); 631 632 data = imsg.data; 633 datalen = imsg.hdr.len - IMSG_HEADER_SIZE; 634 635 log_debug("got %u from server", imsg.hdr.type); 636 switch (imsg.hdr.type) { 637 case MSG_EXIT: 638 case MSG_SHUTDOWN: 639 if (datalen != sizeof retval && datalen != 0) 640 fatalx("bad MSG_EXIT size"); 641 if (datalen == sizeof retval) { 642 memcpy(&retval, data, sizeof retval); 643 client_exitval = retval; 644 } 645 imsg_free(&imsg); 646 return (-1); 647 case MSG_READY: 648 if (datalen != 0) 649 fatalx("bad MSG_READY size"); 650 651 event_del(&client_stdin); 652 client_attached = 1; 653 client_write_server(MSG_RESIZE, NULL, 0); 654 break; 655 case MSG_STDIN: 656 if (datalen != 0) 657 fatalx("bad MSG_STDIN size"); 658 659 event_add(&client_stdin, NULL); 660 break; 661 case MSG_STDOUT: 662 if (datalen != sizeof stdoutdata) 663 fatalx("bad MSG_STDOUT size"); 664 memcpy(&stdoutdata, data, sizeof stdoutdata); 665 666 client_write(STDOUT_FILENO, stdoutdata.data, 667 stdoutdata.size); 668 break; 669 case MSG_STDERR: 670 if (datalen != sizeof stderrdata) 671 fatalx("bad MSG_STDERR size"); 672 memcpy(&stderrdata, data, sizeof stderrdata); 673 674 client_write(STDERR_FILENO, stderrdata.data, 675 stderrdata.size); 676 break; 677 case MSG_VERSION: 678 if (datalen != 0) 679 fatalx("bad MSG_VERSION size"); 680 681 fprintf(stderr, "protocol version mismatch " 682 "(client %d, server %u)\n", PROTOCOL_VERSION, 683 imsg.hdr.peerid); 684 client_exitval = 1; 685 686 imsg_free(&imsg); 687 return (-1); 688 case MSG_SHELL: 689 if (datalen == 0 || data[datalen - 1] != '\0') 690 fatalx("bad MSG_SHELL string"); 691 692 clear_signals(0); 693 client_exec(data); 694 /* NOTREACHED */ 695 case MSG_DETACH: 696 case MSG_DETACHKILL: 697 client_write_server(MSG_EXITING, NULL, 0); 698 break; 699 case MSG_EXITED: 700 imsg_free(&imsg); 701 return (-1); 702 } 703 704 imsg_free(&imsg); 705 } 706 } 707 708 /* Dispatch imsgs in attached state (after MSG_READY). */ 709 int 710 client_dispatch_attached(void) 711 { 712 struct imsg imsg; 713 struct sigaction sigact; 714 char *data; 715 ssize_t n, datalen; 716 717 for (;;) { 718 if ((n = imsg_get(&client_ibuf, &imsg)) == -1) 719 fatalx("imsg_get failed"); 720 if (n == 0) 721 return (0); 722 723 data = imsg.data; 724 datalen = imsg.hdr.len - IMSG_HEADER_SIZE; 725 726 log_debug("got %u from server", imsg.hdr.type); 727 switch (imsg.hdr.type) { 728 case MSG_DETACH: 729 case MSG_DETACHKILL: 730 if (datalen == 0 || data[datalen - 1] != '\0') 731 fatalx("bad MSG_DETACH string"); 732 733 client_exitsession = xstrdup(data); 734 client_exittype = imsg.hdr.type; 735 if (imsg.hdr.type == MSG_DETACHKILL) 736 client_exitreason = CLIENT_EXIT_DETACHED_HUP; 737 else 738 client_exitreason = CLIENT_EXIT_DETACHED; 739 client_write_server(MSG_EXITING, NULL, 0); 740 break; 741 case MSG_EXIT: 742 if (datalen != 0 && datalen != sizeof (int)) 743 fatalx("bad MSG_EXIT size"); 744 745 client_write_server(MSG_EXITING, NULL, 0); 746 client_exitreason = CLIENT_EXIT_EXITED; 747 break; 748 case MSG_EXITED: 749 if (datalen != 0) 750 fatalx("bad MSG_EXITED size"); 751 752 imsg_free(&imsg); 753 return (-1); 754 case MSG_SHUTDOWN: 755 if (datalen != 0) 756 fatalx("bad MSG_SHUTDOWN size"); 757 758 client_write_server(MSG_EXITING, NULL, 0); 759 client_exitreason = CLIENT_EXIT_SERVER_EXITED; 760 client_exitval = 1; 761 break; 762 case MSG_SUSPEND: 763 if (datalen != 0) 764 fatalx("bad MSG_SUSPEND size"); 765 766 memset(&sigact, 0, sizeof sigact); 767 sigemptyset(&sigact.sa_mask); 768 sigact.sa_flags = SA_RESTART; 769 sigact.sa_handler = SIG_DFL; 770 if (sigaction(SIGTSTP, &sigact, NULL) != 0) 771 fatal("sigaction failed"); 772 kill(getpid(), SIGTSTP); 773 break; 774 case MSG_LOCK: 775 if (datalen == 0 || data[datalen - 1] != '\0') 776 fatalx("bad MSG_LOCK string"); 777 778 system(data); 779 client_write_server(MSG_UNLOCK, NULL, 0); 780 break; 781 } 782 783 imsg_free(&imsg); 784 } 785 } 786