oct-procbuf.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1996-2012 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include <cerrno>
00028 
00029 #include <iostream>
00030 
00031 #include <sys/types.h>
00032 #include <unistd.h>
00033 
00034 #include "lo-mappers.h"
00035 #include "lo-utils.h"
00036 #include "oct-procbuf.h"
00037 #include "oct-syscalls.h"
00038 #include "sysdep.h"
00039 #include "variables.h"
00040 
00041 #include "defun.h"
00042 #include "gripes.h"
00043 #include "utils.h"
00044 
00045 // This class is based on the procbuf class from libg++, written by
00046 // Per Bothner, Copyright (C) 1993 Free Software Foundation.
00047 
00048 static octave_procbuf *octave_procbuf_list = 0;
00049 
00050 #ifndef BUFSIZ
00051 #define BUFSIZ 1024
00052 #endif
00053 
00054 octave_procbuf *
00055 octave_procbuf::open (const char *command, int mode)
00056 {
00057 #if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)
00058 
00059   if (is_open ())
00060     return 0;
00061 
00062   f = octave_popen (command, (mode & std::ios::in) ? "r" : "w");
00063 
00064   if (! f)
00065     return 0;
00066 
00067   // Oops... popen doesn't return the associated pid, so fake it for now
00068 
00069   proc_pid = 1;
00070 
00071   open_p = true;
00072 
00073   if (mode & std::ios::out)
00074     ::setvbuf (f, 0, _IOLBF, BUFSIZ);
00075 
00076   return this;
00077 
00078 #elif defined (HAVE_SYS_WAIT_H)
00079 
00080   int pipe_fds[2];
00081 
00082   volatile int child_std_end = (mode & std::ios::in) ? 1 : 0;
00083 
00084   volatile int parent_end, child_end;
00085 
00086   if (is_open ())
00087     return 0;
00088 
00089   if (pipe (pipe_fds) < 0)
00090     return 0;
00091 
00092   if (mode & std::ios::in)
00093     {
00094       parent_end = pipe_fds[0];
00095       child_end = pipe_fds[1];
00096     }
00097   else
00098     {
00099       parent_end = pipe_fds[1];
00100       child_end = pipe_fds[0];
00101     }
00102 
00103   proc_pid = ::fork ();
00104 
00105   if (proc_pid == 0)
00106     {
00107       gnulib::close (parent_end);
00108 
00109       if (child_end != child_std_end)
00110         {
00111           gnulib::dup2 (child_end, child_std_end);
00112           gnulib::close (child_end);
00113         }
00114 
00115       while (octave_procbuf_list)
00116         {
00117           FILE *fp = octave_procbuf_list->f;
00118 
00119           if (fp)
00120             {
00121               gnulib::fclose (fp);
00122               fp = 0;
00123             }
00124 
00125           octave_procbuf_list = octave_procbuf_list->next;
00126         }
00127 
00128       execl ("/bin/sh", "sh", "-c", command, static_cast<void *> (0));
00129 
00130       exit (127);
00131     }
00132 
00133   gnulib::close (child_end);
00134 
00135   if (proc_pid < 0)
00136     {
00137       gnulib::close (parent_end);
00138       return 0;
00139     }
00140 
00141   f = ::fdopen (parent_end, (mode & std::ios::in) ? "r" : "w");
00142 
00143   if (mode & std::ios::out)
00144     ::setvbuf (f, 0, _IOLBF, BUFSIZ);
00145 
00146   open_p = true;
00147 
00148   next = octave_procbuf_list;
00149   octave_procbuf_list = this;
00150 
00151   return this;
00152 
00153 #else
00154 
00155   return 0;
00156 
00157 #endif
00158 }
00159 
00160 octave_procbuf *
00161 octave_procbuf::close (void)
00162 {
00163 #if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)
00164 
00165   if (f)
00166     {
00167       wstatus = octave_pclose (f);
00168       f = 0;
00169     }
00170 
00171   open_p = false;
00172 
00173   return this;
00174 
00175 #elif defined (HAVE_SYS_WAIT_H)
00176 
00177   if (f)
00178     {
00179       pid_t wait_pid;
00180 
00181       int status = -1;
00182 
00183       for (octave_procbuf **ptr = &octave_procbuf_list;
00184            *ptr != 0;
00185            ptr = &(*ptr)->next)
00186         {
00187           if (*ptr == this)
00188             {
00189               *ptr = (*ptr)->next;
00190               status = 0;
00191               break;
00192             }
00193         }
00194 
00195       if (status == 0 && gnulib::fclose (f) == 0)
00196         {
00197           using namespace std;
00198 
00199           do
00200             {
00201               wait_pid = octave_syscalls::waitpid (proc_pid, &wstatus, 0);
00202             }
00203           while (wait_pid == -1 && errno == EINTR);
00204         }
00205 
00206       f = 0;
00207     }
00208 
00209   open_p = false;
00210 
00211   return this;
00212 
00213 #else
00214 
00215   return 0;
00216 
00217 #endif
00218 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines