[BACK]Return to client.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Annotation of src/usr.bin/tmux/client.c, Revision 1.1

1.1     ! nicm        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/ioctl.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 <fcntl.h>
        !            28: #include <pwd.h>
        !            29: #include <stdlib.h>
        !            30: #include <string.h>
        !            31: #include <syslog.h>
        !            32: #include <unistd.h>
        !            33:
        !            34: #include "tmux.h"
        !            35:
        !            36: void   client_handle_winch(struct client_ctx *);
        !            37:
        !            38: int
        !            39: client_init(char *path, struct client_ctx *cctx, int start_server, int flags)
        !            40: {
        !            41:        struct sockaddr_un              sa;
        !            42:        struct stat                     sb;
        !            43:        struct msg_identify_data        data;
        !            44:        struct winsize                  ws;
        !            45:        size_t                          size;
        !            46:        int                             mode;
        !            47:        struct buffer                  *b;
        !            48:        char                           *name;
        !            49:
        !            50:        if (lstat(path, &sb) != 0) {
        !            51:                if (start_server && errno == ENOENT) {
        !            52:                        if ((cctx->srv_fd = server_start(path)) == -1)
        !            53:                                goto start_failed;
        !            54:                        goto server_started;
        !            55:                }
        !            56:                goto not_found;
        !            57:        }
        !            58:        if (!S_ISSOCK(sb.st_mode)) {
        !            59:                errno = ENOTSOCK;
        !            60:                goto not_found;
        !            61:        }
        !            62:
        !            63:        memset(&sa, 0, sizeof sa);
        !            64:        sa.sun_family = AF_UNIX;
        !            65:        size = strlcpy(sa.sun_path, path, sizeof sa.sun_path);
        !            66:        if (size >= sizeof sa.sun_path) {
        !            67:                errno = ENAMETOOLONG;
        !            68:                goto not_found;
        !            69:        }
        !            70:
        !            71:        if ((cctx->srv_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
        !            72:                fatal("socket");
        !            73:
        !            74:        if (connect(
        !            75:            cctx->srv_fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) {
        !            76:                if (errno == ECONNREFUSED) {
        !            77:                        if (unlink(path) != 0 || !start_server)
        !            78:                                goto not_found;
        !            79:                        if ((cctx->srv_fd = server_start(path)) == -1)
        !            80:                                goto start_failed;
        !            81:                        goto server_started;
        !            82:                }
        !            83:                goto not_found;
        !            84:        }
        !            85:
        !            86: server_started:
        !            87:        if ((mode = fcntl(cctx->srv_fd, F_GETFL)) == -1)
        !            88:                fatal("fcntl failed");
        !            89:        if (fcntl(cctx->srv_fd, F_SETFL, mode|O_NONBLOCK) == -1)
        !            90:                fatal("fcntl failed");
        !            91:        cctx->srv_in = buffer_create(BUFSIZ);
        !            92:        cctx->srv_out = buffer_create(BUFSIZ);
        !            93:
        !            94:        if (isatty(STDIN_FILENO)) {
        !            95:                if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
        !            96:                        fatal("ioctl(TIOCGWINSZ)");
        !            97:                data.version = PROTOCOL_VERSION;
        !            98:                data.flags = flags;
        !            99:                data.sx = ws.ws_col;
        !           100:                data.sy = ws.ws_row;
        !           101:                *data.tty = '\0';
        !           102:                if (getcwd(data.cwd, sizeof data.cwd) == NULL)
        !           103:                        *data.cwd = '\0';
        !           104:
        !           105:                if ((name = ttyname(STDIN_FILENO)) == NULL)
        !           106:                        fatal("ttyname failed");
        !           107:                if (strlcpy(data.tty, name, sizeof data.tty) >= sizeof data.tty)
        !           108:                        fatalx("ttyname failed");
        !           109:
        !           110:                b = buffer_create(BUFSIZ);
        !           111:                cmd_send_string(b, getenv("TERM"));
        !           112:                client_write_server2(cctx, MSG_IDENTIFY,
        !           113:                    &data, sizeof data, BUFFER_OUT(b), BUFFER_USED(b));
        !           114:                buffer_destroy(b);
        !           115:        }
        !           116:
        !           117:        return (0);
        !           118:
        !           119: start_failed:
        !           120:        log_warnx("server failed to start");
        !           121:        return (1);
        !           122:
        !           123: not_found:
        !           124:        log_warn("server not found");
        !           125:        return (1);
        !           126: }
        !           127:
        !           128: int
        !           129: client_main(struct client_ctx *cctx)
        !           130: {
        !           131:        struct pollfd    pfd;
        !           132:        char            *error;
        !           133:        int              xtimeout; /* Yay for ncurses namespace! */
        !           134:
        !           135:        siginit();
        !           136:
        !           137:        logfile("client");
        !           138:        setproctitle("client");
        !           139:
        !           140:        error = NULL;
        !           141:        xtimeout = INFTIM;
        !           142:        while (!sigterm) {
        !           143:                if (sigchld) {
        !           144:                        waitpid(WAIT_ANY, NULL, WNOHANG);
        !           145:                        sigchld = 0;
        !           146:                }
        !           147:                if (sigwinch)
        !           148:                        client_handle_winch(cctx);
        !           149:                if (sigcont) {
        !           150:                        siginit();
        !           151:                        client_write_server(cctx, MSG_WAKEUP, NULL, 0);
        !           152:                        sigcont = 0;
        !           153:                }
        !           154:
        !           155:                switch (client_msg_dispatch(cctx, &error)) {
        !           156:                case -1:
        !           157:                        goto out;
        !           158:                case 0:
        !           159:                        /* May be more in buffer, don't let poll block. */
        !           160:                        xtimeout = 0;
        !           161:                        break;
        !           162:                default:
        !           163:                        /* Out of data, poll may block. */
        !           164:                        xtimeout = INFTIM;
        !           165:                        break;
        !           166:                }
        !           167:
        !           168:                pfd.fd = cctx->srv_fd;
        !           169:                pfd.events = POLLIN;
        !           170:                if (BUFFER_USED(cctx->srv_out) > 0)
        !           171:                        pfd.events |= POLLOUT;
        !           172:
        !           173:                if (poll(&pfd, 1, xtimeout) == -1) {
        !           174:                        if (errno == EAGAIN || errno == EINTR)
        !           175:                                continue;
        !           176:                        fatal("poll failed");
        !           177:                }
        !           178:
        !           179:                if (buffer_poll(&pfd, cctx->srv_in, cctx->srv_out) != 0)
        !           180:                        goto server_dead;
        !           181:        }
        !           182:
        !           183: out:
        !           184:        if (sigterm) {
        !           185:                printf("[terminated]\n");
        !           186:                return (1);
        !           187:        }
        !           188:
        !           189:        if (cctx->flags & CCTX_SHUTDOWN) {
        !           190:                printf("[server exited]\n");
        !           191:                return (0);
        !           192:        }
        !           193:
        !           194:        if (cctx->flags & CCTX_EXIT) {
        !           195:                printf("[exited]\n");
        !           196:                return (0);
        !           197:        }
        !           198:
        !           199:        if (cctx->flags & CCTX_DETACH) {
        !           200:                printf("[detached]\n");
        !           201:                return (0);
        !           202:        }
        !           203:
        !           204:        printf("[error: %s]\n", error);
        !           205:        return (1);
        !           206:
        !           207: server_dead:
        !           208:        printf("[lost server]\n");
        !           209:        return (0);
        !           210: }
        !           211:
        !           212: void
        !           213: client_handle_winch(struct client_ctx *cctx)
        !           214: {
        !           215:        struct msg_resize_data  data;
        !           216:        struct winsize          ws;
        !           217:
        !           218:        if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
        !           219:                fatal("ioctl failed");
        !           220:
        !           221:        data.sx = ws.ws_col;
        !           222:        data.sy = ws.ws_row;
        !           223:        client_write_server(cctx, MSG_RESIZE, &data, sizeof data);
        !           224:
        !           225:        sigwinch = 0;
        !           226: }