changeset 1230:92609e161b29

[project @ 1995-04-10 01:08:57 by jwe]
author jwe
date Mon, 10 Apr 1995 01:14:34 +0000
parents 7d7c3eaa1d3b
children 6f1da2eacae3
files liboctave/Array.h liboctave/MArray.cc liboctave/MArray.h src/file-io.cc src/sighandlers.cc
diffstat 5 files changed, 645 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/Array.h	Mon Apr 10 01:04:46 1995 +0000
+++ b/liboctave/Array.h	Mon Apr 10 01:14:34 1995 +0000
@@ -148,6 +148,8 @@
   Array2 (const Array2<T>& a);
   Array2 (const DiagArray<T>& a);
 
+  ~Array2 (void) { }
+
   Array2<T>& operator = (const Array2<T>& a);
 
   int dim1 (void) const;
@@ -192,6 +194,8 @@
   Array3 (int n, int m, int k, const T& val);
   Array3 (const Array3<T>& a);
 
+  ~Array3 (void) { }
+
   Array3<T>& operator = (const Array3<T>& a);
 
   int dim3 (void) const;
@@ -303,6 +307,8 @@
   DiagArray (const Array<T>& a);
   DiagArray (const DiagArray<T>& a);
 
+  ~DiagArray (void) { }
+
   DiagArray<T>& operator = (const DiagArray<T>& a);
 
   int dim1 (void) const;
--- a/liboctave/MArray.cc	Mon Apr 10 01:04:46 1995 +0000
+++ b/liboctave/MArray.cc	Mon Apr 10 01:14:34 1995 +0000
@@ -77,10 +77,10 @@
     }
 
 #define DO_VS_OP2(OP) \
-  int l = length (); \
+  int l = a.length (); \
   if (l > 0) \
     { \
-      T *tmp = fortran_vec (); \
+      T *tmp = a.fortran_vec (); \
       for (int i = 0; i < l; i++) \
 	tmp[i] OP s; \
     }
@@ -88,10 +88,10 @@
 #define DO_VV_OP2(OP) \
   do \
     { \
-      T *tmp = fortran_vec (); \
-      const T *rhs = a.data (); \
+      T *a_tmp = a.fortran_vec (); \
+      const T *b_tmp = b.data (); \
       for (int i = 0; i < l; i++) \
-	tmp[i] += rhs[i]; \
+	a_tmp[i] += b_tmp[i]; \
     } \
   while (0)
 
@@ -103,52 +103,52 @@
 
 template <class T>
 MArray<T>&
-MArray<T>::operator += (const T& s)
+operator += (MArray<T>& a, const T& s)
 {
   DO_VS_OP2 (+=)
-  return *this;
+  return a;
 }
 
 template <class T>
 MArray<T>&
-MArray<T>::operator -= (const T& s)
+operator -= (MArray<T>& a, const T& s)
 {
   DO_VS_OP2 (-=)
-  return *this;
+  return a;
 }
 
 // Element by element MArray by MArray ops.
 
 template <class T>
 MArray<T>&
-MArray<T>::operator += (const MArray<T>& a)
+operator += (MArray<T>& a, const MArray<T>& b)
 {
-  int l = length ();
+  int l = a.length ();
   if (l > 0)
     {
-      if (l != a.length ())
+      if (l != b.length ())
 	(*current_liboctave_error_handler) \
 	  ("nonconformant += array operation attempted"); \
       else
 	DO_VV_OP2 (+=);
     }
-  return *this;
+  return a;
 }
 
 template <class T>
 MArray<T>&
-MArray<T>::operator -= (const MArray<T>& a)
+operator -= (MArray<T>& a, const MArray<T>& b)
 {
-  int l = length ();
+  int l = a.length ();
   if (l > 0)
     {
-      if (l != a.length ())
+      if (l != b.length ())
 	(*current_liboctave_error_handler) \
 	  ("nonconformant -= array operation attempted"); \
       else
 	DO_VV_OP2 (-=);
     }
-  return *this;
+  return a;
 }
 
 // Element by element MArray by scalar ops.
