GNU Octave  3.8.0
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-syscalls.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2013 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 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include <cerrno>
28 #include <cstdlib>
29 
30 #include <string.h>
31 
32 #include <sys/types.h>
33 #include <unistd.h>
34 
35 #include <fcntl.h>
36 
37 // We can't use csignal as kill is not in the std namespace, and picky
38 // compiler runtimes will also exclude it from global scope as well.
39 
40 #include <signal.h>
41 
42 #include "lo-utils.h"
43 #include "lo-sysdep.h"
44 #include "oct-syscalls.h"
45 #include "str-vec.h"
46 
47 #define NOT_SUPPORTED(nm) \
48  nm ": not supported on this system"
49 
50 int
51 octave_syscalls::dup2 (int old_fd, int new_fd)
52 {
53  std::string msg;
54  return dup2 (old_fd, new_fd, msg);
55 }
56 
57 int
58 octave_syscalls::dup2 (int old_fd, int new_fd, std::string& msg)
59 {
60  msg = std::string ();
61 
62  int status = -1;
63 
64 #if defined (HAVE_DUP2)
65  status = gnulib::dup2 (old_fd, new_fd);
66 
67  if (status < 0)
68  msg = gnulib::strerror (errno);
69 #else
70  msg = NOT_SUPPORTED ("dup2");
71 #endif
72 
73  return status;
74 }
75 
76 int
77 octave_syscalls::execvp (const std::string& file, const string_vector& argv)
78 {
79  std::string msg;
80  return execvp (file, argv, msg);
81 }
82 
83 int
84 octave_syscalls::execvp (const std::string& file, const string_vector& args,
85  std::string& msg)
86 {
87  msg = std::string ();
88 
89  int status = -1;
90 
91 #if defined (HAVE_EXECVP)
92  char **argv = args.c_str_vec ();
93 
94  status = ::execvp (file.c_str (), argv);
95 
97 
98  if (status < 0)
99  msg = gnulib::strerror (errno);
100 #else
101  msg = NOT_SUPPORTED ("execvp");
102 #endif
103 
104  return status;
105 }
106 
107 pid_t
108 octave_syscalls::fork (std::string& msg)
109 {
110  pid_t status = -1;
111 
112 #if defined (HAVE_FORK)
113  status = ::fork ();
114 
115  if (status < 0)
116  msg = gnulib::strerror (errno);
117 #else
118  msg = NOT_SUPPORTED ("fork");
119 #endif
120 
121  return status;
122 }
123 
124 pid_t
125 octave_syscalls::vfork (std::string& msg)
126 {
127  pid_t status = -1;
128 
129 #if defined (HAVE_VFORK) || defined (HAVE_FORK)
130 #if defined (HAVE_VFORK)
131  status = ::vfork ();
132 #else
133  status = ::fork ();
134 #endif
135 
136  if (status < 0)
137  msg = gnulib::strerror (errno);
138 #else
139  msg = NOT_SUPPORTED ("vfork");
140 #endif
141 
142  return status;
143 }
144 
145 pid_t
146 octave_syscalls::getpgrp (std::string& msg)
147 {
148  pid_t status = -1;
149 
150 #if defined (HAVE_GETPGRP)
151  status = ::getpgrp ();
152 
153  if (status < 0)
154  msg = gnulib::strerror (errno);
155 #else
156  msg = NOT_SUPPORTED ("getpgrp");
157 #endif
158 
159  return status;
160 }
161 
162 pid_t
164 {
165 #if defined (HAVE_GETPID)
166  return ::getpid ();
167 #else
168  return 0;
169 #endif
170 }
171 
172 pid_t
174 {
175 #if defined (HAVE_GETPPID)
176  return ::getppid ();
177 #else
178  return 0;
179 #endif
180 }
181 
182 gid_t
184 {
185 #if defined (HAVE_GETGID)
186  return ::getgid ();
187 #else
188  return 0;
189 #endif
190 }
191 
192 gid_t
194 {
195 #if defined (HAVE_GETEGID)
196  return ::getegid ();
197 #else
198  return 0;
199 #endif
200 }
201 
202 uid_t
204 {
205 #if defined (HAVE_GETUID)
206  return ::getuid ();
207 #else
208  return 0;
209 #endif
210 }
211 
212 uid_t
214 {
215 #if defined (HAVE_GETEUID)
216  return ::geteuid ();
217 #else
218  return 0;
219 #endif
220 }
221 
222 int
224 {
225  std::string msg;
226  return pipe (fildes, msg);
227 }
228 
229 int
230 octave_syscalls::pipe (int *fildes, std::string& msg)
231 {
232  msg = std::string ();
233 
234  int status = -1;
235 
236 #if defined (HAVE_PIPE)
237  status = ::pipe (fildes);
238 
239  if (status < 0)
240  msg = gnulib::strerror (errno);
241 #else
242  msg = NOT_SUPPORTED ("pipe");
243 #endif
244 
245  return status;
246 }
247 
248 pid_t
249 octave_syscalls::waitpid (pid_t pid, int *status, int options)
250 {
251  std::string msg;
252  return waitpid (pid, status, options, msg);
253 }
254 
255 pid_t
256 octave_syscalls::waitpid (pid_t pid, int *status, int options,
257  std::string& msg)
258 {
259  pid_t retval = -1;
260  msg = std::string ();
261 
262 #if defined (HAVE_WAITPID)
263  retval = ::octave_waitpid (pid, status, options);
264 
265  if (retval < 0)
266  msg = gnulib::strerror (errno);
267 #else
268  msg = NOT_SUPPORTED ("waitpid");
269 #endif
270 
271  return retval;
272 }
273 
274 int
275 octave_syscalls::kill (pid_t pid, int sig)
276 {
277  std::string msg;
278  return kill (pid, sig, msg);
279 }
280 
281 int
282 octave_syscalls::kill (pid_t pid, int sig, std::string& msg)
283 {
284  msg = std::string ();
285 
286  int status = -1;
287 
288 #if defined (HAVE_KILL)
289  status = ::kill (pid, sig);
290 
291  if (status < 0)
292  msg = gnulib::strerror (errno);
293 #else
294  msg = NOT_SUPPORTED ("kill");
295 #endif
296 
297  return status;
298 }
299 
300 pid_t
301 octave_syscalls::popen2 (const std::string& cmd, const string_vector& args,
302  bool sync_mode, int *fildes)
303 {
304  std::string msg;
305  bool interactive = false;
306  return popen2 (cmd, args, sync_mode, fildes, msg, interactive);
307 }
308 
309 pid_t
310 octave_syscalls::popen2 (const std::string& cmd, const string_vector& args,
311  bool sync_mode, int *fildes, std::string& msg)
312 {
313  bool interactive = false;
314  return popen2 (cmd, args, sync_mode, fildes, msg, interactive);
315 }
316 
317 pid_t
318 octave_syscalls::popen2 (const std::string& cmd, const string_vector& args,
319  bool sync_mode, int *fildes, std::string& msg,
320  bool &interactive)
321 {
322 #if defined (__WIN32__) && ! defined (__CYGWIN__)
323  return ::octave_popen2 (cmd, args, sync_mode, fildes, msg);
324 #else
325  pid_t pid;
326  int child_stdin[2], child_stdout[2];
327 
328  if (pipe (child_stdin, msg) == 0)
329  {
330  if (pipe (child_stdout, msg) == 0)
331  {
332  pid = fork (msg);
333  if (pid < 0)
334  msg = "popen2: process creation failed -- " + msg;
335  else if (pid == 0)
336  {
337  std::string child_msg;
338 
339  interactive = false;
340 
341  // Child process
342  gnulib::close (child_stdin[1]);
343  gnulib::close (child_stdout[0]);
344 
345  if (dup2 (child_stdin[0], STDIN_FILENO) >= 0)
346  {
347  gnulib::close (child_stdin[0]);
348  if (dup2 (child_stdout[1], STDOUT_FILENO) >= 0)
349  {
350  gnulib::close (child_stdout[1]);
351  if (execvp (cmd, args, child_msg) < 0)
352  child_msg = "popen2 (child): unable to start process -- " + child_msg;
353  }
354  else
355  child_msg = "popen2 (child): file handle duplication failed -- " + child_msg;
356  }
357  else
358  child_msg = "popen2 (child): file handle duplication failed -- " + child_msg;
359 
360  (*current_liboctave_error_handler)(child_msg.c_str ());
361 
362  exit (0);
363  }
364  else
365  {
366  // Parent process
367  gnulib::close (child_stdin[0]);
368  gnulib::close (child_stdout[1]);
369 
370 #if defined (F_SETFL) && defined (O_NONBLOCK)
371  if (! sync_mode && octave_fcntl (child_stdout[0], F_SETFL,
372  O_NONBLOCK, msg) < 0)
373  msg = "popen2: error setting file mode -- " + msg;
374  else
375 #endif
376  {
377  fildes[0] = child_stdin[1];
378  fildes[1] = child_stdout[0];
379  return pid;
380  }
381  }
382  gnulib::close (child_stdout[0]);
383  gnulib::close (child_stdout[1]);
384  }
385  else
386  msg = "popen2: pipe creation failed -- " + msg;
387 
388  gnulib::close (child_stdin[0]);
389  gnulib::close (child_stdin[1]);
390  }
391  else
392  msg = "popen2: pipe creation failed -- " + msg;
393 
394  return -1;
395 #endif
396 }
397 
398 int
399 octave_fcntl (int fd, int cmd, long arg)
400 {
401  std::string msg;
402  return octave_fcntl (fd, cmd, arg, msg);
403 }
404 
405 int
406 octave_fcntl (int fd, int cmd, long arg, std::string& msg)
407 {
408  msg = std::string ();
409 
410  int status = -1;
411 
412  status = gnulib::fcntl (fd, cmd, arg);
413 
414  if (status < 0)
415  msg = gnulib::strerror (errno);
416 
417  return status;
418 }