You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2023/07/30 03:30:00 UTC

[nuttx-apps] 01/02: system/popen: support r+, w+ mode

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git

commit e86f6c12a55e22d01516c7af416f28ec94b998a9
Author: dongjiuzhu1 <do...@xiaomi.com>
AuthorDate: Sat Jul 29 09:51:32 2023 +0800

    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 <do...@xiaomi.com>
---
 system/popen/popen.c | 78 +++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 56 insertions(+), 22 deletions(-)

diff --git a/system/popen/popen.c b/system/popen/popen.c
index 805667da1..8e09edcd0 100644
--- a/system/popen/popen.c
+++ b/system/popen/popen.c
@@ -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.