diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -3088,17 +3088,17 @@ fi
 ### These are recommended by the gnulib bootstrap script:
 
 GNULIB_LINK_DEPS="$FREXPF_LIBM $FREXP_LIBM $GETHOSTNAME_LIB $LIBSOCKET $LIB_CLOCK_GETTIME $LIB_CRYPTO $LIB_GETLOGIN $LIB_NANOSLEEP $LIB_SELECT $LTLIBICONV $LTLIBINTL $LTLIBTHREAD"
 
 MKOCTFILE_GNULIB_LINK_DEPS="$FREXPF_LIBM $FREXP_LIBM $GETHOSTNAME_LIB $LIBSOCKET $LIB_CLOCK_GETTIME $LIB_CRYPTO $LIB_GETLOGIN $LIB_NANOSLEEP $LIB_SELECT $LIBICONV $LIBINTL $LIBTHREAD"
 
 AC_SUBST(GNULIB_LINK_DEPS)
 
-BASE_LIBOCTAVE_LINK_DEPS="$CURL_LIBS $SPARSE_XLIBS $ARPACK_LIBS $QRUPDATE_LIBS $FFTW_XLIBS $LAPACK_LIBS $BLAS_LIBS $READLINE_LIBS $TERM_LIBS $LIBGLOB $PCRE_LIBS $DL_LIBS $PTHREAD_LIBS $FLIBS $LIBS"
+BASE_LIBOCTAVE_LINK_DEPS="$CURL_LIBS $SPARSE_XLIBS $ARPACK_LIBS $QRUPDATE_LIBS $FFTW_XLIBS $LAPACK_LIBS $BLAS_LIBS $READLINE_LIBS $TERM_LIBS $LIBGLOB $PCRE_LIBS $DL_LIBS $PTHREAD_LIBS $FLIBS $Z_LIBS $LIBS"
 
 LIBOCTAVE_LINK_DEPS="$BASE_LIBOCTAVE_LINK_DEPS $GNULIB_LINK_DEPS"
 
 MKOCTFILE_LIBOCTAVE_LINK_DEPS="$BASE_LIBOCTAVE_LINK_DEPS $MKOCTFILE_GNULIB_LINK_DEPS"
 
 LIBOCTAVE_LINK_OPTS="$CURL_LDFLAGS $SPARSE_XLDFLAGS $ARPACK_LDFLAGS $QRUPDATE_LDFLAGS $FFTW_XLDFLAGS $PCRE_LDFLAGS"
 
 AC_SUBST(LIBOCTAVE_LINK_DEPS)
diff --git a/libinterp/corefcn/c-file-ptr-stream.cc b/libinterp/corefcn/c-file-ptr-stream.cc
deleted file mode 100644
--- a/libinterp/corefcn/c-file-ptr-stream.cc
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
-
-Copyright (C) 2000-2018 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
-<https://www.gnu.org/licenses/>.
-
-*/
-
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
-
-#include <iostream>
-
-#include "filepos-wrappers.h"
-
-#include "c-file-ptr-stream.h"
-
-#if ! defined (SEEK_SET)
-#  define SEEK_SET 0
-#endif
-
-#if ! defined (SEEK_CUR)
-#  define SEEK_CUR 1
-#endif
-
-#if ! defined (SEEK_END)
-#  define SEEK_END 2
-#endif
-
-c_file_ptr_buf::~c_file_ptr_buf (void)
-{
-  buf_close ();
-}
-
-// FIXME: I'm sure there is room for improvement here...
-
-c_file_ptr_buf::int_type
-c_file_ptr_buf::overflow (int_type c)
-{
-  if (f)
-    return (c != traits_type::eof ()) ? std::fputc (c, f) : flush ();
-  else
-    return traits_type::not_eof (c);
-}
-
-c_file_ptr_buf::int_type
-c_file_ptr_buf::underflow_common (bool bump)
-{
-  if (f)
-    {
-      int_type c = std::fgetc (f);
-
-      if (! bump && c != traits_type::eof ())
-        ungetc (c, f);
-
-      return c;
-    }
-  else
-    return traits_type::eof ();
-}
-
-c_file_ptr_buf::int_type
-c_file_ptr_buf::pbackfail (int_type c)
-{
-  return ((c != traits_type::eof () && f)
-          ? ungetc (c, f) : traits_type::not_eof (c));
-}
-
-std::streamsize
-c_file_ptr_buf::xsputn (const char *s, std::streamsize n)
-{
-  if (f)
-    return std::fwrite (s, 1, n, f);
-  else
-    return 0;
-}
-
-std::streamsize
-c_file_ptr_buf::xsgetn (char *s, std::streamsize n)
-{
-  if (f)
-    return std::fread (s, 1, n, f);
-  else
-    return 0;
-}
-
-static inline int
-seekdir_to_whence (std::ios::seekdir dir)
-{
-  return (dir == std::ios::beg
-          ? SEEK_SET : (dir == std::ios::cur
-                        ? SEEK_CUR : (dir == std::ios::end
-                                      ? SEEK_END : dir)));
-}
-
-std::streampos
-c_file_ptr_buf::seekoff (std::streamoff offset,
-                         std::ios::seekdir dir,
-                         std::ios::openmode)
-{
-  if (f)
-    {
-      octave_fseeko_wrapper (f, offset, seekdir_to_whence (dir));
-
-      return octave_ftello_wrapper (f);
-    }
-  else
-    return 0;
-}
-
-std::streampos
-c_file_ptr_buf::seekpos (std::streampos offset, std::ios::openmode)
-{
-  if (f)
-    {
-      octave_fseeko_wrapper (f, offset, SEEK_SET);
-
-      return octave_ftello_wrapper (f);
-    }
-  else
-    return 0;
-}
-
-int
-c_file_ptr_buf::sync (void)
-{
-  flush ();
-
-  return 0;
-}
-
-int
-c_file_ptr_buf::flush (void)
-{
-  return f ? std::fflush (f) : traits_type::eof ();
-}
-
-int
-c_file_ptr_buf::buf_close (void)
-{
-  int retval = -1;
-
-  flush ();
-
-  if (f)
-    {
-      retval = cf (f);
-      f = nullptr;
-    }
-
-  return retval;
-}
-
-int
-c_file_ptr_buf::seek (off_t offset, int origin)
-{
-  return f ? octave_fseeko_wrapper (f, offset, origin) : -1;
-}
-
-off_t
-c_file_ptr_buf::tell (void)
-{
-  return f ? octave_ftello_wrapper (f) : -1;
-}
-
-int
-c_file_ptr_buf::file_close (FILE *f)
-{
-  return std::fclose (f);
-}
-
-#if defined (HAVE_ZLIB)
-
-c_zfile_ptr_buf::~c_zfile_ptr_buf (void)
-{
-  buf_close ();
-}
-
-// FIXME: I'm sure there is room for improvement here...
-
-c_zfile_ptr_buf::int_type
-c_zfile_ptr_buf::overflow (int_type c)
-{
-  if (f)
-    return (c != traits_type::eof ()) ? gzputc (f, c) : flush ();
-  else
-    return traits_type::not_eof (c);
-}
-
-c_zfile_ptr_buf::int_type
-c_zfile_ptr_buf::underflow_common (bool bump)
-{
-  if (f)
-    {
-      int_type c = gzgetc (f);
-
-      if (! bump && c != traits_type::eof ())
-        gzungetc (c, f);
-
-      return c;
-    }
-  else
-    return traits_type::eof ();
-}
-
-c_zfile_ptr_buf::int_type
-c_zfile_ptr_buf::pbackfail (int_type c)
-{
-  return ((c != traits_type::eof () && f)
-          ? gzungetc (c, f) : traits_type::not_eof (c));
-}
-
-std::streamsize
-c_zfile_ptr_buf::xsputn (const char *s, std::streamsize n)
-{
-  if (f)
-    return gzwrite (f, s, n);
-  else
-    return 0;
-}
-
-std::streamsize
-c_zfile_ptr_buf::xsgetn (char *s, std::streamsize n)
-{
-  if (f)
-    return gzread (f, s, n);
-  else
-    return 0;
-}
-
-std::streampos
-c_zfile_ptr_buf::seekoff (std::streamoff /* offset */,
-                          std::ios::seekdir /* dir */,
-                          std::ios::openmode)
-{
-  // FIXME
-#if 0
-  if (f)
-    {
-      gzseek (f, offset, seekdir_to_whence (dir));
-
-      return gztell (f);
-    }
-  else
-    return 0;
-#endif
-  return -1;
-}
-
-std::streampos
-c_zfile_ptr_buf::seekpos (std::streampos /* offset */, std::ios::openmode)
-{
-  // FIXME
-#if 0
-  if (f)
-    {
-      gzseek (f, offset, SEEK_SET);
-
-      return gztell (f);
-    }
-  else
-    return 0;
-#endif
-  return -1;
-}
-
-int
-c_zfile_ptr_buf::sync (void)
-{
-  flush ();
-
-  return 0;
-}
-
-int
-c_zfile_ptr_buf::flush (void)
-{
-  // FIXME: do we need something more complex here, passing
-  // something other than 0 for the second argument to gzflush and
-  // checking the return value, etc.?
-
-  return f ? gzflush (f, 0) : traits_type::eof ();
-}
-
-int
-c_zfile_ptr_buf::buf_close (void)
-{
-  int retval = -1;
-
-  flush ();
-
-  if (f)
-    {
-      retval = cf (f);
-      f = nullptr;
-    }
-
-  return retval;
-}
-
-#endif
diff --git a/libinterp/corefcn/c-file-ptr-stream.h b/libinterp/corefcn/c-file-ptr-stream.h
deleted file mode 100644
--- a/libinterp/corefcn/c-file-ptr-stream.h
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
-
-Copyright (C) 2000-2018 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
-<https://www.gnu.org/licenses/>.
-
-*/
-
-#if ! defined (octave_c_file_ptr_stream_h)
-#define octave_c_file_ptr_stream_h 1
-
-#include "octave-config.h"
-
-#include <cstdio>
-
-#include <iostream>
-#include <streambuf>
-
-class
-c_file_ptr_buf : public std::streambuf
-{
-public:
-
-  typedef std::streambuf::int_type int_type;
-
-  typedef int (*close_fcn) (FILE *);
-
-  FILE *stdiofile (void) { return f; }
-
-  c_file_ptr_buf (FILE *f_arg, close_fcn cf_arg = file_close)
-    : std::streambuf (), f (f_arg), cf (cf_arg)
-  { }
-
-  // No copying!
-
-  c_file_ptr_buf (const c_file_ptr_buf&) = delete;
-
-  c_file_ptr_buf& operator = (const c_file_ptr_buf&) = delete;
-
-  ~c_file_ptr_buf (void);
-
-  int_type overflow (int_type);
-
-  int_type underflow (void) { return underflow_common (false); }
-
-  int_type uflow (void) { return underflow_common (true); }
-
-  int_type pbackfail (int_type);
-
-  std::streamsize xsputn (const char*, std::streamsize);
-
-  std::streamsize xsgetn (char *, std::streamsize);
-
-  std::streampos seekoff (std::streamoff, std::ios::seekdir,
-                          std::ios::openmode = std::ios::in | std::ios::out);
-
-  std::streampos seekpos (std::streampos,
-                          std::ios::openmode = std::ios::in | std::ios::out);
-
-  int sync (void);
-
-  int flush (void);
-
-  int buf_close (void);
-
-  int file_number () const { return f ? fileno (f) : -1; }
-
-  int seek (off_t offset, int origin);
-
-  off_t tell (void);
-
-  void clear (void) { if (f) clearerr (f); }
-
-  static int file_close (FILE *f);
-
-protected:
-
-  FILE *f;
-
-  close_fcn cf;
-
-private:
-
-  int_type underflow_common (bool);
-};
-
-// FIXME: the following three classes could probably share some code...
-
-template <typename STREAM_T, typename FILE_T, typename BUF_T>
-class
-c_file_ptr_stream : public STREAM_T
-{
-public:
-
-  c_file_ptr_stream (FILE_T f, typename BUF_T::close_fcn cf = BUF_T::file_close)
-    : STREAM_T (nullptr), buf (new BUF_T (f, cf)) { STREAM_T::init (buf); }
-
-  // No copying!
-
-  c_file_ptr_stream (const c_file_ptr_stream&) = delete;
-
-  c_file_ptr_stream& operator = (const c_file_ptr_stream&) = delete;
-
-  ~c_file_ptr_stream (void) { delete buf; buf = nullptr; }
-
-  BUF_T * rdbuf (void) { return buf; }
-
-  void stream_close (void) { if (buf) buf->buf_close (); }
-
-  int seek (off_t offset, int origin)
-  { return buf ? buf->seek (offset, origin) : -1; }
-
-  off_t tell (void) { return buf ? buf->tell () : -1; }
-
-  void clear (void) { if (buf) buf->clear (); STREAM_T::clear (); }
-
-private:
-
-  BUF_T *buf;
-};
-
-typedef c_file_ptr_stream<std::istream, FILE *, c_file_ptr_buf>
-  i_c_file_ptr_stream;
-typedef c_file_ptr_stream<std::ostream, FILE *, c_file_ptr_buf>
-  o_c_file_ptr_stream;
-typedef c_file_ptr_stream<std::iostream, FILE *, c_file_ptr_buf>
-  io_c_file_ptr_stream;
-
-#if defined (HAVE_ZLIB)
-
-#if defined (HAVE_ZLIB_H)
-#  include <zlib.h>
-#endif
-
-class
-c_zfile_ptr_buf : public std::streambuf
-{
-public:
-
-  typedef std::streambuf::int_type int_type;
-
-  typedef int (*close_fcn) (gzFile);
-
-  gzFile stdiofile (void) { return f; }
-
-  c_zfile_ptr_buf (gzFile f_arg, close_fcn cf_arg = file_close)
-    : std::streambuf (), f (f_arg), cf (cf_arg)
-  { }
-
-  // No copying!
-
-  c_zfile_ptr_buf (const c_zfile_ptr_buf&) = delete;
-
-  c_zfile_ptr_buf& operator = (const c_zfile_ptr_buf&) = delete;
-
-  ~c_zfile_ptr_buf (void);
-
-  int_type overflow (int_type);
-
-  int_type underflow (void) { return underflow_common (false); }
-
-  int_type uflow (void) { return underflow_common (true); }
-
-  int_type pbackfail (int_type);
-
-  std::streamsize xsputn (const char*, std::streamsize);
-
-  std::streamsize xsgetn (char *, std::streamsize);
-
-  std::streampos seekoff (std::streamoff, std::ios::seekdir,
-                          std::ios::openmode = std::ios::in | std::ios::out);
-
-  std::streampos seekpos (std::streampos,
-                          std::ios::openmode = std::ios::in | std::ios::out);
-
-  int sync (void);
-
-  int flush (void);
-
-  int buf_close (void);
-
-  int file_number () const { return -1; }
-
-  int seek (off_t offset, int origin)
-  { return f ? gzseek (f, offset, origin) >= 0 : -1; }
-
-  off_t tell (void) { return f ? gztell (f) : -1; }
-
-  void clear (void) { if (f) gzclearerr (f); }
-
-  static int file_close (gzFile f) { return ::gzclose (f); }
-
-protected:
-
-  gzFile f;
-
-  close_fcn cf;
-
-private:
-
-  int_type underflow_common (bool);
-};
-
-typedef c_file_ptr_stream<std::istream, gzFile, c_zfile_ptr_buf>
-  i_c_zfile_ptr_stream;
-typedef c_file_ptr_stream<std::ostream, gzFile, c_zfile_ptr_buf>
-  o_c_zfile_ptr_stream;
-typedef c_file_ptr_stream<std::iostream, gzFile, c_zfile_ptr_buf>
-  io_c_zfile_ptr_stream;
-
-#endif
-
-#endif
diff --git a/libinterp/corefcn/module.mk b/libinterp/corefcn/module.mk
--- a/libinterp/corefcn/module.mk
+++ b/libinterp/corefcn/module.mk
@@ -14,17 +14,16 @@ OPT_HANDLERS = \
 
 $(OPT_HANDLERS): $(srcdir)/build-aux/mk-opts.pl
 
 DIRSTAMP_FILES += %reldir%/$(octave_dirstamp)
 
 COREFCN_INC = \
   %reldir%/base-text-renderer.h \
   %reldir%/Cell.h \
