GNU Octave 11.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
oct-procbuf.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-2026 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include <cerrno>
31#include <cstdlib>
32
33#include <iomanip>
34
35// FIXME: we would prefer to avoid including these directly in Octave
36// sources, but eliminating them is complicated by the mingling of
37// octave_procbuf_list and the calls to system library functions like
38// execl.
39
40#if defined (HAVE_UNISTD_H)
41# if defined (HAVE_SYS_TYPES_H)
42# include <sys/types.h>
43# endif
44# include <unistd.h>
45#endif
46
47#include "lo-utils.h"
48#include "mappers.h"
49#include "oct-procbuf.h"
50#include "oct-syscalls.h"
51#include "sysdep.h"
52#include "unistd-wrappers.h"
53#include "variables.h"
54
55#include "defun.h"
56#include "errwarn.h"
57#include "utils.h"
58
60
61#if ! defined (SHELL_PATH)
62# define SHELL_PATH "/bin/sh"
63#endif
64
65// This class is based on the procbuf class from libg++, written by
66// Per Bothner, Copyright (C) 1993 Free Software Foundation.
67
68#if (! (defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)) \
69 && defined (HAVE_UNISTD_H))
70
71static procbuf *procbuf_list = nullptr;
72
73#endif
74
75#if ! defined (BUFSIZ)
76# define BUFSIZ 1024
77#endif
78
79procbuf *
80procbuf::open (const char *command, int mode)
81{
82#if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)
83
84 if (is_open ())
85 return 0;
86
87 m_f = (octave::popen (command, (mode & std::ios::in) ? "r" : "w"));
88
89 if (! m_f)
90 return 0;
91
92 // Oops... popen doesn't return the associated pid, so fake it for now
93
94 m_proc_pid = 1;
95
96 m_open_p = true;
97
98 if (mode & std::ios::out)
99 ::setvbuf (m_f, nullptr, _IOLBF, BUFSIZ);
100
101 return this;
102
103#elif defined (HAVE_UNISTD_H)
104
105 int pipe_fds[2];
106
107 int child_std_end = (mode & std::ios::in) ? 1 : 0;
108
109 int parent_end, child_end;
110
111 if (is_open ())
112 return nullptr;
113
114 if (octave::sys::pipe (pipe_fds) < 0)
115 return nullptr;
116
117 if (mode & std::ios::in)
118 {
119 parent_end = pipe_fds[0];
120 child_end = pipe_fds[1];
121 }
122 else
123 {
124 parent_end = pipe_fds[1];
125 child_end = pipe_fds[0];
126 }
127
128 m_proc_pid = ::fork ();
129
130 if (m_proc_pid == 0)
131 {
132 octave_close_wrapper (parent_end);
133
134 if (child_end != child_std_end)
135 {
136 octave_dup2_wrapper (child_end, child_std_end);
137 octave_close_wrapper (child_end);
138 }
139
140 while (procbuf_list)
141 {
142 FILE *fp = procbuf_list->m_f;
143
144 if (fp)
145 {
146 std::fclose (fp);
147 fp = nullptr;
148 }
149
150 procbuf_list = procbuf_list->m_next;
151 }
152
153 execl (SHELL_PATH, "sh", "-c", command, static_cast<void *> (nullptr));
154
155 std::exit (127);
156 }
157
158 octave_close_wrapper (child_end);
159
160 if (m_proc_pid < 0)
161 {
162 octave_close_wrapper (parent_end);
163 return nullptr;
164 }
165
166 m_f = (::fdopen (parent_end, (mode & std::ios::in) ? "r" : "w"));
167
168 if (mode & std::ios::out)
169 ::setvbuf (m_f, nullptr, _IOLBF, BUFSIZ);
170
171 m_open_p = true;
172
173 m_next = procbuf_list;
174 procbuf_list = this;
175
176 return this;
177
178#else
179
180 return 0;
181
182#endif
183}
184
185procbuf *
187{
188#if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)
189
190 if (m_f)
191 {
192 m_wstatus = octave::pclose (m_f);
193 m_f = 0;
194 }
195
196 m_open_p = false;
197
198 return this;
199
200#elif defined (HAVE_UNISTD_H)
201
202 if (m_f)
203 {
204 pid_t wait_pid;
205
206 int status = -1;
207
208 for (procbuf **ptr = &procbuf_list;
209 *ptr != nullptr;
210 ptr = &(*ptr)->m_next)
211 {
212 if (*ptr == this)
213 {
214 *ptr = (*ptr)->m_next;
215 status = 0;
216 break;
217 }
218 }
219
220 if (status == 0 && std::fclose (m_f) == 0)
221 {
222 using namespace std;
223
224 do
225 {
226 wait_pid = octave::sys::waitpid (m_proc_pid, &m_wstatus, 0);
227 }
228 while (wait_pid == -1 && errno == EINTR);
229 }
230
231 m_f = nullptr;
232 }
233
234 m_open_p = false;
235
236 return this;
237
238#else
239
240 return 0;
241
242#endif
243}
244
245OCTAVE_END_NAMESPACE(octave)
pid_t m_proc_pid
Definition oct-procbuf.h:74
procbuf * close()
bool is_open() const
Definition oct-procbuf.h:64
int m_wstatus
Definition oct-procbuf.h:70
procbuf * m_next
Definition oct-procbuf.h:76
bool m_open_p
Definition oct-procbuf.h:72
procbuf * open(const char *command, int mode)
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
#define BUFSIZ
#define SHELL_PATH
pid_t fork(std::string &msg)
int octave_close_wrapper(int fd)
int octave_dup2_wrapper(int fd1, int fd2)