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

Diff for /src/usr.bin/tmux/client.c between version 1.29 and 1.30

version 1.29, 2009/11/02 13:42:25 version 1.30, 2009/11/04 20:50:11
Line 24 
Line 24 
 #include <sys/wait.h>  #include <sys/wait.h>
   
 #include <errno.h>  #include <errno.h>
   #include <event.h>
 #include <fcntl.h>  #include <fcntl.h>
 #include <pwd.h>  #include <pwd.h>
 #include <stdlib.h>  #include <stdlib.h>
Line 34 
Line 35 
 #include "tmux.h"  #include "tmux.h"
   
 struct imsgbuf  client_ibuf;  struct imsgbuf  client_ibuf;
   struct event    client_event;
 const char     *client_exitmsg;  const char     *client_exitmsg;
   
 void    client_send_identify(int);  void            client_send_identify(int);
 void    client_send_environ(void);  void            client_send_environ(void);
 void    client_write_server(enum msgtype, void *, size_t);  void            client_write_server(enum msgtype, void *, size_t);
 int     client_dispatch(void);  void            client_signal(int, short, void *);
 void    client_suspend(void);  void            client_callback(int, short, void *);
   int             client_dispatch(void);
   
 struct imsgbuf *  struct imsgbuf *
 client_init(char *path, int cmdflags, int flags)  client_init(char *path, int cmdflags, int flags)