-  %reldir%/c-file-ptr-stream.h \
   %reldir%/call-stack.h \
   %reldir%/cdisplay.h \
   %reldir%/data.h \
   %reldir%/defaults.h \
   %reldir%/defun-dld.h \
   %reldir%/defun-int.h \
   %reldir%/defun.h \
   %reldir%/dirfns.h \
@@ -63,17 +62,16 @@ COREFCN_INC = \
   %reldir%/oct-fstrm.h \
   %reldir%/oct-handle.h \
   %reldir%/oct-hdf5-types.h \
   %reldir%/oct-hist.h \
   %reldir%/oct-iostrm.h \
   %reldir%/oct-map.h \
   %reldir%/oct-obj.h \
   %reldir%/oct-prcstrm.h \
-  %reldir%/oct-procbuf.h \
   %reldir%/oct-stdstrm.h \
   %reldir%/oct-stream.h \
   %reldir%/oct-strstrm.h \
   %reldir%/oct.h \
   %reldir%/octave-default-image.h \
   %reldir%/octave-link.h \
   %reldir%/pager.h \
   %reldir%/pr-flt-fmt.h \
@@ -117,17 +115,16 @@ COREFCN_SRC = \
   %reldir%/__lin_interpn__.cc \
   %reldir%/__magick_read__.cc \
   %reldir%/__pchip_deriv__.cc \
   %reldir%/__qp__.cc \
   %reldir%/balance.cc \
   %reldir%/besselj.cc \
   %reldir%/bitfcns.cc \
   %reldir%/bsxfun.cc \
-  %reldir%/c-file-ptr-stream.cc \
   %reldir%/call-stack.cc \
   %reldir%/cdisplay.c \
   %reldir%/cellfun.cc \
   %reldir%/colloc.cc \
   %reldir%/coct-hdf5-types.c \
   %reldir%/conv2.cc \
   %reldir%/daspk.cc \
   %reldir%/dasrt.cc \
@@ -198,29 +195,27 @@ COREFCN_SRC = \
   %reldir%/mgorth.cc \
   %reldir%/nproc.cc \
   %reldir%/oct-fstrm.cc \
   %reldir%/oct-hdf5-types.cc \
   %reldir%/oct-hist.cc \
   %reldir%/oct-iostrm.cc \
   %reldir%/oct-map.cc \
   %reldir%/oct-prcstrm.cc \
-  %reldir%/oct-procbuf.cc \
   %reldir%/oct-stream.cc \
   %reldir%/oct-strstrm.cc \
   %reldir%/oct-tex-lexer.ll \
   %reldir%/oct-tex-parser.h \
   %reldir%/oct-tex-parser.yy \
   %reldir%/octave-link.cc \
   %reldir%/ordschur.cc \
   %reldir%/pager.cc \
   %reldir%/pinv.cc \
   %reldir%/pr-flt-fmt.cc \
   %reldir%/pr-output.cc \
