changeset 2095:36903d507b0e

[project @ 1996-04-28 09:00:07 by jwe]
author jwe
date Sun, 28 Apr 1996 09:00:07 +0000
parents a23645b0364e
children 91c0c3d18339
files src/dassl.cc src/dirfns.cc src/error.cc src/file-io.cc src/fsolve.cc src/help.cc src/input.cc src/load-save.cc src/lsode.cc src/npsol.cc src/oct-hist.cc src/octave.cc src/pager.h src/procstream.h src/pt-const.cc src/pt-fcn.cc src/pt-misc.cc src/pt-mvr.cc src/qpsol.cc src/quad.cc src/syswait.h src/toplev.cc src/variables.cc
diffstat 23 files changed, 780 insertions(+), 2464 deletions(-) [+]
line wrap: on
line diff
--- a/src/dassl.cc
+++ b/src/dassl.cc
@@ -26,7 +26,7 @@
 
 #include <string>
 
-#include <strstream.h>
+#include <iostream.h>
 
 #include "DASSL.h"
 
@@ -242,36 +242,33 @@
 };
 
 static void
-print_dassl_option_list (void)
+print_dassl_option_list (ostream& os)
 {
-  ostrstream output_buf;
-
   print_usage ("dassl_options", 1);
 
-  output_buf << "\n"
-	     << "Options for dassl include:\n\n"
-	     << "  keyword                                  value\n"
-	     << "  -------                                  -----\n\n";
+  os << "\n"
+     << "Options for dassl include:\n\n"
+     << "  keyword                                  value\n"
+     << "  -------                                  -----\n\n";
 
   DASSL_OPTIONS *list = dassl_option_table;
 
   const char *keyword;
   while ((keyword = list->keyword) != 0)
     {
-      output_buf.form ("  %-40s ", keyword);
+      os.form ("  %-40s ", keyword);
 
       double val = (dassl_opts.*list->d_get_fcn) ();
       if (val < 0.0)
-	output_buf << "computed automatically";
+	os << "computed automatically";
       else
-	output_buf << val;
+	os << val;
 
-      output_buf << "\n";
+      os << "\n";
       list++;
     }
 
-  output_buf << "\n" << ends;
-  maybe_page_output (output_buf);
+  os << "\n";
 }
 
 static void
@@ -328,7 +325,7 @@
 
   if (nargin == 0)
     {
-      print_dassl_option_list ();
+      print_dassl_option_list (octave_stdout);
       return retval;
     }
   else if (nargin == 1 || nargin == 2)
--- a/src/dirfns.cc
+++ b/src/dirfns.cc
@@ -390,12 +390,8 @@
   if (cmd && *cmd)
     {
       int ch;
-      ostrstream output_buf;
       while ((ch = cmd->get ()) != EOF)
-	output_buf << (char) ch;
-      output_buf << ends;
-
-      maybe_page_output (output_buf);
+	octave_stdout << (char) ch;
     }
   else
     error ("couldn't start process for ls!");
@@ -426,11 +422,7 @@
   if (! directory.empty ())
     {
       if (nargout == 0)
-	{
-	  ostrstream output_buf;
-	  output_buf << directory << "\n" << ends;
-	  maybe_page_output (output_buf);
-	}
+	octave_stdout << directory << "\n";
       else
 	retval = directory;
     }
--- a/src/error.cc
+++ b/src/error.cc
@@ -53,7 +53,7 @@
 static void
 verror (const char *name, const char *fmt, va_list args)
 {
-  flush_output_to_pager ();
+  flush_octave_stdout ();
 
   int to_beep_or_not_to_beep = user_pref.beep_on_error && ! error_state;
 
@@ -91,7 +91,7 @@
     }
   else
     {
-      maybe_write_to_diary_file (msg);
+      octave_diary << msg;
       cerr << msg;
     }
 
