Re: mg: shuffle shell-command-on-region around
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
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