-  %reldir%/procstream.cc \
   %reldir%/psi.cc \
   %reldir%/quad.cc \
   %reldir%/quadcc.cc \
   %reldir%/qz.cc \
   %reldir%/rand.cc \
   %reldir%/rcond.cc \
   %reldir%/regexp.cc \
   %reldir%/schur.cc \
diff --git a/libinterp/corefcn/oct-procbuf.cc b/libinterp/corefcn/oct-procbuf.cc
deleted file mode 100644
--- a/libinterp/corefcn/oct-procbuf.cc
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
-
-Copyright (C) 1996-2018 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
-<https://www.gnu.org/licenses/>.
-
-*/
-
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
-
-#include <cerrno>
-
-#include <iostream>
-
-// FIXME: we would prefer to avoid including these directly in Octave
-// sources, but eliminating them is complicated by the mingling of
-// octave_procbuf_list and the calls to system library functions like
-// execl.
-
-#if defined (HAVE_UNISTD_H)
-#  if defined (HAVE_SYS_TYPES_H)
-#    include <sys/types.h>
-#  endif
-#  include <unistd.h>
-#endif
-
-#include "lo-mappers.h"
-#include "lo-utils.h"
-#include "oct-procbuf.h"
-#include "oct-syscalls.h"
-#include "sysdep.h"
-#include "unistd-wrappers.h"
-#include "variables.h"
-
-#include "defun.h"
-#include "errwarn.h"
-#include "utils.h"
-
-#if ! defined (SHELL_PATH)
-#  define SHELL_PATH "/bin/sh"
-#endif
-
-// This class is based on the procbuf class from libg++, written by
-// Per Bothner, Copyright (C) 1993 Free Software Foundation.
-
-#if (! (defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)) \
-     && defined (HAVE_UNISTD_H))
-
-static octave_procbuf *octave_procbuf_list = nullptr;
-
-#endif
-
-#if ! defined (BUFSIZ)
-#  define BUFSIZ 1024
-#endif
-
-octave_procbuf *
-octave_procbuf::open (const char *command, int mode)
-{
-#if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)
-
-  if (is_open ())
-    return 0;
-
-  f = (octave_popen (command, (mode & std::ios::in) ? "r" : "w"));
-
-  if (! f)
-    return 0;
-
-  // Oops... popen doesn't return the associated pid, so fake it for now
-
-  proc_pid = 1;
-
-  open_p = true;
-
-  if (mode & std::ios::out)
-    ::setvbuf (f, 0, _IOLBF, BUFSIZ);
-
-  return this;
-
-#elif defined (HAVE_UNISTD_H)
-
-  int pipe_fds[2];
-
-  volatile int child_std_end = (mode & std::ios::in) ? 1 : 0;
-
-  volatile int parent_end, child_end;
-
-  if (is_open ())
-    return nullptr;
-
-  if (octave::sys::pipe (pipe_fds) < 0)
-    return nullptr;
-
-  if (mode & std::ios::in)
-    {
-      parent_end = pipe_fds[0];
-      child_end = pipe_fds[1];
-    }
-  else
-    {
-      parent_end = pipe_fds[1];
-      child_end = pipe_fds[0];
-    }
-
-  proc_pid = ::fork ();
-
-  if (proc_pid == 0)
-    {
-      octave_close_wrapper (parent_end);
-
-      if (child_end != child_std_end)
-        {
-          octave_dup2_wrapper (child_end, child_std_end);
-          octave_close_wrapper (child_end);
-        }
-
-      while (octave_procbuf_list)
-        {
-          FILE *fp = octave_procbuf_list->f;
-
-          if (fp)
-            {
-              std::fclose (fp);
-              fp = nullptr;
-            }
-
-          octave_procbuf_list = octave_procbuf_list->next;
-        }
-
-      execl (SHELL_PATH, "sh", "-c", command, static_cast<void *> (nullptr));
-
-      exit (127);
-    }
-
-  octave_close_wrapper (child_end);
-
-  if (proc_pid < 0)
-    {
-      octave_close_wrapper (parent_end);
-      return nullptr;
-    }
-
-  f = (::fdopen (parent_end, (mode & std::ios::in) ? "r" : "w"));
-
-  if (mode & std::ios::out)
-    ::setvbuf (f, nullptr, _IOLBF, BUFSIZ);
-
-  open_p = true;
-
-  next = octave_procbuf_list;
-  octave_procbuf_list = this;
-
-  return this;
-
-#else
-
-  return 0;
-
-#endif
-}
-
-octave_procbuf *
-octave_procbuf::close (void)
-{
-#if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)
-
-  if (f)
-    {
-      wstatus = octave_pclose (f);
-      f = 0;
-    }
-
-  open_p = false;
-
-  return this;
-
-#elif defined (HAVE_UNISTD_H)
-
-  if (f)
-    {
-      pid_t wait_pid;
-
-      int status = -1;
-
-      for (octave_procbuf **ptr = &octave_procbuf_list;
-           *ptr != nullptr;
-           ptr = &(*ptr)->next)
-        {
-          if (*ptr == this)
-            {
-              *ptr = (*ptr)->next;
-              status = 0;
-              break;
-            }
-        }
-
-      if (status == 0 && std::fclose (f) == 0)
-        {
-          using namespace std;
-
-          do
-            {
-              wait_pid = octave::sys::waitpid (proc_pid, &wstatus, 0);
-            }
-          while (wait_pid == -1 && errno == EINTR);
-        }
-
-      f = nullptr;
-    }
-
-  open_p = false;
-
-  return this;
-
-#else
-
-  return 0;
-
-#endif
-}
diff --git a/libinterp/corefcn/oct-procbuf.h b/libinterp/corefcn/oct-procbuf.h
deleted file mode 100644
--- a/libinterp/corefcn/oct-procbuf.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-
-Copyright (C) 1996-2018 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
-<https://www.gnu.org/licenses/>.
-
-*/
-
-// This class is based on the procbuf class from libg++, written by
-// Per Bothner, Copyright (C) 1993 Free Software Foundation.
-
-#if ! defined (octave_oct_procbuf_h)
-#define octave_oct_procbuf_h 1
-
-#include "octave-config.h"
-
-#include <sys/types.h>
-
-#include "c-file-ptr-stream.h"
-
-class
-octave_procbuf : public c_file_ptr_buf
-{
-public:
-
-  octave_procbuf (void)
-    : c_file_ptr_buf (nullptr), wstatus (-1), open_p (false), proc_pid (-1),
-      next (nullptr) { }
-
-  octave_procbuf (const char *command, int mode)
-    : c_file_ptr_buf (nullptr), wstatus (-1), open_p (false), proc_pid (-1),
-      next (nullptr) { open (command, mode); }
-
-  // No copying!
-
-  octave_procbuf (const octave_procbuf&) = delete;
-
-  octave_procbuf& operator = (const octave_procbuf&) = delete;
-
-  ~octave_procbuf (void) { close (); }
-
-  octave_procbuf * open (const char *command, int mode);
-
-  octave_procbuf * close (void);
-
-  int wait_status (void) const { return wstatus; }
-
-  bool is_open (void) const { return open_p; }
-
-  pid_t pid (void) const { return proc_pid; }
-
-protected:
-
-  int wstatus;
-
-  bool open_p;
-
-  pid_t proc_pid;
-
-  octave_procbuf *next;
-};
-
-extern void symbols_of_oct_procbuf (void);
-
-#endif
diff --git a/libinterp/corefcn/procstream.cc b/libinterp/corefcn/procstream.cc
deleted file mode 100644
--- a/libinterp/corefcn/procstream.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
-
-Copyright (C) 1993-2018 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
-<https://www.gnu.org/licenses/>.
-
-*/
-
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
-
-#include <iostream>
-
-#include "procstream.h"
-
-procstreambase::procstreambase (const std::string& command, int mode)
-{
-  pb_init ();
-
-  if (! pb.open (command.c_str (), mode))
-    std::ios::setstate (std::ios::badbit);
-}
-
-procstreambase::procstreambase (const char *command, int mode)
-{
-  pb_init ();
-
-  if (! pb.open (command, mode))
-    std::ios::setstate (std::ios::badbit);
-}
-
-void
-procstreambase::open (const char *command, int mode)
-{
-  clear ();
-
-  if (! pb.open (command, mode))
-    std::ios::setstate (std::ios::badbit);
-}
-
-int
-procstreambase::close (void)
-{
-  int status = 0;
-
-  if (is_open ())
-    {
-      if (! pb.close ())
-        std::ios::setstate (std::ios::failbit);
-
-      status = pb.wait_status ();
-    }
-
-  return status;
-}
diff --git a/libinterp/corefcn/procstream.h b/libinterp/corefcn/procstream.h
--- a/libinterp/corefcn/procstream.h
+++ b/libinterp/corefcn/procstream.h
@@ -20,145 +20,83 @@ along with Octave; see the file COPYING.
 
 */
 
 #if ! defined (octave_procstream_h)
 #define octave_procstream_h 1
 
 #include "octave-config.h"
 
-#include <istream>
-#include <ostream>
 #include <string>
 
 #include <sys/types.h>
 
-#include "oct-procbuf.h"
+#include "lo-procstream.h"
 
 class
 OCTINTERP_API