@@ -185,7 +185,7 @@
 void
 panic (const char *fmt, ...)
 {
-  flush_output_to_pager ();
+  flush_octave_stdout ();
 
   va_list args;
   va_start (args, fmt);
--- a/src/file-io.cc
+++ b/src/file-io.cc
@@ -20,282 +20,129 @@
 
 */
 
-// Written by John C. Campbell <jcc@bevo.che.wisc.edu>
+// Originally written by John C. Campbell <jcc@bevo.che.wisc.edu>
 //
-// Thomas Baier <baier@ci.tuwien.ac.at> added the following functions:
+// Thomas Baier <baier@ci.tuwien.ac.at> added the original versions of
+// the following functions:
 //
-//   popen    pclose    execute  sync_system  async_system
-//   waitpid  mkfifo   unlink
+//   popen
+//   pclose
+//   execute       (now popen2.m)
+//   sync_system   (now merged with system)
+//   async_system  (now merged with system)
 
+// Completely rewritten by John W. Eaton <jwe@bevo.che.wisc.edu>,
+// April 1996.
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
-#include <cstring>
-#include <cstdio>
-#include <cerrno>
-#include <cstdlib>
-#include <cctype>
+#include <climits>
 
-#include <string>
-
-#include <strstream.h>
+#include <iostream.h>
 
 #ifdef HAVE_UNISTD_H
 #include <sys/types.h>
 #include <unistd.h>
 #endif
 
-#include <fcntl.h>
-
-#include <DLList.h>
-#include <SLStack.h>
-
-#include "dMatrix.h"
-
 #include "defun.h"
 #include "error.h"
-#include "file-info.h"
-#include "file-io.h"
 #include "file-ops.h"
 #include "help.h"
-#include "input.h"
-#include "mappers.h"
+#include "oct-fstrm.h"
+#include "oct-iostrm.h"
 #include "oct-map.h"
-#include "oct-hist.h"
 #include "oct-obj.h"
+#include "oct-prcstrm.h"
+#include "oct-stream.h"
+#include "oct-strstrm.h"
 #include "pager.h"
 #include "sysdep.h"
 #include "syswait.h"
 #include "utils.h"
-#include "variables.h"
-
-// keeps a count of args sent to printf or scanf
-static int fmt_arg_count = 0;
-
-// double linked list containing relevant information about open files
-static DLList <file_info> file_list;
-
-// stack for next available file number
-static SLStack <int> next_available_file_number;
-
-static int
-get_next_avail_file_num (void)
-{
-  if (next_available_file_number.empty ())
-    return file_list.length ();
-  else
-    return next_available_file_number.pop ();
-}
 
 void
 initialize_file_io (void)
 {
-  file_info octave_stdin (0, "stdin", stdin, "r");
-  file_info octave_stdout (1, "stdout", stdout, "w");
-  file_info octave_stderr (2, "stderr", stderr, "w");
+  octave_istream *stdin_stream = new octave_istream (&cin, "stdin");
+  octave_ostream *stdout_stream = new octave_ostream (&cout, "stdout");
+  octave_ostream *stderr_stream = new octave_ostream (&cerr, "stderr");
 
-  file_list.append (octave_stdin);
-  file_list.append (octave_stdout);
-  file_list.append (octave_stderr);
+  octave_stream_list::insert (stdin_stream);
+  octave_stream_list::insert (stdout_stream);
+  octave_stream_list::insert (stderr_stream);
 }
 
-// Given a file name or number, return a pointer to the corresponding
-// open file.  If the file has not already been opened, return NULL.
-
-Pix
-return_valid_file (const tree_constant& arg)
+void
+close_files (void)
 {
-  if (arg.is_string ())
-    {
-      Pix p = file_list.first ();
-      file_info file;
-      int file_count = file_list.length ();
-      for (int i = 0; i < file_count; i++)
-	{
-	  string file_name = arg.string_value ();
-	  file = file_list (p);
-	  if (file.name () == file_name)
-	    return p;
-	  file_list.next (p);
-	}
-    }
-  else
-    {
-      double file_num = arg.double_value ();
+  octave_stream_list::clear ();
+}
 
-      if (! error_state)
-	{
-	  if (D_NINT (file_num) != file_num)
-	    error ("file number not an integer value");
-	  else
-	    {
-	      Pix p = file_list.first ();
-	      file_info file;
-	      int file_count = file_list.length ();
-	      for (int i = 0; i < file_count; i++)
-		{
-		  file = file_list (p);
-		  if (file.number () == file_num)
-		    return p;
-		  file_list.next (p);
-		}
-	      error ("no file with that number");
-	    }
-	}
-      else
-	error ("inapproriate file specifier");
-    }
-
-  return 0;
+static void
+gripe_invalid_file_id (const char *fcn)
+{
+  ::error ("%s: invalid file id", fcn);
 }
 
-static Pix 
-fopen_file_for_user (const string& name, const char *mode,
-		     const char *warn_for)
+static int
+fopen_mode_to_ios_mode (const string& mode)
 {
-  FILE *file_ptr = fopen (name.c_str (), mode);
-  if (file_ptr)
-    { 
-      int file_number = get_next_avail_file_num ();
+  int retval = 0;
 
-      file_info file (file_number, name, file_ptr, mode);
-      file_list.append (file);
-      
-      Pix p = file_list.first ();
-      file_info file_from_list;
-      int file_count = file_list.length ();
-      for (int i = 0; i < file_count; i++)
-	{
-	  file_from_list = file_list (p);
-	  if (file_from_list.name () == name)
-	    return p;
-	  file_list.next (p);
-	}
-    }
-
-  error ("%s: unable to open file `%s'", warn_for, name.c_str ());
-
-  return 0;
-}
-
-static Pix
-file_io_get_file (const tree_constant& arg, const char *mode,
-		  const char *warn_for)
-{
-  Pix p = return_valid_file (arg);
-
-  if (! p)
+  if (! mode.empty ())
     {
-      if (arg.is_string ())
-	{
-	  string name = arg.string_value ();
-
-	  file_stat fs (name);
+      // Could probably be faster, but does it really matter?
 
-	  if (fs)
-	    {
-	      if (fs.is_reg ())
-		p = fopen_file_for_user (name, mode, warn_for);
-	      else
-		error ("%s: invalid file type", warn_for);
-	    }
-	  else
-	    {
-	      if (*mode != 'r')
-		p = fopen_file_for_user (name, mode, warn_for);
-	      else
-		error ("%s: can't stat file `%s'", warn_for, name.c_str ());
-	    }
-	}
+      if (mode == "r")
+	retval = ios::in;
+      else if (mode == "w")
+	retval = ios::out | ios::trunc;
+      else if (mode == "a")
+	retval = ios::out | ios::app;
+      else if (mode == "r+")
+	retval = ios::in | ios::out;
+      else if (mode == "w+")
+	retval = ios::in | ios::out | ios::trunc;
+      else if (mode == "a+")
+	retval = ios::in | ios::out | ios::app;
+      else if (mode == "rb")
+	retval = ios::in | ios::bin;
+      else if (mode == "wb")
+	retval = ios::out | ios::trunc | ios::bin;
+      else if (mode == "ab")
+	retval = ios::out | ios::app | ios::bin;
+      else if (mode == "r+b")
+	retval = ios::in | ios::out | ios::bin;
+      else if (mode == "w+b")
+	retval = ios::in | ios::out | ios::trunc | ios::bin;
+      else if (mode == "a+b")
+	retval = ios::in | ios::out | ios::app | ios::bin;
       else
-	error ("%s: invalid file specifier", warn_for);
-    }
-
-  return p;
-}
-
-static Octave_object
-fclose_internal (const Octave_object& args)
-{
-  Octave_object retval;
-
-  Pix p = return_valid_file (args(0));
-
-  if (! p)
-    return retval;
-
-  file_info file = file_list (p);
-
-  if (file.number () < 3)
-    {
-      warning ("fclose: can't close stdin, stdout, or stderr!");
-      return retval;
-    }
-
-  int success = fclose (file.fptr ());
-  next_available_file_number.push (file.number ());
-  file_list.del (p);
-
-  if (success == 0)
-    retval(0) = 1.0; // succeeded
-  else
-    {
-      error ("fclose: error on closing file");
-      retval(0) = 0.0; // failed
+	::error ("invalid mode specified");
     }
 
   return retval;
 }
 
 DEFUN (fclose, args, ,
-  "fclose (FILENAME or FILENUM):  close a file")
+  "fclose (FILENAME or FILENUM): close a file")
 {
-  Octave_object retval;
+  double retval = -1.0;
 
   int nargin = args.length ();
 
-  if (nargin != 1)
-    print_usage ("fclose");
-  else
-    retval = fclose_internal (args);
-
-  return retval;
-}
-
-static Octave_object
-fflush_internal (const Octave_object& args)
-{
-  Octave_object retval;
-
-  Pix p = return_valid_file (args(0));
-
-  if (! p)
-    return retval;
-
-  file_info file = file_list (p);
+  if (nargin == 1)
+    {
+      retval = (double) octave_stream_list::remove (args(0));
 
-  if (file.mode () == "r")
-    {
-      warning ("can't flush an input stream");
-      return retval;
+      if (retval < 0)
+	gripe_invalid_file_id ("fclose");
     }
-
-  int success = 0;
-
-  if (file.number () == 1)
-    flush_output_to_pager ();
   else
-    success = fflush (file.fptr ());
-
-  if (success == 0)
-    retval(0) = 1.0; // succeeded
-  else
-    {
-      error ("fflush: write error");
-      retval(0) = 0.0; // failed
-    }
+    print_usage ("fclose");
 
   return retval;
 }
@@ -303,263 +150,217 @@
 DEFUN (fflush, args, ,
   "fflush (FILENAME or FILENUM): flush buffered data to output file")
 {
-  Octave_object retval;
+  double retval = -1.0;
 
   int nargin = args.length ();
 
-  if (nargin != 1)
+  if (nargin == 1)
+    {
+      octave_stream *os = octave_stream_list::lookup (args(0));
+
+      if (os)
+	retval = (double) os->flush ();
+      else
+	gripe_invalid_file_id ("fflush");
+    }
+  else
     print_usage ("fflush");
-  else
-    retval = fflush_internal (args);
 
   return retval;
 }
 
-static int
-valid_mode (const string& mode)
-{
-  if (! mode.empty ())
-    {
-      char m = mode[0];
-      if (m == 'r' || m == 'w' || m == 'a')
-	return (mode.length () == 2) ? mode[1] == '+' : 1;
-    }
-  return 0;
-}
-
-static Octave_object
-fgets_internal (const Octave_object& args, int nargin, int nargout,
-		int strip_final_newline = 0)
-{
-  Octave_object retval;
-
-  Pix p = file_io_get_file (args(0), "r", "fgets");
-  
-  if (! p)
-    return retval;
-
-  int length = 0;
-
-  if (nargin == 2)
-    {
-      double dlen = args(1).double_value ();
-
-      if (error_state)
-	return retval;
-
-      if (xisnan (dlen))
-	{
-	  error ("fgets: NaN invalid as length");
-	  return retval;
-	}
-
-      length = NINT (dlen);
-
-      if ((double) length != dlen)
-	{
-	  error ("fgets: length not an integer value");
-	  return retval;
-	}
-
-      if (length < 0)
-	{
-	  error ("fgets: length must be a nonnegative integer");
-	  return retval;
-	}
-    }
-
-  file_info file = file_list (p);
-  FILE *fileptr = file.fptr ();
-
-  ostrstream buf;
-  int c;
-  int count = 0;
-  int newline_stripped = 0;
-
-  if (nargin == 1 || length > 0)
-    {
-      while ((c = fgetc (fileptr)) != EOF)
-	{
-	  count++;
-	  if (c == '\n')
-	    {
-	      if (! strip_final_newline)
-		buf << (char) c;
-	      else
-		newline_stripped = 1;
-
-	      break;
-	    }
-	  else
-	    buf << (char) c;
-
-	  if (nargin == 2 && count == length)
-	    break;
-	}
-    }
-
-  buf << ends;
-  char *string = buf.str ();
-
-  if (count)
-    {
-      if (nargout == 2)
-	retval(1) = (double) (count - newline_stripped);
-
-      retval(0) = string;
-    }
-  else
-    retval(0) = -1.0;
-
-  delete [] string;
-
-  return retval;
-}
-
-DEFUN (fgetl, args, nargout,
-  "[STRING, LENGTH] = fgetl (FILENAME or FILENUM [, LENGTH])\n\
+DEFUN (fgetl, args, ,
+  "STRING = fgetl (FILENAME or FILENUM [, LENGTH])\n\
 \n\
 read a string from a file")
 {
-  Octave_object retval;
+  octave_value retval = -1.0;
 
   int nargin = args.length ();
 
   if (nargin == 1 || nargin == 2)
-    retval = fgets_internal (args, nargin, nargout, 1);
+    {
+      octave_stream *os = octave_stream_list::lookup (args(0));
+
+      if (os)
+	{
+	  octave_value len_arg = (nargin == 2)
+	    ? args(1) : octave_value ((double) INT_MAX);
+
+	  bool err = false;
+
+	  string tmp = os->getl (len_arg, err);
+
+	  if (! err)
+	    retval = tmp;
+	}
+      else
+	gripe_invalid_file_id ("fgetl");
+    }
   else
     print_usage ("fgetl");
 
   return retval;
 }
 
-DEFUN (fgets, args, nargout,
-  "[STRING, LENGTH] = fgets (FILENAME or FILENUM [, LENGTH])\n\
+DEFUN (fgets, args, ,
+  "STRING = fgets (FILENAME or FILENUM [, LENGTH])\n\
 \n\
 read a string from a file")
 {
-  Octave_object retval;
+  octave_value retval = -1.0;
 
   int nargin = args.length ();
 
   if (nargin == 1 || nargin == 2)
-    retval = fgets_internal (args, nargin, nargout);
+    {
+      octave_stream *os = octave_stream_list::lookup (args(0));
+
+      if (os)
+	{
+	  octave_value len_arg = (nargin == 2)
+	    ? args(1) : octave_value ((double) INT_MAX);
+
+	  bool err = false;
+
+	  string tmp = os->gets (len_arg, err);
+
+	  if (! err)
+	    retval = tmp;
+	}
+      else
+	gripe_invalid_file_id ("fgets");
+    }
   else
     print_usage ("fgets");
 
   return retval;
 }
 
-static Octave_object
-fopen_internal (const Octave_object& args)
+static octave_base_stream *
+do_stream_open (const string& name, const string& mode,
+		const string& arch, int& fid)
 {
-  Octave_object retval;
-  Pix p;
+  octave_base_stream *retval = 0;
 
-  if (! args(0).is_string ())
-    {
-      error ("fopen: file name must be a string");
-      return retval;
-    }
-
-  p = return_valid_file (args(0));
+  fid = -1;
 
-  if (p)
-    {
-      file_info file = file_list (p);
-
-      retval(0) = (double) file.number ();
+  int md = fopen_mode_to_ios_mode (mode);
 
-      return retval;
-    }
+  if (! error_state)
+    {
+      octave_base_stream::arch_type at = octave_stream::string_to_arch (arch);
 
-  if (! args(1).is_string ())
-    {
-      error ("fopen: file mode must be a string");
-      return retval;
+      if (! error_state)
+	retval = new octave_fstream (name, md, at);
     }
 
-  string name = args(0).string_value ();
-  string mode = args(1).string_value ();
+  return retval;
+}
 
-  if (! valid_mode (mode))
+static octave_base_stream *
+do_stream_open (const octave_value& tc_name, const octave_value& tc_mode,
+		const octave_value& tc_arch, const char *fcn, int& fid)
+{
+  octave_base_stream *retval = 0;
+
+  fid = -1;
+
+  string name = tc_name.string_value ();
+
+  if (! error_state)
     {
-      error ("fopen: invalid mode");
-      return retval;
-    }
+      string mode = tc_mode.string_value ();
+
+      if (! error_state)
+	{
+	  string arch = tc_arch.string_value ();
 
-  file_stat fs (name);
-
-  if (fs && fs.is_dir ())
-    {
-      error ("fopen: can't open directory");
-      return retval;
+	  if (! error_state)
+	    retval = do_stream_open (name, mode, arch, fid);
+	  else
+	    ::error ("%s: architecture type must be a string", fcn);
+	}
+      else
+	::error ("%s: file mode must be a string", fcn);
     }
-
-  FILE *file_ptr = fopen (name.c_str (), mode.c_str ());
-
-  if (! file_ptr)
-    {
-      error ("fopen: unable to open file `%s'", name.c_str ());
-      return retval;
-    }
-
-  int file_number = get_next_avail_file_num ();
-
-  file_info file (file_number, name, file_ptr, mode);
-  file_list.append (file);
-
-  retval(0) = (double) file_number;
+  else
+    ::error ("%s: file name must be a string", fcn);
 
   return retval;
 }
 
 DEFUN (fopen, args, ,
-  "FILENUM = fopen (FILENAME, MODE): open a file\n\
+  "FILENUM = fopen (FILENAME, MODE [, ARCH]): open a file\n\
 \n\
   Valid values for mode include:\n\
 \n\
-   r  : open text file for reading\n\
-   w  : open text file for writing; discard previous contents if any\n\
-   a  : append; open or create text file for writing at end of file\n\
-   r+ : open text file for update (i.e., reading and writing)\n\
-   w+ : create text file for update; discard previous contents if any\n\
-   a+ : append; open or create text file for update, writing at end\n\n\
- Update mode permits reading from and writing to the same file.")
+    r  : open text file for reading\n\
+    w  : open text file for writing; discard previous contents if any\n\
+    a  : append; open or create text file for writing at end of file\n\
+    r+ : open text file for update (i.e., reading and writing)\n\
+    w+ : create text file for update; discard previous contents if any\n\
+    a+ : append; open or create text file for update, writing at end\n\
+\n\
+  Update mode permits reading from and writing to the same file.")
 {
-  Octave_object retval;
+  octave_value_list retval = -1.0;
 
   int nargin = args.length ();
 
-  if (nargin != 2)
-    print_usage ("fopen");
-  else
-    retval = fopen_internal (args);
-
-  return retval;
-}
+  if (nargin == 1)
+    {
+      if (args(0).is_string () && args(0).string_value () == "all")
+	{
+	  return octave_stream_list::open_file_numbers ();
+	}
+      else
+	{
+	  string_vector tmp = octave_stream_list::get_info (args(0));
 
-static Octave_object
-freport_internal (void)
-{
-  Octave_object retval;
-  Pix p = file_list.first ();
-
-  ostrstream output_buf;
+	  if (! error_state)
+	    {
+	      retval(2) = tmp(2);
+	      retval(1) = tmp(1);
+	      retval(0) = tmp(0);
+	    }
 
-  output_buf << "\n number  mode  name\n\n";
-
-  int file_count = file_list.length ();
-  for (int i = 0; i < file_count; i++)
-    {
-      file_info file = file_list (p);
-      output_buf.form ("%7d%6s  %s\n", file.number (),
-		       file.mode ().c_str (), file.name ().c_str ());
-      file_list.next (p);
+	  return retval;
+	}
     }
 
-  output_buf << "\n" << ends;
-  maybe_page_output (output_buf);
+  if (nargin > 0 && nargin < 4)
+    {
+      octave_value mode = (nargin == 2 || nargin == 3)
+	? args(1) : octave_value ("r");
+
+      octave_value arch = (nargin == 3)
+	? args(2) : octave_value ("native");
+
+      int fid = -1;
+
+      octave_base_stream *os
+	= do_stream_open (args(0), mode, arch, "fopen", fid);
+
+      if (os)
+	{
+	  if (os->ok () && ! error_state)
+	    {
+	      retval(1) = "";
+	      retval(0) = (double) octave_stream_list::insert (os);
+	    }
+	  else
+	    {
+	      int errno = 0;
+	      retval(1) = os->error (false, errno);
+	      retval(0) = -1.0;
+	    }
+	}
+      else
+	::error ("fopen: internal error");
+    }
+  else
+    print_usage ("fopen");
 
   return retval;
 }
@@ -567,30 +368,14 @@
 DEFUN (freport, args, ,
   "freport (): list open files and their status")
 {
-  Octave_object retval;
+  octave_value_list retval;
 
   int nargin = args.length ();
 
   if (nargin > 0)
     warning ("freport: ignoring extra arguments");
 
-  retval = freport_internal ();
-
-  return retval;
-}
-
-static Octave_object
-frewind_internal (const Octave_object& args)
-{
-  Octave_object retval;
-
-  Pix p = file_io_get_file (args(0), "a+", "frewind");
-
-  if (p)
-    {
-      file_info file = file_list (p);
-      rewind (file.fptr ());
-    }
+  octave_stdout << octave_stream_list::list_open_files ();
 
   return retval;
 }
@@ -598,95 +383,21 @@
 DEFUN (frewind, args, ,
   "frewind (FILENAME or FILENUM): set file position at beginning of file")
 {
-  Octave_object retval;
-
-  int nargin = args.length ();
-
-  if (nargin != 1)
-    print_usage ("frewind");
-  else
-    retval = frewind_internal (args);
-
-  return retval;
-}
-
-static Octave_object
-fseek_internal (const Octave_object& args)
-{
-  Octave_object retval;
+  double retval = -1.0;
 
   int nargin = args.length ();
 
-  Pix p = file_io_get_file (args(0), "a+", "fseek");
-
-  if (! p)
-    return retval;
-
-  long origin = SEEK_SET;
-
-  double doff = args(1).double_value ();
-
-  if (error_state)
-    return retval;
-
-  if (xisnan (doff))
+  if (nargin == 1)
     {
-      error ("fseek: NaN invalid as offset");
-      return retval;
-    }
-
-  long offset = NINT (doff);
-
-  if ((double) offset != doff)
-    {
-      error ("fseek: offset not an integer value");
-      return retval;
-    }
-
-  if (nargin == 3)
-    {
-      double dorig = args(2).double_value ();
-
-      if (error_state)
-	return retval;
+      octave_stream *os = octave_stream_list::lookup (args(0));
 
-      if (xisnan (dorig))
-	{
-	  error ("fseek: NaN invalid as origin");
-	  return retval;
-	}
-
-      origin = NINT (dorig);
-
-      if ((double) dorig != origin)
-	{
-	  error ("fseek: origin not an integer value");
-	  return retval;
-	}
-
-      if (origin == 0)
-	origin = SEEK_SET;
-      else if (origin == 1)
-	origin = SEEK_CUR;
-      else if (origin == 2)
-	origin = SEEK_END;
+      if (os)
+	retval = (double) os->rewind ();
       else
-	{
-	  error ("fseek: invalid value for origin");
-	  return retval;
-	}
+	gripe_invalid_file_id ("frewind");
     }
-
-  file_info file = file_list (p);
-  int success = fseek (file.fptr (), offset, origin);
-
-  if (success == 0)
-    retval(0) = 1.0; // succeeded
   else
-    {
-      error ("fseek: file error");
-      retval(0) = 0.0; // failed
-    }
+    print_usage ("frewind");
 
   return retval;
 }
@@ -696,37 +407,26 @@
 \n\
 set file position for reading or writing")
 {
-  Octave_object retval;
+  double retval = -1.0;
 
   int nargin = args.length ();
 
-  if (nargin != 2 && nargin != 3)
-    print_usage ("fseek");
-  else
-    retval = fseek_internal (args);
-
-  return retval;
-}
-
-// Tell current position of file.
+  if (nargin == 2 || nargin == 3)
+    {
+      octave_stream *os = octave_stream_list::lookup (args(0));
 
-static Octave_object
-ftell_internal (const Octave_object& args)
-{
-  Octave_object retval;
-
-  Pix p = file_io_get_file (args(0), "a+", "ftell");
+      if (os)
+	{
+	  octave_value origin_arg = (nargin == 3)
+	    ? args(2) : octave_value (0.0);
 
-  if (p)
-    {
-      file_info file = file_list (p);
-      long offset = ftell (file.fptr ());
-
-      retval(0) = (double) offset;
-
-      if (offset == -1L)
-	error ("ftell: write error");
+	  retval = (double) os->seek (args(1), origin_arg);
+	}
+      else
+	::error ("fseek: invalid file id");
     }
+  else
+    print_usage ("fseek");
 
   return retval;
 }
@@ -734,355 +434,21 @@
 DEFUN (ftell, args, ,
   "POSITION = ftell (FILENAME or FILENUM): returns the current file position")
 {
-  Octave_object retval;
-
-  int nargin = args.length ();
-
-  if (nargin != 1)
-    print_usage ("ftell");
-  else
-    retval = ftell_internal (args);
-
-  return retval;
-}
-
-void
-close_files (void)
-{
-  Pix p = file_list.first ();
-
-  int file_count = file_list.length ();
-  for (int i = 0; i < file_count; i++)
-    {
-      if (p)
-	{
-	  file_info file = file_list (p);
-
-	  if (i > 2)   // do not close stdin, stdout, stderr!
-	    {
-	      int success = fclose (file.fptr ());
-	      if (success != 0)
-		error ("closing %s", file.name ().c_str ());
-	    }
-
-	  next_available_file_number.push (file.number ());
-	  file_list.del (p);
-	}
-      else
-	{
-	  error ("inconsistent state for internal file list!");
-	  break;
-	}
-    }
-}
-
-static int
-process_printf_format (const char *s, const Octave_object& args,
-		       ostrstream& sb, const char *type)
-{
-  ostrstream fmt;
+  double retval = -1.0;
 
   int nargin = args.length ();
 
-  fmt << "%";  // do_printf() already blew past this one...
-
-  int chars_from_fmt_str = 0;
-
- again:
-  switch (*s)
+  if (nargin == 1)
     {
-    case '+': case '-': case ' ': case '0': case '#':
-      chars_from_fmt_str++;
-      fmt << *s++;
-      goto again;
-
-    case '\0':
-      goto invalid_format;
-
-    default:
-      break;
-    }
-
-  if (*s == '*')
-    {
-      if (fmt_arg_count > nargin)
-	{
-	  error ("%s: not enough arguments", type);
-	  return -1;
-	}
-
-      double tmp_len = args(fmt_arg_count++).double_value ();
-
-      if (error_state || xisnan (tmp_len))
-	{
-	  error ("%s: `*' must be replaced by an integer", type);
-	  return -1;
-	}
+      octave_stream *os = octave_stream_list::lookup (args(0));
 
-      fmt << NINT (tmp_len);
-      s++;
-      chars_from_fmt_str++;
-    }
-  else
-    {
-      while (*s != '\0' && isdigit (*s))
-	{
-	  chars_from_fmt_str++;
-	  fmt << *s++;
-	}
-    }
-
-  if (*s == '\0')
-    goto invalid_format;
-
-  if (*s == '.')
-    {
-      chars_from_fmt_str++;
-      fmt << *s++;
-    }
-
-  if (*s == '*')
-    {
-      if (*(s-1) == '*')
-	goto invalid_format;
-
-      if (fmt_arg_count > nargin)
-	{
-	  error ("%s: not enough arguments", type);
-	  return -1;
-	}
-
-      double tmp_len = args(fmt_arg_count++).double_value ();
-
-      if (error_state || xisnan (tmp_len))
-	{
-	  error ("%s: `*' must be replaced by an integer", type);
-	  return -1;
-	}
-
-      fmt << NINT (tmp_len);
-      s++;
-      chars_from_fmt_str++;
+      if (os)
+	retval = (double) os->tell ();
+      else
+	gripe_invalid_file_id ("ftell");
     }
   else
-    {
-      while (*s != '\0' && isdigit (*s))
-	{
-	  chars_from_fmt_str++;
-	  fmt << *s++;
-	}
-    }
-
-  if (*s == '\0')
-    goto invalid_format;
-
-  if (*s != '\0' && (*s == 'h' || *s == 'l' || *s == 'L'))
-    {
-      chars_from_fmt_str++;
-      fmt << *s++;
-    }
-
-  if (*s == '\0')
-    goto invalid_format;
-
-  if (fmt_arg_count > nargin)
-    {
-      error ("%s: not enough arguments", type);
-      return -1;
-    }
-
-  switch (*s)
-    {
-    case 'd': case 'i': case 'o': case 'u': case 'x': case 'X':
-      {
-	double d = args(fmt_arg_count++).double_value ();
-
-	if (error_state || xisnan (d))
-	  goto invalid_conversion;
-
-	int val = NINT (d);
-
-	if ((double) val != d)
-	  goto invalid_conversion;
-	else
-	  {
-	    chars_from_fmt_str++;
-	    fmt << *s << ends;
-	    char *tmp_fmt = fmt.str ();
-	    sb.form (tmp_fmt, val);
-	    delete [] tmp_fmt;
-	    return chars_from_fmt_str;
-	  }
-      }
-
-    case 'e': case 'E': case 'f': case 'g': case 'G':
-      {
-	double val = args(fmt_arg_count++).double_value ();
-
-	if (error_state)
-	  goto invalid_conversion;
-	else
-	  {
-	    chars_from_fmt_str++;
-	    fmt << *s << ends;
-	    char *tmp_fmt = fmt.str ();
-	    sb.form (tmp_fmt, val);
-	    delete [] tmp_fmt;
-	    return chars_from_fmt_str;
-	  }
-      }
-
-    case 's':
-      {
-	string val = args(fmt_arg_count++).string_value ();
-
-	if (error_state)
-	  goto invalid_conversion;
-	else
-	  {
-	    chars_from_fmt_str++;
-	    fmt << *s << ends;
-	    char *tmp_fmt = fmt.str ();
-	    sb.form (tmp_fmt, val.c_str ());
-	    delete [] tmp_fmt;
-	    return chars_from_fmt_str;
-	  }
-      }
-
-    case 'c':
-      {
-	string val = args(fmt_arg_count++).string_value ();
-
-	if (error_state || val.length () != 1)
-	  goto invalid_conversion;
-	else
-	  {
-	    chars_from_fmt_str++;
-	    fmt << *s << ends;
-	    char *tmp_fmt = fmt.str ();
-	    sb.form (tmp_fmt, val[0]);
-	    delete [] tmp_fmt;
-	    return chars_from_fmt_str;
-	  }
-      }
-
-    default:
-      goto invalid_format;
-   }
-
- invalid_conversion:
-  error ("%s: invalid conversion", type);
-  return -1;
-
- invalid_format:
-  error ("%s: invalid format", type);
-  return -1;
-}
-
-// Formatted printing to a file.
-
-static Octave_object
-do_printf (const char *type, const Octave_object& args)
-{
-  Octave_object retval;
-  fmt_arg_count = 0;
-  const char *fmt;
-  string fmt_str;
-  file_info file;
-
-  if (strcmp (type, "fprintf") == 0)
-    {
-      Pix p = file_io_get_file (args(0), "a+", type);
-
-      if (! p)
-	return retval;
-
-      file = file_list (p);
-
-      if (file.mode () == "r")
-	{
-	  error ("%s: file is read only", type);
-	  return retval;
-	}
-
-      fmt_str = args(1).string_value ();
-      fmt = fmt_str.c_str ();
-
-      if (error_state)
-	{
-	  error ("%s: format must be a string", type);
-	  return retval;
-	}
-
-      fmt_arg_count += 2;
-    }
-  else
-    {
-      fmt_str = args(0).string_value ();
-      fmt = fmt_str.c_str ();
-
-      if (error_state)
-	{
-	  error ("%s: invalid format string", type);
-	  return retval;
-	}
-
-      fmt_arg_count++;
-    }
-
-  // Scan fmt for % escapes and print out the arguments.
-
-  ostrstream output_buf;
-
-  const char *ptr = fmt;
-
-  for (;;)
-    {
-      char c;
-      while ((c = *ptr++) != '\0' && c != '%')
-	output_buf << c;
-
-      if (c == '\0')
-	break;
-
-      if (*ptr == '%')
-	{
-	  ptr++;
-	  output_buf << c;
-	  continue;
-	}
-
-      // We must be looking at a format specifier.  Extract it or
-      // fail.
-
-      int status = process_printf_format (ptr, args, output_buf, type);
-
-      if (status < 0)
-	return retval;
-
-      ptr += status;
-    }
-
-  output_buf << ends;
-  if (strcmp (type, "printf") == 0
-      || (strcmp (type, "fprintf") == 0 && file.number () == 1))
-    {
-      maybe_page_output (output_buf);
-    }
-  else if (strcmp (type, "fprintf") == 0)
-    {
-      char *msg = output_buf.str ();
-      int success = fputs (msg, file.fptr ());
-      if (success == EOF)
-	warning ("%s: unknown failure writing to file", type);
-      delete [] msg;
-    }
-  else if (strcmp (type, "sprintf") == 0)
-    {
-      char *msg = output_buf.str ();
-      retval(0) = msg;
-      delete [] msg;
-    }
+    print_usage ("ftell");
 
   return retval;
 }
@@ -1090,639 +456,212 @@
 DEFUN (fprintf, args, ,
   "fprintf (FILENAME or FILENUM, FORMAT, ...)")
 {
-  Octave_object retval;
+  double retval = -1.0;
 
   int nargin = args.length ();
 
-  if (nargin < 2)
+  if (nargin > 1)
+    {
+      octave_stream *os = octave_stream_list::lookup (args(0));
+
+      if (os)
+	{
+	  if (args(1).is_string ())
+	    {
+	      string fmt = args(1).string_value ();
+
+	      octave_value_list tmp_args;
+
+	      if (nargin > 2)
+		{
+		  tmp_args.resize (nargin-2, octave_value ());
+
+		  for (int i = 2; i < nargin; i++)
+		    tmp_args(i-2) = args(i);
+		}
+
+	      retval = os->printf (fmt, tmp_args);
+	    }
+	  else
+	    ::error ("fprintf: format must be a string");
+	}
+      else
+	gripe_invalid_file_id ("fprintf");
+    }
+  else
     print_usage ("fprintf");
-  else
-    retval = do_printf ("fprintf", args);
 
   return retval;
 }
 
-// Formatted printing.
-
-DEFUN (printf, args, ,
-  "printf (FORMAT, ...)")
+DEFUN (fputs, args, ,
+  "fputs (FILENAME or FILENUM, STRING)")
 {
-  Octave_object retval;
+  double retval = -1.0;
 
   int nargin = args.length ();
 
-  if (nargin < 1)
-    print_usage ("printf");
-  else
-    retval = do_printf ("printf", args);
-
-  return retval;
-}
-
-// Formatted printing to a string.
+  if (nargin == 2)
+    {
+      octave_stream *os = octave_stream_list::lookup (args(0));
 
-DEFUN (sprintf, args, ,
-  "s = sprintf (FORMAT, ...)")
-{
-  Octave_object retval;
-
-  int nargin = args.length ();
-
-  if (nargin < 1)
-    print_usage ("sprintf");
+      if (os)
+	retval = os->puts (args(1));
+      else
+	gripe_invalid_file_id ("fputs");
+    }
   else
-    retval = do_printf ("sprintf", args);
+    print_usage ("fputs");
 
   return retval;
 }
 
-static int
-process_scanf_format (const char *s, ostrstream& fmt,
-		      const char *type, int nargout, FILE* fptr,
-		      Octave_object& values)
+DEFUN (sprintf, args, ,
+  "[s, errmsg, status] = sprintf (FORMAT, ...)")
 {
-  fmt << "%";
+  octave_value_list retval;
 
-  int chars_from_fmt_str = 0;
-  int store_value = 1;
-  int string_width = 0;
-  int success = 1;
+  retval(2) = -1.0;
+  retval(1) = "unknown error";
+  retval(0) = "";
 
-  if (*s == '*')
-    {
-      store_value = 0;
-      s++;
-      chars_from_fmt_str++;
-    }
+  int nargin = args.length ();
 
-  if (isdigit (*s))
+  if (nargin > 0)
     {
-      ostrstream str_number;
-      while (*s != '\0' && isdigit (*s))
-	{
-	  chars_from_fmt_str++;
-	  str_number << *s;
-	  fmt << *s++;
-	}
-      str_number << ends;
-      char *number = str_number.str ();
-      string_width = atoi (number);
-      delete [] number;
-    }
-
-  if (*s == '\0')
-    goto invalid_format;
-
-  if (*s != '\0' && (*s == 'h' || *s == 'l' || *s == 'L'))
-    {
-      chars_from_fmt_str++;
-      s++;
-    }
+      octave_ostrstream ostr;
 
-  if (*s == '\0')
-    goto invalid_format;
-
-  // Even if we don't have a place to store them, attempt to convert
-  // everything specified by the format string.
-
-  if (fmt_arg_count > (nargout ? nargout : 1))
-    store_value = 0;
-
-  switch (*s)
-    {
-    case 'd': case 'i': case 'o': case 'u': case 'x': case 'X':
-      {
-	chars_from_fmt_str++;
-	fmt << *s << ends;
-	int temp;
-	char *str = fmt.str ();
-	success = fscanf (fptr, str, &temp);
-	delete [] str;
-	if (success > 0 && store_value)
-	  values(fmt_arg_count++) = (double) temp;
-      }
-      break;
+      octave_stream os (&ostr);
 
-    case 'e': case 'E': case 'f': case 'g': case 'G':
-      {
-	chars_from_fmt_str++;
-	fmt << 'l' << *s << ends;
-	double temp;
-	char *str = fmt.str ();
-	success = fscanf (fptr, str, &temp);
-	delete [] str;
-	if (success > 0 && store_value)
-	  values(fmt_arg_count++) = temp;
-      }
-      break;
+      if (os)
+	{
+	  if (args(0).is_string ())
+	    {
+	      string fmt = args(0).string_value ();
 
-    case 's':
-      {
-	if (string_width < 1)
-	  {
-	    // XXX FIXME XXX -- The code below is miscompiled on the
-	    // Alpha with gcc 2.6.0, so that string_width is never
-	    // incremented, even though reading the data works
-	    // correctly.  One fix is to use a fixed-size buffer...
-//	    string_width = 8192;
-
-	    string_width = 0;
-	    long original_position = ftell (fptr);
-
-	    int c;
+	      octave_value_list tmp_args;
 
-	    while ((c = getc (fptr)) != EOF && isspace (c))
-	      ; // Don't count leading whitespace.
-
-	    if (c != EOF)
-	      string_width++;
-
-	    for (;;)
-	      {
-		c = getc (fptr);
-		if (c != EOF && ! isspace (c))
-		  string_width++;
-		else
-		  break;
-	      }
+	      if (nargin > 1)
+		{
+		  tmp_args.resize (nargin-1, octave_value ());
 
-	    fseek (fptr, original_position, SEEK_SET);
-	  }
-	chars_from_fmt_str++;
-	char temp [string_width+1];
-	fmt << *s << ends;
-	char *str = fmt.str ();
-	success = fscanf (fptr, str, temp);
-	delete [] str;
-	temp[string_width] = '\0';
-	if (success > 0 && store_value)
-	  values(fmt_arg_count++) = temp;
-      }
-      break;
+		  for (int i = 1; i < nargin; i++)
+		    tmp_args(i-1) = args(i);
+		}
 
-    case 'c':
-      {
-	if (string_width < 1)
-	  string_width = 1;
-	chars_from_fmt_str++;
-	char temp [string_width+1];
-	memset (temp, '\0', string_width+1);
-	fmt << *s << ends;
-	char *str = fmt.str ();
-	success = fscanf (fptr, str, temp);
-	delete [] str;
-	temp[string_width] = '\0';
-	if (success > 0 && store_value)
-	  values(fmt_arg_count++) = temp;
-      }
-      break;
-
-    default:
-      goto invalid_format;
-    }
-
-  if (success > 0)
-    return chars_from_fmt_str;
-  else if (success == 0)
-    warning ("%s: invalid conversion", type);
-  else if (success == EOF)
-    {
-      if (strcmp (type, "fscanf") == 0)
-	warning ("%s: end of file reached before final conversion", type);
-      else if (strcmp (type, "sscanf") == 0)
-	warning ("%s: end of string reached before final conversion", type);
-      else if (strcmp (type, "scanf") == 0)
-	warning ("%s: end of input reached before final conversion", type);
+	      retval(2) = os.printf (fmt, tmp_args);
+	      retval(1) = os.error ();
+	      char *tmp = ostr.str ();
+	      retval(0) = tmp;
+	      delete [] tmp;
+	    }
+	  else
+	    ::error ("sprintf: format must be a string");
+	}
+      else
+	::error ("sprintf: unable to create output buffer");
     }
   else
-    {
-    invalid_format:
-      warning ("%s: invalid format", type);
-    }
-
-  return -1;
-}
-
-// Formatted reading from a file.
-
-static Octave_object
-do_scanf (const char *type, const Octave_object& args, int nargout)
-{
-  Octave_object retval;
-  const char *scanf_fmt = 0;
-  string scanf_fmt_str;
-  string tmp_file;
-  int tmp_file_open = 0;
-  FILE *fptr = 0;
-  file_info file;
-
-  fmt_arg_count = 0;
-
-  if (strcmp (type, "scanf") != 0)
-    {
-      scanf_fmt_str = args(1).string_value (); 
-      scanf_fmt = scanf_fmt_str.c_str ();
-
-      if (error_state)
-	{
-	  error ("%s: format must be a string", type);
-	  return retval;
-	}
-    }
-
-  int doing_fscanf = (strcmp (type, "fscanf") == 0);
-
-  if (doing_fscanf)
-    {
-      Pix p = file_io_get_file (args(0), "r", type);
-
-      if (! p)
-	return retval;
-
-      file = file_list (p);
-
-      if (file.mode () == "w" || file.mode () == "a")
-	{
-	  error ("%s: this file is opened for writing only", type);
-	  return retval;
-	}
-
-      fptr = file.fptr ();
-    }
-
-  if ((! fptr && args(0).is_string ())
-      || (doing_fscanf && file.number () == 0))
-    {
-      string xstring_str;
-      const char *xstring;
-
-      if (strcmp (type, "scanf") == 0)
-	{
-	  scanf_fmt_str = args(0).string_value ();
-	  scanf_fmt = scanf_fmt_str.c_str ();
-	}
-
-      if (strcmp (type, "scanf") == 0
-	  || (doing_fscanf && file.number () == 0))
-	{
-	  // XXX FIXME XXX -- this should probably be possible for
-	  // more than just stdin/stdout pairs, using a list of output
-	  // streams to flush.  The list could be created with a
-	  // function like iostream's tie().
-
-	  flush_output_to_pager ();
-
-	  xstring = gnu_readline ("");
-
-	  if (xstring && *xstring)
-	    octave_command_history.add (xstring);
-	}
-      else
-	{
-	  xstring_str = args(0).string_value ();
-	  xstring = xstring_str.c_str ();
-	}
-
-      tmp_file = oct_tempnam ();
-
-      fptr = fopen (tmp_file.c_str (), "w+");
-      if (! fptr)
-	{
-	  error ("%s: error opening temporary file", type);
-	  return retval;
-	}
-      tmp_file_open = 1;
-      unlink (tmp_file.c_str ());
-
-      if (! xstring)
-	{
-	  error ("%s: no string to scan", type); 
-	  return retval;
-	}
-
-      int success = fputs (xstring, fptr);
-      fflush (fptr);
-      rewind (fptr);
-
-      if (success < 0)
-	{
-	  error ("%s: trouble writing temporary file", type);
-	  fclose (fptr);
-	  return retval;
-	}
-    }
-  else if (! doing_fscanf)
-    {
-      error ("%s: first argument must be a string", type);
-      return retval;
-    }
-
-  // Scan scanf_fmt for % escapes and assign the arguments.
-
-  retval.resize (nargout);
-
-  const char *ptr = scanf_fmt;
-
-  for (;;)
-    {
-      ostrstream fmt;
-      char c;
-      while ((c = *ptr++) != '\0' && c != '%')
-	fmt << c;
-
-      if (c == '\0')
-	break;
-
-      if (*ptr == '%')
-	{
-	  ptr++;
-	  fmt << c;
-	  continue;
-	}
-
-      // We must be looking at a format specifier.  Extract it or
-      // fail.
-
-      int status = process_scanf_format (ptr, fmt, type, nargout,
-					 fptr, retval);
-
-      if (status < 0)
-	{
-	  if (fmt_arg_count == 0)
-	    retval.resize (0);
-	  break;
-	}
-
-      ptr += status;
-    }
-
-  if (tmp_file_open)
-    fclose (fptr);
+    print_usage ("sprintf");
 
   return retval;
 }
 
-DEFUN (fscanf, args, nargout,
-  "[A, B, C, ...] = fscanf (FILENAME or FILENUM, FORMAT)")
+DEFUN (fscanf, args, ,
+  "[A, B, C, ...] = fscanf (FILENAME or FILENUM, FORMAT, SIZE)")
 {
-  Octave_object retval;
+  octave_value_list retval;
 
   int nargin = args.length ();
 
-  if (nargin != 1 && nargin != 2)
-    print_usage ("fscanf");
-  else
-    retval = do_scanf ("fscanf", args, nargout);
-
-  return retval;
-}
+  if (nargin == 2 || nargin == 3)
+    {
+      octave_stream *os = octave_stream_list::lookup (args(0));
 
-// Formatted reading.
+      if (os)
+	{
+	  if (args(1).is_string ())
+	    {
+	      string fmt = args(1).string_value ();
 
-DEFUN (scanf, args, nargout,
-  "[A, B, C, ...] = scanf (FORMAT)")
-{
-  Octave_object retval;
-
-  int nargin = args.length ();
+	      int count = 0;
 
-  if (nargin != 1)
-    print_usage ("scanf");
-  else
-    retval = do_scanf ("scanf", args, nargout);
+	      // XXX FIXME XXX
+	      Array<int> size (2);
 
-  return retval;
-}
-
-// Formatted reading from a string.
+	      octave_value tmp = os->scanf (fmt, size, count);
 
-DEFUN (sscanf, args, nargout,
-  "[A, B, C, ...] = sscanf (STRING, FORMAT)")
-{
-  Octave_object retval;
-
-  int nargin = args.length ();
-
-  if (nargin != 2)
-    print_usage ("sscanf");
+	      retval(1) = (double) count;
+	      retval(0) = tmp;
+	    }
+	  else
+	    ::error ("fscanf: format must be a string");
+	}
+      else
+	gripe_invalid_file_id ("fscanf");
+    }
   else
-    retval = do_scanf ("sscanf", args, nargout);
+    print_usage ("fscanf");
 
   return retval;
 }
 
-// Find out how many elements are left to read.
-
-static long
-num_items_remaining (FILE *fptr, const char *type)
+DEFUN (sscanf, args, ,
+  "[A, COUNT, ERRMSG, INDEX] = sscanf (STRING, FORMAT, SIZE)")
 {
-  size_t size;
-
-  if (strcasecmp (type, "uchar") == 0)
-    size = sizeof (u_char);
-  else if (strcasecmp (type, "char") == 0)
-    size = sizeof (char);
-  else if (strcasecmp (type, "short") == 0)
-    size = sizeof (short);
-  else if (strcasecmp (type, "ushort") == 0)
-    size = sizeof (u_short);
-  else if (strcasecmp (type, "int") == 0)
-    size = sizeof (int);
-  else if (strcasecmp (type, "uint") == 0)
-    size = sizeof (u_int);
-  else if (strcasecmp (type, "long") == 0)
-    size = sizeof (long);
-  else if (strcasecmp (type, "ulong") == 0)
-    size = sizeof (u_long);
-  else if (strcasecmp (type, "float") == 0)
-    size = sizeof (float);
-  else if (strcasecmp (type, "double") == 0)
-    size = sizeof (double);
-  else
-    return 0;
-
-  long curr_pos = ftell (fptr);
+  octave_value_list retval;
 
-  fseek (fptr, 0, SEEK_END);
-  long end_of_file = ftell (fptr);
-
-  fseek (fptr, curr_pos, SEEK_SET);
-
-  long len = end_of_file - curr_pos;
-
-  return len / size;
-}
-
-// Read binary data from a file.
-//
-//   [data, count] = fread (fid, size, 'precision')
-//
-//     fid       : the file id from fopen
-//     size      : the size of the matrix or vector or scaler to read
-//
-//                 n	  : reads n elements of a column vector
-//                 inf	  : reads to the end of file (default)
-//                 [m, n] : reads enough elements to fill the matrix
-//                          the number of columns can be inf
-//
-//     precision : type of the element.  Can be:
-//
-//                 char, uchar, schar, short, ushort, int, uint,
-//                 long, ulong, float, double
-//
-//                 Default  is uchar.
-//
-//     data	 : output data
-//     count	 : number of elements read
-
-static Octave_object
-fread_internal (const Octave_object& args, int nargout)
-{
-  Octave_object retval;
+  retval(3) = -1.0;
+  retval(2) = "unknown error";
+  retval(1) = 0.0;
+  retval(0) = Matrix ();
 
   int nargin = args.length ();
 
-  Pix p = file_io_get_file (args(0), "r", "fread");
+  if (nargin == 2 || nargin == 3)
+    {
+      if (args(0).is_string ())
+	{
+	  string data = args(0).string_value ();
 
-  if (! p)
-    return retval;
-
-  // Get type and number of bytes per element to read.
+	  octave_istrstream istr (data);
 
-  const char *prec = "uchar";
-  string tstr;
-  if (nargin > 2)
-    {
-      tstr = args(2).string_value ();
-      prec = tstr.c_str ();
+	  octave_stream os (&istr);
 
-      if (error_state)
-	{
-	  error ("fread: precision must be a specified as a string");
-	  return retval;
-	}
-    }
+	  if (os)
+	    {
+	      if (args(1).is_string ())
+		{
+		  string fmt = args(1).string_value ();
 
-  file_info file = file_list (p);
+		  int count = 0;
 
-  FILE *fptr = file.fptr ();
+		  // XXX FIXME XXX
+		  Array<int> size (2);
 
-  // Set up matrix to read into.  If specified in arguments use that
-  // number, otherwise read everyting left in file.
+		  octave_value tmp = os.scanf (fmt, size, count);
 
-  double dnr = 0.0;
-  double dnc = 0.0;
-  int nr;
-  int nc;
-
-  if (nargin > 1)
-    {
-      if (args(1).is_scalar_type ())
-	{
-	  dnr = args(1).double_value ();
-
-	  if (error_state)
-	    return retval;
-
-	  dnc = 1.0;
+		  retval(3) = (double) (os.tell () + 1);
+		  retval(2) = os.error ();
+		  retval(1) = (double) count;
+		  retval(0) = tmp;
+		}
+	      else
+		::error ("sscanf: format must be a string");
+	    }
+	  else
+	    ::error ("sscanf: unable to create temporary input buffer");
 	}
       else
-	{
-	  ColumnVector tmp = args(1).vector_value ();
-
-	  if (error_state || tmp.length () != 2)
-	    {
-	      error ("fread: invalid size specification\n");
-	      return retval;
-	    }
-
-	  dnr = tmp.elem (0);
-	  dnc = tmp.elem (1);
-	}
-
-      if ((xisinf (dnr)) && (xisinf (dnc)))
-	{
-	  error ("fread: number of rows and columns cannot both be infinite");
-	  return retval;
-	}
-
-      if (xisinf (dnr))
-	{
-	  if (xisnan (dnc))
-	    {
-	      error ("fread: NaN invalid as the number of columns");
-	      return retval;
-	    }
-	  else
-	    {
-	      nc = NINT (dnc);
-	      int n = num_items_remaining (fptr, prec);
-	      nr = n / nc;
-	      if (n > nr * nc)
-		nr++;
-	    }
-	}
-      else if (xisinf (dnc))
-	{
-	  if (xisnan (dnr))
-	    {
-	      error ("fread: NaN invalid as the number of rows");
-	      return retval;
-	    }
-	  else
-	    {
-	      nr = NINT (dnr);
-	      int n = num_items_remaining (fptr, prec);
-	      nc = n / nr;
-	      if (n > nc * nr)
-		nc++;
-	    }
-	}
-      else
-	{
-	  if (xisnan (dnr))
-	    {
-	      error ("fread: NaN invalid as the number of rows");
-	      return retval;
-	    }
-	  else
-	    nr = NINT (dnr);
-
-	  if (xisnan (dnc))
-	    {
-	      error ("fread: NaN invalid as the number of columns");
-	      return retval;
-	    }
-	  else
-	    nc = NINT (dnc);
-	}
+	::error ("sscanf: first argument must be a string");
     }
   else
-    {
-      // No size parameter, read what's left of the file.
-
-      nc = 1;
-      int n = num_items_remaining (fptr, prec);
-      nr = n / nc;
-      if (n > nr * nc)
-	nr++;
-    }
-
-  Matrix m (nr, nc, octave_NaN);
-
-  // Read data.
-
-  int count = m.read (fptr, prec);
-
-  if (nargout > 1)
-    retval(1) = (double) count;
-
-  retval(0) = m;
+    print_usage ("sscanf");
 
   return retval;
 }
 
-DEFUN (fread, args, nargout,
+DEFUN (fread, , ,
   "[DATA, COUNT] = fread (FILENUM, SIZE, PRECISION)\n\
 \n\
  Reads data in binary form of type PRECISION from a file.\n\
@@ -1737,76 +676,12 @@
  DATA      : matrix in which the data is stored\n\
  COUNT     : number of elements read")
 {
-  Octave_object retval;
-
-  int nargin = args.length ();
-
-  if (nargin < 1 || nargin > 3)
-    print_usage ("fread");
-  else
-    retval = fread_internal (args, nargout);
-
+  octave_value_list retval;
+  // XXX IMPLEMENTME XXX
   return retval;
 }
 
-// Write binary data to a file.
-//
-//   count = fwrite (fid, data, 'precision')
-//
-//    fid	: file id from fopen
-//    Data	: data to be written
-//    precision	: type of output element.  Can be:
-//
-//                char, uchar, schar, short, ushort, int, uint,
-//                long, float, double
-//
-//                 Default is uchar.
-//
-//    count     : the number of elements written
-
-static Octave_object
-fwrite_internal (const Octave_object& args)
-{
-  Octave_object retval;
-
-  int nargin = args.length ();
-
-  Pix p = file_io_get_file (args(0), "a+", "fwrite");
-
-  if (! p)
-    return retval;
-
-  // Get type and number of bytes per element to read.
-
-  const char *prec = "uchar";
-  string tstr;
-  if (nargin > 2)
-    {
-      tstr = args(2).string_value ();
-      prec = tstr.c_str ();
-
-      if (error_state)
-	{
-	  error ("fwrite: precision must be a specified as a string");
-	  return retval;
-	}
-    }
-
-  file_info file = file_list (p);
-
-  Matrix m = args(1).matrix_value ();
-
-  if (! error_state)
-    {
-      int count = m.write (file.fptr (), prec);
-
-      retval(0) = (double) count;
-    }
-
-  return retval;
-}
-
-DEFUN (fwrite, args, ,
+DEFUN (fwrite, , ,
   "COUNT = fwrite (FILENUM, DATA, PRECISION)\n\
 \n\
  Writes data to a file in binary form of size PRECISION\n\
@@ -1820,39 +695,8 @@
 \n\
  COUNT     : number of elements written")
 {
-  Octave_object retval;
-
-  int nargin = args.length ();
-
-  if (nargin < 2 || nargin > 3)
-    print_usage ("fwrite");
-  else
-    retval = fwrite_internal (args);
-
-  return retval;
-}
-
-// Check for an EOF condition on a file opened by fopen.
-//
-//   eof = feof (fid)
-//
-//     fid : file id from fopen
-//     eof : non zero for an end of file condition
-
-static Octave_object
-feof_internal (const Octave_object& args)
-{
-  Octave_object retval;
-
-  Pix p = return_valid_file (args(0));
-
-  if (! p)
-    return retval;
-
-  file_info file = file_list (p);
-
-  retval(0) = (double) feof (file.fptr ());
-
+  octave_value_list retval;
+  // XXX IMPLEMENTME XXX
   return retval;
 }
 
@@ -1862,125 +706,65 @@
  Returns a non zero value for an end of file condition for the\n\
  file specified by FILENAME or FILENUM from fopen")
 {
-  Octave_object retval;
+  double retval = -1.0;
 
   int nargin = args.length ();
 
-  if (nargin != 1)
-    print_usage ("feof");
-  else
-    retval = feof_internal (args);
-
-  return retval;
-}
-
-// Check for an error condition on a file opened by fopen.
-//
-//   [message, errnum] = ferror (fid)
-//
-//     fid     : file id from fopen
-//     message : system error message
-//     errnum  : error number
-
-static Octave_object
-ferror_internal (const Octave_object& args, int nargout)
-{
-  Octave_object retval;
-
-  Pix p = return_valid_file (args(0));
-
-  if (! p)
-    return retval;
+  if (nargin == 1)
+    {
+      octave_stream *os = octave_stream_list::lookup (args(0));
 
-  file_info file = file_list (p);
-
-  int ierr = ferror (file.fptr ());
-
-  if (nargout > 1)
-    retval(1) = (double) ierr;
-
-  retval(0) = strerror (ierr);
-
-  return retval;
-}
-
-DEFUN (ferror, args, nargout,
-  "ERROR = ferror (FILENAME or FILENUM)\n\
-\n\
- Returns a non zero value for an error condition on the\n\
- file specified by FILENAME or FILENUM from fopen")
-{
-  Octave_object retval;
-
-  int nargin = args.length ();
-
-  if (nargin != 1)
-    print_usage ("ferror");
+      if (os)
+	retval = os->eof () ? 1.0 : 0.0;
+      else
+	gripe_invalid_file_id ("feof");
+    }
   else
-    retval = ferror_internal (args, nargout);
+    print_usage ("feof");
 
   return retval;
 }
 
-static Octave_object
-popen_internal (const Octave_object& args)
+DEFUN (ferror, args, ,
+  "ERROR = ferror (FILENAME or FILENUM, [\"clear\"])\n\
+\n\
+ Returns a non zero value for an error condition on the\n\
+ file specified by FILENAME or FILENUM from fopen")
 {
-  Octave_object retval;
-
-  if (! args(0).is_string ())
-    {
-      error ("popen: file name must be a string");
-      return retval;
-    }
-
-  Pix p = return_valid_file (args(0));
+  octave_value_list retval;
 
-  if (p)
-    {
-      file_info file = file_list (p);
-
-      retval(0) = (double) file.number ();
+  int nargin = args.length ();
 
-      return retval;
-    }
+  if (nargin == 1 || nargin == 2)
+    {
+      octave_stream *os = octave_stream_list::lookup (args(0));
 
-  if (! args(1).is_string ())
-    {
-      error ("popen: file mode must be a string");
-      return retval;
-    }
+      if (os)
+	{
+	  bool clear = false;
 
-  string name = args(0).string_value ();
-  string mode = args(1).string_value ();
+	  if (nargin == 2)
+	    {
+	      string opt = args(1).string_value ();
+
+	      if (! error_state)
+		clear = (opt == "clear");
+	      else
+		return retval;
+	    }
 
-  if (mode.length () > 1 || (mode[0] != 'w' && mode[0] != 'r'))
-    {
-      error ("popen: invalid mode, must be either \"r\" or \"w\".");
-      return retval;
-    }
+	  int error_number = 0;
+
+	  string error_message = os->error (clear, error_number);
 
-  file_stat fs (name);
-
-  if (fs && fs.is_dir ())
-    {
-      error ("popen: can't open directory");
-      return retval;
+	  retval(1) = (double) error_number;
+	  retval(0) = error_message;
+	}
+      else
+	gripe_invalid_file_id ("ferror");
     }
-
-  FILE *file_ptr = popen (name.c_str (), mode.c_str ());
-
-  if (! file_ptr)
-    {
-      error ("popen: unable to start process `%s'", name.c_str ());
-      return retval;
-    }
-
-  int number = get_next_avail_file_num ();
-
-  file_info file (number, name, file_ptr, mode);
-  file_list.append (file);
-
-  retval(0) = (double) number;
+  else
+    print_usage ("ferror");
 
   return retval;
 }
@@ -1993,47 +777,43 @@
   \"r\" : connect stdout of process to pipe\n\
   \"w\" : connect stdin of process to pipe")
 {
-  Octave_object retval;
+  double retval = -1.0;
 
   int nargin = args.length ();
 
-  if (nargin != 2)
-    print_usage ("popen");
-  else
-    retval = popen_internal (args);
-
-  return retval;
-}
+  if (nargin == 2)
+    {
+      string name = args(0).string_value ();
 
-static Octave_object
-pclose_internal (const Octave_object& args)
-{
-  Octave_object retval;
+      if (! error_state)
+	{
+	  string mode = args(1).string_value ();
 
-  Pix p = return_valid_file (args(0));
-
-  if (! p)
-    return retval;
+	  if (! error_state)
+	    {
+	      if (mode == "r")
+		{
+		  octave_iprocstream *ips = new octave_iprocstream (name);
 
-  file_info file = file_list (p);
-
-  if (file.number () < 3)
-    {
-      warning ("pclose: can't close stdin, stdout, or stderr!");
-      return retval;
-    }
+		  retval = octave_stream_list::insert (ips);
+		}
+	      else if (mode == "w")
+		{
+		  octave_oprocstream *ops = new octave_oprocstream (name);
 
-  int success = pclose (file.fptr ());
-  next_available_file_number.push (file.number ());
-  file_list.del (p);
-
-  if (success == 0)
-    retval(0) = 1.0; // succeeded
+		  retval = octave_stream_list::insert (ops);
+		}
+	      else
+		::error ("popen: invalid mode specified");
+	    }
+	  else
+	    ::error ("popen: mode must be a string");
+	}
+      else
+	::error ("popen: name must be a string");
+    }
   else
-    {
-      error ("pclose: error on closing file");
-      retval(0) = 0.0; // failed
-    }
+    print_usage ("popen");
 
   return retval;
 }
@@ -2043,471 +823,19 @@
 \n\
   Close a pipe and terminate the associated process")
 {
-  Octave_object retval;
-
-  int nargin = args.length ();
-
-  if (nargin != 1)
-    print_usage ("pclose");
-  else
-    retval = pclose_internal (args);
-
-  return retval;
-}
-
-static Octave_object
-execute_internal (const Octave_object& args)
-{
-  Octave_object retval (3, tree_constant (-1.0));
-
-  pid_t pid = 0;
-  int stdin_pipe[2];
-  int stdout_pipe[2];
-  FILE *stdin_file;
-  FILE *stdout_file;
-  int new_stdin;
-  int new_stdout;
-
-  if (! args(0).is_string ())
-    {
-      error ("execute: file name must be a string");
-      return retval;
-    }
-
-  string name = args(0).string_value ();
-
-  if (pipe (stdin_pipe) || pipe (stdout_pipe)) 
-    {
-      error ("execute: pipe creation failed");
-      return retval;
-    }
-
-  pid = fork ();
-
-  if (pid < (pid_t) 0) 
-    {
-      error ("execute: fork failed - can't create child process");
-      return retval;
-    }
-
-  if (pid == (pid_t) 0) 
-    {
-      close (stdin_pipe[1]);
-      close (stdout_pipe[0]);
-
-      dup2 (stdin_pipe[0], STDIN_FILENO);
-      close (stdin_pipe[0]);
-    
-      dup2 (stdout_pipe[1], STDOUT_FILENO);
-      close (stdout_pipe[1]);
-
-      if (execlp (name.c_str (), name.c_str (), 0) == -1)
-	error ("execute: unable to start process `%s'", name.c_str ());
-
-      exit (0);
-      return 0.0;
-    } 
-  else 
-    {
-      close (stdin_pipe[0]);
-      close (stdout_pipe[1]);
-
-      stdout_file = fdopen (stdout_pipe[0], "r");
-      stdin_file = fdopen (stdin_pipe[1], "w"); 
-
-      if (fcntl (fileno (stdout_file), F_SETFL, O_NONBLOCK) < 0) 
-	{
-	  error ("execute: error setting file mode");
-	  return retval;
-	}
-
-      new_stdin = get_next_avail_file_num ();
-      new_stdout = new_stdin + 1;
-
-      file_info new_stdin_file_ptr (new_stdin, name, stdin_file, "w");
-      file_info new_stdout_file_ptr (new_stdout, name, stdout_file, "r");
-
-      file_list.append (new_stdin_file_ptr);
-      file_list.append (new_stdout_file_ptr);
-    }
-  
-  retval(2) = (double) pid;
-  retval(1) = (double) new_stdout;
-  retval(0) = (double) new_stdin;
-
-  return retval;
-}
-
-DEFUN (execute, args, ,
-  "[STDIN, STDOUT, PID] = execute (COMMAND)\n\
-\n\
-  Start a program and redirect its stdin to STDIN and its stdout to STDOUT")
-{
-  Octave_object retval;
-
-  int nargin = args.length ();
-
-  if (nargin != 1)
-    print_usage ("execute");
-  else
-    retval = execute_internal (args);
-
-  return retval;
-}
-
-static Octave_object
-sync_system_internal (const Octave_object& args)
-{
-  Octave_object retval (1, tree_constant (-1.0));
-
-  if (! args(0).is_string ())
-    {
-      error ("sync_system: file name must be a string");
-      return retval;
-    }
-
-  string name = args(0).string_value ();
-
-  retval (0) = (double) system (name.c_str ());
-  return retval;
-}
-
-DEFUN (sync_system, args, ,
-  "RETCODE = sync_system (FILENAME)\n\
-\n\
-  Start a program and wait until it terminates")
-{
-  Octave_object retval;
-
-  int nargin = args.length ();
-
-  if (nargin != 1)
-    print_usage ("sync_system");
-  else
-    retval = sync_system_internal (args);
-
-  return retval;
-}
-
-static Octave_object
-async_system_internal (const Octave_object& args)
-{
-  Octave_object retval (1, tree_constant (-1.0));
-  pid_t pid;
-
-  if (! args(0).is_string ())
-    {
-      error ("async_system: file name must be a string");
-      return retval;
-    }
-
-  string name = args(0).string_value ();
-
-  pid = fork ();
-
-  if (pid < 0) 
-    {
-      error ("async_system: fork failed -- can't create child process");
-      return retval;
-    }
-
-  if (pid == 0) 
-    {
-      system (name.c_str ());
-      exit (0);
-      retval (0) = 0.0;
-      return retval;
-    } 
-  else
-    {
-      retval (0) = (double) pid;
-      return retval;
-    }
-}
-
-DEFUN (async_system, args, ,
-  "PID = async_system (FILENAME)\n\
-\n\
-  Create a new process and start FILENAME")
-{
-  Octave_object retval;
+  double retval = -1.0;
 
   int nargin = args.length ();
 
-  if (nargin != 1)
-    print_usage ("async_system");
-  else
-    retval = async_system_internal (args);
-
-  return retval;
-}
-
-static Octave_object
-waitpid_internal (const Octave_object& args)
-{
-  Octave_object retval (1, tree_constant (-1.0));
-
-  double pid_num = args(0).double_value ();
-  
-  if (! error_state)
+  if (nargin == 1)
     {
-      if (D_NINT (pid_num) != pid_num)
-	error ("waitpid: PID must be an integer value");
-      else
-	{
-	  pid_t pid = (pid_t) pid_num;
-
-	  int options = 0;
-
-	  if (args.length () == 2)
-	    {
-	      double options_num = args(1).double_value ();
-
-	      if (! error_state)
-		{
-		  if (D_NINT (options_num) != options_num)
-		    error ("waitpid: PID must be an integer value");
-		  else
-		    {
-		      options = NINT (options_num);
-		      if (options < 0 || options > 3)
-			error ("waitpid: invalid OPTIONS value specified");
-		    }
-		}
-	    }
-
-	  if (! error_state)
-	    retval (0) = (double) waitpid (pid, 0, options);
-	}
-    }
-
-  return retval;
-}
-
-DEFUN (waitpid, args, ,
-  "STATUS = waitpid (PID, OPTIONS)\n\
-\n\
-  wait for process PID to terminate\n\
-\n\
-  PID can be:\n\
-\n\
-     -1 : wait for any child process\n\
-      0 : wait for any child process whose process group ID is equal to\n\
-          that of the Octave interpreter process.\n\
-    > 0 : wait for termination of the child process with ID PID.\n\
-\n\
-  OPTIONS is:\n\
-\n\
-     0 : wait until signal is received or a child process exits (this\n\
-         is the default if the OPTIONS argument is missing) \n\
-     1 : do not hang if status is not immediately available\n\
-     2 : report the status of any child processes that are\n\
-         stopped, and whose status has not yet been reported\n\
-         since they stopped\n\
-     3 : implies both 1 and 2\n\
-\n\
-  STATUS is:\n\
-\n\
-     -1 : if an error occured\n\
-    > 0 : the process ID of the child process that exited")
-{
-  Octave_object retval;
-
-  int nargin = args.length ();
-
-  if (nargin == 1 || nargin == 2)
-    retval = waitpid_internal (args);
-  else
-    print_usage ("waitpid");
-
-  return retval;
-}
-
-static Octave_object
-mkfifo_internal (const Octave_object& args)
-{
-  Octave_object retval (1, tree_constant (-1.0));
-
-  if (! args(0).is_string ())
-    {
-      error ("mkfifo: file name must be a string");
-      return retval;
-    }
-
-  string name = args(0).string_value ();
-
-  if (! args(1).is_scalar_type ())
-    {
-      error ("mkfifo:  MODE must be an integer");
-      return retval;
-    }
-
-  long mode = (long) args(1).double_value ();
-
-  retval (0) = (double) oct_mkfifo (name, mode);
-
-  return retval;
-}
+      retval = (double) octave_stream_list::remove (args(0));
 
-DEFUN (mkfifo, args, ,
-  "STATUS = mkfifo (NAME, MODE)\n\
-\n\
-  Create a FIFO special file named NAME with file mode MODE\n\
-\n\
-  STATUS is:\n\
-\n\
-    != 0 : if mkfifo failed\n\
-       0 : if the FIFO special file could be created")
-{
-  Octave_object retval;
-
-  int nargin = args.length ();
-
-  if (nargin != 2)
-    print_usage ("mkfifo");
-  else
-    retval = mkfifo_internal (args);
-
-  return retval;
-}
-
-static Octave_object
-unlink_internal (const Octave_object& args)
-{
-  Octave_object retval;
-
-  if (! args(0).is_string ())
-    {
-      error ("unlink: file name must be a string");
-      retval (0) = -1.0;
-      return retval;
-    }
-
-  string name = args(0).string_value ();
-
-  retval (0) = (double) oct_unlink (name);
-
-  return retval;
-}
-
-DEFUN (unlink, args, ,
-  "STATUS = unlink (NAME)\n\
-\n\
-  Delete the file NAME\n\
-\n\
-  STATUS is:\n\
-\n\
-    != 0 : if unlink failed\n\
-       0 : if the file could be successfully deleted")
-{
-  Octave_object retval;
-
-  int nargin = args.length ();
-
-  if (nargin != 1)
-    print_usage ("unlink");
-  else
-    retval = unlink_internal (args);
-
-  return retval;
-}
-
-static Octave_map
-mk_stat_map (const file_stat& fs)
-{
-  Octave_map m;
-
-  m["dev"] = (double) fs.dev ();
-  m["ino"] = (double) fs.ino ();
-  m["modestr"] = fs.mode_as_string ();
-  m["nlink"] = (double) fs.nlink ();
-  m["uid"] = (double) fs.uid ();
-  m["gid"] = (double) fs.gid ();
-#if defined (HAVE_ST_RDEV)
-  m["rdev"] = (double) fs.rdev ();
-#endif
-  m["size"] = (double) fs.size ();
-  m["atime"] = (double) fs.atime ();
-  m["mtime"] = (double) fs.mtime ();
-  m["ctime"] = (double) fs.ctime ();
-#if defined (HAVE_ST_BLKSIZE)
-  m["blksize"] = (double) fs.blksize ();
-#endif
-#if defined (HAVE_ST_BLOCKS)
-  m["blocks"] = (double) fs.blocks ();
-#endif
-
-  return m;
-}
-
-DEFUN (stat, args, ,
-  "stat (NAME)\n\
-\n\
-  Given the name of a file, return a structure with the following
-  elements:\n\
-\n\
-    dev     : id of device containing a directory entry for this file\n\
-    ino     : file number of the file\n\
-    modestr : file mode, as a string of ten letters or dashes as in ls -l\n\
-    nlink   : number of links\n\
-    uid     : user id of file's owner\n\
-    gid     : group id of file's group \n\
-    rdev    : id of device for block or character special files\n\
-    size    : size in bytes\n\
-    atime   : time of last access\n\
-    mtime   : time of last modification\n\
-    ctime   : time of last file status change\n\
-    blksize : size of blocks in the file\n\
-    blocks  : number of blocks allocated for file\n\
-\n\
-  If the file does not exist, -1 is returned.")
-{
-  Octave_object retval;
-
-  if (args.length () == 1)
-    {
-      string fname = oct_tilde_expand (args(0).string_value ());
-
-      if (! error_state)
-	{
-	  file_stat fs (fname);
-
-	  if (fs)
-	    retval = tree_constant (mk_stat_map (fs));
-	  else
-	    retval = -1.0;
-	}
+      if (retval < 0)
+	gripe_invalid_file_id ("pclose");
     }
   else
-    print_usage ("stat");
-
-  return retval;
-}
-
-DEFUN (lstat, args, ,
-  "lstat (NAME)\n\
-\n\
-  Like stat (NAME), but if NAME refers to a symbolic link, returns\n\
-  information about the link itself, not the file that it points to.")
-{
-  Octave_object retval;
-
-  if (args.length () == 1)
-    {
-      string fname = oct_tilde_expand (args(0).string_value ());
-
-      if (! error_state)
-	{
-	  file_stat fs (fname);
-
-	  if (fs)
-	    retval = tree_constant (mk_stat_map (fs));
-	  else
-	    retval = -1.0;
-	}
-    }
-  else
-    print_usage ("stat");
+    print_usage ("pclose");
 
   return retval;
 }
@@ -2515,7 +843,7 @@
 DEFUN (octave_tmp_file_name, args, ,
  "octave_tmp_file_name ()")
 {
-  tree_constant retval;
+  octave_value retval;
 
   if (args.length () == 0)
     retval = oct_tempnam ();
@@ -2533,7 +861,7 @@
   int tmp = x % obase;
 
   if (tmp > ibase - 1)
-    error ("umask: invalid digit");
+    ::error ("umask: invalid digit");
   else
     {
       retval = tmp;
@@ -2543,7 +871,7 @@
 	  tmp = x % obase;
 	  if (tmp > ibase - 1)
 	    {
-	      error ("umask: invalid digit");
+	      ::error ("umask: invalid digit");
 	      break;
 	    }
 	  retval += mult * tmp;
@@ -2563,7 +891,7 @@
 be interpreted as an octal number); otherwise an error message is
 printed.")
 {
-  Octave_object retval;
+  octave_value_list retval;
 
   int status = 0;
 
@@ -2574,7 +902,7 @@
       if (error_state)
 	{
 	  status = -1;
-	  error ("umask: expecting integer argument");
+	  ::error ("umask: expecting integer argument");
 	}
       else
 	{
@@ -2583,7 +911,7 @@
 	  if ((double) mask != dmask || mask < 0)
 	    {
 	      status = -1;
-	      error ("umask: MASK must be a positive integer value");
+	      ::error ("umask: MASK must be a positive integer value");
 	    }
 	  else
 	    {
--- a/src/fsolve.cc
+++ b/src/fsolve.cc
@@ -26,7 +26,7 @@
 
 #include <string>
 
-#include <strstream.h>
+#include <iostream.h>
 
 #include "NLEqn.h"
 
@@ -208,36 +208,33 @@
 };
 
 static void
-print_fsolve_option_list (void)
+print_fsolve_option_list (ostream& os)
 {
-  ostrstream output_buf;
-
   print_usage ("fsolve_options", 1);
 
-  output_buf << "\n"
-	     << "Options for fsolve include:\n\n"
-	     << "  keyword                                  value\n"
-	     << "  -------                                  -----\n\n";
+  os << "\n"
+     << "Options for fsolve include:\n\n"
+     << "  keyword                                  value\n"
+     << "  -------                                  -----\n\n";
 
   NLEQN_OPTIONS *list = fsolve_option_table;
 
   const char *keyword;
   while ((keyword = list->keyword) != 0)
     {
-      output_buf.form ("  %-40s ", keyword);
+      os.form ("  %-40s ", keyword);
 
       double val = (fsolve_opts.*list->d_get_fcn) ();
       if (val < 0.0)
-	output_buf << "computed automatically";
+	os << "computed automatically";
       else
-	output_buf << val;
+	os << val;
 
-      output_buf << "\n";
+      os << "\n";
       list++;
     }
 
-  output_buf << "\n" << ends;
-  maybe_page_output (output_buf);
+  os << "\n";
 }
 
 static void
@@ -294,7 +291,7 @@
 
   if (nargin == 0)
     {
-      print_fsolve_option_list ();
+      print_fsolve_option_list (octave_stdout);
       return retval;
     }
   else if (nargin == 1 || nargin == 2)
--- a/src/help.cc
+++ b/src/help.cc
@@ -315,19 +315,17 @@
 Use the command `help -i <topic>' to search the manual index.\n"
 
 static void
-additional_help_message (ostrstream& output_buf)
+additional_help_message (ostream& os)
 {
 #ifdef USE_GNU_INFO
   if (! user_pref.suppress_verbose_help_message)
-    output_buf << VERBOSE_HELP_MESSAGE;
+    os << VERBOSE_HELP_MESSAGE;
 #endif
 }
 
 void
 print_usage (const string& nm, int just_usage)
 {
-  ostrstream output_buf;
-
   symbol_record *sym_rec = global_sym_tab->lookup (nm, 0, 0);
   if (sym_rec)
     {
@@ -335,13 +333,11 @@
 
       if (h.length () > 0)
 	{
-	  output_buf << "\n*** " << nm << ":\n\n"
+	  octave_stdout << "\n*** " << nm << ":\n\n"
 	    << h << "\n";
 
 	  if (! just_usage)
-	    additional_help_message (output_buf);
-	  output_buf << ends;
-	  maybe_page_output (output_buf);
+	    additional_help_message (octave_stdout);
 	}
     }
   else
@@ -349,20 +345,20 @@
 }
 
 static void
-display_names_from_help_list (ostrstream& output_buf, help_list *list,
+display_names_from_help_list (ostream& os, help_list *list,
 			      const char *desc)
 {
   int count = 0;
   string_vector symbols = names (list, count);
   if (! symbols.empty ())
     {
-      output_buf << "\n*** " << desc << ":\n\n";
-      symbols.list_in_columns (output_buf);
+      os << "\n*** " << desc << ":\n\n";
+      symbols.list_in_columns (os);
     }
 }
 
 static string
-print_symbol_type (ostrstream& output_buf, symbol_record *sym_rec,
+print_symbol_type (ostream& os, symbol_record *sym_rec,
 		   const string& name, int print)
 {
   string retval;
@@ -380,16 +376,16 @@
 	  ff = ff.length () > 0 ? ff : fn;
 
 	  if (print)
-	    output_buf << name
-	      << " is the function defined from:\n"
-		<< ff << "\n";
+	    os << name
+	       << " is the function defined from:\n"
+	       << ff << "\n";
 	  else
 	    retval = ff;
 	}
       else
 	{
 	  if (print)
-	    output_buf << name << " is a user-defined function\n";
+	    os << name << " is a user-defined function\n";
 	  else
 	    retval = "user-defined function";
 	}
@@ -397,36 +393,35 @@
   else if (sym_rec->is_text_function ())
     {
       if (print)
-	output_buf << name << " is a builtin text-function\n";
+	os << name << " is a builtin text-function\n";
       else
 	retval = "builtin text-function";
     }
   else if (sym_rec->is_builtin_function ())
     {
       if (print)
-	output_buf << name << " is a builtin function\n";
+	os << name << " is a builtin function\n";
       else
 	retval = "builtin function";
     }
   else if (sym_rec->is_user_variable ())
     {
       if (print)
-	output_buf << name << " is a user-defined variable\n";
+	os << name << " is a user-defined variable\n";
       else
 	retval = "user-defined variable";
     }
   else if (sym_rec->is_builtin_variable ())
     {
       if (print)
-	output_buf << name << " is a builtin variable\n";
+	os << name << " is a builtin variable\n";
       else
 	retval = "builtin variable";
     }
   else
     {
       if (print)
-	output_buf << "which: `" << name
-	  << "' has unknown type\n";
+	os << "which: `" << name << "' has unknown type\n";
       else
 	retval = "unknown type";
     }
@@ -435,25 +430,23 @@
 }
 
 static void
-display_symtab_names (ostrstream& output_buf, const string_vector& names,
+display_symtab_names (ostream& os, const string_vector& names,
 		      int /* count */, const string& desc)
 {
   if (! names.empty ())
     {
-      output_buf << "\n*** " << desc << ":\n\n";
-      names.list_in_columns (output_buf);
+      os << "\n*** " << desc << ":\n\n";
+      names.list_in_columns (os);
     }
 }
 
 static void
 simple_help (void)
 {
-  ostrstream output_buf;
-
-  display_names_from_help_list (output_buf, operator_help (),
+  display_names_from_help_list (octave_stdout, operator_help (),
 				"operators");
 
-  display_names_from_help_list (output_buf, keyword_help (),
+  display_names_from_help_list (octave_stdout, keyword_help (),
 				"reserved words");
 
 #ifdef LIST_SYMBOLS
@@ -464,7 +457,7 @@
     { \
       int count; \
       string_vector names = global_sym_tab->list (count, 0, 0, 1, type); \
-      display_symtab_names (output_buf, names, count, msg); \
+      display_symtab_names (octave_stdout, names, count, msg); \
     } \
   while (0)
 
@@ -496,17 +489,16 @@
 
       if (! names.empty ())
 	{
-	  output_buf << "\n*** function files in "
-		     << make_absolute (dirs[i], the_current_working_directory)
-		     << ":\n\n";
+	  octave_stdout << "\n*** function files in "
+			<< make_absolute (dirs[i],
+					  the_current_working_directory)
+			<< ":\n\n";
 
-	  names.list_in_columns (output_buf);
+	  names.list_in_columns (octave_stdout);
 	}
     }
 
-  additional_help_message (output_buf);
-  output_buf << ends;
-  maybe_page_output (output_buf);
+  additional_help_message (octave_stdout);
 }
 
 #ifdef USE_GNU_INFO
@@ -591,7 +583,7 @@
 }
 
 int
-help_from_list (ostrstream& output_buf, const help_list *list,
+help_from_list (ostream& os, const help_list *list,
 		const string& nm, int usage)
 {
   char *name;
@@ -600,13 +592,13 @@
       if (strcmp (name, nm.c_str ()) == 0)
 	{
 	  if (usage)
-	    output_buf << "\nusage: ";
+	    os << "\nusage: ";
 	  else
 	    {
-	      output_buf << "\n*** " << nm << ":\n\n";
+	      os << "\n*** " << nm << ":\n\n";
 	    }
 
-	  output_buf << list->help << "\n";
+	  os << list->help << "\n";
 
 	  return 1;
 	}
@@ -618,17 +610,15 @@
 static void
 builtin_help (int argc, const string_vector& argv)
 {
-  ostrstream output_buf;
-
   help_list *op_help_list = operator_help ();
   help_list *kw_help_list = keyword_help ();
 
   for (int i = 1; i < argc; i++)
     {
-      if (help_from_list (output_buf, op_help_list, argv[i], 0))
+      if (help_from_list (octave_stdout, op_help_list, argv[i], 0))
 	continue;
 
-      if (help_from_list (output_buf, kw_help_list, argv[i], 0))
+      if (help_from_list (octave_stdout, kw_help_list, argv[i], 0))
 	continue;
 
       symbol_record *sym_rec = lookup_by_name (argv[i], 0);
@@ -639,8 +629,8 @@
 
 	  if (h.length () > 0)
 	    {
-	      print_symbol_type (output_buf, sym_rec, argv[i], 1);
-	      output_buf << "\n" << h << "\n";
+	      print_symbol_type (octave_stdout, sym_rec, argv[i], 1);
+	      octave_stdout << "\n" << h << "\n";
 	      continue;
 	    }
 	}
@@ -651,18 +641,17 @@
 
       if (! h.empty ())
 	{
-	  output_buf << argv[i] << " is the file:\n"
+	  octave_stdout << argv[i] << " is the file:\n"
 	    << path << "\n\n" << h << "\n";
 
 	  continue;
 	}
 
-      output_buf << "\nhelp: sorry, `" << argv[i] << "' is not documented\n"; 
+      octave_stdout << "\nhelp: sorry, `" << argv[i]
+		    << "' is not documented\n"; 
     }
 
-  additional_help_message (output_buf);
-  output_buf << ends;
-  maybe_page_output (output_buf);
+  additional_help_message (octave_stdout);
 }
 
 #ifdef USE_GNU_INFO
@@ -834,14 +823,14 @@
 
       output_buf << ends;
 
+      char *s = output_buf.str ();
+
       if (nargout == 0)
-	maybe_page_output (output_buf);
+	octave_stdout << s;
       else
-	{
-	  char *s = output_buf.str ();
-	  retval = s;
-	  delete [] s;
-	}
+	retval = s;
+
+      delete [] s;
     }
   else
     print_usage ("type");
@@ -871,8 +860,6 @@
       if (nargout > 0)
 	retval.resize (argc-1, Matrix ());
 
-      ostrstream output_buf;
-
       for (int i = 1; i < argc; i++)
 	{
 	  symbol_record *sym_rec = lookup_by_name (argv[i], 0);
@@ -880,7 +867,7 @@
 	  if (sym_rec)
 	    {
 	      int print = (nargout == 0);
-	      string tmp = print_symbol_type (output_buf, sym_rec,
+	      string tmp = print_symbol_type (octave_stdout, sym_rec,
 					      argv[i], print);
 	      if (! print)
 		retval(i) = tmp;
@@ -888,13 +875,11 @@
 	  else
 	    {
 	      if (nargout == 0)
-		output_buf << "which: `" << argv[i] << "' is undefined\n";
+		octave_stdout << "which: `" << argv[i] << "' is undefined\n";
 	      else
 		retval(i) = "undefined";
 	    }
 	}
-      output_buf << ends;
-      maybe_page_output (output_buf);
     }
   else
     print_usage ("which");
--- a/src/input.cc
+++ b/src/input.cc
@@ -46,7 +46,6 @@
 #include <string>
 
 #include <iostream.h>
-#include <strstream.h>
 
 #ifdef HAVE_UNISTD_H
 #include <sys/types.h>
@@ -369,27 +368,23 @@
 
   if (do_echo)
     {
-      ostrstream buf;
-
       if (forced_interactive)
 	{
 	  if (promptflag > 0)
-	    buf << decode_prompt_string (user_pref.ps1);
+	    octave_stdout << decode_prompt_string (user_pref.ps1);
 	  else
-	    buf << decode_prompt_string (user_pref.ps2);
+	    octave_stdout << decode_prompt_string (user_pref.ps2);
 	}
       else
-	buf << decode_prompt_string (user_pref.ps4);
+	octave_stdout << decode_prompt_string (user_pref.ps4);
 
       if (! input_string.empty ())
 	{
-	  buf << input_string;
+	  octave_stdout << input_string;
 
 	  if (input_string[input_string.length () - 1] != '\n')
-	    buf << "\n";
+	    octave_stdout << "\n";
 	}
-
-      maybe_page_output (buf);
     }
 }
 
@@ -478,10 +473,10 @@
       if (interactive)
 	{
 	  pipe_handler_error_count = 0;
-	  flush_output_to_pager ();
+	  flush_octave_stdout ();
 	}
 
-      maybe_write_to_diary_file (prompt);
+      octave_diary << prompt;
 
       retval = gnu_readline (prompt.c_str ());
     }
@@ -498,12 +493,12 @@
       if (! input_from_startup_file)
 	octave_command_history.add (current_input_line);
 
-      maybe_write_to_diary_file (current_input_line);
+      octave_diary << current_input_line;
 
       do_input_echo (current_input_line);
     }
 
-  maybe_write_to_diary_file ("\n");
+  octave_diary << "\n";
   
   return retval;
 }
@@ -1030,7 +1025,7 @@
 
  again:
 
-  flush_output_to_pager ();
+  flush_octave_stdout ();
 
   char *input_buf = gnu_readline (prompt.c_str ());
 
--- a/src/load-save.cc
+++ b/src/load-save.cc
@@ -1350,15 +1350,16 @@
 
   if (list_only && count)
     {
+      output_buf << ends;
+
+      char *msg = output_buf.str ();
+
       if (nargout > 0)
-	{
-	  output_buf << ends;
-	  char *msg = output_buf.str ();
-	  retval = msg;
-	  delete [] msg;
-	}
+	retval = msg;
       else
-	maybe_page_output (output_buf);
+	octave_stdout << msg;
+
+      delete [] msg;
     }
 
   return retval;
@@ -2117,14 +2118,15 @@
 }
 
 static void
-write_binary_header (ostream& stream, load_save_format format)
+write_binary_header (ostream& os, load_save_format format)
 {
   if (format == LS_BINARY)
     {
-      stream << (octave_words_big_endian ? "Octave-1-B" : "Octave-1-L");
+      os << (octave_words_big_endian ? "Octave-1-B" : "Octave-1-L");
 
       char tmp = (char) native_float_format;
-      stream.write (&tmp, 1);
+
+      os.write (&tmp, 1);
     }
 }
 
@@ -2248,12 +2250,8 @@
       // XXX FIXME XXX -- should things intended for the screen end up
       // in a octave_value (string)?
 
-      ostrstream buf;
-
-      save_vars (argv, i, argc, buf, save_builtins, format,
+      save_vars (argv, i, argc, octave_stdout, save_builtins, format,
 		 save_as_floats);
-
-      maybe_page_output (buf);
     }
 
   // Guard against things like `save a*', which are probably mistakes...
--- a/src/lsode.cc
+++ b/src/lsode.cc
@@ -26,7 +26,7 @@
 
 #include <string>
 
-#include <strstream.h>
+#include <iostream.h>
 
 #include "LSODE.h"
 
@@ -223,36 +223,33 @@
 };
 
 static void
-print_lsode_option_list (void)
+print_lsode_option_list (ostream& os)
 {
-  ostrstream output_buf;
-
   print_usage ("lsode_options", 1);
 
-  output_buf << "\n"
-	     << "Options for lsode include:\n\n"
-	     << "  keyword                                  value\n"
-	     << "  -------                                  -----\n\n";
+  os << "\n"
+     << "Options for lsode include:\n\n"
+     << "  keyword                                  value\n"
+     << "  -------                                  -----\n\n";
 
   LSODE_OPTIONS *list = lsode_option_table;
 
   const char *keyword;
   while ((keyword = list->keyword) != 0)
     {
-      output_buf.form ("  %-40s ", keyword);
+      os.form ("  %-40s ", keyword);
 
       double val = (lsode_opts.*list->d_get_fcn) ();
       if (val < 0.0)
-	output_buf << "computed automatically";
+	os << "computed automatically";
       else
-	output_buf << val;
+	os << val;
 
-      output_buf << "\n";
+      os << "\n";
       list++;
     }
 
-  output_buf << "\n" << ends;
-  maybe_page_output (output_buf);
+  os << "\n";
 }
 
 static void
@@ -309,7 +306,7 @@
 
   if (nargin == 0)
     {
-      print_lsode_option_list ();
+      print_lsode_option_list (octave_stdout);
       return retval;
     }
   else if (nargin == 1 || nargin == 2)
--- a/src/npsol.cc
+++ b/src/npsol.cc
@@ -26,7 +26,7 @@
 
 #include <string>
 
-#include <strstream.h>
+#include <iostream.h>
 
 #include "NPSOL.h"
 
@@ -673,45 +673,42 @@
 };
 
 static void
-print_npsol_option_list (void)
+print_npsol_option_list (ostream& os)
 {
-  ostrstream output_buf;
-
   print_usage ("npsol_options", 1);
 
-  output_buf << "\n"
-	     << "Options for npsol include:\n\n"
-	     << "  keyword                                  value\n"
-	     << "  -------                                  -----\n\n";
+  os << "\n"
+     << "Options for npsol include:\n\n"
+     << "  keyword                                  value\n"
+     << "  -------                                  -----\n\n";
 
   NPSOL_OPTIONS *list = npsol_option_table;
 
   const char *keyword;
   while ((keyword = list->keyword) != 0)
     {
-      output_buf.form ("  %-40s ", keyword);
+      os.form ("  %-40s ", keyword);
       if (list->d_get_fcn)
 	{
 	  double val = (npsol_opts.*list->d_get_fcn) ();
 	  if (val < 0.0)
-	    output_buf << "computed automatically";
+	    os << "computed automatically";
 	  else
-	    output_buf << val;
+	    os << val;
 	}
       else
 	{
 	  int val = (npsol_opts.*list->i_get_fcn) ();
 	  if (val < 0)
-	    output_buf << "depends on problem size";
+	    os << "depends on problem size";
 	  else
-	    output_buf << val;
+	    os << val;
 	}
-      output_buf << "\n";
+      os << "\n";
       list++;
     }
 
-  output_buf << "\n" << ends;
-  maybe_page_output (output_buf);
+  os << "\n";
 }
 
 static void
@@ -796,7 +793,7 @@
 
   if (nargin == 0)
     {
-      print_npsol_option_list ();
+      print_npsol_option_list (octave_stdout);
       return retval;
     }
   else if (nargin == 1 || nargin == 2)
--- a/src/oct-hist.cc
+++ b/src/oct-hist.cc
@@ -38,7 +38,6 @@
 #include <string>
 
 #include <fstream.h>
-#include <strstream.h>
 
 #ifdef HAVE_UNISTD_H
 #include <sys/types.h>
@@ -196,17 +195,8 @@
 
   int len = hlist.length ();
 
-  if (len > 0)
-    {
-      ostrstream output_buf;
-
-      for (i = 0; i < len; i++)
-	output_buf << hlist[i] << "\n";
-
-      output_buf << ends;
-
-      maybe_page_output (output_buf);
-    }
+  for (i = 0; i < len; i++)
+    octave_stdout << hlist[i] << "\n";
 }
 
 // Read the edited history lines from STREAM and return them
--- a/src/octave.cc
+++ b/src/octave.cc
@@ -58,7 +58,6 @@
 #include "lex.h"
 #include "oct-hist.h"
 #include "toplev.h"
-#include "pager.h"
 #include "parse.h"
 #include "pathsearch.h"
 #include "procstream.h"
@@ -398,8 +397,6 @@
 
   init_user_prefs ();
 
-  initialize_pager ();
-
   sysdep_init ();
 
   initialize_error_handlers ();
--- a/src/pager.h
+++ b/src/pager.h
@@ -23,17 +23,98 @@
 #if !defined (octave_pager_h)
 #define octave_pager_h 1
 
-class ostrstream;
-
 #include <string>
 
-extern char *get_pager (void);
-extern void initialize_pager (void);
-extern void maybe_page_output (ostrstream& msg_buf);
-extern void flush_output_to_pager (void);
+#include <iostream.h>
+#include <strstream.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+class
+octave_pager_buf : public strstreambuf
+{
+public:
+
+  octave_pager_buf (int size = 0) : strstreambuf (size) { }
+
+protected:
+
+  int sync (void);
+};
+
+class
+octave_pager_stream : public ostream
+{
+protected:
+
+  octave_pager_stream (void);
+
+public:
+
+  ~octave_pager_stream (void);
+
+  static octave_pager_stream& stream (void);
+
+private:
+
+  static octave_pager_stream *instance;
+
+  octave_pager_buf *pb;
+
+  // No copying!
+
+  octave_pager_stream (const octave_pager_stream&);
+
+  octave_pager_stream& operator = (const octave_pager_stream&);
+};
 
-extern void close_diary_file (void);
-extern void maybe_write_to_diary_file (const string& s);
+class
+octave_diary_buf : public strstreambuf
+{
+public:
+
+  octave_diary_buf (int size = 0) : strstreambuf (size) { }
+
+protected:
+
+  int sync (void);
+};
+
+class
+octave_diary_stream : public ostream
+{
+protected:
+
+  octave_diary_stream (void);
+
+public:
+
+  ~octave_diary_stream (void);
+
+  static octave_diary_stream& stream (void);
+
+private:
+
+  static octave_diary_stream *instance;
+
+  octave_diary_buf *db;
+
+  // No copying!
+
+  octave_diary_stream (const octave_diary_stream&);
+
+  octave_diary_stream& operator = (const octave_diary_stream&);
+};
+
+#define octave_stdout (octave_pager_stream::stream ())
+
+#define octave_diary (octave_diary_stream::stream ())
+
+extern void flush_octave_stdout (void);
+
+extern pid_t octave_pager_pid;
 
 #endif
 
--- a/src/procstream.h
+++ b/src/procstream.h
@@ -28,7 +28,12 @@
 #endif
 
 #include <iostream.h>
-#include <procbuf.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "oct-procbuf.h"
 
 class
 procstreambase : virtual public ios
@@ -47,9 +52,11 @@
 
   int close (void);
 
+  pid_t pid (void) { return pb.pid (); }
+
 private:
 
-  procbuf pb;
+  octave_procbuf pb;
 
   void pb_init (void) { init (&pb); }
 
--- a/src/pt-const.cc
+++ b/src/pt-const.cc
@@ -35,7 +35,6 @@
 
 #include <fstream.h>
 #include <iostream.h>
-#include <strstream.h>
 
 #include <SLList.h>
 
@@ -252,24 +251,18 @@
 void
 octave_value::print (void)
 {
-  ostrstream output_buf;
-  print (output_buf);
-  output_buf << ends;
-  maybe_page_output (output_buf);
+  print (octave_stdout);
 }
 
 void
 octave_value::print_with_name (const string& name, bool print_padding)
 {
-  ostrstream output_buf;
-  print_with_name (output_buf, name, print_padding);
-  output_buf << ends;
-  maybe_page_output (output_buf);
+  print_with_name (octave_stdout, name, print_padding);
 }
 
 void
 octave_value::print_with_name (ostream& output_buf, const string& name,
-				bool print_padding) 
+			       bool print_padding) 
 {
   bool pad_after = false;
 
--- a/src/pt-fcn.cc
+++ b/src/pt-fcn.cc
@@ -29,7 +29,6 @@
 #endif
 
 #include <iostream.h>
-#include <strstream.h>
 
 #include "defun.h"
 #include "error.h"
@@ -416,10 +415,7 @@
 void
 tree_function::print_code_function_header (void)
 {
-  ostrstream output_buf;
-  print_code_function_header (output_buf);
-  output_buf << ends;
-  maybe_page_output (output_buf);
+  print_code_function_header (octave_stdout);
 }
 
 void
@@ -470,10 +466,7 @@
 void
 tree_function::print_code_function_trailer (void)
 {
-  ostrstream output_buf;
-  print_code_function_trailer (output_buf);
-  output_buf << ends;
-  maybe_page_output (output_buf);
+  print_code_function_trailer (octave_stdout);
 }
 
 void
--- a/src/pt-misc.cc
+++ b/src/pt-misc.cc
@@ -29,7 +29,6 @@
 #endif
 
 #include <iostream.h>
-#include <strstream.h>
 
 #ifdef HAVE_UNISTD_H
 #include <sys/types.h>
@@ -85,12 +84,7 @@
 {
   if (in_function_body
       && (user_pref.echo_executing_commands & ECHO_FUNCTIONS))
-    {
-      ostrstream output_buf;
-      print_code (output_buf);
-      output_buf << ends;
-      maybe_page_output (output_buf);
-    }
+    print_code (octave_stdout);
 }
 
 void
--- a/src/pt-mvr.cc
+++ b/src/pt-mvr.cc
@@ -29,7 +29,6 @@
 #endif
 
 #include <iostream.h>
-#include <strstream.h>
 
 #include "error.h"
 #include "oct-obj.h"
@@ -342,11 +341,7 @@
 		break;
 
 	      if (print && pad_after)
-		{
-		  ostrstream output_buf;
-		  output_buf << "\n" << ends;
-		  maybe_page_output (output_buf);
-		}
+		octave_stdout << "\n";
 
 	      if (print)
 		results(i).print_with_name (lhs_expr->name (), 0);
@@ -365,11 +360,7 @@
 	}
 
       if (print && pad_after)
-	{
-	  ostrstream output_buf;
-	  output_buf << "\n" << ends;
-	  maybe_page_output (output_buf);
-	}
+	octave_stdout << "\n";
     }
 
   return results;
--- a/src/qpsol.cc
+++ b/src/qpsol.cc
@@ -26,7 +26,7 @@
 
 #include <string>
 
-#include <strstream.h>
+#include <iostream.h>
 
 #include "QPSOL.h"
 
@@ -314,45 +314,42 @@
 };
 
 static void
-print_qpsol_option_list (void)
+print_qpsol_option_list (ostream& os)
 {
-  ostrstream output_buf;
-
   print_usage ("qpsol_options", 1);
 
-  output_buf << "\n"
-	     << "Options for qpsol include:\n\n"
-	     << "  keyword                                  value\n"
-	     << "  -------                                  -----\n\n";
+  os << "\n"
+     << "Options for qpsol include:\n\n"
+     << "  keyword                                  value\n"
+     << "  -------                                  -----\n\n";
 
   QPSOL_OPTIONS *list = qpsol_option_table;
 
   const char *keyword;
   while ((keyword = list->keyword) != 0)
     {
-      output_buf.form ("  %-40s ", keyword);
+      os.form ("  %-40s ", keyword);
       if (list->d_get_fcn)
 	{
 	  double val = (qpsol_opts.*list->d_get_fcn) ();
 	  if (val < 0.0)
-	    output_buf << "computed automatically";
+	    os << "computed automatically";
 	  else
-	    output_buf << val;
+	    os << val;
 	}
       else
 	{
 	  int val = (qpsol_opts.*list->i_get_fcn) ();
 	  if (val < 0)
-	    output_buf << "depends on problem size";
+	    os << "depends on problem size";
 	  else
-	    output_buf << val;
+	    os << val;
 	}
-      output_buf << "\n";
+      os << "\n";
       list++;
     }
 
-  output_buf << "\n" << ends;
-  maybe_page_output (output_buf);
+  os << "\n";
 }
 
 static void
@@ -437,7 +434,7 @@
 
   if (nargin == 0)
     {
-      print_qpsol_option_list ();
+      print_qpsol_option_list (octave_stdout);
       return retval;
     }
   else if (nargin == 1 || nargin == 2)
--- a/src/quad.cc
+++ b/src/quad.cc
@@ -26,7 +26,7 @@
 
 #include <string>
 
-#include <strstream.h>
+#include <iostream.h>
 
 #include "Quad.h"
 
@@ -280,36 +280,33 @@
 };
 
 static void
-print_quad_option_list (void)
+print_quad_option_list (ostream& os)
 {
-  ostrstream output_buf;
-
   print_usage ("quad_options", 1);
 
-  output_buf << "\n"
-	     << "Options for quad include:\n\n"
-	     << "  keyword                                  value\n"
-	     << "  -------                                  -----\n\n";
+  os << "\n"
+     << "Options for quad include:\n\n"
+     << "  keyword                                  value\n"
+     << "  -------                                  -----\n\n";
 
   QUAD_OPTIONS *list = quad_option_table;
 
   const char *keyword;
   while ((keyword = list->keyword) != 0)
     {
-      output_buf.form ("  %-40s ", keyword);
+      os.form ("  %-40s ", keyword);
 
       double val = (quad_opts.*list->d_get_fcn) ();
       if (val < 0.0)
-	output_buf << "computed automatically";
+	os << "computed automatically";
       else
-	output_buf << val;
+	os << val;
 
-      output_buf << "\n";
+      os << "\n";
       list++;
     }
 
-  output_buf << "\n" << ends;
-  maybe_page_output (output_buf);
+  os << "\n";
 }
 
 static void
@@ -366,7 +363,7 @@
 
   if (nargin == 0)
     {
-      print_quad_option_list ();
+      print_quad_option_list (octave_stdout);
       return retval;
     }
   else if (nargin == 1 || nargin == 2)
--- a/src/syswait.h
+++ b/src/syswait.h
@@ -26,14 +26,22 @@
 // This mess suggested by the autoconf manual.
 
 #include <sys/types.h>
+
 #if HAVE_SYS_WAIT_H
 #include <sys/wait.h>
 #endif
+
+#ifndef WIFEXITED
+#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+
 #ifndef WEXITSTATUS
 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
 #endif
-#ifndef WIFEXITED
-#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+
+#ifndef WIFSIGNALLED
+#define WIFSIGNALLED(stat_val) \
+  (((stat_val) & 0177) != 0177 && ((stat_val) & 0177) != 0)
 #endif
 
 #endif
--- a/src/toplev.cc
+++ b/src/toplev.cc
@@ -308,8 +308,6 @@
 
   close_plot_stream ();
 
-  close_diary_file ();
-
   close_files ();
 
   cleanup_tmp_files ();
@@ -362,25 +360,17 @@
   if (nargin != 0)
     warning ("computer: ignoring extra arguments");
 
-  ostrstream output_buf;
+  string msg;
 
   if (strcmp (TARGET_HOST_TYPE, "unknown") == 0)
-    output_buf << "Hi Dave, I'm a HAL-9000";
+    msg = "Hi Dave, I'm a HAL-9000";
   else
-    output_buf << TARGET_HOST_TYPE;
+    msg = TARGET_HOST_TYPE;
 
   if (nargout == 0)
-    {
-      output_buf << "\n" << ends;
-      maybe_page_output (output_buf);
-    }
+    octave_stdout << msg << "\n";
   else
-    {
-      output_buf << ends;
-      char *msg = output_buf.str ();
-      retval = msg;
-      delete [] msg;
-    }
+    retval = msg;
 
   return retval;
 }
@@ -420,8 +410,7 @@
 {
   octave_value_list retval;
 
-  ostrstream output_buf;
-  output_buf << "\n" OCTAVE_NAME_VERSION_AND_COPYRIGHT "\n\n\
+  octave_stdout << "\n" OCTAVE_NAME_VERSION_AND_COPYRIGHT "\n\n\
 This program is free software; you can redistribute it and/or modify\n\
 it under the terms of the GNU General Public License as published by\n\
 the Free Software Foundation; either version 2 of the License, or\n\
@@ -437,9 +426,6 @@
 Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n\
 \n";
 
-  output_buf << ends;
-  maybe_page_output (output_buf);
-
   return retval;
 }
 
@@ -627,18 +613,19 @@
   if (cmd && *cmd)
     {
       ostrstream output_buf;
-	      
+
       char ch;
       while (cmd->get (ch))
 	{
-	  if (return_output || user_pref.page_screen_output)
+	  if (return_output)
 	    output_buf.put (ch);
+
+	  if (user_pref.page_screen_output)
+	    octave_stdout.put (ch);
 	  else
 	    cout.put (ch);
 	}
 
-      output_buf << ends;
-
       status = cmd->close ();
 
       // The value in status is as returned by waitpid.  If the
@@ -657,8 +644,6 @@
 
 	  delete [] msg;
 	}
-      else
-	maybe_page_output (output_buf);
     }
   else
     error ("unable to start subprocess for `%s'", cmd_str.c_str ());
--- a/src/variables.cc
+++ b/src/variables.cc
@@ -30,6 +30,7 @@
 
 #include <string>
 
+#include <iostream.h>
 #include <strstream.h>
 
 #ifdef HAVE_UNISTD_H
@@ -1122,26 +1123,26 @@
 // List variable names.
 
 static void
-print_symbol_info_line (ostrstream& output_buf, const symbol_record_info& s)
+print_symbol_info_line (ostream& os, const symbol_record_info& s)
 {
-  output_buf << (s.is_read_only () ? " -" : " w");
-  output_buf << (s.is_eternal () ? "- " : "d ");
+  os << (s.is_read_only () ? " -" : " w");
+  os << (s.is_eternal () ? "- " : "d ");
 #if 0
-  output_buf << (s.hides_fcn () ? "f" : (s.hides_builtin () ? "F" : "-"));
+  os << (s.hides_fcn () ? "f" : (s.hides_builtin () ? "F" : "-"));
 #endif
-  output_buf.form ("  %-16s", s.type_as_string ().c_str ());
+  os.form ("  %-16s", s.type_as_string ().c_str ());
   if (s.is_function ())
-    output_buf << "      -      -";
+    os << "      -      -";
   else
     {
-      output_buf.form ("%7d", s.rows ());
-      output_buf.form ("%7d", s.columns ());
+      os.form ("%7d", s.rows ());
+      os.form ("%7d", s.columns ());
     }
-  output_buf << "  " << s.name () << "\n";
+  os << "  " << s.name () << "\n";
 }
 
 static void
-print_long_listing (ostrstream& output_buf, symbol_record_info *s)
+print_long_listing (ostream& os, symbol_record_info *s)
 {
   if (! s)
     return;
@@ -1149,14 +1150,14 @@
   symbol_record_info *ptr = s;
   while (ptr->is_defined ())
     {
-      print_symbol_info_line (output_buf, *ptr);
+      print_symbol_info_line (os, *ptr);
       ptr++;
     }
 }
 
 static int
 maybe_list (const char *header, const string_vector& argv, int argc,
-	    ostrstream& output_buf, int show_verbose, symbol_table
+	    ostream& os, int show_verbose, symbol_table
 	    *sym_tab, unsigned type, unsigned scope)
 {
   int count;
@@ -1167,11 +1168,11 @@
       symbols = sym_tab->long_list (count, argv, argc, 1, type, scope);
       if (symbols && count > 0)
 	{
-	  output_buf << "\n" << header << "\n\n"
+	  os << "\n" << header << "\n\n"
 		     << "prot  type               rows   cols  name\n"
 		     << "====  ====               ====   ====  ====\n";
 
-	  print_long_listing (output_buf, symbols);
+	  print_long_listing (os, symbols);
 	  status = 1;
 	}
       delete [] symbols;
@@ -1182,8 +1183,8 @@
 					     type, scope);
       if (symbols.length () > 0 && count > 0)
 	{
-	  output_buf << "\n" << header << "\n\n";
-	  symbols.list_in_columns (output_buf);
+	  os << "\n" << header << "\n\n";
+	  symbols.list_in_columns (os);
 	  status = 1;
 	}
     }
