[BACK]Return to region.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Diff for /src/usr.bin/mg/region.c between version 1.31 and 1.32

version 1.31, 2012/10/26 20:46:12 version 1.32, 2012/12/27 18:49:59
Line 24 
Line 24 
 static char leftover[BUFSIZ];  static char leftover[BUFSIZ];
   
 static  int     getregion(struct region *);  static  int     getregion(struct region *);
 static  int     iomux(int);  static  int     iomux(int, char * const, int, struct buffer *);
 static  int     pipeio(const char *);  
 static  int     preadin(int, struct buffer *);  static  int     preadin(int, struct buffer *);
 static  void    pwriteout(int, char **, int *);  static  void    pwriteout(int, char **, int *);
 static  int     setsize(struct region *, RSIZE);  static  int     setsize(struct region *, RSIZE);
Line 406 
Line 405 
 int  int
 piperegion(int f, int n)  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 */          /* C-u M-| is not supported yet */
         if (n > 1)          if (n > 1)
Line 416 
Line 419 
                 ewprintf("The mark is not set now, so there is no region");                  ewprintf("The mark is not set now, so there is no region");
                 return (FALSE);                  return (FALSE);
         }          }
   
         if ((cmd = eread("Shell command on region: ", cmdbuf, sizeof(cmdbuf),          if ((cmd = eread("Shell command on region: ", cmdbuf, sizeof(cmdbuf),
             EFNEW | EFCR)) == NULL || (cmd[0] == '\0'))              EFNEW | EFCR)) == NULL || (cmd[0] == '\0'))
                 return (ABORT);                  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   * Create a socketpair, fork and execv path with argv.
  * and STDERR of child process are redirected to socket.   * STDIN, STDOUT and STDERR of child process are redirected to socket.
    * Parent writes len chars from text to socket.
  */   */
 int  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];          int s[2];
         char *shellp;          char *err;
   
         if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, s) == -1) {          if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, s) == -1) {
                 ewprintf("socketpair error");                  ewprintf("socketpair error");
                 return (FALSE);                  return (FALSE);
         }          }
   
         switch(fork()) {          switch(fork()) {
         case -1:          case -1:
                 ewprintf("Can't fork");                  ewprintf("Can't fork");
Line 450 
Line 488 
                         _exit(1);                          _exit(1);
                 if (dup2(s[1], STDERR_FILENO) == -1)                  if (dup2(s[1], STDERR_FILENO) == -1)
                         _exit(1);                          _exit(1);
                 if ((shellp = getenv("SHELL")) == NULL)                  if (path == NULL)
                         _exit(1);                          _exit(1);
                 execl(shellp, "sh", "-c", cmd, (char *)NULL);  
                   execv(path, argv);
                   err = strerror(errno);
                   write(s[1], err, strlen(err));
                 _exit(1);                  _exit(1);
         default:          default:
                 /* Parent process */                  /* Parent process */
                 close(s[1]);                  close(s[1]);
                 return iomux(s[0]);                  return (iomux(s[0], text, len, outbp));
         }          }
         return (FALSE);          return (FALSE);
 }  }
   
 /*  /*
  * Multiplex read, write on socket fd passed. First get the region,   * Multiplex read, write on socket fd passed. Put output in outbp
  * find/create *Shell Command Output* buffer and clear it's contents.  
  * Poll on the fd for both read and write readiness.   * Poll on the fd for both read and write readiness.
  */   */
 int  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];          struct pollfd pfd[1];
         int nfds;          int nfds;
         char *text, *textcopy;          char *textcopy;
   
         if (getregion(&region) != 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;          textcopy = text;
         fcntl(fd, F_SETFL, O_NONBLOCK);          fcntl(fd, F_SETFL, O_NONBLOCK);
           pfd[0].fd = fd;
         /* There is nothing to write if r_size is zero  
           /* There is nothing to write if len is zero
          * but the cmd's output should be read so shutdown           * 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
          */           */
         if (region.r_size == 0)          if (len == 0) {
                 shutdown(fd, SHUT_WR);                  shutdown(fd, SHUT_WR);
                   pfd[0].events = POLLIN;
         bp = bfind("*Shell Command Output*", TRUE);          } else
         bp->b_flag |= BFREADONLY;                  pfd[0].events = POLLIN | POLLOUT;
         if (bclear(bp) != TRUE) {  
                 close(fd);  
                 free(text);  
                 return (FALSE);  
         }  
   
         pfd[0].fd = fd;  
         pfd[0].events = POLLIN | POLLOUT;  
         while ((nfds = poll(pfd, 1, TIMEOUT)) != -1 ||          while ((nfds = poll(pfd, 1, TIMEOUT)) != -1 ||
             (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL))) {              (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL))) {
                 if (pfd[0].revents & POLLOUT && region.r_size > 0)                  if (pfd[0].revents & POLLOUT && len > 0)
                         pwriteout(fd, &textcopy, &region.r_size);                          pwriteout(fd, &textcopy, &len);
                 else if (pfd[0].revents & POLLIN)                  else if (pfd[0].revents & POLLIN)
                         if (preadin(fd, bp) == FALSE)                          if (preadin(fd, outbp) == FALSE)
                                 break;                                  break;
                   if (len == 0 && pfd[0].events & POLLOUT)
                           pfd[0].events = POLLIN;
         }          }
         close(fd);          close(fd);
         free(text);  
         /* In case if last line doesn't have a '\n' add the leftover          /* In case if last line doesn't have a '\n' add the leftover
          * characters to buffer.           * characters to buffer.
          */           */
         if (leftover[0] != '\0') {          if (leftover[0] != '\0') {
                 addline(bp, leftover);                  addline(outbp, leftover);
                 leftover[0] = '\0';                  leftover[0] = '\0';
         }          }
         if (nfds == 0) {          if (nfds == 0) {
Line 531 
Line 554 
                 ewprintf("poll error");                  ewprintf("poll error");
                 return (FALSE);                  return (FALSE);
         }          }
         return (popbuftop(bp, WNONE));          return (popbuftop(outbp, WNONE));
 }  }
   
 /*  /*
Line 568 
Line 591 
 preadin(int fd, struct buffer *bp)  preadin(int fd, struct buffer *bp)
 {  {
         int len;          int len;
         static int nooutput;  
         char buf[BUFSIZ], *p, *q;          char buf[BUFSIZ], *p, *q;
   
         if ((len = read(fd, buf, BUFSIZ - 1)) == 0) {          if ((len = read(fd, buf, BUFSIZ - 1)) == 0)
                 if (nooutput == 0)  
                         addline(bp, "(Shell command succeeded with no output)");  
                 nooutput = 0;  
                 return (FALSE);                  return (FALSE);
         }  
         nooutput = 1;  
         buf[len] = '\0';          buf[len] = '\0';
         p = q = buf;          p = q = buf;
         if (leftover[0] != '\0' && ((q = strchr(p, '\n')) != NULL)) {          if (leftover[0] != '\0' && ((q = strchr(p, '\n')) != NULL)) {

Legend:
Removed from v.1.31  
changed lines
  Added in v.1.32