-procstreambase : virtual public std::ios
+procstreambase : public octave::sys::procstreambase
 {
 public:
 
-  procstreambase (void) : pb () { pb_init (); }
-
-  procstreambase (const std::string& name, int mode);
-
-  procstreambase (const char *name, int mode);
+  procstreambase (void) : octave::sys::procstreambase () { }
 
-  ~procstreambase (void) { close (); }
-
-  void open (const std::string& name, int mode)
-  { open (name.c_str (), mode); }
-
-  void open (const char *name, int mode);
-
-  int is_open (void) const { return pb.is_open (); }
+  procstreambase (const std::string& name, int mode)
+    : octave::sys::procstreambase (name, mode) { }
 
-  int close (void);
-
-  pid_t pid (void) const { return pb.pid (); }
-
-  int file_number (void) const { return pb.file_number (); }
-
-private:
+  procstreambase (const char *name, int mode)
+    : octave::sys::procstreambase (name, mode) { }
 
-  octave_procbuf pb;
-
-  void pb_init (void) { init (&pb); }
-
-  procstreambase (const procstreambase&);
-
-  procstreambase& operator = (const procstreambase&);
+  ~procstreambase (void) = default;
 };
 
 class
 OCTINTERP_API
-iprocstream : public std::istream, public procstreambase
-// iprocstream : public procstreambase, public std::istream
+iprocstream : public octave::sys::iprocstream
 {
 public:
 
-  iprocstream (void) : std::istream (nullptr), procstreambase () { }
+  iprocstream (void) : octave::sys::iprocstream () { }
 
   iprocstream (const std::string& name, int mode = std::ios::in)
-    : std::istream (nullptr), procstreambase (name, mode) { }
+    : octave::sys::iprocstream (name, mode) { }
 
   iprocstream (const char *name, int mode = std::ios::in)
-    : std::istream (nullptr), procstreambase (name, mode) { }
+    : octave::sys::iprocstream (name, mode) { }
 
   ~iprocstream (void) = default;
-
-  void open (const std::string& name, int mode = std::ios::in)
-  { procstreambase::open (name, mode); }
-
-  void open (const char *name, int mode = std::ios::in)
-  { procstreambase::open (name, mode); }
-
-private:
-
-  iprocstream (const iprocstream&);
-
-  iprocstream& operator = (const iprocstream&);
 };
 
 class
 OCTINTERP_API
-oprocstream : public std::ostream, public procstreambase
-// oprocstream : public procstreambase, public std::ostream
+oprocstream : public octave::sys::oprocstream
 {
 public:
 
-  oprocstream (void) : std::ostream (nullptr), procstreambase () { }
+  oprocstream (void) : octave::sys::oprocstream () { }
 
   oprocstream (const std::string& name, int mode = std::ios::out)
-    : std::ostream (nullptr), procstreambase (name, mode) { }
+    : octave::sys::oprocstream (name, mode) { }
 
   oprocstream (const char *name, int mode = std::ios::out)
-    : std::ostream (nullptr), procstreambase (name, mode) { }
+    : octave::sys::oprocstream (name, mode) { }
 
   ~oprocstream (void) = default;
-
-  void open (const std::string& name, int mode = std::ios::out)
-  { procstreambase::open (name, mode); }
-
-  void open (const char *name, int mode = std::ios::out)
-  { procstreambase::open (name, mode); }
-
-private:
-
-  oprocstream (const oprocstream&);
-
-  oprocstream& operator = (const oprocstream&);
 };
 
 class
 OCTINTERP_API
-procstream : public std::iostream, public procstreambase
-// procstream : public procstreambase, public std::iostream
+procstream : public octave::sys::procstream
 {
 public:
 
-  procstream (void) : std::iostream (nullptr), procstreambase () { }
+  procstream (void) : octave::sys::procstream () { }
 
   procstream (const std::string& name, int mode)
-    : std::iostream (nullptr), procstreambase (name, mode) { }
+    : octave::sys::procstream (name, mode) { }
 
   procstream (const char *name, int mode)
-    : std::iostream (nullptr), procstreambase (name, mode) { }
+    : octave::sys::procstream (name, mode) { }
 
   ~procstream (void) = default;
-
-  void open (const std::string& name, int mode)
-  { procstreambase::open (name, mode); }
-
-  void open (const char *name, int mode)
-  { procstreambase::open (name, mode); }
-
-private:
-
-  procstream (const procstream&);
-
-  procstream& operator = (const procstream&);
 };
 
 #endif
diff --git a/libinterp/corefcn/sysdep.cc b/libinterp/corefcn/sysdep.cc
--- a/libinterp/corefcn/sysdep.cc
+++ b/libinterp/corefcn/sysdep.cc
@@ -56,16 +56,17 @@ along with Octave; see the file COPYING.
 
 #if defined (HAVE_OMP_H)
 #  include <omp.h>
 #endif
 
 #include "cmd-edit.h"
 #include "file-ops.h"
 #include "lo-mappers.h"
+#include "lo-sysdep.h"
 #include "lo-sysinfo.h"
 #include "mach-info.h"
 #include "oct-env.h"
 #include "unistd-wrappers.h"
 #include "unsetenv-wrapper.h"
 
 #include "builtin-defun-decls.h"
 #include "Cell.h"
