Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:06

0001 // Copyright (c) 2019 Klemens D. Morgenstern
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 #ifndef BOOST_PROCESS_DETAIL_POSIX_HANDLES_HPP_
0007 #define BOOST_PROCESS_DETAIL_POSIX_HANDLES_HPP_
0008 
0009 #include <vector>
0010 #include <system_error>
0011 #include <dirent.h>
0012 #include <sys/stat.h>
0013 #include <algorithm>
0014 #include <memory>
0015 #include <cstdlib>
0016 #include <boost/process/detail/posix/handler.hpp>
0017 
0018 namespace boost { namespace process { namespace detail { namespace posix {
0019 
0020 
0021 using native_handle_type = int;
0022 
0023 inline std::vector<native_handle_type> get_handles(std::error_code & ec)
0024 {
0025     std::vector<native_handle_type> res;
0026 
0027     std::unique_ptr<DIR, void(*)(DIR*)> dir{::opendir("/dev/fd"), +[](DIR* p){::closedir(p);}};
0028     if (!dir)
0029     {
0030         ec = ::boost::process::detail::get_last_error();
0031         return {};
0032     }
0033     else
0034         ec.clear();
0035 
0036     auto my_fd = dirfd(dir.get());
0037 
0038     struct ::dirent * ent_p;
0039 
0040     while ((ent_p = readdir(dir.get())) != nullptr)
0041     {
0042         if (ent_p->d_name[0] == '.')
0043             continue;
0044 
0045         const auto conv = std::atoi(ent_p->d_name);
0046         if (conv == 0 && (ent_p->d_name[0] != '0' && ent_p->d_name[1] != '\0'))
0047             continue;
0048 
0049         if (conv == my_fd)
0050             continue;
0051 
0052         res.push_back(conv);
0053     }
0054     return res;
0055 }
0056 
0057 inline std::vector<native_handle_type> get_handles()
0058 {
0059     std::error_code ec;
0060 
0061     auto res = get_handles(ec);
0062     if (ec)
0063         boost::process::detail::throw_error(ec, "open_dir(\"/dev/fd\") failed");
0064 
0065     return res;
0066 }
0067 
0068 
0069 inline bool is_stream_handle(native_handle_type handle, std::error_code & ec)
0070 {
0071     struct ::stat stat_;
0072 
0073     if (::fstat(handle, &stat_) != 0)
0074     {
0075         ec = ::boost::process::detail::get_last_error();
0076     }
0077     else
0078         ec.clear();
0079 
0080     return S_ISCHR  (stat_.st_mode)  //This macro returns non-zero if the file is a character special file (a device like a terminal).
0081         || S_ISBLK  (stat_.st_mode) // This macro returns non-zero if the file is a block special file (a device like a disk).
0082         || S_ISREG  (stat_.st_mode) // This macro returns non-zero if the file is a regular file.
0083         || S_ISFIFO (stat_.st_mode) // This macro returns non-zero if the file is a FIFO special file, or a pipe. See section 15. Pipes and FIFOs.
0084         || S_ISSOCK (stat_.st_mode) ;// This macro returns non-zero if the file is a socket. See section 16. Sockets.;
0085 }
0086 
0087 
0088 inline bool is_stream_handle(native_handle_type handle)
0089 {
0090     std::error_code ec;
0091     auto res = is_stream_handle(handle, ec);
0092     if (ec)
0093         boost::process::detail::throw_error(ec, "fstat() failed");
0094 
0095     return res;
0096 }
0097 
0098 struct limit_handles_ : handler_base_ext
0099 {
0100     limit_handles_() {}
0101     ~limit_handles_() {}
0102     mutable std::vector<int> used_handles;
0103 
0104     template<typename Executor>
0105     void on_setup(Executor & exec) const
0106     {
0107         used_handles = get_used_handles(exec);
0108     }
0109 
0110     template<typename Executor>
0111     void on_exec_setup(Executor & exec) const
0112     {
0113         auto dir = ::opendir("/dev/fd");
0114         if (!dir)
0115         {
0116             exec.set_error(::boost::process::detail::get_last_error(), "opendir(\"/dev/fd\")");
0117             return;
0118         }
0119 
0120         auto my_fd = dirfd(dir);
0121         struct ::dirent * ent_p;
0122 
0123         while ((ent_p = readdir(dir)) != nullptr)
0124         {
0125             if (ent_p->d_name[0] == '.')
0126                 continue;
0127 
0128             const auto conv = std::atoi(ent_p->d_name);
0129 
0130             if ((conv == my_fd) || (conv == -1))
0131                 continue;
0132 
0133             if (std::find(used_handles.begin(), used_handles.end(), conv) != used_handles.end())
0134                 continue;
0135 
0136             if (::close(conv) != 0)
0137             {
0138                 exec.set_error(::boost::process::detail::get_last_error(), "close() failed");
0139                 return;
0140             }
0141         }
0142         ::closedir(dir);
0143     }
0144 };
0145 
0146 }}}}
0147 
0148 #endif //PROCESS_HANDLES_HPP