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

Diff for /src/usr.bin/tmux/tmux.c between version 1.91 and 1.92

version 1.91, 2010/10/16 08:42:35 version 1.92, 2010/10/18 20:00:03
Line 18 
Line 18 
   
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/stat.h>  #include <sys/stat.h>
 #include <sys/wait.h>  
   
 #include <errno.h>  #include <errno.h>
 #include <event.h>  #include <event.h>
 #include <fcntl.h>  #include <fcntl.h>
 #include <paths.h>  #include <paths.h>
 #include <pwd.h>  #include <pwd.h>
 #include <signal.h>  
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <syslog.h>  
 #include <unistd.h>  #include <unistd.h>
   
 #include "tmux.h"  #include "tmux.h"
Line 37 
Line 34 
 extern char     *malloc_options;  extern char     *malloc_options;
 #endif  #endif
   
 char            *cfg_file;  
 struct options   global_options;        /* server options */  struct options   global_options;        /* server options */
 struct options   global_s_options;      /* session options */  struct options   global_s_options;      /* session options */
 struct options   global_w_options;      /* window options */  struct options   global_w_options;      /* window options */
Line 45 
Line 41 
   
 struct event_base *ev_base;  struct event_base *ev_base;
   
   char            *cfg_file;
   char            *shell_cmd;
 int              debug_level;  int              debug_level;
 time_t           start_time;  time_t           start_time;
 char            *socket_path;  char             socket_path[MAXPATHLEN];
 int              login_shell;  int              login_shell;
   char            *environ_path;
   pid_t            environ_pid;
   u_int            environ_idx;
   
 struct env_data {  
         char    *path;  
         pid_t    pid;  
         u_int    idx;  
 };  
   
 __dead void      usage(void);  __dead void      usage(void);
 void             parse_env(struct env_data *);  void             parseenvironment(void);
 char            *makesockpath(const char *);  char            *makesocketpath(const char *);
 __dead void      shell_exec(const char *, const char *);  
   
 struct imsgbuf  *main_ibuf;  
 struct event     main_event;  
   
 void             main_signal(int, short, unused void *);  
 void             main_callback(int, short, void *);  
 void             main_dispatch(const char *);  
   
 __dead void  __dead void
 usage(void)  usage(void)
 {  {
Line 136 
Line 123 
 }  }
   
 void  void
 parse_env(struct env_data *data)  parseenvironment(void)
 {  {
         char            *env, *path_pid, *pid_idx, buf[256];          char            *env, *path_pid, *pid_idx, buf[256];
         size_t           len;          size_t           len;
         const char      *errstr;          const char      *errstr;
         long long        ll;          long long        ll;
   
         data->pid = -1;          environ_pid = -1;
         if ((env = getenv("TMUX")) == NULL)          if ((env = getenv("TMUX")) == NULL)
                 return;                  return;
   
Line 156 
Line 143 
   
         /* path */          /* path */
         len = path_pid - env;          len = path_pid - env;
         data->path = xmalloc (len + 1);          environ_path = xmalloc(len + 1);
         memcpy(data->path, env, len);          memcpy(environ_path, env, len);
         data->path[len] = '\0';          environ_path[len] = '\0';
   
         /* pid */          /* pid */
         len = pid_idx - path_pid - 1;          len = pid_idx - path_pid - 1;
Line 170 
Line 157 
         ll = strtonum(buf, 0, LONG_MAX, &errstr);          ll = strtonum(buf, 0, LONG_MAX, &errstr);
         if (errstr != NULL)          if (errstr != NULL)
                 return;                  return;
         data->pid = ll;          environ_pid = ll;
   
         /* idx */          /* idx */
         ll = strtonum(pid_idx+1, 0, UINT_MAX, &errstr);          ll = strtonum(pid_idx + 1, 0, UINT_MAX, &errstr);
         if (errstr != NULL)          if (errstr != NULL)
                 return;                  return;
         data->idx = ll;          environ_idx = ll;
 }  }
   
 char *  char *
 makesockpath(const char *label)  makesocketpath(const char *label)
 {  {
         char            base[MAXPATHLEN], *path;          char            base[MAXPATHLEN], *path;
         struct stat     sb;          struct stat     sb;
Line 240 
Line 227 
 int  int
 main(int argc, char **argv)  main(int argc, char **argv)
 {  {
         struct cmd_list         *cmdlist;          struct passwd   *pw;
         struct cmd              *cmd;          struct options  *oo, *so, *wo;
         enum msgtype             msg;          struct keylist  *keylist;
         struct passwd           *pw;          char            *s, *path, *label, *home, **var;
         struct options          *oo, *so, *wo;          int              opt, flags, quiet = 0;
         struct keylist          *keylist;  
         struct env_data          envdata;  
         struct msg_command_data  cmddata;  
         char                    *s, *shellcmd, *path, *label, *home, *cause;  
         char                   **var;  
         void                    *buf;  
         size_t                   len;  
         int                      opt, flags, quiet = 0, cmdflags = 0;  
         short                    events;  
   
 #ifdef DEBUG  #ifdef DEBUG
         malloc_options = (char *) "AFGJPX";          malloc_options = (char *) "AFGJPX";
 #endif  #endif
   
         flags = 0;          flags = 0;
         shellcmd = label = path = NULL;          label = path = NULL;
         envdata.path = NULL;  
         login_shell = (**argv == '-');          login_shell = (**argv == '-');
         while ((opt = getopt(argc, argv, "28c:df:lL:qS:uUv")) != -1) {          while ((opt = getopt(argc, argv, "28c:df:lL:qS:uUv")) != -1) {
                 switch (opt) {                  switch (opt) {
Line 274 
Line 251 
                         flags &= ~IDENTIFY_256COLOURS;                          flags &= ~IDENTIFY_256COLOURS;
                         break;                          break;
                 case 'c':                  case 'c':
                         if (shellcmd != NULL)                          if (shell_cmd != NULL)
                                 xfree(shellcmd);                                  xfree(shell_cmd);
                         shellcmd = xstrdup(optarg);                          shell_cmd = xstrdup(optarg);
                         break;                          break;
                 case 'f':                  case 'f':
                         if (cfg_file != NULL)                          if (cfg_file != NULL)
Line 312 
Line 289 
         argc -= optind;          argc -= optind;
         argv += optind;          argv += optind;
   
         if (shellcmd != NULL && argc != 0)          if (shell_cmd != NULL && argc != 0)
                 usage();                  usage();
   
         log_open_tty(debug_level);          log_open_tty(debug_level);
Line 448 
Line 425 
                 options_set_number(wo, "utf8", 0);                  options_set_number(wo, "utf8", 0);
         }          }
   
           /* Locate the configuration file. */
         if (cfg_file == NULL) {          if (cfg_file == NULL) {
                 home = getenv("HOME");                  home = getenv("HOME");
                 if (home == NULL || *home == '\0') {                  if (home == NULL || *home == '\0') {
Line 463 
Line 441 
         }          }
   
         /*          /*
          * Figure out the socket path. If specified on the command-line with           * Figure out the socket path. If specified on the command-line with -S
          * -S or -L, use it, otherwise try $TMUX or assume -L default.           * or -L, use it, otherwise try $TMUX or assume -L default.
          */           */
         parse_env(&envdata);          parseenvironment();
         if (path == NULL) {          if (path == NULL) {
                 /* No -L. Try $TMUX, or default. */                  /* If no -L, use the environment. */
                 if (label == NULL) {                  if (label == NULL) {
                         path = envdata.path;                          if (environ_path != NULL)
                         if (path == NULL)                                  path = xstrdup(environ_path);
                           else
                                 label = xstrdup("default");                                  label = xstrdup("default");
                 }                  }
   
                 /* -L or default set. */                  /* -L or default set. */
                 if (label != NULL) {                  if (label != NULL) {
                         if ((path = makesockpath(label)) == NULL) {                          if ((path = makesocketpath(label)) == NULL) {
                                 log_warn("can't create socket");                                  log_warn("can't create socket");
                                 exit(1);                                  exit(1);
                         }                          }
Line 485 
Line 464 
         }          }
         if (label != NULL)          if (label != NULL)
                 xfree(label);                  xfree(label);
           if (realpath(path, socket_path) == NULL)
         if (shellcmd != NULL) {                  strlcpy(socket_path, path, sizeof socket_path);
                 msg = MSG_SHELL;  
                 buf = NULL;  
                 len = 0;  
         } else {  
                 cmddata.pid = envdata.pid;  
                 cmddata.idx = envdata.idx;  
   
                 /* Prepare command for server. */  
                 cmddata.argc = argc;  
                 if (cmd_pack_argv(  
                     argc, argv, cmddata.argv, sizeof cmddata.argv) != 0) {  
                         log_warnx("command too long");  
                         exit(1);  
                 }  
   
                 msg = MSG_COMMAND;  
                 buf = &cmddata;  
                 len = sizeof cmddata;  
         }  
   
         if (shellcmd != NULL)  
                 cmdflags |= CMD_STARTSERVER;  
         else if (argc == 0)     /* new-session is the default */  
                 cmdflags |= CMD_STARTSERVER|CMD_SENDENVIRON|CMD_CANTNEST;  
         else {  
                 /*  
                  * It sucks parsing the command string twice (in client and  
                  * later in server) but it is necessary to get the start server  
                  * flag.  
                  */  
                 if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) {  
                         log_warnx("%s", cause);  
                         exit(1);  
                 }  
                 cmdflags &= ~CMD_STARTSERVER;  
                 TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {  
                         if (cmd->entry->flags & CMD_STARTSERVER)  
                                 cmdflags |= CMD_STARTSERVER;  
                         if (cmd->entry->flags & CMD_SENDENVIRON)  
                                 cmdflags |= CMD_SENDENVIRON;  
                         if (cmd->entry->flags & CMD_CANTNEST)  
                                 cmdflags |= CMD_CANTNEST;  
                 }  
                 cmd_list_free(cmdlist);  
         }  
   
         /*  
          * Check if this could be a nested session, if the command can't nest:  
          * if the socket path matches $TMUX, this is probably the same server.  
          */  
         if (shellcmd == NULL && envdata.path != NULL &&  
             cmdflags & CMD_CANTNEST &&  
             (path == envdata.path || strcmp(path, envdata.path) == 0)) {  
                 log_warnx("sessions should be nested with care. "  
                     "unset $TMUX to force.");  
                 exit(1);  
         }  
   
         ev_base = event_init();  
         set_signals(main_signal);  
   
         /* Initialise the client socket/start the server. */  
         if ((main_ibuf = client_init(path, cmdflags, flags)) == NULL)  
                 exit(1);  
         xfree(path);          xfree(path);
   
         imsg_compose(main_ibuf, msg, PROTOCOL_VERSION, -1, -1, buf, len);          /* Set process title. */
           setproctitle("%s (%s)", __progname, socket_path);
   
         events = EV_READ;          /* Pass control to the client. */
         if (main_ibuf->w.queued > 0)          ev_base = event_init();
                 events |= EV_WRITE;          exit(client_main(argc, argv, flags));
         event_set(&main_event, main_ibuf->fd, events, main_callback, shellcmd);  
         event_add(&main_event, NULL);  
   
         event_dispatch();  
   
         event_del(&main_event);  
   
         clear_signals(0);  
         client_main();  /* doesn't return */  
 }  
   
 /* ARGSUSED */  
 void  
 main_signal(int sig, unused short events, unused void *data)  
 {  
         int     status;  
   
         switch (sig) {  
         case SIGTERM:  
                 exit(1);  
         case SIGCHLD:  
                 waitpid(WAIT_ANY, &status, WNOHANG);  
                 break;  
         }  
 }  
   
 /* ARGSUSED */  
 void  
 main_callback(unused int fd, short events, void *data)  
 {  
         char    *shellcmd = data;  
   
         if (events & EV_READ)  
                 main_dispatch(shellcmd);  
   
         if (events & EV_WRITE) {  
                 if (msgbuf_write(&main_ibuf->w) < 0)  
                         fatalx("msgbuf_write failed");  
         }  
   
         event_del(&main_event);  
         events = EV_READ;  
         if (main_ibuf->w.queued > 0)  
                 events |= EV_WRITE;  
         event_set(&main_event, main_ibuf->fd, events, main_callback, shellcmd);  
         event_add(&main_event, NULL);  
 }  
   
 void  
 main_dispatch(const char *shellcmd)  
 {  
         struct imsg             imsg;  
         ssize_t                 n, datalen;  
         struct msg_shell_data   shelldata;  
         struct msg_exit_data    exitdata;  
   
         if ((n = imsg_read(main_ibuf)) == -1 || n == 0)  
                 fatalx("imsg_read failed");  
   
         for (;;) {  
                 if ((n = imsg_get(main_ibuf, &imsg)) == -1)  
                         fatalx("imsg_get failed");  
                 if (n == 0)  
                         return;  
                 datalen = imsg.hdr.len - IMSG_HEADER_SIZE;  
   
                 switch (imsg.hdr.type) {  
                 case MSG_EXIT:  
                 case MSG_SHUTDOWN:  
                         if (datalen != sizeof exitdata) {  
                                 if (datalen != 0)  
                                         fatalx("bad MSG_EXIT size");  
                                 exit(0);  
                         }  
                         memcpy(&exitdata, imsg.data, sizeof exitdata);  
                         exit(exitdata.retcode);  
                 case MSG_READY:  
                         if (datalen != 0)  
                                 fatalx("bad MSG_READY size");  
   
                         event_loopexit(NULL);   /* move to client_main() */  
                         break;  
                 case MSG_VERSION:  
                         if (datalen != 0)  
                                 fatalx("bad MSG_VERSION size");  
   
                         log_warnx("protocol version mismatch (client %u, "  
                             "server %u)", PROTOCOL_VERSION, imsg.hdr.peerid);  
                         exit(1);  
                 case MSG_SHELL:  
                         if (datalen != sizeof shelldata)  
                                 fatalx("bad MSG_SHELL size");  
                         memcpy(&shelldata, imsg.data, sizeof shelldata);  
                         shelldata.shell[(sizeof shelldata.shell) - 1] = '\0';  
   
                         clear_signals(0);  
   
                         shell_exec(shelldata.shell, shellcmd);  
                 default:  
                         fatalx("unexpected message");  
                 }  
   
                 imsg_free(&imsg);  
         }  
 }  }

Legend:
Removed from v.1.91  
changed lines
  Added in v.1.92