changeset 21911:c66c156e1d1d

hide fcntl.h header * liboctave/wrappers/fcntl-wrappers.c, liboctave/wrappers/fcntl-wrappers.h, liboctave/wrappers/octave-popen2.c, liboctave/wrappers/octave-popen2.h: New files. * liboctave/wrappers/module.mk: Update. * file-io.cc, syscalls.cc, octave.cc, lo-sysdep.cc, oct-syscalls.cc: Use new wrapper functions. Don't include fcntl.h.
author John W. Eaton <jwe@octave.org>
date Wed, 15 Jun 2016 13:51:00 -0400
parents 4d723ba06b4a
children d92dcbcd7691
files libinterp/corefcn/file-io.cc libinterp/corefcn/syscalls.cc libinterp/octave.cc liboctave/system/lo-sysdep.cc liboctave/system/oct-syscalls.cc liboctave/wrappers/fcntl-wrappers.c liboctave/wrappers/fcntl-wrappers.h liboctave/wrappers/module.mk liboctave/wrappers/octave-popen2.c liboctave/wrappers/octave-popen2.h
diffstat 10 files changed, 537 insertions(+), 172 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/file-io.cc	Tue Jun 14 18:10:04 2016 -0400
+++ b/libinterp/corefcn/file-io.cc	Wed Jun 15 13:51:00 2016 -0400
@@ -47,8 +47,6 @@
 #include <string>
 #include <vector>
 
-#include <fcntl.h>
-
 #if defined (HAVE_ZLIB_H)
 #  include <zlib.h>
 #endif
--- a/libinterp/corefcn/syscalls.cc	Tue Jun 14 18:10:04 2016 -0400
+++ b/libinterp/corefcn/syscalls.cc	Wed Jun 15 13:51:00 2016 -0400
@@ -33,9 +33,8 @@
 #include <cstdio>
 #include <cstring>
 
-#include <fcntl.h>
-
 #include "cmd-hist.h"
+#include "fcntl-wrappers.h"
 #include "file-ops.h"
 #include "file-stat.h"
 #include "oct-env.h"
@@ -1305,11 +1304,7 @@
   return octave_value (val);
 }
 
