diff src/file-io.cc @ 1230:92609e161b29

[project @ 1995-04-10 01:08:57 by jwe]
author jwe
date Mon, 10 Apr 1995 01:14:34 +0000
parents b2b7c5264ac2
children 611d403c7f3d
line wrap: on
line diff
--- 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++ ***