GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
oct-procbuf.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2018 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
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License 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 <https://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 
62 #if (! (defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)) \
63  && defined (HAVE_UNISTD_H))
64 
65 static octave_procbuf *octave_procbuf_list = nullptr;
66 
67 #endif
68 
69 #if ! defined (BUFSIZ)
70 # define BUFSIZ 1024
71 #endif
72 
74 octave_procbuf::open (const char *command, int mode)
75 {
76 #if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)
77 
78  if (is_open ())
79  return 0;
80 
81  f = (octave_popen (command, (mode & std::ios::in) ? "r" : "w"));
82 
83  if (! f)
84  return 0;
85 
86  // Oops... popen doesn't return the associated pid, so fake it for now
87 
88  proc_pid = 1;
89 
90  open_p = true;
91 
92  if (mode & std::ios::out)
93  ::setvbuf (f, 0, _IOLBF, BUFSIZ);
94 
95  return this;
96 
97 #elif defined (HAVE_UNISTD_H)
98 
99  int pipe_fds[2];
100 
101  volatile int child_std_end = (mode & std::ios::in) ? 1 : 0;
102 
103  volatile int parent_end, child_end;
104 
105  if (is_open ())
106  return nullptr;
107 
108  if (octave::sys::pipe (pipe_fds) < 0)
109  return nullptr;
110 
111  if (mode & std::ios::in)
112  {
113  parent_end = pipe_fds[0];
114  child_end = pipe_fds[1];
115  }
116  else
117  {
118  parent_end = pipe_fds[1];
119  child_end = pipe_fds[0];
120  }
121 
122  proc_pid = ::fork ();
123 
124  if (proc_pid == 0)
125  {
126  octave_close_wrapper (parent_end);
127 
128  if (child_end != child_std_end)
129  {
130  octave_dup2_wrapper (child_end, child_std_end);
131  octave_close_wrapper (child_end);
132  }
133 
134  while (octave_procbuf_list)
135  {
136  FILE *fp = octave_procbuf_list->f;
137 
138  if (fp)
139  {
140  std::fclose (fp);
141  fp = nullptr;
142  }
143 
144  octave_procbuf_list = octave_procbuf_list->next;
145  }
146 
147  execl (SHELL_PATH, "sh", "-c", command, static_cast<void *> (nullptr));
148 
149  exit (127);
150  }
151 
152  octave_close_wrapper (child_end);
153 
154  if (proc_pid < 0)
155  {
156  octave_close_wrapper (parent_end);
157  return nullptr;
158  }
159 
160  f = (::fdopen (parent_end, (mode & std::ios::in) ? "r" : "w"));
161 
162  if (mode & std::ios::out)
163  ::setvbuf (f, nullptr, _IOLBF, BUFSIZ);
164 
165  open_p = true;
166 
167  next = octave_procbuf_list;
168  octave_procbuf_list = this;
169 
170  return this;
171 
172 #else
173 
174  return 0;
175 
176 #endif
177 }
178 
181 {
182 #if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)
183 
184  if (f)
185  {
186  wstatus = octave_pclose (f);
187  f = 0;
188  }
189 
190  open_p = false;
191 
192  return this;
193 
194 #elif defined (HAVE_UNISTD_H)
195 
196  if (f)
197  {
198  pid_t wait_pid;
199 
200  int status = -1;
201 
202  for (octave_procbuf **ptr = &octave_procbuf_list;
203  *ptr != nullptr;
204  ptr = &(*ptr)->next)
205  {
206  if (*ptr == this)
207  {
208  *ptr = (*ptr)->next;
209  status = 0;
210  break;
211  }
212  }
213 
214  if (status == 0 && std::fclose (f) == 0)
215  {
216  using namespace std;
217 
218  do
219  {
220  wait_pid = octave::sys::waitpid (proc_pid, &wstatus, 0);
221  }
222  while (wait_pid == -1 && errno == EINTR);
223  }
224 
225  f = nullptr;
226  }
227 
228  open_p = false;
229 
230  return this;
231 
232 #else
233 
234  return 0;
235 
236 #endif
237 }
FILE * octave_popen(const char *command, const char *mode)
Definition: sysdep.cc:506
int octave_pclose(FILE *f)
Definition: sysdep.cc:524
octave_procbuf * open(const char *command, int mode)
Definition: oct-procbuf.cc:74
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:6348
STL namespace.
octave_procbuf * next
Definition: oct-procbuf.h:74
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_EXPORT octave_value_list or both For fclose
Definition: file-io.cc:676
octave_procbuf * close(void)
Definition: oct-procbuf.cc:180
#define BUFSIZ
Definition: oct-procbuf.cc:70
bool is_open(void) const
Definition: oct-procbuf.h: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)