Ok problem: if we have a blank line then len will be 0 (after trimming
the \n) so the continuation check will read before the start of the
buffer.

I've tweaked this a bit and hopefully fixed that, please look at this:

Index: cfg.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/cfg.c,v
retrieving revision 1.12
diff -u -p -r1.12 cfg.c
--- cfg.c       29 Dec 2010 21:28:32 -0000      1.12
+++ cfg.c       24 Aug 2011 09:52:38 -0000
@@ -92,22 +92,37 @@ load_cfg(const char *path, struct cmd_ct
        retval = 0;
        while ((buf = fgetln(f, &len))) {
                if (buf[len - 1] == '\n')
-                       buf[len - 1] = '\0';
+                       len--;
+
+               if (line != NULL)
+                       line = xrealloc(line, 1, strlen(line) + len + 1);
                else {
-                       line = xrealloc(line, 1, len + 1);
-                       memcpy(line, buf, len);
-                       line[len] = '\0';
-                       buf = line;
+                       line = xmalloc(len + 1);
+                       *line = '\0';
                }
+
+               /* Append buffer to line. strncat will terminate. */
+               strncat(line, buf, len);
                n++;
 
+               /* Continuation: get next line? */
+               len = strlen(line);
+               if (len > 0 && line[len - 1] == '\\') {
+                       line[len - 1] = '\0';
+                       continue;
+               }
+               buf = line;
+               line = NULL;
+
                if (cmd_string_parse(buf, &cmdlist, &cause) != 0) {
+                       xfree(buf);
                        if (cause == NULL)
                                continue;
                        cfg_add_cause(causes, "%s: %u: %s", path, n, cause);
                        xfree(cause);
                        continue;
-               }
+               } else
+                       xfree(buf);
                if (cmdlist == NULL)
                        continue;
                cfg_cause = NULL;
@@ -131,12 +146,16 @@ load_cfg(const char *path, struct cmd_ct
                        retval = 1;
                cmd_list_free(cmdlist);
                if (cfg_cause != NULL) {
-                       cfg_add_cause(causes, "%s: %d: %s", path, n, cfg_cause);
+                       cfg_add_cause(
+                           causes, "%s: %d: %s", path, n, cfg_cause);
                        xfree(cfg_cause);
                }
        }
-       if (line != NULL)
+       if (line != NULL) {
+               cfg_add_cause(causes,
+                   "%s: %d: line continuation at end of file", path, n);
                xfree(line);
+       }
        fclose(f);
 
        return (retval);
Index: tmux.1
===================================================================
RCS file: /cvs/src/usr.bin/tmux/tmux.1,v
retrieving revision 1.242
diff -u -p -r1.242 tmux.1
--- tmux.1      16 Aug 2011 10:00:52 -0000      1.242
+++ tmux.1      24 Aug 2011 09:49:02 -0000
@@ -491,7 +491,8 @@ $ tmux bind-key F1 set-window-option for
 Multiple commands may be specified together as part of a
 .Em command sequence .
 Each command should be separated by spaces and a semicolon;
-commands are executed sequentially from left to right.
+commands are executed sequentially from left to right;
+lines ending with a backslash continue until the next line.
 A literal semicolon may be included by escaping it with a backslash (for
 example, when specifying a command sequence to
 .Ic bind-key ) .
@@ -507,6 +508,9 @@ rename-session -tfirst newname
 set-window-option -t:0 monitor-activity on
 
 new-window ; split-window -d
+
+bind-key R source-file ~/.tmux.conf \e; \e
+  display-message "tmux: config reloaded"
 .Ed
 .Pp
 Or from
@@ -3010,6 +3014,8 @@ Creating new key bindings:
 bind-key b set-option status
 bind-key / command-prompt "split-window 'exec man %%'"
 bind-key S command-prompt "new-window -n %1 'ssh %1'"
+bind-key R source-file ~/.tmux.conf \e; \e
+  display-message "tmux: config reloaded"
 .Ed
 .Sh SEE ALSO
 .Xr pty 4





On Tue, Aug 23, 2011 at 09:46:24AM +0200, Julius Plenz wrote:
> Hi, Nicholas!
> 
> * Nicholas Marriott <nicholas.marri...@gmail.com> [2011-08-20 22:51]:
> > I think if possible the unfinished command thing should not be
> > log_warnx but should an error and be added to the causes.
> 
> Right. Also, I fixed a small memory leak.
> 
> > Also this needs to go somewhere in the manpage.
> 
> I added two examples in the man page.
> 
> Much appreciated,
> 
> Julius
> 
> -- 
> Here's the new patch:
> 
> diff --git c/cfg.c i/cfg.c
> index b69e29f..6927495 100644
> --- c/cfg.c
> +++ i/cfg.c
> @@ -92,22 +92,34 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct 
> causelist *causes)
>     retval = 0;
>     while ((buf = fgetln(f, &len))) {
>         if (buf[len - 1] == '\n')
> -           buf[len - 1] = '\0';
> -       else {
> -           line = xrealloc(line, 1, len + 1);
> -           memcpy(line, buf, len);
> -           line[len] = '\0';
> -           buf = line;
> -       }
> +           len--;
> +
> +       if(line != NULL)
> +           line = xrealloc(line, 1, strlen(line) + len + 1);
> +       else
> +           line = xcalloc(1, len + 1);
> +
> +       /* append buffer to line */
> +       strncat(line, buf, len);
> +       buf = line;
>         n++;
>  
> +       /* continuation: slurp in next line? */
> +       if (buf[strlen(buf) - 1] == '\\') {
> +           buf[strlen(buf) - 1] = '\0';
> +           continue;
> +       }
> +       line = NULL;
> +
>         if (cmd_string_parse(buf, &cmdlist, &cause) != 0) {
> +           xfree(buf);
>             if (cause == NULL)
>                 continue;
>             cfg_add_cause(causes, "%s: %u: %s", path, n, cause);
>             xfree(cause);
>             continue;
> -       }
> +       } else
> +           xfree(buf);
>         if (cmdlist == NULL)
>             continue;
>         cfg_cause = NULL;
> @@ -135,8 +147,11 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct 
> causelist *causes)
>             xfree(cfg_cause);
>         }
>     }
> -   if (line != NULL)
> +   if (line != NULL) {
> +       xasprintf(&cause, "continuation via \\ until end of file");
> +       cfg_add_cause(causes, "%s: %d: %s", path, n, cause);
>         xfree(line);
> +   }
>     fclose(f);
>  
>     return (retval);
> diff --git c/tmux.1 i/tmux.1
> index 6de074e..c465375 100644
> --- c/tmux.1
> +++ i/tmux.1
> @@ -495,7 +495,8 @@ $ tmux bind-key F1 set-window-option force-width 81
>  Multiple commands may be specified together as part of a
>  .Em command sequence .
>  Each command should be separated by spaces and a semicolon;
> -commands are executed sequentially from left to right.
> +commands are executed sequentially from left to right;
> +lines ending with a backslash continue until the next line.
>  A literal semicolon may be included by escaping it with a backslash (for
>  example, when specifying a command sequence to
>  .Ic bind-key ) .
> @@ -511,6 +512,9 @@ rename-session -tfirst newname
>  set-window-option -t:0 monitor-activity on
>  
>  new-window ; split-window -d
> +
> +bind-key R source-file ~/.tmux.conf \e; \e
> +  display-message "tmux: config reloaded"
>  .Ed
>  .Pp
>  Or from
> @@ -3004,6 +3008,8 @@ Creating new key bindings:
>  bind-key b set-option status
>  bind-key / command-prompt "split-window 'exec man %%'"
>  bind-key S command-prompt "new-window -n %1 'ssh %1'"
> +bind-key R source-file ~/.tmux.conf \e; \e
> +  display-message "tmux: config reloaded"
>  .Ed
>  .Sh SEE ALSO
>  .Xr pty 4
> 
> 
> ------------------------------------------------------------------------------
> Get a FREE DOWNLOAD! and learn more about uberSVN rich system, 
> user administration capabilities and model configuration. Take 
> the hassle out of deploying and managing Subversion and the 
> tools developers use with it. http://p.sf.net/sfu/wandisco-d2d-2
> _______________________________________________
> tmux-users mailing list
> tmux-users@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/tmux-users

------------------------------------------------------------------------------
EMC VNX: the world's simplest storage, starting under $10K
The only unified storage solution that offers unified management 
Up to 160% more powerful than alternatives and 25% more efficient. 
Guaranteed. http://p.sf.net/sfu/emc-vnx-dev2dev
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to