Line 154 
Line 157 
 __dead void  __dead void
 client_main(void)  client_main(void)
 {  {
         struct pollfd    pfd;          struct event            ev_sigcont, ev_sigterm, ev_sigwinch;
         int              n, nfds;          struct sigaction        sigact;
           short                   events;
   
         siginit();  
   
         logfile("client");          logfile("client");
   
           /* Note: event_init() has already been called. */
   
           /* Set up signals. */
           memset(&sigact, 0, sizeof sigact);
           sigemptyset(&sigact.sa_mask);
           sigact.sa_flags = SA_RESTART;
           sigact.sa_handler = SIG_IGN;
           if (sigaction(SIGINT, &sigact, NULL) != 0)
                   fatal("sigaction failed");
           if (sigaction(SIGPIPE, &sigact, NULL) != 0)
                   fatal("sigaction failed");
           if (sigaction(SIGUSR1, &sigact, NULL) != 0)
                   fatal("sigaction failed");
           if (sigaction(SIGUSR2, &sigact, NULL) != 0)
                   fatal("sigaction failed");
           if (sigaction(SIGTSTP, &sigact, NULL) != 0)
                   fatal("sigaction failed");
   
           signal_set(&ev_sigcont, SIGCONT, client_signal, NULL);
           signal_add(&ev_sigcont, NULL);
           signal_set(&ev_sigterm, SIGTERM, client_signal, NULL);
           signal_add(&ev_sigterm, NULL);
           signal_set(&ev_sigwinch, SIGWINCH, client_signal, NULL);
           signal_add(&ev_sigwinch, NULL);
   
         /*          /*
          * imsg_read in the first client poll loop (before the terminal has           * imsg_read in the first client poll loop (before the terminal has
          * been initialiased) may have read messages into the buffer after the           * been initialised) may have read messages into the buffer after the
          * MSG_READY switched to here. Process anything outstanding now so poll           * MSG_READY switched to here. Process anything outstanding now to
          * doesn't hang waiting for messages that have already arrived.           * avoid hanging waiting for messages that have already arrived.
          */           */
         if (client_dispatch() != 0)          if (client_dispatch() != 0)
                 goto out;                  goto out;
   
         for (;;) {          /* Set up the client-server socket event. */
                 if (sigterm) {          events = EV_READ;
                         client_exitmsg = "terminated";          if (client_ibuf.w.queued > 0)
                         client_write_server(MSG_EXITING, NULL, 0);                  events |= EV_WRITE;
                 }          event_set(&client_event, client_ibuf.fd, events, client_callback, NULL);
                 if (sigchld) {          event_add(&client_event, NULL);
                         sigchld = 0;  
                         waitpid(WAIT_ANY, NULL, WNOHANG);          event_dispatch();
                         continue;  
                 }  
                 if (sigwinch) {  
                         sigwinch = 0;  
                         client_write_server(MSG_RESIZE, NULL, 0);  
                         continue;  
                 }  
                 if (sigcont) {  
                         sigcont = 0;  
                         siginit();  
                         client_write_server(MSG_WAKEUP, NULL, 0);  
                         continue;  
                 }  
   
                 pfd.fd = client_ibuf.fd;  
                 pfd.events = POLLIN;  
                 if (client_ibuf.w.queued > 0)  
                         pfd.events |= POLLOUT;  
   
                 if ((nfds = poll(&pfd, 1, INFTIM)) == -1) {  
                         if (errno == EAGAIN || errno == EINTR)  
                                 continue;  
                         fatal("poll failed");  
                 }  
                 if (nfds == 0)  
                         continue;  
   
                 if (pfd.revents & (POLLERR|POLLHUP|POLLNVAL))  
                         fatalx("socket error");  
   
                 if (pfd.revents & POLLIN) {  
                         if ((n = imsg_read(&client_ibuf)) == -1 || n == 0) {  
                                 client_exitmsg = "lost server";  
                                 break;  
                         }  
                         if (client_dispatch() != 0)  
                                 break;  
                 }  
   
                 if (pfd.revents & POLLOUT) {  
                         if (msgbuf_write(&client_ibuf.w) < 0) {  
                                 client_exitmsg = "lost server";  
                                 break;  
                         }  
                 }  
         }  
   
 out:  out:
         /* Print the exit message, if any, and exit. */          /* Print the exit message, if any, and exit. */
         if (client_exitmsg != NULL) {          if (client_exitmsg != NULL) {
Line 235 
Line 216 
         exit(0);          exit(0);
 }  }
   
   void
   client_signal(int sig, short events, unused void *data)
   {
           struct sigaction        sigact;
   
           switch (sig) {
           case SIGTERM:
                   client_exitmsg = "terminated";
                   client_write_server(MSG_EXITING, NULL, 0);
                   break;
           case SIGWINCH:
                   client_write_server(MSG_RESIZE, NULL, 0);
                   break;
           case SIGCONT:
                   memset(&sigact, 0, sizeof sigact);
                   sigemptyset(&sigact.sa_mask);
                   sigact.sa_flags = SA_RESTART;
                   sigact.sa_handler = SIG_IGN;
                   if (sigaction(SIGTSTP, &sigact, NULL) != 0)
                           fatal("sigaction failed");
                   client_write_server(MSG_WAKEUP, NULL, 0);
                   break;
           }
   
           event_del(&client_event);
           events = EV_READ;
           if (client_ibuf.w.queued > 0)
                   events |= EV_WRITE;
           event_set(&client_event, client_ibuf.fd, events, client_callback, NULL);
           event_add(&client_event, NULL);
   }
   
   void
   client_callback(unused int fd, short events, unused void *data)
   {
           int     n;
   
           if (events & EV_READ) {
                   if ((n = imsg_read(&client_ibuf)) == -1 || n == 0)
                           goto lost_server;
                   if (client_dispatch() != 0) {
                           event_loopexit(NULL);
                           return;
                   }
           }
   
           if (events & EV_WRITE) {
                   if (msgbuf_write(&client_ibuf.w) < 0)
                           goto lost_server;
           }
   
           event_del(&client_event);
           events = EV_READ;
           if (client_ibuf.w.queued > 0)
                   events |= EV_WRITE;
           event_set(&client_event, client_ibuf.fd, events, client_callback, NULL);
           event_add(&client_event, NULL);
   
           return;
   
   lost_server:
           client_exitmsg = "lost server";
           event_loopexit(NULL);
   }
   
 int  int
 client_dispatch(void)  client_dispatch(void)
 {  {
         struct imsg              imsg;          struct imsg             imsg;
         struct msg_lock_data     lockdata;          struct msg_lock_data    lockdata;
         ssize_t                  n, datalen;          struct sigaction        sigact;
           ssize_t                 n, datalen;
   
         for (;;) {          for (;;) {
                 if ((n = imsg_get(&client_ibuf, &imsg)) == -1)                  if ((n = imsg_get(&client_ibuf, &imsg)) == -1)
Line 249 
Line 296 
                         return (0);                          return (0);
                 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;                  datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
   
                   log_debug("client got %d", imsg.hdr.type);
                 switch (imsg.hdr.type) {                  switch (imsg.hdr.type) {
                 case MSG_DETACH:                  case MSG_DETACH:
                         if (datalen != 0)                          if (datalen != 0)
Line 281 
Line 329 
                         if (datalen != 0)                          if (datalen != 0)
                                 fatalx("bad MSG_SUSPEND size");                                  fatalx("bad MSG_SUSPEND size");
   
                         client_suspend();                          memset(&sigact, 0, sizeof sigact);
                           sigemptyset(&sigact.sa_mask);
                           sigact.sa_flags = SA_RESTART;
                           sigact.sa_handler = SIG_DFL;
                           if (sigaction(SIGTSTP, &sigact, NULL) != 0)
                                   fatal("sigaction failed");
                           kill(getpid(), SIGTSTP);
                         break;                          break;
                 case MSG_LOCK:                  case MSG_LOCK:
                         if (datalen != sizeof lockdata)                          if (datalen != sizeof lockdata)
Line 298 
Line 352 
   
                 imsg_free(&imsg);                  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);  
 }  }

Legend:
Removed from v.1.29  
changed lines
  Added in v.1.30