tacme: fix crash in X |cat with multiple windows - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit d2df5d6cbd345e101732fe7d22bb5b3baa5fb61a
 (DIR) parent 59b460f845ee7d2e0156a4ba43fbe75c2531489b
 (HTM) Author: Russ Cox <rsc@swtch.com>
       Date:   Mon, 13 Jan 2020 18:15:57 -0500
       
       acme: fix crash in X |cat with multiple windows
       
       Fixes #9.
       Fixes #219.
       Fixes #222.
       Fixes #330.
       
       Diffstat:
         M src/cmd/acme/ecmd.c                 |      29 ++++++++++++++++++++++++-----
       
       1 file changed, 24 insertions(+), 5 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/acme/ecmd.c b/src/cmd/acme/ecmd.c
       t@@ -28,7 +28,7 @@ int        append(File*, Cmd*, long);
        int        pdisplay(File*);
        void        pfilename(File*);
        void        looper(File*, Cmd*, int);
       -void        filelooper(Cmd*, int);
       +void        filelooper(Text*, Cmd*, int);
        void        linelooper(File*, Cmd*);
        Address        lineaddr(long, Address, int);
        int        filematch(File*, String*);
       t@@ -584,7 +584,7 @@ X_cmd(Text *t, Cmd *cp)
        {
                USED(t);
        
       -        filelooper(cp, cp->cmdc=='X');
       +        filelooper(t, cp, cp->cmdc=='X');
                return TRUE;
        }
        
       t@@ -978,9 +978,10 @@ alllocker(Window *w, void *v)
        }
        
        void
       -filelooper(Cmd *cp, int XY)
       +filelooper(Text *t, Cmd *cp, int XY)
        {
                int i;
       +        Text *targ;
        
                if(Glooping++)
                        editerror("can't nest %c command", "YX"[XY]);
       t@@ -1001,8 +1002,26 @@ filelooper(Cmd *cp, int XY)
                 */
                allwindows(alllocker, (void*)1);
                globalincref = 1;
       -        for(i=0; i<loopstruct.nw; i++)
       -                cmdexec(&loopstruct.w[i]->body, cp->u.cmd);
       +        
       +        /*
       +         * Unlock the window running the X command.
       +         * We'll need to lock and unlock each target window in turn.
       +         */
       +        if(t && t->w)
       +                winunlock(t->w);
       +        
       +        for(i=0; i<loopstruct.nw; i++) {
       +                targ = &loopstruct.w[i]->body;
       +                if(targ && targ->w)
       +                        winlock(targ->w, cp->cmdc);
       +                cmdexec(targ, cp->u.cmd);
       +                if(targ && targ->w)
       +                        winunlock(targ->w);
       +        }
       +
       +        if(t && t->w)
       +                winlock(t->w, cp->cmdc);
       +
                allwindows(alllocker, (void*)0);
                globalincref = 0;
                free(loopstruct.w);