oct-syscalls.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1996-2012 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include <cerrno>
00028 #include <cstdlib>
00029 
00030 #include <string.h>
00031 
00032 #include <sys/types.h>
00033 #include <unistd.h>
00034 
00035 #include <fcntl.h>
00036 
00037 // We can't use csignal as kill is not in the std namespace, and picky
00038 // compiler runtimes will also exclude it from global scope as well.
00039 
00040 #include <signal.h>
00041 
00042 #include "lo-utils.h"
00043 #include "lo-sysdep.h"
00044 #include "oct-syscalls.h"
00045 #include "str-vec.h"
00046 
00047 #define NOT_SUPPORTED(nm) \
00048   nm ": not supported on this system"
00049 
00050 int
00051 octave_syscalls::dup2 (int old_fd, int new_fd)
00052 {
00053   std::string msg;
00054   return dup2 (old_fd, new_fd, msg);
00055 }
00056 
00057 int
00058 octave_syscalls::dup2 (int old_fd, int new_fd, std::string& msg)
00059 {
00060   msg = std::string ();
00061 
00062   int status = -1;
00063 
00064 #if defined (HAVE_DUP2)
00065   status = gnulib::dup2 (old_fd, new_fd);
00066 
00067   if (status < 0)
00068     msg = gnulib::strerror (errno);
00069 #else
00070   msg = NOT_SUPPORTED ("dup2");
00071 #endif
00072 
00073   return status;
00074 }
00075 
00076 int
00077 octave_syscalls::execvp (const std::string& file, const string_vector& argv)
00078 {
00079   std::string msg;
00080   return execvp (file, argv, msg);
00081 }
00082 
00083 int
00084 octave_syscalls::execvp (const std::string& file, const string_vector& args,
00085                          std::string& msg)
00086 {
00087   msg = std::string ();
00088 
00089   int status = -1;
00090 
00091 #if defined (HAVE_EXECVP)
00092   char **argv = args.c_str_vec ();
00093 
00094   status = ::execvp (file.c_str (), argv);
00095 
00096   string_vector::delete_c_str_vec (argv);
00097 
00098   if (status < 0)
00099     msg = gnulib::strerror (errno);
00100 #else
00101   msg = NOT_SUPPORTED ("execvp");
00102 #endif
00103 
00104   return status;
00105 }
00106 
00107 pid_t
00108 octave_syscalls::fork (std::string& msg)
00109 {
00110   pid_t status = -1;
00111 
00112 #if defined (HAVE_FORK)
00113   status = ::fork ();
00114 
00115   if (status < 0)
00116     msg = gnulib::strerror (errno);
00117 #else
00118   msg = NOT_SUPPORTED ("fork");
00119 #endif
00120 
00121   return status;
00122 }
00123 
00124 pid_t
00125 octave_syscalls::vfork (std::string& msg)
00126 {
00127   pid_t status = -1;
00128 
00129 #if defined (HAVE_VFORK) || defined (HAVE_FORK)
00130 #if defined (HAVE_VFORK)
00131   status = ::vfork ();
00132 #else
00133   status = ::fork ();
00134 #endif
00135 
00136   if (status < 0)
00137     msg = gnulib::strerror (errno);
00138 #else
00139   msg = NOT_SUPPORTED ("vfork");
00140 #endif
00141 
00142   return status;
00143 }
00144 
00145 pid_t
00146 octave_syscalls::getpgrp (std::string& msg)
00147 {
00148   pid_t status = -1;
00149 
00150 #if defined (HAVE_GETPGRP)
00151   status = ::getpgrp ();
00152 
00153   if (status < 0)
00154     msg = gnulib::strerror (errno);
00155 #else
00156   msg = NOT_SUPPORTED ("getpgrp");
00157 #endif
00158 
00159   return status;
00160 }
00161 
00162 pid_t
00163 octave_syscalls::getpid (void)
00164 {
00165 #if defined (HAVE_GETPID)
00166   return ::getpid ();
00167 #else
00168   return 0;
00169 #endif
00170 }
00171 
00172 pid_t
00173 octave_syscalls::getppid (void)
00174 {
00175 #if defined (HAVE_GETPPID)
00176   return ::getppid ();
00177 #else
00178   return 0;
00179 #endif
00180 }
00181 
00182 gid_t
00183 octave_syscalls::getgid (void)
00184 {
00185 #if defined (HAVE_GETGID)
00186   return ::getgid ();
00187 #else
00188   return 0;
00189 #endif
00190 }
00191 
00192 gid_t
00193 octave_syscalls::getegid (void)
00194 {
00195 #if defined (HAVE_GETEGID)
00196   return ::getegid ();
00197 #else
00198   return 0;
00199 #endif
00200 }
00201 
00202 uid_t
00203 octave_syscalls::getuid (void)
00204 {
00205 #if defined (HAVE_GETUID)
00206   return ::getuid ();
00207 #else
00208   return 0;
00209 #endif
00210 }
00211 
00212 uid_t
00213 octave_syscalls::geteuid (void)
00214 {
00215 #if defined (HAVE_GETEUID)
00216   return ::geteuid ();
00217 #else
00218   return 0;
00219 #endif
00220 }
00221 
00222 int
00223 octave_syscalls::pipe (int *fildes)
00224 {
00225   std::string msg;
00226   return pipe (fildes, msg);
00227 }
00228 
00229 int
00230 octave_syscalls::pipe (int *fildes, std::string& msg)
00231 {
00232   msg = std::string ();
00233 
00234   int status = -1;
00235 
00236 #if defined (HAVE_PIPE)
00237   status = ::pipe (fildes);
00238 
00239   if (status < 0)
00240     msg = gnulib::strerror (errno);
00241 #else
00242   msg = NOT_SUPPORTED ("pipe");
00243 #endif
00244 
00245   return status;
00246 }
00247 
00248 pid_t
00249 octave_syscalls::waitpid (pid_t pid, int *status, int options)
00250 {
00251   std::string msg;
00252   return waitpid (pid, status, options, msg);
00253 }
00254 
00255 pid_t
00256 octave_syscalls::waitpid (pid_t pid, int *status, int options,
00257                           std::string& msg)
00258 {
00259   pid_t retval = -1;
00260   msg = std::string ();
00261 
00262 #if defined (HAVE_WAITPID)
00263   retval = ::octave_waitpid (pid, status, options);
00264 
00265   if (retval < 0)
00266     msg = gnulib::strerror (errno);
00267 #else
00268   msg = NOT_SUPPORTED ("waitpid");
00269 #endif
00270 
00271   return retval;
00272 }
00273 
00274 int
00275 octave_syscalls::kill (pid_t pid, int sig)
00276 {
00277   std::string msg;
00278   return kill (pid, sig, msg);
00279 }
00280 
00281 int
00282 octave_syscalls::kill (pid_t pid, int sig, std::string& msg)
00283 {
00284   msg = std::string ();
00285 
00286   int status = -1;
00287 
00288 #if defined (HAVE_KILL)
00289   status = ::kill (pid, sig);
00290 
00291   if (status < 0)
00292     msg = gnulib::strerror (errno);
00293 #else
00294   msg = NOT_SUPPORTED ("kill");
00295 #endif
00296 
00297   return status;
00298 }
00299 
00300 pid_t
00301 octave_syscalls::popen2 (const std::string& cmd, const string_vector& args,
00302     bool sync_mode, int *fildes)
00303 {
00304   std::string msg;
00305   bool interactive = false;
00306   return popen2 (cmd, args, sync_mode, fildes, msg, interactive);
00307 }
00308 
00309 pid_t
00310 octave_syscalls::popen2 (const std::string& cmd, const string_vector& args,
00311     bool sync_mode, int *fildes, std::string& msg)
00312 {
00313   bool interactive = false;
00314   return popen2 (cmd, args, sync_mode, fildes, msg, interactive);
00315 }
00316 
00317 pid_t
00318 octave_syscalls::popen2 (const std::string& cmd, const string_vector& args,
00319     bool sync_mode, int *fildes, std::string& msg, bool &interactive)
00320 {
00321 #if defined (__WIN32__) && ! defined (__CYGWIN__)
00322   return ::octave_popen2 (cmd, args, sync_mode, fildes, msg);
00323 #else
00324   pid_t pid;
00325   int child_stdin[2], child_stdout[2];
00326 
00327   if (pipe (child_stdin, msg) == 0)
00328     {
00329       if (pipe (child_stdout, msg) == 0)
00330         {
00331           pid = fork (msg);
00332           if (pid < 0)
00333             msg = "popen2: process creation failed -- " + msg;
00334           else if (pid == 0)
00335             {
00336               std::string child_msg;
00337 
00338               interactive = false;
00339 
00340               // Child process
00341               gnulib::close (child_stdin[1]);
00342               gnulib::close (child_stdout[0]);
00343 
00344               if (dup2 (child_stdin[0], STDIN_FILENO) >= 0)
00345                 {
00346                   gnulib::close (child_stdin[0]);
00347                   if (dup2 (child_stdout[1], STDOUT_FILENO) >= 0)
00348                     {
00349                       gnulib::close (child_stdout[1]);
00350                       if (execvp (cmd, args, child_msg) < 0)
00351                         child_msg = "popen2 (child): unable to start process -- " + child_msg;
00352                     }
00353                   else
00354                     child_msg = "popen2 (child): file handle duplication failed -- " + child_msg;
00355                 }
00356               else
00357                 child_msg = "popen2 (child): file handle duplication failed -- " + child_msg;
00358 
00359               (*current_liboctave_error_handler)(child_msg.c_str());
00360 
00361               exit(0);
00362             }
00363           else
00364             {
00365               // Parent process
00366               gnulib::close (child_stdin[0]);
00367               gnulib::close (child_stdout[1]);
00368 
00369 #if defined (F_SETFL) && defined (O_NONBLOCK)
00370               if (! sync_mode && octave_fcntl (child_stdout[0], F_SETFL, O_NONBLOCK, msg) < 0)
00371                 msg = "popen2: error setting file mode -- " + msg;
00372               else
00373 #endif
00374                 {
00375                   fildes[0] = child_stdin [1];
00376                   fildes[1] = child_stdout [0];
00377                   return pid;
00378                 }
00379             }
00380           gnulib::close (child_stdout[0]);
00381           gnulib::close (child_stdout[1]);
00382         }
00383       else
00384         msg = "popen2: pipe creation failed -- " + msg;
00385 
00386       gnulib::close (child_stdin[0]);
00387       gnulib::close (child_stdin[1]);
00388     }
00389   else
00390     msg = "popen2: pipe creation failed -- " + msg;
00391 
00392   return -1;
00393 #endif
00394 }
00395 
00396 int
00397 octave_fcntl (int fd, int cmd, long arg)
00398 {
00399   std::string msg;
00400   return octave_fcntl (fd, cmd, arg, msg);
00401 }
00402 
00403 int
00404 octave_fcntl (int fd, int cmd, long arg, std::string& msg)
00405 {
00406   msg = std::string ();
00407 
00408   int status = -1;
00409 
00410   status = gnulib::fcntl (fd, cmd, arg);
00411 
00412   if (status < 0)
00413     msg = gnulib::strerror (errno);
00414 
00415   return status;
00416 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines