diff --git a/src/common/execio.c b/src/common/execio.c --- a/src/common/execio.c +++ b/src/common/execio.c @@ -24,6 +24,7 @@ #include #include #include +#include #include int execio_open(struct execio **rem, const char *progname, char *const argv[]) @@ -52,6 +53,9 @@ int execio_open(struct execio **rem, con return 1; } + /* make our side of the pipes nonblocking? I'll consider this type of stuff later and just keep this code in a comment like I always do... */ + //fcntl(pipe_write[1], F_SETFD, fcntl(pipe_write[1], F_GETFD) | O_NONBLOCK); + //fucntl(pipe_read[0], F_SETFD, fcntl(pipe_read[0], F_GETFD) | O_NONBLOCK); /* parent */ child = fork(); @@ -64,6 +68,7 @@ int execio_open(struct execio **rem, con return 1; } if(child) + /* the parent proc: */ { /* close sides of pipe we won't use */ close(pipe_write[0]); @@ -100,8 +105,14 @@ int execio_open(struct execio **rem, con /* reset stdin, stdout, and stderr to the appropriate files. OK, not stderr :-) */ - dup2(pipe_read[1], 0); - dup2(pipe_write[0], 1); + dup2(pipe_read[1], STDOUT_FILENO); + dup2(pipe_write[0], STDIN_FILENO); + /* + close the fds that were dup'd + */ + close(pipe_read[1]); + close(pipe_write[0]); + /* close all other file descriptors. We want to keep 0, 1, and 2 open. We don't know that the last open() or pipe() always gives the highest fd number. However, I will assume that it does. Maybe this is a bad idea: */ @@ -134,10 +145,23 @@ int execio_open(struct execio **rem, con } } -size_t execio_read(struct execio *eio, void *buf, size_t len) +/* + returns 1 if child has exited, + returns 0 if child is still alive + */ +int _execio_checkpid(struct execio *eio) { - int toreturn; + int childstatus; + + waitpid(eio->child, &childstatus, WNOHANG); + /* perror()? */ + return WIFEXITED(childstatus); +} + + +int execio_read(struct execio *eio, void *buf, size_t len, size_t *bytesread) +{ /* TODO: detect NULL eio? TODO: errno? @@ -145,25 +169,27 @@ size_t execio_read(struct execio *eio, v whenever read() returns 0, it means EOF */ - toreturn = read(eio->pipe_read, buf, len); - if(!toreturn) - /* should also be able to figure out if is bad fd and should set EXECIO_STATE_ERROR instead of _EOF */ - eio->state = EXECIO_STATE_EOF; + (*bytesread) = read(eio->pipe_read, buf, len); + if(!*bytesread) + { + /* should also be able to figure out if is bad fd and should set EXECIO_STATE_ERROR instead of _EOF */ + eio->state = EXECIO_STATE_EOF; + return 1; + } - return toreturn; + return 0; } -size_t execio_write(struct execio *eio, void *buf, size_t len) +int execio_write(struct execio *eio, void *buf, size_t len, size_t *bytesread) { - int toreturn; /* TODO: errno handling */ - toreturn = write(eio->pipe_write, buf, len); - if(!toreturn) + (*bytesread) = write(eio->pipe_write, buf, len); + if(!*bytesread) eio->state = EXECIO_STATE_ERROR; - return toreturn; + return 0; } @@ -175,9 +201,16 @@ enum execio_state execio_state(struct ex int execio_close(struct execio *eio) { + int childstatus; + close(eio->pipe_read); close(eio->pipe_write); + /* maybe we should just kill the child */ + kill(eio->child, SIGTERM); + /* the waitpid(2) seems to indicate that only when the child is terminated will this wait return. */ + waitpid(eio->child, &childstatus, 0); + return 0; }