@@ -234,29 +234,29 @@
 
 template <class T>
 MArray2<T>&
-MArray2<T>::operator += (const T& s)
+operator += (MArray2<T>& a, const T& s)
 {
   DO_VS_OP2 (+=)
-  return *this;
+  return a;
 }
 
 template <class T>
 MArray2<T>&
-MArray2<T>::operator -= (const T& s)
+operator -= (MArray2<T>& a, const T& s)
 {
   DO_VS_OP2 (-=)
-  return *this;
+  return a;
 }
 
 // Element by element MArray2 by MArray2 ops.
 
 template <class T>
 MArray2<T>&
-MArray2<T>::operator += (const MArray2<T>& a)
+operator += (MArray2<T>& a, const MArray2<T>& b)
 {
-  int r = rows ();
-  int c = cols ();
-  if (r != a.rows () || c != a.cols ())
+  int r = a.rows ();
+  int c = a.cols ();
+  if (r != b.rows () || c != b.cols ())
     {
       (*current_liboctave_error_handler)
 	("nonconformant += array operation attempted");
@@ -269,16 +269,16 @@
 	  DO_VV_OP2 (+=);
 	}
     }
-  return *this;
+  return a;
 }
 
 template <class T>
 MArray2<T>&
-MArray2<T>::operator -= (const MArray2<T>& a)
+operator -= (MArray2<T>& a, const MArray2<T>& b)
 {
-  int r = rows ();
-  int c = cols ();
-  if (r != a.rows () || c != a.cols ())
+  int r = a.rows ();
+  int c = a.cols ();
+  if (r != b.rows () || c != b.cols ())
     {
       (*current_liboctave_error_handler)
 	("nonconformant -= array operation attempted");
@@ -291,7 +291,7 @@
 	  DO_VV_OP2 (-=);
 	}
     }
-  return *this;
+  return a;
 }
 
 // Element by element MArray2 by scalar ops.
@@ -371,18 +371,48 @@
 
 template <class T>
 MDiagArray<T>&
-MDiagArray<T>::operator += (const MDiagArray<T>& a)
+operator += (MDiagArray<T>& a, const MDiagArray<T>& b)
 {
-  // XXX FIXME XXX
-  return *this;
+  int r = a.rows ();
+  int c = a.cols ();
+  if (r != b.rows () || c != b.cols ())
+    {
+      (*current_liboctave_error_handler)
+	("nonconformant array " OP_STR " attempted");
+      return MArray2<T> ();
+    }
+  else
+    {
+      int l = a.length ();
+      T *a_tmp = a.fortran_vec ();
+      const T *b_tmp = b.data ();
+      for (int i = 0; i < l; i++)
+	a_tmp[i] += b_tmp[i];
+    }
+  return a;
 }
 
 template <class T>
 MDiagArray<T>&
-MDiagArray<T>::operator -= (const MDiagArray<T>& a)
+operator -= (MDiagArray<T>& a, const MDiagArray<T>& b)
 {
-  // XXX FIXME XXX
-  return *this;
+  int r = a.rows ();
+  int c = a.cols ();
+  if (r != b.rows () || c != b.cols ())
+    {
+      (*current_liboctave_error_handler)
+	("nonconformant array " OP_STR " attempted");
+      return MArray2<T> ();
+    }
+  else
+    {
+      int l = a.length ();
+      T *a_tmp = a.fortran_vec ();
+      const T *b_tmp = b.data ();
+      for (int i = 0; i < l; i++)
+	a_tmp[i] -= b_tmp[i];
+    }
+  return a;
 }
 
 // Element by element MDiagArray by scalar ops.
--- a/liboctave/MArray.h	Mon Apr 10 01:04:46 1995 +0000
+++ b/liboctave/MArray.h	Mon Apr 10 01:14:34 1995 +0000
@@ -53,6 +53,8 @@
   MArray (const Array<T>& a) : Array<T> (a) { }
   MArray (const MArray<T>& a) : Array<T> (a) { }
 