@@ -1286,18 +1287,17 @@
       show_variables = 1;
     }
 
-  ostrstream output_buf;
   int pad_after = 0;
 
   if (show_builtins)
     {
       pad_after += maybe_list ("*** built-in variables:", pats, npats,
-			       output_buf, show_verbose, global_sym_tab,
+			       octave_stdout, show_verbose, global_sym_tab,
 			       symbol_def::BUILTIN_VARIABLE,
 			       SYMTAB_ALL_SCOPES);
 
       pad_after += maybe_list ("*** built-in functions:", pats, npats,
-			       output_buf, show_verbose, global_sym_tab,
+			       octave_stdout, show_verbose, global_sym_tab,
 			       symbol_def::BUILTIN_FUNCTION,
 			       SYMTAB_ALL_SCOPES);
     }
@@ -1305,7 +1305,7 @@
   if (show_functions)
     {
       pad_after += maybe_list ("*** currently compiled functions:",
-			       pats, npats, output_buf, show_verbose,
+			       pats, npats, octave_stdout, show_verbose,
 			       global_sym_tab, symbol_def::USER_FUNCTION,
 			       SYMTAB_ALL_SCOPES);
     }
@@ -1313,21 +1313,18 @@
   if (show_variables)
     {
       pad_after += maybe_list ("*** local user variables:", pats, npats,
-			       output_buf, show_verbose, curr_sym_tab,
+			       octave_stdout, show_verbose, curr_sym_tab,
 			       symbol_def::USER_VARIABLE,
 			       SYMTAB_LOCAL_SCOPE);
 
       pad_after += maybe_list ("*** globally visible user variables:",
-			       pats, npats, output_buf, show_verbose,
+			       pats, npats, octave_stdout, show_verbose,
 			       curr_sym_tab, symbol_def::USER_VARIABLE,
 			       SYMTAB_GLOBAL_SCOPE);
     }
 
   if (pad_after)
-    output_buf << "\n";
-
-  output_buf << ends;
-  maybe_page_output (output_buf);
+    octave_stdout << "\n";
 
   return retval;
 }