Re: [PATCH 2/9] configurator: Reimplement run using popen
David Gibson <[email protected]> Tue, 20 Sep 2016 15:00:23 +1000
| Newsgroups | org.ozlabs.lists.ccan |
|---|---|
| Message-ID | <20160920050023.GL20488@umbus> |
On Sun, Sep 18, 2016 at 06:51:59PM -0600, Kevin Locke wrote: > Rather than using fork+pipe+system+waitpid, most of which are only > available on POSIX-like systems, use popen which is also available on > Windows (under the name _popen). Concept looks good, one little wart. > > Signed-off-by: Kevin Locke <[email protected]> > --- > tools/configurator/configurator.c | 77 +++++++++++++++------------------------ > 1 file changed, 29 insertions(+), 48 deletions(-) > > diff --git a/tools/configurator/configurator.c b/tools/configurator/configurator.c > index e322c76..9817fcd 100644 > --- a/tools/configurator/configurator.c > +++ b/tools/configurator/configurator.c > @@ -24,14 +24,14 @@ > #include <stdio.h> > #include <stdbool.h> > #include <stdlib.h> > -#include <unistd.h> > #include <err.h> > -#include <sys/types.h> > -#include <sys/wait.h> > -#include <sys/stat.h> > -#include <fcntl.h> > #include <string.h> > > +#ifdef _MSC_VER > +#define popen _popen > +#define pclose _pclose > +#endif > + > #define DEFAULT_COMPILER "cc" > #define DEFAULT_FLAGS "-g3 -ggdb -Wall -Wundef -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes -Wold-style-definition" > > @@ -367,20 +367,19 @@ static struct test tests[] = { > }, > }; > > -static char *grab_fd(int fd) > +static char *grab_stream(FILE *file) > { > - int ret; > - size_t max, size = 0; > + size_t max, ret, size = 0; > char *buffer; > > - max = 16384; > - buffer = malloc(max+1); > - while ((ret = read(fd, buffer + size, max - size)) > 0) { > + max = BUFSIZ; > + buffer = malloc(max); > + while ((ret = fread(buffer+size, 1, max - size, file)) == max - size) { This assumes that fread() will never return a short read except on EOF or error. I expect that will be true in practice for regular files, but I'm not sure if it's a good idea to rely on it. > size += ret; > - if (size == max) > - buffer = realloc(buffer, max *= 2); > + buffer = realloc(buffer, max *= 2); > } > - if (ret < 0) > + size += ret; > + if (ferror(file)) > err(1, "reading from command"); > buffer[size] = '\0'; > return buffer; > @@ -388,43 +387,25 @@ static char *grab_fd(int fd) > > static char *run(const char *cmd, int *exitstatus) > { > - pid_t pid; > - int p[2]; > + static const char redir[] = " 2>&1"; > + size_t cmdlen; > + char *cmdredir; > + FILE *cmdout; > char *ret; > - int status; > > - if (pipe(p) != 0) > - err(1, "creating pipe"); > - > - pid = fork(); > - if (pid == -1) > - err(1, "forking"); > - > - if (pid == 0) { > - if (dup2(p[1], STDOUT_FILENO) != STDOUT_FILENO > - || dup2(p[1], STDERR_FILENO) != STDERR_FILENO > - || close(p[0]) != 0 > - || close(STDIN_FILENO) != 0 > - || open("/dev/null", O_RDONLY) != STDIN_FILENO) > - exit(128); > - > - status = system(cmd); > - if (WIFEXITED(status)) > - exit(WEXITSTATUS(status)); > - /* Here's a hint... */ > - exit(128 + WTERMSIG(status)); > - } > + cmdlen = strlen(cmd); > + cmdredir = malloc(cmdlen + sizeof(redir)); > + memcpy(cmdredir, cmd, cmdlen); > + memcpy(cmdredir + cmdlen, redir, sizeof(redir)); > + > + cmdout = popen(cmdredir, "r"); > + if (!cmdout) > + err(1, "popen \"%s\"", cmdredir); > + > + free(cmdredir); > > - close(p[1]); > - ret = grab_fd(p[0]); > - /* This shouldn't fail... */ > - if (waitpid(pid, &status, 0) != pid) > - err(1, "Failed to wait for child"); > - close(p[0]); > - if (WIFEXITED(status)) > - *exitstatus = WEXITSTATUS(status); > - else > - *exitstatus = -WTERMSIG(status); > + ret = grab_stream(cmdout); > + *exitstatus = pclose(cmdout); > return ret; > } > -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson _______________________________________________ ccan mailing list [email protected] https://lists.ozlabs.org/listinfo/ccan
signature.asc
(application/pgp-signature, 819 B)
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCAAGBQJX4MJmAAoJEGw4ysog2bOSwVEQALqw07ZBuVlL/MG9UlAGD7dJ mAgrgBcf6IYq3O+aGlRtcEMyU7cyKab1g/1LzZjd+pXuINEHnw4lliSlTrHK3RPf NugTxXDgDUB9EqYUYIX3v7GISQKj5kr5nCgtLoYefh5JtvLB1/nPDJBKj1VBCK6X BGYm1vD7EUj9vy9sLYJjT4dDnA0qdWdfuJN7Ne26KlvUxcmr42p+AOWJcPOcIlC7 +wxdqmpgPMNVj6LtICqS8LykC2A9pwrMwOywKVA412gp5RJJvcwd6MYbeKz2LiXe uz6edM3CRwtWkNEr71OLuIqDWepOeutAzVkivB3YAxhyrX7UqW+/RbIW4GxaS+GN /VidXk1mfT/Bf61isjdENeNQsMHp9VBaCfo6/7CINa48dG6lKRhsKjfbYSDD9olA KQAfKLatlGHGESzaODwAlEinTKzliLneSHdgmyz9gVNtx6jX/1d/KR7E0D2AmTLD 4mZWoJSyGH6wXKwto4dsQUAQY2sOmUGQzYr4+FAzulue/2Xrkwr3GBbHiA7WYIWD bqeEEYWZHlGan+IYh9A0UDw0v301Xq+Il76aw+8p7hSPvpg1FxIInlueIKnoz2An ILR5CSsHnchbyqkp6ZDTCSVaYQaZLasXEKNNjazORYjM+XqhBgGLpgUwjkGhBIC9 NKE8byHXWrKXr8W7Ubt+ =eZOv -----END PGP SIGNATURE-----