+  ~MArray (void) { }
+
   MArray<T>& operator = (const MArray<T>& a)
     {
       Array<T>::operator = (a);
@@ -61,13 +63,13 @@
 
 // Element by element MArray by scalar ops.
 
-  MArray<T>& operator += (const T& s);
-  MArray<T>& operator -= (const T& s);
+  friend MArray<T>& operator += (MArray<T>& a, const T& s);
+  friend MArray<T>& operator -= (MArray<T>& a, const T& s);
 
 // Element by element MArray by MArray ops.
 
-  MArray<T>& operator += (const MArray<T>& a);
-  MArray<T>& operator -= (const MArray<T>& a);
+  friend MArray<T>& operator += (MArray<T>& a, const MArray<T>& b);
+  friend MArray<T>& operator -= (MArray<T>& a, const MArray<T>& b);
 
 // Element by element MArray by scalar ops.
 
@@ -115,6 +117,8 @@
   MArray2 (const MArray2<T>& a) : Array2<T> (a) { }
   MArray2 (const MDiagArray<T>& a);
 
+  ~MArray2 (void) { }
+
   MArray2<T>& operator = (const MArray2<T>& a)
     {
       Array2<T>::operator = (a);
@@ -123,13 +127,13 @@
 
 // Element by element MArray2 by scalar ops.
 
-  MArray2<T>& operator += (const T& s);
-  MArray2<T>& operator -= (const T& s);
+  friend MArray2<T>& operator += (MArray2<T>& a, const T& s);
+  friend MArray2<T>& operator -= (MArray2<T>& a, const T& s);
 
 // Element by element MArray2 by MArray2 ops.
 
-  MArray2<T>& operator += (const MArray2<T>& a);
-  MArray2<T>& operator -= (const MArray2<T>& a);
+  friend MArray2<T>& operator += (MArray2<T>& a, const MArray2<T>& b);
+  friend MArray2<T>& operator -= (MArray2<T>& a, const MArray2<T>& b);
 
 // Element by element MArray2 by scalar ops.
 
@@ -178,6 +182,8 @@
   MDiagArray (const MDiagArray<T>& a) : DiagArray<T> (a) { }
   MDiagArray (const MArray<T>& a) : DiagArray<T> (a) { }
 
+  ~MDiagArray (void) { }
+
   MDiagArray<T>& operator = (const MDiagArray<T>& a)
     {
       DiagArray<T>::operator = (a);
@@ -186,8 +192,8 @@
 
 // Element by element MDiagArray by MDiagArray ops.
 
-  MDiagArray<T>& operator += (const MDiagArray<T>& a);
-  MDiagArray<T>& operator -= (const MDiagArray<T>& a);
+  friend MDiagArray<T>& operator += (MDiagArray<T>& a, const MDiagArray<T>& b);
+  friend MDiagArray<T>& operator -= (MDiagArray<T>& a, const MDiagArray<T>& b);
 
 // Element by element MDiagArray by scalar ops.
 
--- a/src/file-io.cc	Mon Apr 10 01:04:46 1995 +0000
+++ b/src/file-io.cc	Mon Apr 10 01:14:34 1995 +0000
@@ -22,20 +22,30 @@
 */
 
 // Written by John C. Campbell <jcc@che.utexas.edu>.
+//
+// Thomas Baier <baier@ci.tuwien.ac.at> added the following functions:
+//
+//   popen    pclose    execute  sync_system  async_system
+//   waitpid  mkfifo   unlink
+
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
-#include <DLList.h>
+#include <sys/types.h>
 #include <unistd.h>
 #include <string.h>
 #include <stdio.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <strstream.h>
+#include <sys/wait.h>
+#include <fcntl.h>
 #include <ctype.h>
 
+#include <DLList.h>
+
 #include "dMatrix.h"
 
 #include "statdefs.h"
@@ -285,7 +295,7 @@
 }
 
 DEFUN ("fclose", Ffclose, Sfclose, 1, 1,
-  "fclose (FILENAME or FILENUM): close a file")
+  "fclose (FILENAME or FILENUM):  close a file")
 {
   Octave_object retval;
 
@@ -1693,8 +1703,8 @@
  SIZE      : size specification for the Data matrix\n\
  PRECISION : type of data to read, valid types are\n\
 \n\
-               'char',   'schar', 'short',  'int',  'long', 'float'\n\
-               'double', 'uchar', 'ushort', 'uint', 'ulong'\n\
+             \"char\"   \"schar\" \"short\"  \"int\"  \"long\" \"float\"\n\
+             \"double\" \"uchar\" \"ushort\" \"uint\" \"ulong\"\n\
 \n\
  DATA      : matrix in which the data is stored\n\
  COUNT     : number of elements read")
@@ -1774,8 +1784,8 @@
  DATA      : matrix of elements to be written\n\
  PRECISION : type of data to read, valid types are\n\
 \n\
-               'char',   'schar', 'short',  'int',  'long', 'float'\n\
-               'double', 'uchar', 'ushort', 'uint', 'ulong'\n\
+             \"char\"   \"schar\" \"short\"  \"int\"  \"long\" \"float\"\n\
+             \"double\" \"uchar\" \"ushort\" \"uint\" \"ulong\"\n\
 \n\
  COUNT     : number of elements written")
 {
@@ -1883,6 +1893,495 @@
   return retval;
 }
 