-#if ! defined (O_NONBLOCK) && defined (O_NDELAY)
-#define O_NONBLOCK O_NDELAY
-#endif
-
-DEFUNX ("F_DUPFD", FF_DUPFD, args, ,
+DEFUN (F_DUPFD, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {} {} F_DUPFD ()\n\
 Return the numerical value to pass to @code{fcntl} to return\n\
@@ -1317,14 +1312,15 @@
 @seealso{fcntl, F_GETFD, F_GETFL, F_SETFD, F_SETFL}\n\
 @end deftypefn")
 {
-#if defined (F_DUPFD)
-  return const_value (args, F_DUPFD);
-#else
-  err_disabled_feature ("F_DUPFD", "F_DUPFD");
-#endif
+  static int val = octave_f_dupfd_wrapper ();
+
+  if (val < 0)
+    err_disabled_feature ("F_DUPFD", "F_DUPFD");
+
+  return const_value (args, val);
 }
 
-DEFUNX ("F_GETFD", FF_GETFD, args, ,
+DEFUN (F_GETFD, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {} {} F_GETFD ()\n\
 Return the numerical value to pass to @code{fcntl} to return\n\
@@ -1332,14 +1328,15 @@
 @seealso{fcntl, F_DUPFD, F_GETFL, F_SETFD, F_SETFL}\n\
 @end deftypefn")
 {
-#if defined (F_GETFD)
-  return const_value (args, F_GETFD);
-#else
-  err_disabled_feature ("F_GETFD", "F_GETFD");
-#endif
+  static int val = octave_f_getfd_wrapper ();
+
+  if (val < 0)
+    err_disabled_feature ("F_GETFD", "F_GETFD");
+
+  return const_value (args, val);
 }
 
-DEFUNX ("F_GETFL", FF_GETFL, args, ,
+DEFUN (F_GETFL, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {} {} F_GETFL ()\n\
 Return the numerical value to pass to @code{fcntl} to return\n\
@@ -1347,14 +1344,15 @@
 @seealso{fcntl, F_DUPFD, F_GETFD, F_SETFD, F_SETFL}\n\
 @end deftypefn")
 {
-#if defined (F_GETFL)
-  return const_value (args, F_GETFL);
-#else
-  err_disabled_feature ("F_GETFL", "F_GETFL");
-#endif
+  static int val = octave_f_getfl_wrapper ();
+
+  if (val < 0)
+    err_disabled_feature ("F_GETFL", "F_GETFL");
+
+  return const_value (args, val);
 }
 
-DEFUNX ("F_SETFD", FF_SETFD, args, ,
+DEFUN (F_SETFD, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {} {} F_SETFD ()\n\
 Return the numerical value to pass to @code{fcntl} to set the file\n\
@@ -1362,14 +1360,15 @@
 @seealso{fcntl, F_DUPFD, F_GETFD, F_GETFL, F_SETFL}\n\
 @end deftypefn")
 {
-#if defined (F_SETFD)
-  return const_value (args, F_SETFD);
-#else
-  err_disabled_feature ("F_SETFD", "F_SETFD");
-#endif
+  static int val = octave_f_setfd_wrapper ();
+
+  if (val < 0)
+    err_disabled_feature ("F_SETFD", "F_SETFD");
+
+  return const_value (args, val);
 }
 
-DEFUNX ("F_SETFL", FF_SETFL, args, ,
+DEFUN (F_SETFL, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {} {} F_SETFL ()\n\
 Return the numerical value to pass to @code{fcntl} to set the file\n\
@@ -1377,14 +1376,15 @@
 @seealso{fcntl, F_DUPFD, F_GETFD, F_GETFL, F_SETFD}\n\
 @end deftypefn")
 {
-#if defined (F_SETFL)
-  return const_value (args, F_SETFL);
-#else
-  err_disabled_feature ("F_SETFL", "F_SETFL");
-#endif
+  static int val = octave_f_setfl_wrapper ();
+
+  if (val < 0)
+    err_disabled_feature ("F_SETFL", "F_SETFL");
+
+  return const_value (args, val);
 }
 
-DEFUNX ("O_APPEND", FO_APPEND, args, ,
+DEFUN (O_APPEND, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {} {} O_APPEND ()\n\
 Return the numerical value of the file status flag that may be\n\
@@ -1393,14 +1393,15 @@
 @seealso{fcntl, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY}\n\
 @end deftypefn")
 {
-#if defined (O_APPEND)
-  return const_value (args, O_APPEND);
-#else
-  err_disabled_feature ("O_APPEND", "O_APPEND");
-#endif
+  static int val = octave_o_append_wrapper ();
+
+  if (val < 0)
+    err_disabled_feature ("O_APPEND", "O_APPEND");
+
+  return const_value (args, val);
 }
 
-DEFUNX ("O_ASYNC", FO_ASYNC, args, ,
+DEFUN (O_ASYNC, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {} {} O_ASYNC ()\n\
 Return the numerical value of the file status flag that may be\n\
@@ -1408,14 +1409,15 @@
 @seealso{fcntl, O_APPEND, O_CREAT, O_EXCL, O_NONBLOCK, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY}\n\
 @end deftypefn")
 {
-#if defined (O_ASYNC)
-  return const_value (args, O_ASYNC);
-#else
-  err_disabled_feature ("O_ASYNC", "O_ASYNC");
-#endif
+  static int val = octave_o_async_wrapper ();
+
+  if (val < 0)
+    err_disabled_feature ("O_ASYNC", "O_ASYNC");
+
+  return const_value (args, val);
 }
 
-DEFUNX ("O_CREAT", FO_CREAT, args, ,
+DEFUN (O_CREAT, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {} {} O_CREAT ()\n\
 Return the numerical value of the file status flag that may be\n\
@@ -1424,14 +1426,15 @@
 @seealso{fcntl, O_APPEND, O_ASYNC, O_EXCL, O_NONBLOCK, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY}\n\
 @end deftypefn")
 {
-#if defined (O_CREAT)
-  return const_value (args, O_CREAT);
-#else
-  err_disabled_feature ("O_CREAT", "O_CREAT");
-#endif
+  static int val = octave_o_creat_wrapper ();
+
+  if (val < 0)
+    err_disabled_feature ("O_CREAT", "O_CREAT");
+
+  return const_value (args, val);
 }
 
-DEFUNX ("O_EXCL", FO_EXCL, args, ,
+DEFUN (O_EXCL, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {} {} O_EXCL ()\n\
 Return the numerical value of the file status flag that may be\n\
@@ -1439,14 +1442,15 @@
 @seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_NONBLOCK, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY}\n\
 @end deftypefn")
 {
-#if defined (O_EXCL)
-  return const_value (args, O_EXCL);
-#else
-  err_disabled_feature ("O_EXCL", "O_EXCL");
-#endif
+  static int val = octave_o_excl_wrapper ();
+
+  if (val < 0)
+    err_disabled_feature ("O_EXCL", "O_EXCL");
+
+  return const_value (args, val);
 }
 
-DEFUNX ("O_NONBLOCK", FO_NONBLOCK, args, ,
+DEFUN (O_NONBLOCK, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {} {} O_NONBLOCK ()\n\
 Return the numerical value of the file status flag that may be\n\
@@ -1455,14 +1459,15 @@
 @seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY}\n\
 @end deftypefn")
 {
-#if defined (O_NONBLOCK)
-  return const_value (args, O_NONBLOCK);
-#else
-  err_disabled_feature ("O_NONBLOCK", "O_NONBLOCK");
-#endif
+  static int val = octave_o_nonblock_wrapper ();
+
+  if (val < 0)
+    err_disabled_feature ("O_NONBLOCK", "O_NONBLOCK");
+
+  return const_value (args, val);
 }
 
-DEFUNX ("O_RDONLY", FO_RDONLY, args, ,
+DEFUN (O_RDONLY, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {} {} O_RDONLY ()\n\
 Return the numerical value of the file status flag that may be\n\
@@ -1470,14 +1475,15 @@
 @seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY}\n\
 @end deftypefn")
 {
-#if defined (O_RDONLY)
-  return const_value (args, O_RDONLY);
-#else
-  err_disabled_feature ("O_RDONLY", "O_RDONLY");
-#endif
+  static int val = octave_o_rdonly_wrapper ();
+
+  if (val < 0)
+    err_disabled_feature ("O_RDONLY", "O_RDONLY");
+
+  return const_value (args, val);
 }
 
-DEFUNX ("O_RDWR", FO_RDWR, args, ,
+DEFUN (O_RDWR, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {} {} O_RDWR ()\n\
 Return the numerical value of the file status flag that may be\n\
@@ -1486,14 +1492,15 @@
 @seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK, O_RDONLY, O_SYNC, O_TRUNC, O_WRONLY}\n\
 @end deftypefn")
 {
-#if defined (O_RDWR)
-  return const_value (args, O_RDWR);
-#else
-  err_disabled_feature ("O_RDWR", "O_RDWR");
-#endif
+  static int val = octave_o_rdwr_wrapper ();
+
+  if (val < 0)
+    err_disabled_feature ("O_RDWR", "O_RDWR");
+
+  return const_value (args, val);
 }
 
-DEFUNX ("O_SYNC", FO_SYNC, args, ,
+DEFUN (O_SYNC, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {} {} O_SYNC ()\n\
 Return the numerical value of the file status flag that may be\n\
@@ -1502,14 +1509,15 @@
 @seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY}\n\
 @end deftypefn")
 {
-#if defined (O_SYNC)
-  return const_value (args, O_SYNC);
-#else
-  err_disabled_feature ("O_SYNC", "O_SYNC");
-#endif
+  static int val = octave_o_sync_wrapper ();
+
+  if (val < 0)
+    err_disabled_feature ("O_SYNC", "O_SYNC");
+
+  return const_value (args, val);
 }
 
-DEFUNX ("O_TRUNC", FO_TRUNC, args, ,
+DEFUN (O_TRUNC, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {} {} O_TRUNC ()\n\
 Return the numerical value of the file status flag that may be\n\
@@ -1518,14 +1526,15 @@
 @seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK, O_RDONLY, O_RDWR, O_SYNC, O_WRONLY}\n\
 @end deftypefn")
 {
-#if defined (O_TRUNC)
-  return const_value (args, O_TRUNC);
-#else
-  err_disabled_feature ("O_TRUNC", "O_TRUNC");
-#endif
+  static int val = octave_o_trunc_wrapper ();
+
+  if (val < 0)
+    err_disabled_feature ("O_TRUNC", "O_TRUNC");
+
+  return const_value (args, val);
 }
 
-DEFUNX ("O_WRONLY", FO_WRONLY, args, ,
+DEFUN (O_WRONLY, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {} {} O_WRONLY ()\n\
 Return the numerical value of the file status flag that may be\n\
@@ -1533,11 +1542,12 @@
 @seealso{fcntl, O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC}\n\
 @end deftypefn")
 {
-#if defined (O_WRONLY)
-  return const_value (args, O_WRONLY);
-#else
-  err_disabled_feature ("O_WRONLY", "O_WRONLY");
-#endif
+  static int val = octave_o_wronly_wrapper ();
+
+  if (val < 0)
+    err_disabled_feature ("O_WRONLY", "O_WRONLY");
+
+  return const_value (args, val);
 }
 
 #if ! defined (WNOHANG)
--- a/libinterp/octave.cc	Tue Jun 14 18:10:04 2016 -0400
+++ b/libinterp/octave.cc	Wed Jun 15 13:51:00 2016 -0400
@@ -34,7 +34,6 @@
 
 #include <iostream>
 
-#include <fcntl.h>
 #include <getopt.h>
 
 #include "cmd-edit.h"
--- a/liboctave/system/lo-sysdep.cc	Tue Jun 14 18:10:04 2016 -0400
+++ b/liboctave/system/lo-sysdep.cc	Wed Jun 15 13:51:00 2016 -0400
@@ -28,8 +28,6 @@
 #include <string>
 #include <vector>
 
-#include <fcntl.h>
-
 #if defined (__WIN32__) && ! defined (__CYGWIN__)
 #  define WIN32_LEAN_AND_MEAN 1
 #  include <windows.h>
@@ -82,6 +80,9 @@
 
 #if defined (__WIN32__) && ! defined (__CYGWIN__)
 
+    // FIXME: this function could be combined with octave_popen2 in
+    // liboctave/wrappers/octave-popen2.c.
+
     pid_t
     win_popen2 (const std::string& cmd, const string_vector& args,
                 bool sync_mode, int *fildes, std::string& msg)
--- a/liboctave/system/oct-syscalls.cc	Tue Jun 14 18:10:04 2016 -0400
+++ b/liboctave/system/oct-syscalls.cc	Wed Jun 15 13:51:00 2016 -0400
@@ -29,16 +29,16 @@
 
 #include <string.h>
 
-#include <fcntl.h>
-
 // We can't use csignal as kill is not in the std namespace, and picky
 // compiler runtimes will also exclude it from global scope as well.
 
 #include <signal.h>
 
+#include "fcntl-wrappers.h"
 #include "lo-utils.h"
 #include "lo-sysdep.h"
 #include "oct-syscalls.h"
+#include "octave-popen2.h"
 #include "str-vec.h"
 #include "unistd-wrappers.h"
 
@@ -277,82 +277,24 @@
     pid_t
     popen2 (const std::string& cmd, const string_vector& args,
             bool sync_mode, int *fildes, std::string& msg,
-            bool &interactive)
+            bool & /* interactive */)
     {
 #if defined (__WIN32__) && ! defined (__CYGWIN__)
+      // FIXME: this function could be combined with octave_popen2 in
+      // liboctave/wrappers/octave-popen2.c.
+
       return octave::sys::win_popen2 (cmd, args, sync_mode, fildes, msg);
 #else
-      pid_t pid;
-      int child_stdin[2], child_stdout[2];
-
-      if (pipe (child_stdin, msg) == 0)
-        {
-          if (pipe (child_stdout, msg) == 0)
-            {
-              pid = fork (msg);
-              if (pid < 0)
-                msg = "popen2: process creation failed -- " + msg;
-              else if (pid == 0)
-                {
-                  std::string child_msg;
-
-                  interactive = false;
+      char **argv = args.c_str_vec ();
 
-                  // Child process
-                  octave_close_wrapper (child_stdin[1]);
-                  octave_close_wrapper (child_stdout[0]);
-
-                  if (dup2 (child_stdin[0], octave_stdin_fileno ()) >= 0)
-                    {
-                      octave_close_wrapper (child_stdin[0]);
-                      if (dup2 (child_stdout[1], octave_stdout_fileno ()) >= 0)
-                        {
-                          octave_close_wrapper (child_stdout[1]);
-                          if (execvp (cmd, args, child_msg) < 0)
-                            child_msg = "popen2 (child): unable to start process -- " + child_msg;
-                        }
-                      else
-                        child_msg = "popen2 (child): file handle duplication failed -- " + child_msg;
-                    }
-                  else
-                    child_msg = "popen2 (child): file handle duplication failed -- " + child_msg;
+      pid_t pid = octave_popen2 (cmd.c_str (), argv, sync_mode, fildes);
 
-                  (*current_liboctave_error_handler) (child_msg.c_str ());
-
-                  exit (0);
-                }
-              else
-                {
-                  // Parent process
-                  octave_close_wrapper (child_stdin[0]);
-                  octave_close_wrapper (child_stdout[1]);
+      string_vector::delete_c_str_vec (argv);
 
-#if defined (F_SETFL) && defined (O_NONBLOCK)
-                  if (! sync_mode
-                      && octave::sys::fcntl (child_stdout[0], F_SETFL,
-                                                  O_NONBLOCK, msg) < 0)
-                    msg = "popen2: error setting file mode -- " + msg;
-                  else
-#endif
-                    {
-                      fildes[0] = child_stdin[1];
-                      fildes[1] = child_stdout[0];
-                      return pid;
-                    }
-                }
-              octave_close_wrapper (child_stdout[0]);
-              octave_close_wrapper (child_stdout[1]);
-            }
-          else
-            msg = "popen2: pipe creation failed -- " + msg;
+      if (pid < 0)
+        msg = gnulib::strerror (errno);
 
-          octave_close_wrapper (child_stdin[0]);
-          octave_close_wrapper (child_stdin[1]);
-        }
-      else
-        msg = "popen2: pipe creation failed -- " + msg;
-
-      return -1;
+      return pid;
 #endif
     }
 
@@ -370,7 +312,7 @@
 
       int status = -1;
 
-      status = gnulib::fcntl (fd, cmd, arg);
+      status = octave_fcntl_wrapper (fd, cmd, arg);
 
       if (status < 0)
         msg = gnulib::strerror (errno);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/wrappers/fcntl-wrappers.c	Wed Jun 15 13:51:00 2016 -0400
@@ -0,0 +1,196 @@
+/*
+
+Copyright (C) 2016 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+// These functions may be provided by gnulib.  We don't include gnulib
+// headers directly in Octave's C++ source files to avoid problems that
+// may be caused by the way that gnulib overrides standard library
+// functions.
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <fcntl.h>
+
+#include "fcntl-wrappers.h"
+
+int
+octave_fcntl_wrapper (int fd, int cmd, int arg)
+{
+  return fcntl (fd, cmd, arg);
+}
+
+int
+octave_open_wrapper (const char *nm, int flags, mode_t mode)
+{
+  return open (nm, flags, mode);
+}
+
+int
+octave_f_dupfd_wrapper (void)
+{
+#if defined (F_DUPFD)
+  return F_DUPFD;
+#else
+  return -1;
+#endif
+}
+
+int
+octave_f_getfd_wrapper (void)
+{
+#if defined (F_GETFD)
+  return F_GETFD;
+#else
+  return -1;
+#endif
+}
+
+int
+octave_f_getfl_wrapper (void)
+{
+#if defined (F_GETFL)
+  return F_GETFL;
+#else
+  return -1;
+#endif
+}
+
+int
+octave_f_setfd_wrapper (void)
+{
+#if defined (F_SETFD)
+  return F_SETFD;
+#else
+  return -1;
+#endif
+}
+
+int
+octave_f_setfl_wrapper (void)
+{
+#if defined (F_SETFL)
+  return F_SETFL;
+#else
+  return -1;
+#endif
+}
+
+int
+octave_o_append_wrapper (void)
+{
+#if defined (O_APPEND)
+  return O_APPEND;
+#else
+  return -1;
+#endif
+}
+
+int
+octave_o_async_wrapper (void)
+{
+#if defined (O_ASYNC)
+  return O_ASYNC;
+#else
+  return -1;
+#endif
+}
+
+int
+octave_o_creat_wrapper (void)
+{
+#if defined (O_CREAT)
+  return O_CREAT;
+#else
+  return -1;
+#endif
+}
+
+int
+octave_o_excl_wrapper (void)
+{
+#if defined (O_EXCL)
+  return O_EXCL;
+#else
+  return -1;
+#endif
+}
+
+int
+octave_o_nonblock_wrapper (void)
+{
+#if defined (O_NONBLOCK)
+  return O_NONBLOCK;
+#else
+  return -1;
+#endif
+}
+
+int
+octave_o_rdonly_wrapper (void)
+{
+#if defined (O_RDONLY)
+  return O_RDONLY;
+#else
+  return -1;
+#endif
+}
+
+int
+octave_o_rdwr_wrapper (void)
+{
+#if defined (O_RDWR)
+  return O_RDWR;
+#else
+  return -1;
+#endif
+}
+
+int
+octave_o_sync_wrapper (void)
+{
+#if defined (O_SYNC)
+  return O_SYNC;
+#else
+  return -1;
+#endif
+}
+
+int
+octave_o_trunc_wrapper (void)
+{
+#if defined (O_TRUNC)
+  return O_TRUNC;
+#else
+  return -1;
+#endif
+}
+
+int
+octave_o_wronly_wrapper (void)
+{
+#if defined (O_WRONLY)
+  return O_WRONLY;
+#else
+  return -1;
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/wrappers/fcntl-wrappers.h	Wed Jun 15 13:51:00 2016 -0400
@@ -0,0 +1,68 @@
+/*
+
+Copyright (C) 2016 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_fcntl_wrappers_h)
+#define octave_fcntl_wrappers_h 1
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+extern int octave_fcntl_wrapper (int fd, int cmd, int arg);
+
+extern int octave_open_wrapper (const char *nm, int flags, mode_t mode);
+
+extern int octave_f_dupfd_wrapper (void);
+
+extern int octave_f_getfd_wrapper (void);
+
+extern int octave_f_getfl_wrapper (void);
+
+extern int octave_f_setfd_wrapper (void);
+
+extern int octave_f_setfl_wrapper (void);
+
+extern int octave_o_append_wrapper (void);
+
+extern int octave_o_async_wrapper (void);
+
+extern int octave_o_creat_wrapper (void);
+
+extern int octave_o_excl_wrapper (void);
+
+extern int octave_o_nonblock_wrapper (void);
+
+extern int octave_o_rdonly_wrapper (void);
+
+extern int octave_o_rdwr_wrapper (void);
+
+extern int octave_o_sync_wrapper (void);
+
+extern int octave_o_trunc_wrapper (void);
+
+extern int octave_o_wronly_wrapper (void);
+  
+#if defined __cplusplus
+}
+#endif
+
+#endif
--- a/liboctave/wrappers/module.mk	Tue Jun 14 18:10:04 2016 -0400
+++ b/liboctave/wrappers/module.mk	Wed Jun 15 13:51:00 2016 -0400
@@ -2,12 +2,14 @@
   liboctave/wrappers/areadlink-wrapper.h \
   liboctave/wrappers/base64-wrappers.h \
   liboctave/wrappers/canonicalize-file-name-wrapper.h \
+  liboctave/wrappers/fcntl-wrappers.h \
   liboctave/wrappers/fpucw-wrapper.h \
   liboctave/wrappers/gen-tempname-wrapper.h \
   liboctave/wrappers/hash-wrappers.h \
   liboctave/wrappers/mkostemp-wrapper.h \
   liboctave/wrappers/nanosleep-wrapper.h \
   liboctave/wrappers/nproc-wrapper.h \
+  liboctave/wrappers/octave-popen2.h \
   liboctave/wrappers/putenv-wrapper.h \
   liboctave/wrappers/set-program-name-wrapper.h \
   liboctave/wrappers/stat-wrappers.h \
@@ -24,12 +26,14 @@
   liboctave/wrappers/areadlink-wrapper.c \
   liboctave/wrappers/base64-wrappers.c \
   liboctave/wrappers/canonicalize-file-name-wrapper.c \
+  liboctave/wrappers/fcntl-wrappers.c \
   liboctave/wrappers/fpucw-wrapper.c \
   liboctave/wrappers/gen-tempname-wrapper.c \
   liboctave/wrappers/hash-wrappers.c \
   liboctave/wrappers/mkostemp-wrapper.c \
   liboctave/wrappers/nanosleep-wrapper.c \
   liboctave/wrappers/nproc-wrapper.c \
+  liboctave/wrappers/octave-popen2.c \
   liboctave/wrappers/putenv-wrapper.c \
   liboctave/wrappers/set-program-name-wrapper.c \
   liboctave/wrappers/stat-wrappers.c \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/wrappers/octave-popen2.c	Wed Jun 15 13:51:00 2016 -0400
@@ -0,0 +1,109 @@
+/*
+
+Copyright (C) 2016 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+// It makes more sense to define octave_popen2 with the wrapper
+// functions than it does to try to provide wrappers for all the
+// individual functions and macros that it uses and that may be provided
+// by gnulib.  We don't include gnulib headers directly in Octave's C++
+// source files to avoid problems that may be caused by the way that
+// gnulib overrides standard library functions.
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "octave-popen2.h"
+
+pid_t
+octave_popen2 (const char *cmd, char *const *args, bool sync_mode, int *fildes)
+{
+  pid_t pid;
+
+  int child_stdin[2], child_stdout[2];
+
+  if (pipe (child_stdin) < 0)
+    return -1;
+
+  if (pipe (child_stdout) < 0)
+    {
+      close (child_stdin[0]);
+      close (child_stdin[1]);
+
+      return -1;
+    }
+
+  pid = fork ();
+
+  if (pid == 0)
+    {
+      // Child process
+
+      close (child_stdin[1]);
+      close (child_stdout[0]);
+
+      if (dup2 (child_stdin[0], STDIN_FILENO) >= 0)
+        {
+          close (child_stdin[0]);
+
+          if (dup2 (child_stdout[1], STDOUT_FILENO) >= 0)
+            {
+              close (child_stdout[1]);
+
+              if (execvp (cmd, args) < 0)
+                perror ("popen2 (child)");
+            }
+          else
+            perror ("popen2 (child)");
+        }
+      else
+        perror ("popen2 (child)");
+
+      exit (0);
+    }
+  else if (pid > 0)
+    {
+      // Parent process
+
+      close (child_stdin[0]);
+      close (child_stdout[1]);
+
+#if defined (F_SETFL) && defined (O_NONBLOCK)
+      if (! sync_mode && fcntl (child_stdout[0], F_SETFL, O_NONBLOCK) < 0)
+        return -1;
+      else
+#endif
+        {
+          fildes[0] = child_stdin[1];
+          fildes[1] = child_stdout[0];
+
+          return pid;
+        }
+    }
+
+  return pid;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/wrappers/octave-popen2.h	Wed Jun 15 13:51:00 2016 -0400
@@ -0,0 +1,38 @@
+/*
+
+Copyright (C) 2016 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_octave_popen2_h)
+#define octave_octave_popen2_h 1
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+extern pid_t
+octave_popen2 (const char *cmd, char *const *args, bool sync_mode,
+               int *fildes);
+
+#if defined __cplusplus
+}
+#endif
+
+#endif