Hi,

I've just pushed to the wiki and attached to this message[1] an updated
externalpipe patch (which I find very useful in combination with dmenu
for fishing links and the like). 

One version applies cleanly to master and one to 0.6.

As a bonus, both handle utf8 chars correctly.

cheers
--s

[1]: not sure whether this plays well with the new mailing list
separation. apparently they will end up in both wiki@ and hackers@, but
well, they modify the wiki and are patches, so kinda makes sense. let me
know if this is a sin. 

diff --git a/config.def.h b/config.def.h
index 64e75b8..9245814 100644
--- a/config.def.h
+++ b/config.def.h
@@ -128,6 +128,7 @@ static Shortcut shortcuts[] = {
        { MODKEY|ShiftMask,     XK_C,           clipcopy,       {.i =  0} },
        { MODKEY|ShiftMask,     XK_V,           clippaste,      {.i =  0} },
        { MODKEY,               XK_Num_Lock,    numlock,        {.i =  0} },
+       { MODKEY,               XK_u,           externalpipe,   {.v =  "rot13 > 
/tmp/test-externalpipe.txt"} },
 };
 
 /*
diff --git a/st.c b/st.c
index b89d094..941deb5 100644
--- a/st.c
+++ b/st.c
@@ -326,6 +326,7 @@ static void clipcopy(const Arg *);
 static void clippaste(const Arg *);
 static void numlock(const Arg *);
 static void selpaste(const Arg *);
+static void externalpipe(const Arg *);
 static void xzoom(const Arg *);
 static void xzoomabs(const Arg *);
 static void xzoomreset(const Arg *);
@@ -2684,6 +2685,62 @@ eschandle(uchar ascii) {
 }
 
 void
+externalpipe(const Arg *arg)
+{
+       int to[2]; /* 0 = read, 1 = write */
+       pid_t child;
+       int n;
+       void (*oldsigpipe)(int);
+       char buf[UTF_SIZ];
+       Glyph *bp, *end;
+
+       if (pipe(to) == -1)
+               return;
+
+       /* sigchld() handles this */
+       switch(child = fork()){
+               case -1:
+                       close(to[0]), close(to[1]);
+                       return;
+               case 0:
+                       /* child */
+                       close(to[1]);
+                       dup2(to[0], STDIN_FILENO); /* 0<&to */
+                       close(to[0]);
+                       execvp(
+                                       "sh",
+                                       (char *const []){
+                                               "/bin/sh",
+                                               "-c",
+                                               (char *)arg->v,
+                                               0
+                                       });
+                       exit(127);
+       }
+
+       /* parent */
+       close(to[0]);
+       /* ignore sigpipe for now, in case child exits early */
+       oldsigpipe = signal(SIGPIPE, SIG_IGN);
+
+       for(n = 0; n < term.row; n++){
+               bp = &term.line[n][0];
+               end = &bp[MIN(tlinelen(n), term.col) - 1];
+               if(bp != end || bp->u != ' ')
+                       for(; bp <= end; ++bp)
+                               if(xwrite(to[1], buf, utf8encode(bp->u, buf)) < 
0)
+                                       break;
+               if(xwrite(to[1], "\n", 1) < 0)
+                       break;
+       }
+
+       close(to[1]);
+
+       /* restore */
+       signal(SIGPIPE, oldsigpipe);
+}
+
+void
 tputc(Rune u) {
        char c[UTF_SIZ];
        bool control;
diff --git a/st.c b/st.c
index 35a840b..bb2dd17 100644
--- a/st.c
+++ b/st.c
@@ -327,6 +327,7 @@ static void clipcopy(const Arg *);
 static void clippaste(const Arg *);
 static void numlock(const Arg *);
 static void selpaste(const Arg *);
+static void externalpipe(const Arg *);
 static void xzoom(const Arg *);
 static void xzoomabs(const Arg *);
 static void xzoomreset(const Arg *);
@@ -2888,6 +2889,62 @@ eschandle(uchar ascii)
 }
 
 void
+externalpipe(const Arg *arg)
+{
+       int to[2]; /* 0 = read, 1 = write */
+       pid_t child;
+       int n;
+       void (*oldsigpipe)(int);
+       char buf[UTF_SIZ];
+       Glyph *bp, *end;
+
+       if(pipe(to) == -1)
+               return;
+
+       /* sigchld() handles this */
+       switch(child = fork()){
+               case -1:
+                       close(to[0]), close(to[1]);
+                       return;
+               case 0:
+                       /* child */
+                       close(to[1]);
+                       dup2(to[0], STDIN_FILENO); /* 0<&to */
+                       close(to[0]);
+                       execvp(
+                                       "sh",
+                                       (char *const []){
+                                               "/bin/sh",
+                                               "-c",
+                                               (char *)arg->v,
+                                               0
+                                       });
+                       exit(127);
+       }
+
+       /* parent */
+       close(to[0]);
+       /* ignore sigpipe for now, in case child exits early */
+       oldsigpipe = signal(SIGPIPE, SIG_IGN);
+
+       for(n = 0; n < term.row; n++){
+               bp = &term.line[n][0];
+               end = &bp[MIN(tlinelen(n), term.col) - 1];
+               if(bp != end || bp->u != ' ')
+                       for( ;bp <= end; ++bp)
+                               if(xwrite(to[1], buf, utf8encode(bp->u, buf)) < 
0)
+                                       break;
+               if(xwrite(to[1], "\n", 1) < 0)
+                       break;
+       }
+
+       close(to[1]);
+
+       /* restore */
+       signal(SIGPIPE, oldsigpipe);
+}
+
+void
 tputc(Rune u)
 {
        char c[UTF_SIZ];

Reply via email to