system/popen: support r+, w+ mode
The standard popen uses the pipeline internally, so the stream returned by it can only support read-only or write-only. Now this patch is expanded through sockpair, which can support both read and write. Therefore, we can use the stream to read and write access this task (posix_spawn start). Signed-off-by: dongjiuzhu1 <dongjiuzhu1@xiaomi.com>
This commit is contained in:
parent
c10e78869b
commit
e86f6c12a5
@ -115,11 +115,12 @@ FILE *popen(FAR const char *command, FAR const char *mode)
|
||||
posix_spawn_file_actions_t file_actions;
|
||||
FAR char *argv[4];
|
||||
int fd[2];
|
||||
int oldfd;
|
||||
int newfd;
|
||||
int oldfd[2];
|
||||
int newfd[2];
|
||||
int retfd;
|
||||
int errcode;
|
||||
int result;
|
||||
int result = 0;
|
||||
bool rw = false;
|
||||
|
||||
/* Allocate a container for returned FILE stream */
|
||||
|
||||
@ -130,34 +131,51 @@ FILE *popen(FAR const char *command, FAR const char *mode)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
oldfd[1] = 0;
|
||||
newfd[1] = 0;
|
||||
|
||||
/* Create a pipe. fd[0] refers to the read end of the pipe; fd[1] refers
|
||||
* to the write end of the pipe.
|
||||
* Is the pipe the input to the shell? Or the output?
|
||||
*/
|
||||
|
||||
result = pipe(fd);
|
||||
if (result < 0)
|
||||
{
|
||||
errcode = errno;
|
||||
goto errout_with_container;
|
||||
}
|
||||
|
||||
/* Is the pipe the input to the shell? Or the output? */
|
||||
|
||||
if (strcmp(mode, "r") == 0)
|
||||
if (strcmp(mode, "r") == 0 && (result = pipe(fd)) >= 0)
|
||||
{
|
||||
/* Pipe is the output from the shell */
|
||||
|
||||
oldfd = 1; /* Replace stdout with the write side of the pipe */
|
||||
newfd = fd[1];
|
||||
retfd = fd[0]; /* Use read side of the pipe to create the return stream */
|
||||
oldfd[0] = 1; /* Replace stdout with the write side of the pipe */
|
||||
newfd[0] = fd[1];
|
||||
retfd = fd[0]; /* Use read side of the pipe to create the return stream */
|
||||
}
|
||||
else if (strcmp(mode, "w") == 0)
|
||||
else if (strcmp(mode, "w") == 0 && (result = pipe(fd)) >= 0)
|
||||
{
|
||||
/* Pipe is the input to the shell */
|
||||
|
||||
oldfd = 0; /* Replace stdin with the read side of the pipe */
|
||||
newfd = fd[0];
|
||||
retfd = fd[1]; /* Use write side of the pipe to create the return stream */
|
||||
oldfd[0] = 0; /* Replace stdin with the read side of the pipe */
|
||||
newfd[0] = fd[0];
|
||||
retfd = fd[1]; /* Use write side of the pipe to create the return stream */
|
||||
}
|
||||
|
||||
/* Create a socketpair. Using fd[0] as the input and output to the shell */
|
||||
|
||||
#if defined(CONFIG_NET_LOCAL) && defined(CONFIG_NET_LOCAL_STREAM)
|
||||
else if ((strcmp(mode, "r+") == 0 || strcmp(mode, "w+") == 0) &&
|
||||
(result = socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) >= 0)
|
||||
{
|
||||
/* Socketpair is the input/output to the shell */
|
||||
|
||||
rw = true;
|
||||
oldfd[0] = 0; /* Replace stdin with the one side of a socket pair */
|
||||
newfd[0] = fd[0];
|
||||
oldfd[1] = 1; /* Replace stdout with the one side of a socket pair */
|
||||
newfd[1] = fd[0];
|
||||
retfd = fd[1]; /* Use other side of the socket pair to create the return stream */
|
||||
}
|
||||
#endif
|
||||
else if (result < 0)
|
||||
{
|
||||
errcode = errno;
|
||||
goto errout_with_container;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -236,12 +254,23 @@ FILE *popen(FAR const char *command, FAR const char *mode)
|
||||
|
||||
/* Redirect input or output as determined by the mode parameter */
|
||||
|
||||
errcode = posix_spawn_file_actions_adddup2(&file_actions, newfd, oldfd);
|
||||
errcode = posix_spawn_file_actions_adddup2(&file_actions,
|
||||
newfd[0], oldfd[0]);
|
||||
if (errcode != 0)
|
||||
{
|
||||
goto errout_with_actions;
|
||||
}
|
||||
|
||||
if (rw)
|
||||
{
|
||||
errcode = posix_spawn_file_actions_adddup2(&file_actions,
|
||||
newfd[1], oldfd[1]);
|
||||
if (errcode != 0)
|
||||
{
|
||||
goto errout_with_actions;
|
||||
}
|
||||
}
|
||||
|
||||
/* Call task_spawn() (or posix_spawn), re-directing stdin or stdout
|
||||
* appropriately.
|
||||
*/
|
||||
@ -273,7 +302,12 @@ FILE *popen(FAR const char *command, FAR const char *mode)
|
||||
* the interface.
|
||||
*/
|
||||
|
||||
close(newfd);
|
||||
close(newfd[0]);
|
||||
|
||||
if (rw)
|
||||
{
|
||||
close(newfd[1]);
|
||||
}
|
||||
|
||||
/* Free attributes and file actions. Ignoring return values in the case
|
||||
* of an error.
|
||||
|
Loading…
Reference in New Issue
Block a user