+static Octave_object
+popen_internal (const Octave_object& args)
+{
+  Octave_object retval;
+
+  if (! args(0).is_string ())
+    {
+      error ("popen: file name must be a string");
+      return retval;
+    }
+
+  char *name = args(0).string_value ();
+
+  Pix p = return_valid_file (name);
+
+  if (p)
+    {
+      file_info file = file_list (p);
+
+      retval(0) = (double) file.number ();
+
+      return retval;
+    }
+
+  if (! args(1).is_string ())
+    {
+      error ("popen: file mode must be a string");
+      return retval;
+    }
+
+  char *mode = args(1).string_value ();
+
+  if (mode[1] || (mode[0] != 'w' && mode[0] != 'r'))
+    {
+      error ("popen: invalid mode, must be either \"r\" or \"w\".");
+      return retval;
+    }
+
+  struct stat buffer;
+  if (stat (name, &buffer) == 0 && (buffer.st_mode & S_IFDIR) == S_IFDIR)
+    {
+      error ("popen: can't open directory");
+      return retval;
+    }
+
+  FILE *file_ptr = popen (name, mode);
+
+  if (! file_ptr)
+    {
+      error ("popen: unable to start process `%s'", name);
+      return retval;
+    }
+
+  int number = file_list.length () + 1;
+
+  file_info file (number, name, file_ptr, mode);
+  file_list.append (file);
+
+  retval(0) = (double) number;
+
+  return retval;
+}
+
+DEFUN ("popen", Fpopen, Spopen, 2, 1,
+  "FILENUM = popen (FILENAME, MODE)\n\
+\n\
+  start a process and create a pipe.  Valid values for mode are:\n\
+\n\
+  \"r\" : connect stdout of process to pipe\n\
+  \"w\" : connect stdin of process to pipe")
+{
+  Octave_object retval;
+
+  int nargin = args.length ();
+
+  if (nargin != 2)
+    print_usage ("popen");
+  else
+    retval = popen_internal (args);
+
+  return retval;
+}
+
+static Octave_object
+pclose_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 ("pclose: can't close stdin, stdout, or stderr!");
+      return retval;
+    }
+
+  int success = pclose (file.fptr ());
+  file_list.del (p);
+
+  if (success == 0)
+    retval(0) = 1.0; // succeeded
+  else
+    {
+      error ("pclose: error on closing file");
+      retval(0) = 0.0; // failed
+    }
+
+  return retval;
+}
+
+DEFUN ("pclose", Fpclose, Spclose, 1, 1,
+  "pclose (FILENAME or FILENUM)\n\
+\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, int nargout)
+{
+  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;
+    }
+
+  char *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, name, 0) == -1)
+	error ("execute: unable to start process `%s'", name);
+
+      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 = file_list.length () + 1;
+      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", Fexecute, Sexecute, 1, 3,
+  "[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, nargout);
+
+  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;
+    }
+
+  char *name = args(0).string_value ();
+
+  retval (0) = (double) system (name);
+  return retval;
+}
+
+DEFUN ("sync_system", Fsync_system, Ssync_system, 1, 1,
+  "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;
+    }
+
+  char *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);
+      exit (0);
+      retval (0) = 0.0;
+      return retval;
+    } 
+  else
+    {
+      retval (0) = (double) pid;
+      return retval;
+    }
+}
+
+DEFUN ("async_system", Fasync_system, Sasync_system, 1, 1,
+  "PID = async_system (FILENAME)\n\
+\n\
+  Create a new process and start FILENAME")
+{
+  Octave_object retval;
+
+  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 (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", Fwaitpid, Swaitpid, 1, 1,
+  "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;
+    }
+
+  char *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) mkfifo (name, mode);
+
+  return retval;
+}
+
+DEFUN ("mkfifo", Fmkfifo, Smkfifo, 2, 1,
+  "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;
+    }
+
+  char *name = args(0).string_value ();
+
+  retval (0) = (double) unlink (name);
+
+  return retval;
+}
+
+DEFUN ("unlink", Funlink, Sunlink, 1, 1,
+  "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;
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/sighandlers.cc	Mon Apr 10 01:04:46 1995 +0000
+++ b/src/sighandlers.cc	Mon Apr 10 01:14:34 1995 +0000
@@ -22,15 +22,17 @@
 */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/types.h>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
+#include <sys/wait.h>
 #include <new.h>
 #include <signal.h>
+#include <iostream.h>
 
 #include "sighandlers.h"
 #include "octave.h"
@@ -72,6 +74,47 @@
 #endif
 }
 
