Thanks - full diff below with some mostly style changes.

In the manpage I changed it a bit because shell-command is still used as
a single item for pipe-pane and some other places so better to list the
commands that accept it as a multiple.

I'd like a better example for the multiple arguments case to demonstrate
when this can avoid quoting nonsense, but I can't think of a good one
offhand.

Full diff below.

I will apply this and the named buffers one tomorrow or next week
probably.


Index: cmd-new-session.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/cmd-new-session.c,v
retrieving revision 1.59
diff -u -p -r1.59 cmd-new-session.c
--- cmd-new-session.c   17 Apr 2014 13:02:59 -0000      1.59
+++ cmd-new-session.c   9 May 2014 10:36:41 -0000
@@ -35,10 +35,10 @@ enum cmd_retval      cmd_new_session_exec(st
 
 const struct cmd_entry cmd_new_session_entry = {
        "new-session", "new",
-       "Ac:dDF:n:Ps:t:x:y:", 0, 1,
+       "Ac:dDF:n:Ps:t:x:y:", 0, -1,
        "[-AdDP] [-c start-directory] [-F format] [-n window-name] "
-       "[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] [-y height] "
-       "[command]",
+       "[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] "
+       "[-y height] [command]",
        CMD_STARTSERVER|CMD_CANTNEST,
        NULL,
        cmd_new_session_exec
@@ -55,8 +55,9 @@ cmd_new_session_exec(struct cmd *self, s
        struct termios           tio, *tiop;
        const char              *newname, *target, *update, *errstr, *template;
        const char              *path;
-       char                    *cmd, *cause, *cp;
+       char                   **argv, *cmd, *cause, *cp;
        int                      detached, already_attached, idx, cwd, fd = -1;
+       int                      argc;
        u_int                    sx, sy;
        struct format_tree      *ft;
        struct environ_entry    *envent;
@@ -183,12 +184,21 @@ cmd_new_session_exec(struct cmd *self, s
                sy = 1;
 
        /* Figure out the command for the new window. */
-       if (target != NULL)
-               cmd = NULL;
-       else if (args->argc != 0)
-               cmd = args->argv[0];
-       else
+       argc = -1;
+       argv = NULL;
+       if (target == NULL && args->argc != 0) {
+               argc = args->argc;
+               argv = args->argv;
+       } else if (target == NULL) {
                cmd = options_get_string(&global_s_options, "default-command");
+               if (cmd != NULL && *cmd != '\0') {
+                       argc = 1;
+                       argv = &cmd;
+               } else {
+                       argc = 0;
+                       argv = NULL;
+               }
+       }
 
        path = NULL;
        if (c != NULL && c->session == NULL)
@@ -206,8 +216,8 @@ cmd_new_session_exec(struct cmd *self, s
 
        /* Create the new session. */
        idx = -1 - options_get_number(&global_s_options, "base-index");
-       s = session_create(newname, cmd, path, cwd, &env, tiop, idx, sx, sy,
-           &cause);
+       s = session_create(newname, argc, argv, path, cwd, &env, tiop, idx, sx,
+           sy, &cause);
        if (s == NULL) {
                cmdq_error(cmdq, "create session failed: %s", cause);
                free(cause);
@@ -216,7 +226,7 @@ cmd_new_session_exec(struct cmd *self, s
        environ_free(&env);
 
        /* Set the initial window name if one given. */
-       if (cmd != NULL && args_has(args, 'n')) {
+       if (argc >= 0 && args_has(args, 'n')) {
                w = s->curw->window;
                window_set_name(w, args_get(args, 'n'));
                options_set_number(&w->options, "automatic-rename", 0);
Index: cmd-new-window.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/cmd-new-window.c,v
retrieving revision 1.39
diff -u -p -r1.39 cmd-new-window.c
--- cmd-new-window.c    17 Apr 2014 13:02:59 -0000      1.39
+++ cmd-new-window.c    9 May 2014 10:40:09 -0000
@@ -34,7 +34,7 @@ enum cmd_retval       cmd_new_window_exec(stru
 
 const struct cmd_entry cmd_new_window_entry = {
        "new-window", "neww",
-       "ac:dF:kn:Pt:", 0, 1,
+       "ac:dF:kn:Pt:", 0, -1,
        "[-adkP] [-c start-directory] [-F format] [-n window-name] "
        CMD_TARGET_WINDOW_USAGE " [command]",
        0,
@@ -50,8 +50,8 @@ cmd_new_window_exec(struct cmd *self, st
        struct winlink          *wl;
        struct client           *c;
        const char              *cmd, *path, *template;
-       char                    *cause, *cp;
-       int                      idx, last, detached, cwd, fd = -1;
+       char                   **argv, *cause, *cp;
+       int                      argc, idx, last, detached, cwd, fd = -1;
        struct format_tree      *ft;
        struct environ_entry    *envent;
 
@@ -84,10 +84,19 @@ cmd_new_window_exec(struct cmd *self, st
        }
        detached = args_has(args, 'd');
 
-       if (args->argc == 0)
+       if (args->argc == 0) {
                cmd = options_get_string(&s->options, "default-command");
-       else
-               cmd = args->argv[0];
+               if (cmd != NULL && *cmd != '\0') {
+                       argc = 1;
+                       argv = (char**)&cmd;
+               } else {
+                       argc = 0;
+                       argv = NULL;
+               }
+       } else {
+               argc = args->argc;
+               argv = args->argv;
+       }
 
        path = NULL;
        if (cmdq->client != NULL && cmdq->client->session == NULL)
@@ -145,7 +154,8 @@ cmd_new_window_exec(struct cmd *self, st
 
        if (idx == -1)
                idx = -1 - options_get_number(&s->options, "base-index");
-       wl = session_new(s, args_get(args, 'n'), cmd, path, cwd, idx, &cause);
+       wl = session_new(s, args_get(args, 'n'), argc, argv, path, cwd, idx,
+               &cause);
        if (wl == NULL) {
                cmdq_error(cmdq, "create window failed: %s", cause);
                free(cause);
Index: cmd-respawn-pane.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/cmd-respawn-pane.c,v
retrieving revision 1.11
diff -u -p -r1.11 cmd-respawn-pane.c
--- cmd-respawn-pane.c  17 Apr 2014 13:02:59 -0000      1.11
+++ cmd-respawn-pane.c  9 May 2014 09:00:59 -0000
@@ -32,7 +32,7 @@ enum cmd_retval        cmd_respawn_pane_exec(s
 
 const struct cmd_entry cmd_respawn_pane_entry = {
        "respawn-pane", "respawnp",
-       "kt:", 0, 1,
+       "kt:", 0, -1,
        "[-k] " CMD_TARGET_PANE_USAGE " [command]",
        0,
        NULL,
@@ -48,7 +48,7 @@ cmd_respawn_pane_exec(struct cmd *self, 
        struct window_pane      *wp;
        struct session          *s;
        struct environ           env;
-       const char              *cmd, *path;
+       const char              *path;
        char                    *cause;
        u_int                    idx;
        struct environ_entry    *envent;
@@ -74,11 +74,6 @@ cmd_respawn_pane_exec(struct cmd *self, 
        screen_reinit(&wp->base);
        input_init(wp);
 
-       if (args->argc != 0)
-               cmd = args->argv[0];
-       else
-               cmd = NULL;
-
        path = NULL;
        if (cmdq->client != NULL && cmdq->client->session == NULL)
                envent = environ_find(&cmdq->client->environ, "PATH");
@@ -87,8 +82,8 @@ cmd_respawn_pane_exec(struct cmd *self, 
        if (envent != NULL)
                path = envent->value;
 
-       if (window_pane_spawn(wp, cmd, path, NULL, -1, &env, s->tio,
-           &cause) != 0) {
+       if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, -1, &env,
+           s->tio, &cause) != 0) {
                cmdq_error(cmdq, "respawn pane failed: %s", cause);
                free(cause);
                environ_free(&env);
Index: cmd-respawn-window.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/cmd-respawn-window.c,v
retrieving revision 1.21
diff -u -p -r1.21 cmd-respawn-window.c
--- cmd-respawn-window.c        17 Apr 2014 13:02:59 -0000      1.21
+++ cmd-respawn-window.c        9 May 2014 09:00:59 -0000
@@ -31,7 +31,7 @@ enum cmd_retval        cmd_respawn_window_exec
 
 const struct cmd_entry cmd_respawn_window_entry = {
        "respawn-window", "respawnw",
-       "kt:", 0, 1,
+       "kt:", 0, -1,
        "[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
        0,
        NULL,
@@ -47,7 +47,7 @@ cmd_respawn_window_exec(struct cmd *self
        struct window_pane      *wp;
        struct session          *s;
        struct environ           env;
-       const char              *cmd, *path;
+       const char              *path;
        char                    *cause;
        struct environ_entry    *envent;
 
@@ -76,10 +76,6 @@ cmd_respawn_window_exec(struct cmd *self
        window_destroy_panes(w);
        TAILQ_INSERT_HEAD(&w->panes, wp, entry);
        window_pane_resize(wp, w->sx, w->sy);
-       if (args->argc != 0)
-               cmd = args->argv[0];
-       else
-               cmd = NULL;
 
        path = NULL;
        if (cmdq->client != NULL && cmdq->client->session == NULL)
@@ -89,8 +85,8 @@ cmd_respawn_window_exec(struct cmd *self
        if (envent != NULL)
                path = envent->value;
 
-       if (window_pane_spawn(wp, cmd, path, NULL, -1, &env, s->tio,
-           &cause) != 0) {
+       if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, -1, &env,
+           s->tio, &cause) != 0) {
                cmdq_error(cmdq, "respawn window failed: %s", cause);
                free(cause);
                environ_free(&env);
Index: cmd-split-window.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/cmd-split-window.c,v
retrieving revision 1.49
diff -u -p -r1.49 cmd-split-window.c
--- cmd-split-window.c  17 Apr 2014 13:02:59 -0000      1.49
+++ cmd-split-window.c  9 May 2014 10:38:54 -0000
@@ -36,7 +36,7 @@ enum cmd_retval        cmd_split_window_exec(s
 
 const struct cmd_entry cmd_split_window_entry = {
        "split-window", "splitw",
-       "c:dF:l:hp:Pt:v", 0, 1,
+       "c:dF:l:hp:Pt:v", 0, -1,
        "[-dhvP] [-c start-directory] [-F format] [-p percentage|-l size] "
        CMD_TARGET_PANE_USAGE " [command]",
        0,
@@ -62,9 +62,9 @@ cmd_split_window_exec(struct cmd *self, 
        struct window_pane      *wp, *new_wp = NULL;
        struct environ           env;
        const char              *cmd, *path, *shell, *template;
-       char                    *cause, *new_cause, *cp;
+       char                   **argv, *cause, *new_cause, *cp;
        u_int                    hlimit;
-       int                      size, percentage, cwd, fd = -1;
+       int                      argc, size, percentage, cwd, fd = -1;
        enum layout_type         type;
        struct layout_cell      *lc;
        struct client           *c;
@@ -81,10 +81,19 @@ cmd_split_window_exec(struct cmd *self, 
        environ_copy(&s->environ, &env);
        server_fill_environ(s, &env);
 
-       if (args->argc == 0)
+       if (args->argc == 0) {
                cmd = options_get_string(&s->options, "default-command");
-       else
-               cmd = args->argv[0];
+               if (cmd != NULL && *cmd != '\0') {
+                       argc = 1;
+                       argv = (char**)&cmd;
+               } else {
+                       argc = 0;
+                       argv = NULL;
+               }
+       } else {
+               argc = args->argc;
+               argv = args->argv;
+       }
 
        if (args_has(args, 'c')) {
                ft = format_create();
@@ -158,8 +167,8 @@ cmd_split_window_exec(struct cmd *self, 
        if (envent != NULL)
                path = envent->value;
 
-       if (window_pane_spawn(
-           new_wp, cmd, path, shell, cwd, &env, s->tio, &cause) != 0)
+       if (window_pane_spawn(new_wp, argc, argv, path, shell, cwd, &env,
+           s->tio, &cause) != 0)
                goto error;
        layout_assign_pane(lc, new_wp);
 
Index: cmd.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/cmd.c,v
retrieving revision 1.93
diff -u -p -r1.93 cmd.c
--- cmd.c       9 May 2014 09:11:24 -0000       1.93
+++ cmd.c       9 May 2014 10:32:01 -0000
@@ -187,7 +187,7 @@ cmd_copy_argv(int argc, char **argv)
 
        if (argc == 0)
                return (NULL);
-       new_argv = xcalloc(argc, sizeof *new_argv);
+       new_argv = xcalloc(argc + 1, sizeof *new_argv);
        for (i = 0; i < argc; i++) {
                if (argv[i] != NULL)
                        new_argv[i] = xstrdup(argv[i]);
@@ -205,6 +205,32 @@ cmd_free_argv(int argc, char **argv)
        for (i = 0; i < argc; i++)
                free(argv[i]);
        free(argv);
+}
+
+char *
+cmd_stringify_argv(int argc, char **argv)
+{
+       char    *buf;
+       int      i;
+       size_t   len;
+
+       if (argc == 0)
+               return (xstrdup(""));
+
+       len = 0;
+       buf = NULL;
+
+       for (i = 0; i < argc; i++) {
+               len += strlen(argv[i]) + 1;
+               buf = xrealloc(buf, 1, len);
+
+               if (i == 0)
+                       *buf = '\0';
+               else
+                       strlcat(buf, " ", len);
+               strlcat(buf, argv[i], len);
+       }
+       return (buf);
 }
 
 struct cmd *
Index: format.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/format.c,v
retrieving revision 1.44
diff -u -p -r1.44 format.c
--- format.c    17 Apr 2014 15:37:55 -0000      1.44
+++ format.c    9 May 2014 09:02:05 -0000
@@ -368,7 +368,7 @@ format_get_command(struct window_pane *w
        cmd = get_proc_name(wp->fd, wp->tty);
        if (cmd == NULL || *cmd == '\0') {
                free(cmd);
-               cmd = xstrdup(wp->cmd);
+               cmd = cmd_stringify_argv(wp->argc, wp->argv);
                if (cmd == NULL || *cmd == '\0') {
                        free(cmd);
                        cmd = xstrdup(wp->shell);
@@ -559,8 +559,10 @@ format_window_pane(struct format_tree *f
        if (wp->tty != NULL)
                format_add(ft, "pane_tty", "%s", wp->tty);
        format_add(ft, "pane_pid", "%ld", (long) wp->pid);
-       if (wp->cmd != NULL)
-               format_add(ft, "pane_start_command", "%s", wp->cmd);
+       if ((cmd = cmd_stringify_argv(wp->argc, wp->argv)) != NULL) {
+               format_add(ft, "pane_start_command", "%s", cmd);
+               free(cmd);
+       }
        if ((cmd = format_get_command(wp)) != NULL) {
                format_add(ft, "pane_current_command", "%s", cmd);
                free(cmd);
Index: names.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/names.c,v
retrieving revision 1.22
diff -u -p -r1.22 names.c
--- names.c     10 Oct 2013 11:56:50 -0000      1.22
+++ names.c     9 May 2014 10:37:57 -0000
@@ -68,9 +68,15 @@ window_name_callback(unused int fd, unus
 char *
 default_window_name(struct window *w)
 {
-       if (w->active->cmd != NULL && *w->active->cmd != '\0')
-               return (parse_window_name(w->active->cmd));
-       return (parse_window_name(w->active->shell));
+       char    *cmd, *s;
+
+       cmd = cmd_stringify_argv(w->active->argc, w->active->argv);
+       if (cmd != NULL && *cmd != '\0')
+               s = parse_window_name(cmd);
+       else
+               s = parse_window_name(w->active->shell);
+       free(cmd);
+       return (s);
 }
 
 char *
Index: session.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/session.c,v
retrieving revision 1.43
diff -u -p -r1.43 session.c
--- session.c   17 Apr 2014 13:02:59 -0000      1.43
+++ session.c   9 May 2014 10:33:37 -0000
@@ -85,11 +85,12 @@ session_find_by_id(u_int id)
 
 /* Create a new session. */
 struct session *
-session_create(const char *name, const char *cmd, const char *path, int cwd,
-    struct environ *env, struct termios *tio, int idx, u_int sx, u_int sy,
-    char **cause)
+session_create(const char *name, int argc, char **argv, const char *path,
+    int cwd, struct environ *env, struct termios *tio, int idx, u_int sx,
+    u_int sy, char **cause)
 {
        struct session  *s;
+       struct winlink  *wl;
 
        s = xmalloc(sizeof *s);
        s->references = 0;
@@ -132,8 +133,9 @@ session_create(const char *name, const c
        }
        RB_INSERT(sessions, &sessions, s);
 
-       if (cmd != NULL) {
-               if (session_new(s, NULL, cmd, path, cwd, idx, cause) == NULL) {
+       if (argc >= 0) {
+               wl = session_new(s, NULL, argc, argv, path, cwd, idx, cause);
+               if (wl == NULL) {
                        session_destroy(s);
                        return (NULL);
                }
@@ -227,7 +229,7 @@ session_previous_session(struct session 
 
 /* Create a new window on a session. */
 struct winlink *
-session_new(struct session *s, const char *name, const char *cmd,
+session_new(struct session *s, const char *name, int argc, char **argv,
     const char *path, int cwd, int idx, char **cause)
 {
        struct window   *w;
@@ -251,8 +253,8 @@ session_new(struct session *s, const cha
                shell = _PATH_BSHELL;
 
        hlimit = options_get_number(&s->options, "history-limit");
-       w = window_create(name, cmd, path, shell, cwd, &env, s->tio, s->sx,
-           s->sy, hlimit, cause);
+       w = window_create(name, argc, argv, path, shell, cwd, &env, s->tio,
+           s->sx, s->sy, hlimit, cause);
        if (w == NULL) {
                winlink_remove(&s->windows, wl);
                environ_free(&env);
Index: tmux.1
===================================================================
RCS file: /cvs/src/usr.bin/tmux/tmux.1,v
retrieving revision 1.391
diff -u -p -r1.391 tmux.1
--- tmux.1      17 Apr 2014 15:48:02 -0000      1.391
+++ tmux.1      9 May 2014 10:50:00 -0000
@@ -478,11 +478,36 @@ It may be used alone to target a pane or
 arguments are
 .Xr sh 1
 commands.
-These must be passed as a single item, which typically means quoting them, for
-example:
+This may be a single argument passed to the shell, for example:
 .Bd -literal -offset indent
 new-window 'vi /etc/passwd'
 .Ed
+.Pp
+Will run:
+.Bd -literal -offset indent
+/bin/sh -c 'vi /etc/passwd'
+.Ed
+.Pp
+Additionally, the
+.Ic new-window ,
+.Ic new-session ,
+.Ic split-window ,
+.Ic respawn-window
+and
+.Ic respawn-pane
+commands allow
+.Ar shell-command
+to be given as multiple arguments and executed directly (without
+.Ql sh -c ) .
+This can avoid issues with shell quoting.
+For example:
+.Bd -literal -offset indent
+$ tmux new-window vi /etc/passwd
+.Ed
+.Pp
+Will run
+.Xr vi 1
+directly without invoking the shell.
 .Pp
 .Ar command
 .Op Ar arguments
Index: tmux.h
===================================================================
RCS file: /cvs/src/usr.bin/tmux/tmux.h,v
retrieving revision 1.460
diff -u -p -r1.460 tmux.h
--- tmux.h      9 May 2014 09:11:24 -0000       1.460
+++ tmux.h      9 May 2014 09:11:43 -0000
@@ -912,7 +912,8 @@ struct window_pane {
 #define PANE_RESIZE 0x8
 #define PANE_FOCUSPUSH 0x10
 
-       char            *cmd;
+       int              argc;
+       char           **argv;
        char            *shell;
        int              cwd;
 
@@ -1740,6 +1741,7 @@ int                cmd_pack_argv(int, char **, char *
 int             cmd_unpack_argv(char *, size_t, int, char ***);
 char          **cmd_copy_argv(int, char **);
 void            cmd_free_argv(int, char **);
+char           *cmd_stringify_argv(int, char **);
 struct cmd     *cmd_parse(int, char **, const char *, u_int, char **);
 size_t          cmd_print(struct cmd *, char *, size_t);
 struct session *cmd_current_session(struct cmd_q *, int);
@@ -2130,7 +2132,7 @@ void               winlink_stack_remove(struct winli
 int             window_index(struct window *, u_int *);
 struct window  *window_find_by_id(u_int);
 struct window  *window_create1(u_int, u_int);
-struct window  *window_create(const char *, const char *, const char *,
+struct window  *window_create(const char *, int, char **, const char *,
                     const char *, int, struct environ *, struct termios *,
                     u_int, u_int, u_int, char **);
 void            window_destroy(struct window *);
@@ -2156,7 +2158,7 @@ struct window_pane *window_pane_find_by_
 struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int);
 void            window_pane_destroy(struct window_pane *);
 void            window_pane_timer_start(struct window_pane *);
-int             window_pane_spawn(struct window_pane *, const char *,
+int             window_pane_spawn(struct window_pane *, int, char **,
                     const char *, const char *, int, struct environ *,
                     struct termios *, char **);
 void            window_pane_resize(struct window_pane *, u_int, u_int);
@@ -2294,18 +2296,18 @@ RB_PROTOTYPE(sessions, session, entry, s
 int             session_alive(struct session *);
 struct session *session_find(const char *);
 struct session *session_find_by_id(u_int);
-struct session *session_create(const char *, const char *, const char *, int,
-                    struct environ *, struct termios *, int, u_int, u_int,
-                    char **);
+struct session *session_create(const char *, int, char **, const char *,
+                    int, struct environ *, struct termios *, int, u_int,
+                    u_int, char **);
 void            session_destroy(struct session *);
 int             session_check_name(const char *);
 void            session_update_activity(struct session *);
 struct session *session_next_session(struct session *);
 struct session *session_previous_session(struct session *);
-struct winlink *session_new(struct session *, const char *, const char *,
+struct winlink *session_new(struct session *, const char *, int, char **,
                     const char *, int, int, char **);
-struct winlink *session_attach(
-                    struct session *, struct window *, int, char **);
+struct winlink *session_attach(struct session *, struct window *, int,
+                    char **);
 int             session_detach(struct session *, struct winlink *);
 struct winlink *session_has(struct session *, struct window *);
 int             session_next(struct session *, int);
Index: window.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/window.c,v
retrieving revision 1.109
diff -u -p -r1.109 window.c
--- window.c    8 May 2014 06:03:30 -0000       1.109
+++ window.c    9 May 2014 10:50:31 -0000
@@ -307,7 +307,7 @@ window_create1(u_int sx, u_int sy)
 }
 
 struct window *
-window_create(const char *name, const char *cmd, const char *path,
+window_create(const char *name, int argc, char **argv, const char *path,
     const char *shell, int cwd, struct environ *env, struct termios *tio,
     u_int sx, u_int sy, u_int hlimit, char **cause)
 {
@@ -318,7 +318,7 @@ window_create(const char *name, const ch
        wp = window_add_pane(w, hlimit);
        layout_init(w, wp);
 
-       if (window_pane_spawn(wp, cmd, path, shell, cwd, env, tio,
+       if (window_pane_spawn(wp, argc, argv, path, shell, cwd, env, tio,
            cause) != 0) {
                window_destroy(w);
                return (NULL);
@@ -678,7 +678,8 @@ window_pane_create(struct window *w, u_i
        wp->id = next_window_pane_id++;
        RB_INSERT(window_pane_tree, &all_window_panes, wp);
 
-       wp->cmd = NULL;
+       wp->argc = 0;
+       wp->argv = NULL;
        wp->shell = NULL;
        wp->cwd = -1;
 
@@ -737,27 +738,29 @@ window_pane_destroy(struct window_pane *
 
        close(wp->cwd);
        free(wp->shell);
-       free(wp->cmd);
+       cmd_free_argv(wp->argc, wp->argv);
        free(wp);
 }
 
 int
-window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path,
-    const char *shell, int cwd, struct environ *env, struct termios *tio,
-    char **cause)
+window_pane_spawn(struct window_pane *wp, int argc, char **argv,
+    const char *path, const char *shell, int cwd, struct environ *env,
+    struct termios *tio, char **cause)
 {
        struct winsize   ws;
-       char            *argv0, paneid[16];
-       const char      *ptr;
+       char            *argv0, *cmd, **argvp, paneid[16];
+       const char      *ptr, *first;
        struct termios   tio2;
+       int              i;
 
        if (wp->fd != -1) {
                bufferevent_free(wp->event);
                close(wp->fd);
        }
-       if (cmd != NULL) {
-               free(wp->cmd);
-               wp->cmd = xstrdup(cmd);
+       if (argc > 0) {
+               cmd_free_argv(wp->argc, wp->argv);
+               wp->argc = argc;
+               wp->argv = cmd_copy_argv(argc, argv);
        }
        if (shell != NULL) {
                free(wp->shell);
@@ -768,7 +771,10 @@ window_pane_spawn(struct window_pane *wp
                wp->cwd = dup(cwd);
        }
 
-       log_debug("spawn: %s -- %s", wp->shell, wp->cmd);
+       cmd = cmd_stringify_argv(wp->argc, wp->argv);
+       log_debug("spawn: %s -- %s", wp->shell, cmd);
+       for (i = 0; i < wp->argc; i++)
+               log_debug("spawn: argv[%d] = %s", i, wp->argv[i]);
 
        memset(&ws, 0, sizeof ws);
        ws.ws_col = screen_size_x(&wp->base);
@@ -778,6 +784,7 @@ window_pane_spawn(struct window_pane *wp
        case -1:
                wp->fd = -1;
                xasprintf(cause, "%s: %s", cmd, strerror(errno));
+               free(cmd);
                return (-1);
        case 0:
                if (fchdir(wp->cwd) != 0)
@@ -805,31 +812,42 @@ window_pane_spawn(struct window_pane *wp
                setenv("SHELL", wp->shell, 1);
                ptr = strrchr(wp->shell, '/');
 
-               if (*wp->cmd != '\0') {
-                       /* Use the command. */
+               /*
+                * If given one argument, assume it should be passed to sh -c;
+                * with more than one argument, use execvp(). If there is no
+                * arguments, create a login shell.
+                */
+               if (wp->argc > 0) {
+                       if (wp->argc != 1) {
+                               /* Copy to ensure argv ends in NULL. */
+                               argvp = cmd_copy_argv(wp->argc, wp->argv);
+                               execvp(argvp[0], argvp);
+                               fatal("execvp failed");
+                       }
+                       first = wp->argv[0];
+
                        if (ptr != NULL && *(ptr + 1) != '\0')
                                xasprintf(&argv0, "%s", ptr + 1);
                        else
                                xasprintf(&argv0, "%s", wp->shell);
-                       execl(wp->shell, argv0, "-c", wp->cmd, (char *) NULL);
+                       execl(wp->shell, argv0, "-c", first, (char *)NULL);
                        fatal("execl failed");
                }
-
-               /* No command; fork a login shell. */
                if (ptr != NULL && *(ptr + 1) != '\0')
                        xasprintf(&argv0, "-%s", ptr + 1);
                else
                        xasprintf(&argv0, "-%s", wp->shell);
-               execl(wp->shell, argv0, (char *) NULL);
+               execl(wp->shell, argv0, (char *)NULL);
                fatal("execl failed");
        }
 
        setblocking(wp->fd, 0);
 
-       wp->event = bufferevent_new(wp->fd,
-           window_pane_read_callback, NULL, window_pane_error_callback, wp);
+       wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL,
+           window_pane_error_callback, wp);
        bufferevent_enable(wp->event, EV_READ|EV_WRITE);
 
+       free(cmd);
        return (0);
 }
 




On Thu, May 08, 2014 at 08:03:08PM -0500, J Raynor wrote:
> I've attached a patch that just updates the man page.  If this patch
> is acceptable, let me know if you would like this combined with the
> patch for the code into a single patch.
> 
> On Thu, May 8, 2014 at 2:41 AM, Nicholas Marriott
> <nicholas.marri...@gmail.com> wrote:
> > This looks good, it needs to go in the man page, but I'm not sure
> > where... any ideas?

> diff --git a/tmux.1 b/tmux.1
> index c05eacf..d35f88c 100644
> --- a/tmux.1
> +++ b/tmux.1
> @@ -482,12 +482,16 @@ It may be used alone to target a pane or the window 
> containing it.
>  arguments are
>  .Xr sh 1
>  commands.
> -These must be passed as a single item, which typically means quoting them, 
> for
> +These may be passed as a single item, which typically means quoting them, for
>  example:
>  .Bd -literal -offset indent
>  new-window 'vi /etc/passwd'
>  .Ed
>  .Pp
> +If passed as a single item, the SHELL will receive them as a single argument,
> +and will parse the command according to its rules.  If not passed as a single
> +item, the command will be spawned directly, without the use of the SHELL.
> +.Pp
>  .Ar command
>  .Op Ar arguments
>  refers to a


------------------------------------------------------------------------------
Is your legacy SCM system holding you back? Join Perforce May 7 to find out:
&#149; 3 signs your SCM is hindering your productivity
&#149; Requirements for releasing software faster
&#149; Expert tips and advice for migrating your SCM now
http://p.sf.net/sfu/perforce
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to