00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00019 #ifndef BOOST_PROCESS_DETAIL_FILE_HANDLE_HPP
00020 #define BOOST_PROCESS_DETAIL_FILE_HANDLE_HPP
00021
00022 #include <boost/process/config.hpp>
00023
00024 #if defined(BOOST_POSIX_API)
00025 # include <cerrno>
00026 # include <unistd.h>
00027 #elif defined(BOOST_WINDOWS_API)
00028 # include <windows.h>
00029 #else
00030 # error "Unsupported platform."
00031 #endif
00032
00033 #include <boost/assert.hpp>
00034 #include <boost/system/system_error.hpp>
00035 #include <boost/throw_exception.hpp>
00036
00037 namespace boost {
00038 namespace process {
00039 namespace detail {
00040
00058 class file_handle
00059 {
00060 public:
00061 #if defined(BOOST_PROCESS_DOXYGEN)
00062
00073 typedef NativeSystemHandle handle_type;
00074 #elif defined(BOOST_POSIX_API)
00075 typedef int handle_type;
00076 #elif defined(BOOST_WINDOWS_API)
00077 typedef HANDLE handle_type;
00078 #endif
00079
00089 file_handle()
00090 : handle_(invalid_value())
00091 {
00092 }
00093
00106 file_handle(handle_type h)
00107 : handle_(h)
00108 {
00109 BOOST_ASSERT(handle_ != invalid_value());
00110 }
00111
00125 file_handle(const file_handle &fh)
00126 : handle_(fh.handle_)
00127 {
00128 fh.handle_ = invalid_value();
00129 }
00130
00138 ~file_handle()
00139 {
00140 if (valid())
00141 close();
00142 }
00143
00157 file_handle &operator=(const file_handle &fh)
00158 {
00159 handle_ = fh.handle_;
00160 fh.handle_ = invalid_value();
00161 return *this;
00162 }
00163
00173 bool valid() const
00174 {
00175 return handle_ != invalid_value();
00176 }
00177
00188 void close()
00189 {
00190 BOOST_ASSERT(valid());
00191
00192 #if defined(BOOST_POSIX_API)
00193 ::close(handle_);
00194 #elif defined(BOOST_WINDOWS_API)
00195 ::CloseHandle(handle_);
00196 #endif
00197
00198 handle_ = invalid_value();
00199 }
00200
00212 handle_type release()
00213 {
00214 BOOST_ASSERT(valid());
00215
00216 handle_type h = handle_;
00217 handle_ = invalid_value();
00218 return h;
00219 }
00220
00232 handle_type get() const
00233 {
00234 BOOST_ASSERT(valid());
00235
00236 return handle_;
00237 }
00238
00239 #if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN)
00240
00259 void posix_remap(handle_type h)
00260 {
00261 BOOST_ASSERT(valid());
00262
00263 if (::dup2(handle_, h) == -1)
00264 boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::file_handle::posix_remap: dup2(2) failed"));
00265
00266 if (::close(handle_) == -1)
00267 {
00268 ::close(h);
00269 boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::file_handle::posix_remap: close(2) failed"));
00270 }
00271
00272 handle_ = h;
00273 }
00274
00292 static file_handle posix_dup(int h1, int h2)
00293 {
00294 if (::dup2(h1, h2) == -1)
00295 boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::file_handle::posix_dup: dup2(2) failed"));
00296
00297 return file_handle(h2);
00298 }
00299 #endif
00300
00301 #if defined(BOOST_WINDOWS_API) || defined(BOOST_PROCESS_DOXYGEN)
00302
00315 static file_handle win32_dup(HANDLE h, bool inheritable)
00316 {
00317 HANDLE h2;
00318 if (!::DuplicateHandle(::GetCurrentProcess(), h, ::GetCurrentProcess(), &h2, 0, inheritable ? TRUE : FALSE, DUPLICATE_SAME_ACCESS))
00319 boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::file_handle::win32_dup: DuplicateHandle failed"));
00320
00321 return file_handle(h2);
00322 }
00323
00341 static file_handle win32_std(DWORD d, bool inheritable)
00342 {
00343 BOOST_ASSERT(d == STD_INPUT_HANDLE || d == STD_OUTPUT_HANDLE || d == STD_ERROR_HANDLE);
00344
00345 HANDLE h = ::GetStdHandle(d);
00346 if (h == INVALID_HANDLE_VALUE)
00347 boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::file_handle::win32_std: GetStdHandle failed"));
00348
00349 return win32_dup(h, inheritable);
00350 }
00351
00364 void win32_set_inheritable(bool i)
00365 {
00366 BOOST_ASSERT(valid());
00367
00368 if (!::SetHandleInformation(handle_, HANDLE_FLAG_INHERIT, i ? HANDLE_FLAG_INHERIT : 0))
00369 boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::file_handle::win32_set_inheritable: SetHandleInformation failed"));
00370 }
00371 #endif
00372
00373 private:
00382 mutable handle_type handle_;
00383
00392 static const handle_type invalid_value()
00393 {
00394 #if defined(BOOST_POSIX_API)
00395 return -1;
00396 #elif defined(BOOST_WINDOWS_API)
00397 return INVALID_HANDLE_VALUE;
00398 #endif
00399 }
00400 };
00401
00402 }
00403 }
00404 }
00405
00406 #endif