Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00046
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
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 }