Re: mg: shuffle shell-command-on-region around

2012-12-19 Thread Florian Obser
updated diff:
- pull output buffer creation up to piperegion
- pull message Shell command succeeded with no output up to piperegion
- erase echo line

diff --git def.h def.h
index a99421c..3c7702c 100644
--- def.h
+++ def.h
@@ -591,6 +591,8 @@ int  region_get_data(struct region *, char *, int);
 voidregion_put_data(const char *, int);
 int markbuffer(int, int);
 int piperegion(int, int);
+int pipeio(const char * const, char * const[], char * const, int,
+struct buffer *);
 
 /* search.c X */
 int forwsearch(int, int);
diff --git region.c region.c
index 7a21182..2a8d842 100644
--- region.c
+++ region.c
@@ -24,8 +24,7 @@
 static char leftover[BUFSIZ];
 
 static int getregion(struct region *);
-static int iomux(int);
-static int pipeio(const char *);
+static int iomux(int, char * const, int, struct buffer *);
 static int preadin(int, struct buffer *);
 static voidpwriteout(int, char **, int *);
 static int setsize(struct region *, RSIZE);
@@ -406,7 +405,11 @@ markbuffer(int f, int n)
 int
 piperegion(int f, int n)
 {
-   char *cmd, cmdbuf[NFILEN];
+   struct region region;
+   struct buffer *bp;
+   int len, ret;
+   char *cmd, cmdbuf[NFILEN], *shellp, *text;
+   char *argv[] = {sh, -c, (char *) NULL, (char *) NULL};
 
/* C-u M-| is not supported yet */
if (n  1)
@@ -416,27 +419,62 @@ piperegion(int f, int n)
ewprintf(The mark is not set now, so there is no region);
return (FALSE);
}
+
if ((cmd = eread(Shell command on region: , cmdbuf, sizeof(cmdbuf),
EFNEW | EFCR)) == NULL || (cmd[0] == '\0'))
return (ABORT);
 
-   return (pipeio(cmdbuf));
+   argv[2] = cmd;
+
+   if (getregion(region) != TRUE)
+   return (FALSE);
+
+   len = region.r_size;
+
+   if ((text = malloc(len + 1)) == NULL) {
+   ewprintf(Cannot allocate memory.);
+   return (FALSE);
+   }
+
+   bp = bfind(*Shell Command Output*, TRUE);
+   bp-b_flag |= BFREADONLY;
+   if (bclear(bp) != TRUE) {
+   free(text);
+   return (FALSE);
+   }
+
+   region_get_data(region, text, len);
+   shellp = getenv(SHELL);
+
+   ret = pipeio(shellp, argv, text, len, bp);
+
+   if (ret == TRUE) {
+   eerase();
+   if (lforw(bp-b_headp) == bp-b_headp)
+   addline(bp, (Shell command succeeded with no output));
+   }
+
+   free(text);
+   return (ret);
 }
 
 /*
- * Create a socketpair, fork and execl cmd passed. STDIN, STDOUT
- * and STDERR of child process are redirected to socket.
+ * Create a socketpair, fork and execv path with argv.
+ * STDIN, STDOUT and STDERR of child process are redirected to socket.
+ * Parent writes len chars from text to socket.
  */
 int
-pipeio(const char* const cmd)
+pipeio(const char* const path, char* const argv[], char* const text, int len,
+struct buffer *outbp)
 {
int s[2];
-   char *shellp;
+   char *err;
 
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, s) == -1) {
ewprintf(socketpair error);
return (FALSE);
}
+
switch(fork()) {
case -1:
ewprintf(Can't fork);
@@ -450,78 +488,63 @@ pipeio(const char* const cmd)
_exit(1);
if (dup2(s[1], STDERR_FILENO) == -1)
_exit(1);
-   if ((shellp = getenv(SHELL)) == NULL)
+   if (path == NULL)
_exit(1);
-   execl(shellp, sh, -c, cmd, (char *)NULL);
+
+   execv(path, argv);
+   err = strerror(errno);
+   write(s[1], err, strlen(err));
_exit(1);
default:
/* Parent process */
close(s[1]);
-   return iomux(s[0]);
+   return (iomux(s[0], text, len, outbp));
}
return (FALSE);
 }
 
 /*
- * Multiplex read, write on socket fd passed. First get the region,
- * find/create *Shell Command Output* buffer and clear it's contents.
+ * Multiplex read, write on socket fd passed. Put output in outbp
  * Poll on the fd for both read and write readiness.
  */
 int
-iomux(int fd)
+iomux(int fd, char* const text, int len, struct buffer *outbp)
 {
-   struct region region;
-   struct buffer *bp;
struct pollfd pfd[1];
int nfds;
-   char *text, *textcopy;
-   
-   if (getregion(region) != TRUE) {
-   close(fd);
-   return (FALSE);
-   }
-
-   if ((text = malloc(region.r_size + 1)) == NULL) {
-   close(fd);
-   return (ABORT);
-   }
+   char *textcopy;
 
-   region_get_data(region, text, region.r_size);
textcopy = text;
fcntl(fd, F_SETFL, O_NONBLOCK);
-   

mg: shuffle shell-command-on-region around

2012-12-18 Thread Florian Obser
Shuffle shell-command-on-region around to make pipeio() useable for
other functions. (Needed for an upcomming diff for
diff-buffer-with-file.)
While there:
- generate error message when exec fails
- prevent busy wait in poll when nothing more has to be written
- use return value of eread, not the passed in buffer

(I'm going to revisit eread at a later time, on first pass it looks
rather bizarre.)

Comments, ok?

diff --git def.h def.h
index a99421c..5cc6525 100644
--- def.h
+++ def.h
@@ -591,6 +591,7 @@ int  region_get_data(struct region *, char *, int);
 voidregion_put_data(const char *, int);
 int markbuffer(int, int);
 int piperegion(int, int);
+int pipeio(const char * const, char * const[], char * const, int);
 
 /* search.c X */
 int forwsearch(int, int);
diff --git region.c region.c
index 7a21182..315baa9 100644
--- region.c
+++ region.c
@@ -24,8 +24,7 @@
 static char leftover[BUFSIZ];
 
 static int getregion(struct region *);
-static int iomux(int);
-static int pipeio(const char *);
+static int iomux(int, char * const, int);
 static int preadin(int, struct buffer *);
 static voidpwriteout(int, char **, int *);
 static int setsize(struct region *, RSIZE);
@@ -406,7 +405,10 @@ markbuffer(int f, int n)
 int
 piperegion(int f, int n)
 {
-   char *cmd, cmdbuf[NFILEN];
+   struct region region;
+   int len, ret;
+   char *cmd, cmdbuf[NFILEN], *shellp, *text;
+   char *argv[] = {sh, -c, (char *) NULL, (char *) NULL};
 
/* C-u M-| is not supported yet */
if (n  1)
@@ -416,27 +418,48 @@ piperegion(int f, int n)
ewprintf(The mark is not set now, so there is no region);
return (FALSE);
}
+
if ((cmd = eread(Shell command on region: , cmdbuf, sizeof(cmdbuf),
EFNEW | EFCR)) == NULL || (cmd[0] == '\0'))
return (ABORT);
 
-   return (pipeio(cmdbuf));
+   argv[2] = cmd;
+
+   if (getregion(region) != TRUE)
+   return (FALSE);
+
+   len = region.r_size;
+
+   if ((text = malloc(len + 1)) == NULL) {
+   ewprintf(Cannot allocate memory.);
+   return (FALSE);
+   }
+
+   region_get_data(region, text, len);
+   shellp = getenv(SHELL);
+
+   ret = pipeio(shellp, argv, text, len);
+
+   free(text);
+   return (ret);
 }
 
 /*
- * Create a socketpair, fork and execl cmd passed. STDIN, STDOUT
- * and STDERR of child process are redirected to socket.
+ * Create a socketpair, fork and execv path with argv.
+ * STDIN, STDOUT and STDERR of child process are redirected to socket.
+ * Parent writes len chars from text to socket.
  */
 int
-pipeio(const char* const cmd)
+pipeio(const char* const path, char* const argv[], char* const text, int len)
 {
int s[2];
-   char *shellp;
+   char *err;
 
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, s) == -1) {
ewprintf(socketpair error);
return (FALSE);
}
+
switch(fork()) {
case -1:
ewprintf(Can't fork);
@@ -450,14 +473,17 @@ pipeio(const char* const cmd)
_exit(1);
if (dup2(s[1], STDERR_FILENO) == -1)
_exit(1);
-   if ((shellp = getenv(SHELL)) == NULL)
+   if (path == NULL)
_exit(1);
-   execl(shellp, sh, -c, cmd, (char *)NULL);
+
+   execv(path, argv);
+   err = strerror(errno);
+   write(s[1], err, strlen(err));
_exit(1);
default:
/* Parent process */
close(s[1]);
-   return iomux(s[0]);
+   return (iomux(s[0], text, len));
}
return (FALSE);
 }
@@ -468,55 +494,46 @@ pipeio(const char* const cmd)
  * Poll on the fd for both read and write readiness.
  */
 int
-iomux(int fd)
+iomux(int fd, char* const text, int len)
 {
-   struct region region;
struct buffer *bp;
struct pollfd pfd[1];
int nfds;
-   char *text, *textcopy;
+   char *textcopy;

-   if (getregion(region) != TRUE) {
+   bp = bfind(*Shell Command Output*, TRUE);
+   bp-b_flag |= BFREADONLY;
+   if (bclear(bp) != TRUE) {
close(fd);
return (FALSE);
}
 
-   if ((text = malloc(region.r_size + 1)) == NULL) {
-   close(fd);
-   return (ABORT);
-   }
-
-   region_get_data(region, text, region.r_size);
textcopy = text;
fcntl(fd, F_SETFL, O_NONBLOCK);
-   
-   /* There is nothing to write if r_size is zero
+   pfd[0].fd = fd;
+
+   /* There is nothing to write if len is zero
 * but the cmd's output should be read so shutdown 
-* the socket for writing only.
+* the socket for writing only and don't wait for POLLOUT