+// Handle SIGCHLD.  Should use waitpid and ignore stopped jobs.
+// Needs to restore state of plotter such that it will be restarted
+// again when needed.  Needs to close file descriptors corresponding
+// to processes started with execute().
+
+#if 0
+static RETSIGTYPE
+sigchld_handler (int i)
+{
+  int status;
+  pid_t pid = wait (&status);
+
+  if (pid < 0)
+    cerr << "wait error\n";
+  else
+    {
+      cerr << "sigchld caught, PID = " << pid << "; status: ";
+
+      int lo_byte = (status & 0xff);
+      int hi_byte = ((status >> 8) & 0xff);
+      if (lo_byte == 0177)
+	{
+	  cerr << "stopped with signal = " << hi_byte << "\n";
+	}
+      else if (lo_byte)
+	{
+	  int sig_num = (lo_byte & 0x7f);
+	  cerr << "stopped with signal = " << sig_num << "\n";
+	  if (lo_byte & 0200)
+	    cerr << "child dumped core\n";
+	}
+      else
+	{
+	  cerr << "exited with status = " << hi_byte << "\n";
+	}
+    }
+
+  signal (SIGCHLD, sigchld_handler);
+}
+#endif
+
 // Handle SIGINT by restarting the parser (see octave.cc).
 
 // XXX FIXME XXX -- it would probably be good to try to use POSIX
@@ -139,6 +182,12 @@
   signal (SIGBUS, generic_sig_handler);
 #endif
 
+#if 0
+#ifdef SIGCHLD
+  signal (SIGCHLD, sigchld_handler);
+#endif
+#endif
+
 #ifdef SIGEMT
   signal (SIGEMT, generic_sig_handler);
 #endif