@@ -500,39 +501,23 @@ raw_mode (bool on, bool wait)
 #endif
 
   curr_on = on;
 }
 
 FILE *
 octave_popen (const char *command, const char *mode)
 {
-#if defined (__MINGW32__) || defined (_MSC_VER)
-  if (mode && mode[0] && ! mode[1])
-    {
-      // Use binary mode on Windows if unspecified
-      char tmode[3] = {mode[0], 'b', '\0'};
-
-      return _popen (command, tmode);
-    }
-  else
-    return _popen (command, mode);
-#else
-  return popen (command, mode);
-#endif
+  return octave::sys::popen(command, mode);
 }
 
 int
 octave_pclose (FILE *f)
 {
-#if defined (__MINGW32__) || defined (_MSC_VER)
-  return _pclose (f);
-#else
-  return pclose (f);
-#endif
+  return octave::sys::pclose(f);
 }
 
 // Read one character from the terminal.
 
 int
 octave_kbhit (bool wait)
 {
 #if defined (HAVE__KBHIT) && defined (HAVE__GETCH)
diff --git a/libinterp/octave-value/ov-java.cc b/libinterp/octave-value/ov-java.cc
--- a/libinterp/octave-value/ov-java.cc
+++ b/libinterp/octave-value/ov-java.cc
@@ -29,19 +29,19 @@ along with Octave; see the file COPYING.
 #  include "config.h"
 #endif
 
 #if defined (HAVE_WINDOWS_H)
 #  include <windows.h>
 #endif
 
 #include <algorithm>
-#include <map>
+#include <fstream>
 #include <iostream>
-#include <fstream>
+#include <map>
 #include <string>
 #include <vector>
 
 #include <clocale>
 
 #include "Cell.h"
 #include "builtin-defun-decls.h"
 #include "cmd-edit.h"
@@ -53,16 +53,17 @@ along with Octave; see the file COPYING.
 #include "file-stat.h"
 #include "fpucw-wrappers.h"
 #include "load-path.h"
 #include "oct-env.h"
 #include "oct-shlib.h"
 #include "ov-java.h"
 #include "parse.h"
 #include "variables.h"
+#include "proc-ops.h"
 
 #if defined (HAVE_JAVA)
 #include <jni.h>
 #endif
 
 #if defined (HAVE_JAVA)
 
 #define TO_JOBJECT(obj) reinterpret_cast<jobject> (obj)
@@ -520,37 +521,45 @@ get_regkey_value (HKEY h_rootkey, const 
 //! classpath can be added and removed using the m-file scripts
 //! @c javaaddpath.m and @c javarmpath.m.
 //!
 //! @see #terminate_jvm()
 
 static void
 initialize_jvm (void)
 {
+
   // Most of the time JVM already exists and has been initialized.
   // Also it seems, as if jvm is set, the jvm is already attached.
   // This does not fit terminate_jvm.
   if (jvm)
     return;
 
   JNIEnv *current_env;
   const char *static_locale = setlocale (LC_ALL, nullptr);
   const std::string locale (static_locale);
 
   octave::dynamic_library lib ("");
-  std::string jvm_lib_path = "linked in or loaded libraries";
+  std::string jvm_lib_path = "";
 
   // Check whether the Java VM library is already loaded or linked in.
   JNI_CreateJavaVM_t create_vm = reinterpret_cast<JNI_CreateJavaVM_t>
                                  (lib.search ("JNI_CreateJavaVM"));
   JNI_GetCreatedJavaVMs_t get_vm = reinterpret_cast<JNI_GetCreatedJavaVMs_t>
                                    (lib.search ("JNI_GetCreatedJavaVMs"));
 
-  if (! create_vm || ! get_vm)
+  if ( create_vm && get_vm )
+    jvm_lib_path = "linked in or loaded libraries";
+  else 
     {
+#  if defined (__APPLE__)
+      std::string dylib_extension = std::string ("dylib");
+#  else
+      std::string dylib_extension = std::string ("so");
+#  endif
 #if defined (OCTAVE_USE_WINDOWS_API)
       // In Windows, find the location of the JRE from the registry
       // and load the symbol from the dll.
       std::string key, jversion, value;
 
       // First search for JRE >= 9
       key = R"(software\javasoft\jre)";
 
@@ -596,22 +605,50 @@ initialize_jvm (void)
       jvm_lib_path = regval.xstring_value (
             "initialize_jvm: registry value \"%s\" at \"%s\" must be a string",
             value.c_str (), key.c_str ());
 
       if (jvm_lib_path.empty ())
         error ("unable to find Java Runtime Environment: %s::%s",
                key.c_str (), value.c_str ());
 #else
-      // JAVA_LDPATH determined by configure and set in config.h
+      // Respect JAVA_HOME environment variable
+      std::string java_home_env = octave::sys::env::getenv ("JAVA_HOME");
+      if (!java_home_env.empty ())
+        {
+          std::string libjvm_file = java_home_env + std::string ("/jre/lib/server/libjvm.") + dylib_extension;
+          octave::sys::file_stat libjvm_exists (libjvm_file);
+          if (libjvm_exists)
+            jvm_lib_path = libjvm_file;
+        }
+
 #  if defined (__APPLE__)
-      jvm_lib_path = JAVA_LDPATH + std::string ("/libjvm.dylib");
-#  else
-      jvm_lib_path = JAVA_LDPATH + std::string ("/libjvm.so");
+      // Use standard /usr/libexec/java_home if available
+      if (jvm_lib_path.empty ())
+        {
+          octave::sys::file_stat libexec_java_home_exists ("/usr/libexec/java_home");
+          if (libexec_java_home_exists)
+            {
+              octave::sys::process_execution_result rslt = octave::sys::run_command_and_return_output (
+                  "/usr/libexec/java_home --failfast --version 1.6+ 2>/dev/null");
+              if (rslt.exit_status () == 0)
+                {
+                  std::string output = rslt.stdout_output ();
+                  std::string found_path = output.substr (0, output.length() - 1);
+                  jvm_lib_path = found_path + "/jre/lib/server/libjvm.dylib";
+                }
+            }
+        }
 #  endif
+
+      // Fall back to JAVA_LDPATH determined by configure and set in config.h
+      if (jvm_lib_path.empty ())
+        {
+          jvm_lib_path = std::string (JAVA_LDPATH) + "/libjvm." + dylib_extension;
+        }
 #endif
       lib = octave::dynamic_library (jvm_lib_path);
 
       if (! lib)
         error ("unable to load Java Runtime Environment from %s",
                jvm_lib_path.c_str ());
 
       create_vm = reinterpret_cast<JNI_CreateJavaVM_t>
@@ -1426,17 +1463,17 @@ box (JNIEnv *jni_env, void *jobj_arg, vo
             }
         }
 
       cls = find_octave_class (jni_env, "org/octave/OctaveReference");
       if (jni_env->IsInstanceOf (jobj, cls))
         {
           jmethodID mID = jni_env->GetMethodID (cls, "getID", "()I");
           int ID = jni_env->CallIntMethod (jobj, mID);
-          std::map<int,octave_value>::iterator it = octave_ref_map.find (ID);
+          auto it = octave_ref_map.find (ID);
 
           if (it != octave_ref_map.end ())
             retval = it->second;
           break;
         }
 
       // No suitable class found.  Return a generic octave_java object.
       retval = octave_value (new octave_java (jobj, jcls));
@@ -1916,17 +1953,17 @@ Java_org_octave_OctaveReference_doFinali
 {
   octave_ref_map.erase (ID);
 }
 
 JNIEXPORT void JNICALL
 Java_org_octave_Octave_doInvoke (JNIEnv *env, jclass, jint ID,
                                  jobjectArray args)
 {
-  std::map<int,octave_value>::iterator it = octave_ref_map.find (ID);
+  auto it = octave_ref_map.find (ID);
 
   if (it != octave_ref_map.end ())
     {
       octave_value val = it->second;
       int len = env->GetArrayLength (args);
       octave_value_list oct_args;
 
       for (int i = 0; i < len; i++)
@@ -2062,17 +2099,17 @@ octave_java::subsref (const std::string&
     {
     case '.':
       if (type.length () > 1 && type[1] == '(')
         {
           octave_value_list ovl;
           count++;
           ovl(1) = octave_value (this);
           ovl(0) = (idx.front ())(0);
-          std::list<octave_value_list>::const_iterator it = idx.begin ();
+          auto it = idx.begin ();
           ovl.append (*++it);
           retval = FjavaMethod (ovl, 1);
           skip++;
         }
       else
         {
           octave_value_list ovl;
           count++;
@@ -2137,17 +2174,17 @@ octave_java::subsasgn (const std::string
           F__java_set__ (ovl);
 
           count++;
           retval = octave_value (this);
         }
       else if (type.length () > 2 && type[1] == '(')
         {
           std::list<octave_value_list> new_idx;
-          std::list<octave_value_list>::const_iterator it = idx.begin ();
+          auto it = idx.begin ();
           new_idx.push_back (*it++);
           new_idx.push_back (*it++);
           octave_value_list u = subsref (type.substr (0, 2), new_idx, 1);
 
           std::list<octave_value_list> next_idx (idx);
           next_idx.erase (next_idx.begin ());
           next_idx.erase (next_idx.begin ());
           u(0).subsasgn (type.substr (2), next_idx, rhs);
diff --git a/liboctave/system/c-file-ptr-stream.cc b/liboctave/system/c-file-ptr-stream.cc
new file mode 100644
--- /dev/null
+++ b/liboctave/system/c-file-ptr-stream.cc
@@ -0,0 +1,316 @@
+/*
+
+Copyright (C) 2000-2018 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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <iostream>
+
+#include "filepos-wrappers.h"
+
+#include "c-file-ptr-stream.h"
+
+#if ! defined (SEEK_SET)
+#  define SEEK_SET 0
+#endif
+
+#if ! defined (SEEK_CUR)
+#  define SEEK_CUR 1
+#endif
+
+#if ! defined (SEEK_END)
+#  define SEEK_END 2
+#endif
+
+c_file_ptr_buf::~c_file_ptr_buf (void)
+{
+  buf_close ();
+}
+
+// FIXME: I'm sure there is room for improvement here...
+
+c_file_ptr_buf::int_type
+c_file_ptr_buf::overflow (int_type c)
+{
+  if (f)
+    return (c != traits_type::eof ()) ? std::fputc (c, f) : flush ();
+  else
+    return traits_type::not_eof (c);
+}
+
+c_file_ptr_buf::int_type
+c_file_ptr_buf::underflow_common (bool bump)
+{
+  if (f)
+    {
+      int_type c = std::fgetc (f);
+
+      if (! bump && c != traits_type::eof ())
+        ungetc (c, f);
+
+      return c;
+    }
+  else
+    return traits_type::eof ();
+}
+
+c_file_ptr_buf::int_type
+c_file_ptr_buf::pbackfail (int_type c)
+{
+  return ((c != traits_type::eof () && f)
+          ? ungetc (c, f) : traits_type::not_eof (c));
+}
+
+std::streamsize
+c_file_ptr_buf::xsputn (const char *s, std::streamsize n)
+{
+  if (f)
+    return std::fwrite (s, 1, n, f);
+  else
+    return 0;
+}
+
+std::streamsize
+c_file_ptr_buf::xsgetn (char *s, std::streamsize n)
+{
+  if (f)
+    return std::fread (s, 1, n, f);
+  else
+    return 0;
+}
+
+static inline int
+seekdir_to_whence (std::ios::seekdir dir)
+{
+  return (dir == std::ios::beg
+          ? SEEK_SET : (dir == std::ios::cur
+                        ? SEEK_CUR : (dir == std::ios::end
+                                      ? SEEK_END : dir)));
+}
+
+std::streampos
+c_file_ptr_buf::seekoff (std::streamoff offset,
+                         std::ios::seekdir dir,
+                         std::ios::openmode)
+{
+  if (f)
+    {
+      octave_fseeko_wrapper (f, offset, seekdir_to_whence (dir));
+
+      return octave_ftello_wrapper (f);
+    }
+  else
+    return 0;
+}
+
+std::streampos
+c_file_ptr_buf::seekpos (std::streampos offset, std::ios::openmode)
+{
+  if (f)
+    {
+      octave_fseeko_wrapper (f, offset, SEEK_SET);
+
+      return octave_ftello_wrapper (f);
+    }
+  else
+    return 0;
+}
+
+int
+c_file_ptr_buf::sync (void)
+{
+  flush ();
+
+  return 0;
+}
+
+int
+c_file_ptr_buf::flush (void)
+{
+  return f ? std::fflush (f) : traits_type::eof ();
+}
+
+int
+c_file_ptr_buf::buf_close (void)
+{
+  int retval = -1;
+
+  flush ();
+
+  if (f)
+    {
+      retval = cf (f);
+      f = nullptr;
+    }
+
+  return retval;
+}
+
+int
+c_file_ptr_buf::seek (off_t offset, int origin)
+{
+  return f ? octave_fseeko_wrapper (f, offset, origin) : -1;
+}
+
+off_t
+c_file_ptr_buf::tell (void)
+{
+  return f ? octave_ftello_wrapper (f) : -1;
+}
+
+int
+c_file_ptr_buf::file_close (FILE *f)
+{
+  return std::fclose (f);
+}
+
+#if defined (HAVE_ZLIB)
+
+c_zfile_ptr_buf::~c_zfile_ptr_buf (void)
+{
+  buf_close ();
+}
+
+// FIXME: I'm sure there is room for improvement here...
+
+c_zfile_ptr_buf::int_type
+c_zfile_ptr_buf::overflow (int_type c)
+{
+  if (f)
+    return (c != traits_type::eof ()) ? gzputc (f, c) : flush ();
+  else
+    return traits_type::not_eof (c);
+}
+
+c_zfile_ptr_buf::int_type
+c_zfile_ptr_buf::underflow_common (bool bump)
+{
+  if (f)
+    {
+      int_type c = gzgetc (f);
+
+      if (! bump && c != traits_type::eof ())
+        gzungetc (c, f);
+
+      return c;
+    }
+  else
+    return traits_type::eof ();
+}
+
+c_zfile_ptr_buf::int_type
+c_zfile_ptr_buf::pbackfail (int_type c)
+{
+  return ((c != traits_type::eof () && f)
+          ? gzungetc (c, f) : traits_type::not_eof (c));
+}
+
+std::streamsize
+c_zfile_ptr_buf::xsputn (const char *s, std::streamsize n)
+{
+  if (f)
+    return gzwrite (f, s, n);
+  else
+    return 0;
+}
+
+std::streamsize
+c_zfile_ptr_buf::xsgetn (char *s, std::streamsize n)
+{
+  if (f)
+    return gzread (f, s, n);
+  else
+    return 0;
+}
+
+std::streampos
+c_zfile_ptr_buf::seekoff (std::streamoff /* offset */,
+                          std::ios::seekdir /* dir */,
+                          std::ios::openmode)
+{
+  // FIXME
+#if 0
+  if (f)
+    {
+      gzseek (f, offset, seekdir_to_whence (dir));
+
+      return gztell (f);
+    }
+  else
+    return 0;
+#endif
+  return -1;
+}
+
+std::streampos
+c_zfile_ptr_buf::seekpos (std::streampos /* offset */, std::ios::openmode)
+{
+  // FIXME
+#if 0
+  if (f)
+    {
+      gzseek (f, offset, SEEK_SET);
+
+      return gztell (f);
+    }
+  else
+    return 0;
+#endif
+  return -1;
+}
+
+int
+c_zfile_ptr_buf::sync (void)
+{
+  flush ();
+
+  return 0;
+}
+
+int
+c_zfile_ptr_buf::flush (void)
+{
+  // FIXME: do we need something more complex here, passing
+  // something other than 0 for the second argument to gzflush and
+  // checking the return value, etc.?
+
+  return f ? gzflush (f, 0) : traits_type::eof ();
+}
+
+int
+c_zfile_ptr_buf::buf_close (void)
+{
+  int retval = -1;
+
+  flush ();
+
+  if (f)
+    {
+      retval = cf (f);
+      f = nullptr;
+    }
+
+  return retval;
+}
+
+#endif
diff --git a/liboctave/system/c-file-ptr-stream.h b/liboctave/system/c-file-ptr-stream.h
new file mode 100644
--- /dev/null
+++ b/liboctave/system/c-file-ptr-stream.h
@@ -0,0 +1,227 @@
+/*
+
+Copyright (C) 2000-2018 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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_c_file_ptr_stream_h)
+#define octave_c_file_ptr_stream_h 1
+
+#include "octave-config.h"
+
+#include <cstdio>
+
+#include <iostream>
+#include <streambuf>
+
+class
+c_file_ptr_buf : public std::streambuf
+{
+public:
+
+  typedef std::streambuf::int_type int_type;
+
+  typedef int (*close_fcn) (FILE *);
+
+  FILE *stdiofile (void) { return f; }
+
+  c_file_ptr_buf (FILE *f_arg, close_fcn cf_arg = file_close)
+    : std::streambuf (), f (f_arg), cf (cf_arg)
+  { }
+
+  // No copying!
+
+  c_file_ptr_buf (const c_file_ptr_buf&) = delete;
+
+  c_file_ptr_buf& operator = (const c_file_ptr_buf&) = delete;
+
+  ~c_file_ptr_buf (void);
+
+  int_type overflow (int_type);
+
+  int_type underflow (void) { return underflow_common (false); }
+
+  int_type uflow (void) { return underflow_common (true); }
+
+  int_type pbackfail (int_type);
+
+  std::streamsize xsputn (const char*, std::streamsize);
+
+  std::streamsize xsgetn (char *, std::streamsize);
+
+  std::streampos seekoff (std::streamoff, std::ios::seekdir,
+                          std::ios::openmode = std::ios::in | std::ios::out);
+
+  std::streampos seekpos (std::streampos,
+                          std::ios::openmode = std::ios::in | std::ios::out);
+
+  int sync (void);
+
+  int flush (void);
+
+  int buf_close (void);
+
+  int file_number () const { return f ? fileno (f) : -1; }
+
+  int seek (off_t offset, int origin);
+
+  off_t tell (void);
+
+  void clear (void) { if (f) clearerr (f); }
+
+  static int file_close (FILE *f);
+
+protected:
+
+  FILE *f;
+
+  close_fcn cf;
+
+private:
+
+  int_type underflow_common (bool);
+};
+
+// FIXME: the following three classes could probably share some code...
+
+template <typename STREAM_T, typename FILE_T, typename BUF_T>
+class
+c_file_ptr_stream : public STREAM_T
+{
+public:
+
+  c_file_ptr_stream (FILE_T f, typename BUF_T::close_fcn cf = BUF_T::file_close)
+    : STREAM_T (nullptr), buf (new BUF_T (f, cf)) { STREAM_T::init (buf); }
+
+  // No copying!
+
+  c_file_ptr_stream (const c_file_ptr_stream&) = delete;
+
+  c_file_ptr_stream& operator = (const c_file_ptr_stream&) = delete;
+
+  ~c_file_ptr_stream (void) { delete buf; buf = nullptr; }
+
+  BUF_T * rdbuf (void) { return buf; }
+
+  void stream_close (void) { if (buf) buf->buf_close (); }
+
+  int seek (off_t offset, int origin)
+  { return buf ? buf->seek (offset, origin) : -1; }
+
+  off_t tell (void) { return buf ? buf->tell () : -1; }
+
+  void clear (void) { if (buf) buf->clear (); STREAM_T::clear (); }
+
+private:
+
+  BUF_T *buf;
+};
+
+typedef c_file_ptr_stream<std::istream, FILE *, c_file_ptr_buf>
+  i_c_file_ptr_stream;
+typedef c_file_ptr_stream<std::ostream, FILE *, c_file_ptr_buf>
+  o_c_file_ptr_stream;
+typedef c_file_ptr_stream<std::iostream, FILE *, c_file_ptr_buf>
+  io_c_file_ptr_stream;
+
+#if defined (HAVE_ZLIB)
+
+#if defined (HAVE_ZLIB_H)
+#  include <zlib.h>
+#endif
+
+class
+c_zfile_ptr_buf : public std::streambuf
+{
+public:
+
+  typedef std::streambuf::int_type int_type;
+
+  typedef int (*close_fcn) (gzFile);
+
+  gzFile stdiofile (void) { return f; }
+
+  c_zfile_ptr_buf (gzFile f_arg, close_fcn cf_arg = file_close)
+    : std::streambuf (), f (f_arg), cf (cf_arg)
+  { }
+
+  // No copying!
+
+  c_zfile_ptr_buf (const c_zfile_ptr_buf&) = delete;
+
+  c_zfile_ptr_buf& operator = (const c_zfile_ptr_buf&) = delete;
+
+  ~c_zfile_ptr_buf (void);
+
+  int_type overflow (int_type);
+
+  int_type underflow (void) { return underflow_common (false); }
+
+  int_type uflow (void) { return underflow_common (true); }
+
+  int_type pbackfail (int_type);
+
+  std::streamsize xsputn (const char*, std::streamsize);
+
+  std::streamsize xsgetn (char *, std::streamsize);
+
+  std::streampos seekoff (std::streamoff, std::ios::seekdir,
+                          std::ios::openmode = std::ios::in | std::ios::out);
+
+  std::streampos seekpos (std::streampos,
+                          std::ios::openmode = std::ios::in | std::ios::out);
+
+  int sync (void);
+
+  int flush (void);
+
+  int buf_close (void);
+
+  int file_number () const { return -1; }
+
+  int seek (off_t offset, int origin)
+  { return f ? gzseek (f, offset, origin) >= 0 : -1; }
+
+  off_t tell (void) { return f ? gztell (f) : -1; }
+
+  void clear (void) { if (f) gzclearerr (f); }
+
+  static int file_close (gzFile f) { return ::gzclose (f); }
+
+protected:
+
+  gzFile f;
+
+  close_fcn cf;
+
+private:
+
+  int_type underflow_common (bool);
+};
+
+typedef c_file_ptr_stream<std::istream, gzFile, c_zfile_ptr_buf>
+  i_c_zfile_ptr_stream;
+typedef c_file_ptr_stream<std::ostream, gzFile, c_zfile_ptr_buf>
+  o_c_zfile_ptr_stream;
+typedef c_file_ptr_stream<std::iostream, gzFile, c_zfile_ptr_buf>
+  io_c_zfile_ptr_stream;
+
+#endif
+
+#endif
diff --git a/liboctave/system/lo-procstream.cc b/liboctave/system/lo-procstream.cc
new file mode 100644
--- /dev/null
+++ b/liboctave/system/lo-procstream.cc
@@ -0,0 +1,78 @@
+/*
+
+Copyright (C) 1993-2018 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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <iostream>
+
+#include "lo-procstream.h"
+
+namespace octave
+{
+  namespace sys
+  {
+
+    procstreambase::procstreambase (const std::string& command, int mode)
+    {
+      pb_init ();
+
+      if (! pb.open (command.c_str (), mode))
+        std::ios::setstate (std::ios::badbit);
+    }
+
+    procstreambase::procstreambase (const char *command, int mode)
+    {
+      pb_init ();
+
+      if (! pb.open (command, mode))
+        std::ios::setstate (std::ios::badbit);
+    }
+
+    void
+    procstreambase::open (const char *command, int mode)
+    {
+      clear ();
+
+      if (! pb.open (command, mode))
+        std::ios::setstate (std::ios::badbit);
+    }
+
+    int
+    procstreambase::close (void)
+    {
+      int status = 0;
+
+      if (is_open ())
+        {
+          if (! pb.close ())
+            std::ios::setstate (std::ios::failbit);
+
+          status = pb.wait_status ();
+        }
+
+      return status;
+    }
+
+  }
+}
diff --git a/liboctave/system/lo-procstream.h b/liboctave/system/lo-procstream.h
new file mode 100644
--- /dev/null
+++ b/liboctave/system/lo-procstream.h
@@ -0,0 +1,168 @@
+/*
+
+Copyright (C) 1993-2018 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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_lo_procstream_h)
+#define octave_lo_procstream_h 1
+
+#include "octave-config.h"
+
+#include <istream>
+#include <ostream>
+#include <string>
+
+#include <sys/types.h>
+
+#include "oct-procbuf.h"
+
+namespace octave
+{
+  namespace sys
+  {
+
+    class
+    procstreambase : virtual public std::ios
+    {
+    public:
+
+      procstreambase (void) : pb () { pb_init (); }
+
+      procstreambase (const std::string& name, int mode);
+
+      procstreambase (const char *name, int mode);
+
+      ~procstreambase (void) { close (); }
+
+      void open (const std::string& name, int mode)
+      { open (name.c_str (), mode); }
+
+      void open (const char *name, int mode);
+
+      int is_open (void) const { return pb.is_open (); }
+
+      int close (void);
+
+      pid_t pid (void) const { return pb.pid (); }
+
+      int file_number (void) const { return pb.file_number (); }
+
+    private:
+
+      octave_procbuf pb;
+
+      void pb_init (void) { init (&pb); }
+
+      procstreambase (const procstreambase&);
+
+      procstreambase& operator = (const procstreambase&);
+    };
+
+    class
+    iprocstream : public std::istream, public procstreambase
+    // iprocstream : public procstreambase, public std::istream
+    {
+    public:
+
+      iprocstream (void) : std::istream (nullptr), procstreambase () { }
+
+      iprocstream (const std::string& name, int mode = std::ios::in)
+        : std::istream (nullptr), procstreambase (name, mode) { }
+
+      iprocstream (const char *name, int mode = std::ios::in)
+        : std::istream (nullptr), procstreambase (name, mode) { }
+
+      ~iprocstream (void) = default;
+
+      void open (const std::string& name, int mode = std::ios::in)
+      { procstreambase::open (name, mode); }
+
+      void open (const char *name, int mode = std::ios::in)
+      { procstreambase::open (name, mode); }
+
+    private:
+
+      iprocstream (const iprocstream&);
+
+      iprocstream& operator = (const iprocstream&);
+    };
+
+    class
+    oprocstream : public std::ostream, public procstreambase
+    // oprocstream : public procstreambase, public std::ostream
+    {
+    public:
+
+      oprocstream (void) : std::ostream (nullptr), procstreambase () { }
+
+      oprocstream (const std::string& name, int mode = std::ios::out)
+          : std::ostream (nullptr), procstreambase (name, mode) { }
+
+      oprocstream (const char *name, int mode = std::ios::out)
+          : std::ostream (nullptr), procstreambase (name, mode) { }
+
+      ~oprocstream (void) = default;
+
+      void open (const std::string& name, int mode = std::ios::out)
+      { procstreambase::open (name, mode); }
+
+      void open (const char *name, int mode = std::ios::out)
+      { procstreambase::open (name, mode); }
+
+    private:
+
+      oprocstream (const oprocstream&);
+
+      oprocstream& operator = (const oprocstream&);
+    };
+
+    class
+    procstream : public std::iostream, public procstreambase
+    // procstream : public procstreambase, public std::iostream
+    {
+    public:
+
+      procstream (void) : std::iostream (nullptr), procstreambase () { }
+
+      procstream (const std::string& name, int mode)
+          : std::iostream (nullptr), procstreambase (name, mode) { }
+
+      procstream (const char *name, int mode)
+          : std::iostream (nullptr), procstreambase (name, mode) { }
+
+      ~procstream (void) = default;
+
+      void open (const std::string& name, int mode)
+      { procstreambase::open (name, mode); }
+
+      void open (const char *name, int mode)
+      { procstreambase::open (name, mode); }
+
+    private:
+
+      procstream (const procstream&);
+
+      procstream& operator = (const procstream&);
+    };
+
+  }
+}
+
+#endif
diff --git a/liboctave/system/lo-sysdep.cc b/liboctave/system/lo-sysdep.cc
--- a/liboctave/system/lo-sysdep.cc
+++ b/liboctave/system/lo-sysdep.cc
@@ -62,10 +62,38 @@ namespace octave
 
 #if defined (OCTAVE_USE_WINDOWS_API)
       if (path.length () == 2 && path[1] == ':')
         path += '\\';
 #endif
 
       return octave_chdir_wrapper (path.c_str ());
     }
+
+    FILE *
+    popen (const char *command, const char *mode)
+    {
+    #if defined (__MINGW32__) || defined (_MSC_VER)
+      if (mode && mode[0] && ! mode[1])
+        {
+          // Use binary mode on Windows if unspecified
+          char tmode[3] = {mode[0], 'b', '\0'};
+
+          return _popen (command, tmode);
+        }
+      else
+        return _popen (command, mode);
+    #else
+      return ::popen (command, mode);
+    #endif
+    }
+
+    int
+    pclose (FILE *f)
+    {
+    #if defined (__MINGW32__) || defined (_MSC_VER)
+      return _pclose (f);
+    #else
+      return ::pclose (f);
+    #endif
+    }
   }
 }
diff --git a/liboctave/system/lo-sysdep.h b/liboctave/system/lo-sysdep.h
--- a/liboctave/system/lo-sysdep.h
+++ b/liboctave/system/lo-sysdep.h
@@ -35,16 +35,21 @@ class string_vector;
 
 namespace octave
 {
   namespace sys
   {
     extern std::string getcwd (void);
 
     extern int chdir (const std::string&);
+
+    extern FILE * popen (const char *command,
+                                          const char *mode);
+
+    extern int pclose (FILE *f);
   }
 }
 
 #if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
 
 OCTAVE_DEPRECATED (4.2, "use 'octave::sys::getcwd' instead")
 const auto octave_getcwd = octave::sys::getcwd;
 
diff --git a/liboctave/system/module.mk b/liboctave/system/module.mk
--- a/liboctave/system/module.mk
+++ b/liboctave/system/module.mk
@@ -1,45 +1,55 @@
 SYSTEM_INC = \
+  %reldir%/c-file-ptr-stream.h \
   %reldir%/child-list.h \
   %reldir%/dir-ops.h \
   %reldir%/file-ops.h \
   %reldir%/file-stat.h \
+  %reldir%/lo-procstream.h \
   %reldir%/lo-sysdep.h \
   %reldir%/lo-sysinfo.h \
   %reldir%/mach-info.h \
   %reldir%/oct-env.h \
   %reldir%/oct-group.h \
   %reldir%/oct-passwd.h \
+  %reldir%/oct-procbuf.h \
   %reldir%/oct-syscalls.h \
   %reldir%/oct-time.h \
-  %reldir%/oct-uname.h
+  %reldir%/oct-uname.h \
+  %reldir%/proc-ops.h
 
 SYSTEM_SRC = \
+  %reldir%/c-file-ptr-stream.cc \
   %reldir%/child-list.cc \
   %reldir%/cmach-info.c \
   %reldir%/dir-ops.cc \
   %reldir%/file-ops.cc \
   %reldir%/file-stat.cc \
+  %reldir%/lo-procstream.cc \
   %reldir%/lo-sysdep.cc \
   %reldir%/lo-sysinfo.cc \
   %reldir%/mach-info.cc \
   %reldir%/oct-env.cc \
   %reldir%/oct-group.cc \
   %reldir%/oct-passwd.cc \
+  %reldir%/oct-procbuf.cc \
   %reldir%/oct-syscalls.cc \
   %reldir%/oct-time.cc \
-  %reldir%/oct-uname.cc
+  %reldir%/oct-uname.cc \
+  %reldir%/proc-ops.cc
 
 noinst_HEADERS += \
   %reldir%/cmach-info.h
 
 noinst_LTLIBRARIES += %reldir%/libsystem.la
 
 %canon_reldir%_libsystem_la_SOURCES = $(SYSTEM_SRC)
 
-%canon_reldir%_libsystem_la_CPPFLAGS = $(liboctave_liboctave_la_CPPFLAGS)
+%canon_reldir%_libsystem_la_CPPFLAGS = \
+  $(liboctave_liboctave_la_CPPFLAGS) \
+  $(Z_CPPFLAGS)
 
 %canon_reldir%_libsystem_la_CFLAGS = $(liboctave_liboctave_la_CFLAGS)
 
 %canon_reldir%_libsystem_la_CXXFLAGS = $(liboctave_liboctave_la_CXXFLAGS)
 
 liboctave_liboctave_la_LIBADD += %reldir%/libsystem.la
diff --git a/liboctave/system/oct-procbuf.cc b/liboctave/system/oct-procbuf.cc
new file mode 100644
--- /dev/null
+++ b/liboctave/system/oct-procbuf.cc
@@ -0,0 +1,232 @@
+/*
+
+Copyright (C) 1996-2018 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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <cerrno>
+
+#include <iostream>
+
+// FIXME: we would prefer to avoid including these directly in Octave
+// sources, but eliminating them is complicated by the mingling of
+// octave_procbuf_list and the calls to system library functions like
+// execl.
+
+#if defined (HAVE_UNISTD_H)
+#  if defined (HAVE_SYS_TYPES_H)
+#    include <sys/types.h>
+#  endif
+#  include <unistd.h>
+#endif
+
+#include "lo-mappers.h"
+#include "lo-utils.h"
+#include "oct-procbuf.h"
+#include "oct-syscalls.h"
+#include "lo-sysdep.h"
+#include "unistd-wrappers.h"
+
+#if ! defined (SHELL_PATH)
+#  define SHELL_PATH "/bin/sh"
+#endif
+
+// This class is based on the procbuf class from libg++, written by
+// Per Bothner, Copyright (C) 1993 Free Software Foundation.
+
+#if (! (defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)) \
+     && defined (HAVE_UNISTD_H))
+
+static octave_procbuf *octave_procbuf_list = nullptr;
+
+#endif
+
+#if ! defined (BUFSIZ)
+#  define BUFSIZ 1024
+#endif
+
+octave_procbuf *
+octave_procbuf::open (const char *command, int mode)
+{
+#if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)
+
+  if (is_open ())
+    return 0;
+
+  f = (octave::sys::popen (command, (mode & std::ios::in) ? "r" : "w"));
+
+  if (! f)
+    return 0;
+
+  // Oops... popen doesn't return the associated pid, so fake it for now
+
+  proc_pid = 1;
+
+  open_p = true;
+
+  if (mode & std::ios::out)
+    ::setvbuf (f, 0, _IOLBF, BUFSIZ);
+
+  return this;
+
+#elif defined (HAVE_UNISTD_H)
+
+  int pipe_fds[2];
+
+  volatile int child_std_end = (mode & std::ios::in) ? 1 : 0;
+
+  volatile int parent_end, child_end;
+
+  if (is_open ())
+    return nullptr;
+
+  if (octave::sys::pipe (pipe_fds) < 0)
+    return nullptr;
+
+  if (mode & std::ios::in)
+    {
+      parent_end = pipe_fds[0];
+      child_end = pipe_fds[1];
+    }
+  else
+    {
+      parent_end = pipe_fds[1];
+      child_end = pipe_fds[0];
+    }
+
+  proc_pid = ::fork ();
+
+  if (proc_pid == 0)
+    {
+      octave_close_wrapper (parent_end);
+
+      if (child_end != child_std_end)
+        {
+          octave_dup2_wrapper (child_end, child_std_end);
+          octave_close_wrapper (child_end);
+        }
+
+      while (octave_procbuf_list)
+        {
+          FILE *fp = octave_procbuf_list->f;
+
+          if (fp)
+            {
+              std::fclose (fp);
+              fp = nullptr;
+            }
+
+          octave_procbuf_list = octave_procbuf_list->next;
+        }
+
+      execl (SHELL_PATH, "sh", "-c", command, static_cast<void *> (nullptr));
+
+      exit (127);
+    }
+
+  octave_close_wrapper (child_end);
+
+  if (proc_pid < 0)
+    {
+      octave_close_wrapper (parent_end);
+      return nullptr;
+    }
+
+  f = (::fdopen (parent_end, (mode & std::ios::in) ? "r" : "w"));
+
+  if (mode & std::ios::out)
+    ::setvbuf (f, nullptr, _IOLBF, BUFSIZ);
+
+  open_p = true;
+
+  next = octave_procbuf_list;
+  octave_procbuf_list = this;
+
+  return this;
+
+#else
+
+  return 0;
+
+#endif
+}
+
+octave_procbuf *
+octave_procbuf::close (void)
+{
+#if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)
+
+  if (f)
+    {
+      wstatus = octave::sys::pclose (f);
+      f = 0;
+    }
+
+  open_p = false;
+
+  return this;
+
+#elif defined (HAVE_UNISTD_H)
+
+  if (f)
+    {
+      pid_t wait_pid;
+
+      int status = -1;
+
+      for (octave_procbuf **ptr = &octave_procbuf_list;
+           *ptr != nullptr;
+           ptr = &(*ptr)->next)
+        {
+          if (*ptr == this)
+            {
+              *ptr = (*ptr)->next;
+              status = 0;
+              break;
+            }
+        }
+
+      if (status == 0 && std::fclose (f) == 0)
+        {
+          using namespace std;
+
+          do
+            {
+              wait_pid = octave::sys::waitpid (proc_pid, &wstatus, 0);
+            }
+          while (wait_pid == -1 && errno == EINTR);
+        }
+
+      f = nullptr;
+    }
+
+  open_p = false;
+
+  return this;
+
+#else
+
+  return 0;
+
+#endif
+}
diff --git a/liboctave/system/oct-procbuf.h b/liboctave/system/oct-procbuf.h
new file mode 100644
--- /dev/null
+++ b/liboctave/system/oct-procbuf.h
@@ -0,0 +1,79 @@
+/*
+
+Copyright (C) 1996-2018 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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+// This class is based on the procbuf class from libg++, written by
+// Per Bothner, Copyright (C) 1993 Free Software Foundation.
+
+#if ! defined (octave_oct_procbuf_h)
+#define octave_oct_procbuf_h 1
+
+#include "octave-config.h"
+
+#include <sys/types.h>
+
+#include "c-file-ptr-stream.h"
+
+class
+octave_procbuf : public c_file_ptr_buf
+{
+public:
+
+  octave_procbuf (void)
+    : c_file_ptr_buf (nullptr), wstatus (-1), open_p (false), proc_pid (-1),
+      next (nullptr) { }
+
+  octave_procbuf (const char *command, int mode)
+    : c_file_ptr_buf (nullptr), wstatus (-1), open_p (false), proc_pid (-1),
+      next (nullptr) { open (command, mode); }
+
+  // No copying!
+
+  octave_procbuf (const octave_procbuf&) = delete;
+
+  octave_procbuf& operator = (const octave_procbuf&) = delete;
+
+  ~octave_procbuf (void) { close (); }
+
+  octave_procbuf * open (const char *command, int mode);
+
+  octave_procbuf * close (void);
+
+  int wait_status (void) const { return wstatus; }
+
+  bool is_open (void) const { return open_p; }
+
+  pid_t pid (void) const { return proc_pid; }
+
+protected:
+
+  int wstatus;
+
+  bool open_p;
+
+  pid_t proc_pid;
+
+  octave_procbuf *next;
+};
+
+extern void symbols_of_oct_procbuf (void);
+
+#endif
diff --git a/liboctave/system/proc-ops.cc b/liboctave/system/proc-ops.cc
new file mode 100644
--- /dev/null
+++ b/liboctave/system/proc-ops.cc
@@ -0,0 +1,87 @@
+/*
+
+Copyright (C) 1996-2018 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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#include <stdio.h>
+#include <iostream>
+#include <sstream>
+
+#include "oct-syscalls.h"
+#include "proc-ops.h"
+#include "lo-procstream.h"
+
+namespace octave
+{
+  namespace sys
+  {
+    process_execution_result
+    process_execution_result::of_success (int exit_status, std::string stdout_output)
+    {
+      return process_execution_result (0, exit_status, stdout_output, "");
+    }
+
+    process_execution_result
+    process_execution_result::of_error (int status, std::string err_msg)
+    {
+      return process_execution_result (status, -1, "", err_msg);      
+    }
+
+    process_execution_result
+    run_command_and_return_output (const std::string& cmd_str)
+    {
+      octave::sys::iprocstream cmd (cmd_str.c_str ());
+      if (! cmd)
+        return process_execution_result::of_error (-1, std::string ("unable to start subprocess for '")
+          + cmd_str + "'");
+
+      int fid = cmd.file_number ();
+
+      std::ostringstream output_buf;
+
+      char ch;
+
+      for (;;)
+        {
+          if (cmd.get (ch))
+            output_buf.put (ch);
+          else
+            {
+              if (! cmd.eof () && errno == EAGAIN)
+                {
+                  cmd.clear ();
+                }
+              else
+                break;
+            }
+        }
+
+      int cmd_status = cmd.close ();
+
+      if (octave::sys::wifexited (cmd_status))
+        cmd_status = octave::sys::wexitstatus (cmd_status);
+      else
+        cmd_status = 127;
+
+      return process_execution_result::of_success (cmd_status, output_buf.str ());
+    }
+
+  }
+}
\ No newline at end of file
diff --git a/liboctave/system/proc-ops.h b/liboctave/system/proc-ops.h
new file mode 100644
--- /dev/null
+++ b/liboctave/system/proc-ops.h
@@ -0,0 +1,84 @@
+/*
+
+Copyright (C) 1996-2018 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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_proc_ops_h)
+#define octave_proc_ops_h 1
+
+#include "octave-config.h"
+
+#include <string>
+#include <sys/types.h>
+
+namespace octave
+{
+  namespace sys
+  {
+  	class
+  	process_execution_result
+  	{
+    public:
+
+      process_execution_result ()
+        : m_status(-1), m_err_msg(""), m_exit_status(-1), m_stdout_output("") { }
+
+      process_execution_result (int status, int exit_status, std::string stdout_output, std::string err_msg)
+        : m_status(status), m_err_msg(err_msg), m_exit_status(exit_status), m_stdout_output(stdout_output)
+           { }
+
+      static
+      process_execution_result
+      of_success(int exit_status, std::string stdout_output);
+
+      static
+      process_execution_result
+      of_error(int status, std::string err_msg);
+
+      int status (void) const { return m_status; }
+
+      int exit_status (void) const { return m_exit_status; }
+
+      std::string err_msg (void) const { return m_err_msg; }
+
+      std::string stdout_output (void) const { return m_stdout_output; }
+
+    private:
+
+      // launch status of the process, 0 for success, nonzero for error
+      int m_status;
+
+      // error message if executing command failed
+      std::string m_err_msg;
+
+      // exit status of the process
+      int m_exit_status;
+
+      // collected stdout output of the process
+      std::string m_stdout_output;
+
+  	};
+
+    extern OCTAVE_API process_execution_result
+    run_command_and_return_output (const std::string& cmd_str);
+  }
+}
+
+#endif
\ No newline at end of file
