GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
oct-procbuf.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2017 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <cerrno>
28 
29 #include <iostream>
30 
31 // FIXME: we would prefer to avoid including these directly in Octave
32 // sources, but eliminating them is complicated by the mingling of
33 // octave_procbuf_list and the calls to system library functions like
34 // execl.
35 
36 #if defined (HAVE_UNISTD_H)
37 # if defined (HAVE_SYS_TYPES_H)
38 # include <sys/types.h>
39 # endif
40 # include <unistd.h>
41 #endif
42 
43 #include "lo-mappers.h"
44 #include "lo-utils.h"
45 #include "oct-procbuf.h"
46 #include "oct-syscalls.h"
47 #include "sysdep.h"
48 #include "unistd-wrappers.h"
49 #include "variables.h"
50 
51 #include "defun.h"
52 #include "errwarn.h"
53 #include "utils.h"
54 
55 #if ! defined (SHELL_PATH)
56 # define SHELL_PATH "/bin/sh"
57 #endif
58 
59 // This class is based on the procbuf class from libg++, written by
60 // Per Bothner, Copyright (C) 1993 Free Software Foundation.
61 
63 
64 #if ! defined (BUFSIZ)
65 # define BUFSIZ 1024
66 #endif
67 
69 octave_procbuf::open (const char *command, int mode)
70 {
71 #if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)
72 
73  if (is_open ())
74  return 0;
75 
76  f = octave_popen (command, (mode & std::ios::in) ? "r" : "w");
77 
78  if (! f)
79  return 0;
80 
81  // Oops... popen doesn't return the associated pid, so fake it for now
82 
83  proc_pid = 1;
84 
85  open_p = true;
86 
87  if (mode & std::ios::out)
88  ::setvbuf (f, 0, _IOLBF, BUFSIZ);
89 
90  return this;
91 
92 #elif defined (HAVE_UNISTD_H)
93 
94  int pipe_fds[2];
95 
96  volatile int child_std_end = (mode & std::ios::in) ? 1 : 0;
97 
98  volatile int parent_end, child_end;
99 
100  if (is_open ())
101  return 0;
102 
103  if (octave::sys::pipe (pipe_fds) < 0)
104  return 0;
105 
106  if (mode & std::ios::in)
107  {
108  parent_end = pipe_fds[0];
109  child_end = pipe_fds[1];
110  }
111  else
112  {
113  parent_end = pipe_fds[1];
114  child_end = pipe_fds[0];
115  }
116 
117  proc_pid = ::fork ();
118 
119  if (proc_pid == 0)
120  {
121  octave_close_wrapper (parent_end);
122 
123  if (child_end != child_std_end)
124  {
125  octave_dup2_wrapper (child_end, child_std_end);
126  octave_close_wrapper (child_end);
127  }
128 
129  while (octave_procbuf_list)
130  {
131  FILE *fp = octave_procbuf_list->f;
132 
133  if (fp)
134  {
135  std::fclose (fp);
136  fp = 0;
137  }
138 
139  octave_procbuf_list = octave_procbuf_list->next;
140  }
141 
142  execl (SHELL_PATH, "sh", "-c", command, static_cast<void *> (0));
143 
144  exit (127);
145  }
146 
147  octave_close_wrapper (child_end);
148 
149  if (proc_pid < 0)
150  {
151  octave_close_wrapper (parent_end);
152  return 0;
153  }
154 
155  f = ::fdopen (parent_end, (mode & std::ios::in) ? "r" : "w");
156 
157  if (mode & std::ios::out)
158  ::setvbuf (f, 0, _IOLBF, BUFSIZ);
159 
160  open_p = true;
161 
163  octave_procbuf_list = this;
164 
165  return this;
166 
167 #else
168 
169  return 0;
170 
171 #endif
172 }
173 
176 {
177 #if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)
178 
179  if (f)
180  {
181  wstatus = octave_pclose (f);
182  f = 0;
183  }
184 
185  open_p = false;
186 
187  return this;
188 
189 #elif defined (HAVE_UNISTD_H)
190 
191  if (f)
192  {
193  pid_t wait_pid;
194 
195  int status = -1;
196 
197  for (octave_procbuf **ptr = &octave_procbuf_list;
198  *ptr != 0;
199  ptr = &(*ptr)->next)
200  {
201  if (*ptr == this)
202  {
203  *ptr = (*ptr)->next;
204  status = 0;
205  break;
206  }
207  }
208 
209  if (status == 0 && std::fclose (f) == 0)
210  {
211  using namespace std;
212 
213  do
214  {
215  wait_pid = octave::sys::waitpid (proc_pid, &wstatus, 0);
216  }
217  while (wait_pid == -1 && errno == EINTR);
218  }
219 
220  f = 0;
221  }
222 
223  open_p = false;
224 
225  return this;
226 
227 #else
228 
229  return 0;
230 
231 #endif
232 }
FILE * octave_popen(const char *command, const char *mode)
Definition: sysdep.cc:510
int octave_pclose(FILE *f)
Definition: sysdep.cc:530
fclose(in)
octave_procbuf * open(const char *command, int mode)
Definition: oct-procbuf.cc:69
Return the CPU time used by your Octave session The first output is the total time spent executing your process and is equal to the sum of second and third which are the number of CPU seconds spent executing in user mode and the number of CPU seconds spent executing in system mode
Definition: data.cc:6386
STL namespace.
octave_procbuf * next
Definition: oct-procbuf.h:68
to define functions rather than attempting to enter them directly on the command line The block of commands is executed as soon as you exit the editor To avoid executing any simply delete all the lines from the buffer before leaving the editor When invoked with no edit the previously executed command
Definition: oct-hist.cc:587
#define SHELL_PATH
Definition: oct-procbuf.cc:56
pid_t waitpid(pid_t pid, int *status, int options)
octave_procbuf * close(void)
Definition: oct-procbuf.cc:175
#define BUFSIZ
Definition: oct-procbuf.cc:65
bool is_open(void) const
Definition: oct-procbuf.h:56
static octave_procbuf * octave_procbuf_list
Definition: oct-procbuf.cc:62
int octave_close_wrapper(int fd)
pid_t fork(std::string &msg)
Definition: oct-syscalls.cc:97
int pipe(int *fildes)
int octave_dup2_wrapper(int fd1, int fd2)