=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/client.c,v retrieving revision 1.24 retrieving revision 1.25 diff -u -r1.24 -r1.25 --- src/usr.bin/tmux/client.c 2009/10/13 13:15:26 1.24 +++ src/usr.bin/tmux/client.c 2009/10/21 20:11:47 1.25 @@ -1,4 +1,4 @@ -/* $OpenBSD: client.c,v 1.24 2009/10/13 13:15:26 nicm Exp $ */ +/* $OpenBSD: client.c,v 1.25 2009/10/21 20:11:47 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -33,10 +33,16 @@ #include "tmux.h" -void client_send_environ(struct client_ctx *); +struct imsgbuf client_ibuf; +const char *client_exitmsg; -int -client_init(char *path, struct client_ctx *cctx, int cmdflags, int flags) +void client_send_environ(void); +void client_write_server(enum msgtype, void *, size_t); +int client_dispatch(void); +void client_suspend(void); + +struct imsgbuf * +client_init(char *path, int cmdflags, int flags) { struct sockaddr_un sa; struct stat sb; @@ -93,10 +99,10 @@ fatal("fcntl failed"); if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) fatal("fcntl failed"); - imsg_init(&cctx->ibuf, fd); + imsg_init(&client_ibuf, fd); if (cmdflags & CMD_SENDENVIRON) - client_send_environ(cctx); + client_send_environ(); if (isatty(STDIN_FILENO)) { if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) fatal("ioctl(TIOCGWINSZ)"); @@ -114,23 +120,23 @@ if ((fd2 = dup(STDIN_FILENO)) == -1) fatal("dup failed"); - imsg_compose(&cctx->ibuf, MSG_IDENTIFY, + imsg_compose(&client_ibuf, MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd2, &data, sizeof data); } - return (0); + return (&client_ibuf); start_failed: log_warnx("server failed to start"); - return (1); + return (NULL); not_found: log_warn("server not found"); - return (1); + return (NULL); } void -client_send_environ(struct client_ctx *cctx) +client_send_environ(void) { char **var; struct msg_environ_data data; @@ -138,13 +144,19 @@ for (var = environ; *var != NULL; var++) { if (strlcpy(data.var, *var, sizeof data.var) >= sizeof data.var) continue; - client_write_server(cctx, MSG_ENVIRON, &data, sizeof data); + client_write_server(MSG_ENVIRON, &data, sizeof data); } } -int -client_main(struct client_ctx *cctx) +void +client_write_server(enum msgtype type, void *buf, size_t len) { + imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, -1, buf, len); +} + +__dead void +client_main(void) +{ struct pollfd pfd; int n, nfds; @@ -158,29 +170,31 @@ * MSG_READY switched to here. Process anything outstanding now so poll * doesn't hang waiting for messages that have already arrived. */ - if (client_msg_dispatch(cctx) != 0) + if (client_dispatch() != 0) goto out; for (;;) { - if (sigterm) - client_write_server(cctx, MSG_EXITING, NULL, 0); + if (sigterm) { + client_exitmsg = "terminated"; + client_write_server(MSG_EXITING, NULL, 0); + } if (sigchld) { waitpid(WAIT_ANY, NULL, WNOHANG); sigchld = 0; } if (sigwinch) { - client_write_server(cctx, MSG_RESIZE, NULL, 0); + client_write_server(MSG_RESIZE, NULL, 0); sigwinch = 0; } if (sigcont) { siginit(); - client_write_server(cctx, MSG_WAKEUP, NULL, 0); + client_write_server(MSG_WAKEUP, NULL, 0); sigcont = 0; } - pfd.fd = cctx->ibuf.fd; + pfd.fd = client_ibuf.fd; pfd.events = POLLIN; - if (cctx->ibuf.w.queued > 0) + if (client_ibuf.w.queued > 0) pfd.events |= POLLOUT; if ((nfds = poll(&pfd, 1, INFTIM)) == -1) { @@ -195,67 +209,41 @@ fatalx("socket error"); if (pfd.revents & POLLIN) { - if ((n = imsg_read(&cctx->ibuf)) == -1 || n == 0) { - cctx->exittype = CCTX_DIED; + if ((n = imsg_read(&client_ibuf)) == -1 || n == 0) { + client_exitmsg = "lost server"; break; } - if (client_msg_dispatch(cctx) != 0) + if (client_dispatch() != 0) break; } if (pfd.revents & POLLOUT) { - if (msgbuf_write(&cctx->ibuf.w) < 0) { - cctx->exittype = CCTX_DIED; + if (msgbuf_write(&client_ibuf.w) < 0) { + client_exitmsg = "lost server"; break; } } } out: - /* - * Print exit status message, unless running as a login shell where it - * would either be pointless or irritating. - */ - if (sigterm) { - printf("[terminated]\n"); - return (1); - } - switch (cctx->exittype) { - case CCTX_DIED: - printf("[lost server]\n"); - return (0); - case CCTX_SHUTDOWN: - if (!login_shell) - printf("[server exited]\n"); - return (0); - case CCTX_EXIT: - if (cctx->errstr != NULL) { - printf("[error: %s]\n", cctx->errstr); - return (1); - } - if (!login_shell) - printf("[exited]\n"); - return (0); - case CCTX_DETACH: + /* Print the exit message, if any, and exit. */ + if (client_exitmsg != NULL) { if (!login_shell) - printf("[detached]\n"); - return (0); - default: - printf("[unknown error]\n"); - return (1); + printf("[%s]\n", client_exitmsg); + exit(1); } + exit(0); } int -client_msg_dispatch(struct client_ctx *cctx) +client_dispatch(void) { struct imsg imsg; - struct msg_print_data printdata; struct msg_lock_data lockdata; ssize_t n, datalen; for (;;) { - if ((n = imsg_get(&cctx->ibuf, &imsg)) == -1) + if ((n = imsg_get(&client_ibuf, &imsg)) == -1) fatalx("imsg_get failed"); if (n == 0) return (0); @@ -266,25 +254,15 @@ if (datalen != 0) fatalx("bad MSG_DETACH size"); - client_write_server(cctx, MSG_EXITING, NULL, 0); - cctx->exittype = CCTX_DETACH; + client_write_server(MSG_EXITING, NULL, 0); + client_exitmsg = "detached"; break; - case MSG_ERROR: - if (datalen != sizeof printdata) - fatalx("bad MSG_ERROR size"); - memcpy(&printdata, imsg.data, sizeof printdata); - - printdata.msg[(sizeof printdata.msg) - 1] = '\0'; - /* Error string used after exit message from server. */ - cctx->errstr = xstrdup(printdata.msg); - imsg_free(&imsg); - return (-1); case MSG_EXIT: if (datalen != 0) fatalx("bad MSG_EXIT size"); - client_write_server(cctx, MSG_EXITING, NULL, 0); - cctx->exittype = CCTX_EXIT; + client_write_server(MSG_EXITING, NULL, 0); + client_exitmsg = "exited"; break; case MSG_EXITED: if (datalen != 0) @@ -296,8 +274,8 @@ if (datalen != 0) fatalx("bad MSG_SHUTDOWN size"); - client_write_server(cctx, MSG_EXITING, NULL, 0); - cctx->exittype = CCTX_SHUTDOWN; + client_write_server(MSG_EXITING, NULL, 0); + client_exitmsg = "server exited"; break; case MSG_SUSPEND: if (datalen != 0) @@ -312,7 +290,7 @@ lockdata.cmd[(sizeof lockdata.cmd) - 1] = '\0'; system(lockdata.cmd); - client_write_server(cctx, MSG_UNLOCK, NULL, 0); + client_write_server(MSG_UNLOCK, NULL, 0); break; default: fatalx("unexpected message"); @@ -320,4 +298,24 @@ imsg_free(&imsg); } +} + +void +client_suspend(void) +{ + struct sigaction act; + + memset(&act, 0, sizeof act); + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + + act.sa_handler = SIG_DFL; + if (sigaction(SIGTSTP, &act, NULL) != 0) + fatal("sigaction failed"); + + act.sa_handler = sighandler; + if (sigaction(SIGCONT, &act, NULL) != 0) + fatal("sigaction failed"); + + kill(getpid(), SIGTSTP); }