| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 | // Copyright (c) 2019 Klemens D. Morgenstern//// Distributed under the Boost Software License, Version 1.0. (See accompanying// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)#ifndef BOOST_PROCESS_DETAIL_POSIX_HANDLES_HPP_#define BOOST_PROCESS_DETAIL_POSIX_HANDLES_HPP_#include <vector>#include <system_error>#include <dirent.h>#include <sys/stat.h>#include <algorithm>#include <boost/process/detail/posix/handler.hpp>namespace boost { namespace process { namespace detail { namespace posix {using native_handle_type = int;inline std::vector<native_handle_type> get_handles(std::error_code & ec){    std::vector<native_handle_type> res;    std::unique_ptr<DIR, void(*)(DIR*)> dir{::opendir("/dev/fd"), +[](DIR* p){::closedir(p);}};    if (!dir)    {        ec = ::boost::process::detail::get_last_error();        return {};    }    else        ec.clear();    auto my_fd = ::dirfd(dir.get());    struct ::dirent * ent_p;    while ((ent_p = readdir(dir.get())) != nullptr)    {        if (ent_p->d_name[0] == '.')            continue;        const auto conv = std::atoi(ent_p->d_name);        if (conv == 0 && (ent_p->d_name[0] != '0' && ent_p->d_name[1] != '\0'))            continue;        if (conv == my_fd)            continue;        res.push_back(conv);    }    return res;}inline std::vector<native_handle_type> get_handles(){    std::error_code ec;    auto res = get_handles(ec);    if (ec)        boost::process::detail::throw_error(ec, "open_dir(\"/dev/fd\") failed");    return res;}inline bool is_stream_handle(native_handle_type handle, std::error_code & ec){    struct ::stat stat_;    if (::fstat(handle, &stat_) != 0)    {        ec = ::boost::process::detail::get_last_error();    }    else        ec.clear();    return S_ISCHR  (stat_.st_mode)  //This macro returns non-zero if the file is a character special file (a device like a terminal).        || S_ISBLK  (stat_.st_mode) // This macro returns non-zero if the file is a block special file (a device like a disk).        || S_ISREG  (stat_.st_mode) // This macro returns non-zero if the file is a regular file.        || 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.        || S_ISSOCK (stat_.st_mode) ;// This macro returns non-zero if the file is a socket. See section 16. Sockets.;}inline bool is_stream_handle(native_handle_type handle){    std::error_code ec;    auto res = is_stream_handle(handle, ec);    if (ec)        boost::process::detail::throw_error(ec, "fstat() failed");    return res;}struct limit_handles_ : handler_base_ext{    limit_handles_() {}    ~limit_handles_() {}    mutable std::vector<int> used_handles;    template<typename Executor>    void on_setup(Executor & exec) const    {        used_handles = get_used_handles(exec);    }    template<typename Executor>    void on_exec_setup(Executor & exec) const    {        auto dir = ::opendir("/dev/fd");        if (!dir)        {            exec.set_error(::boost::process::detail::get_last_error(), "opendir(\"/dev/fd\")");            return;        }        auto my_fd = ::dirfd(dir);        struct ::dirent * ent_p;        while ((ent_p = readdir(dir)) != nullptr)        {            if (ent_p->d_name[0] == '.')                continue;            const auto conv = std::atoi(ent_p->d_name);            if ((conv == my_fd) || (conv == -1))                continue;            if (std::find(used_handles.begin(), used_handles.end(), conv) != used_handles.end())                continue;            if (::close(conv) != 0)            {                exec.set_error(::boost::process::detail::get_last_error(), "close() failed");                return;            }        }        ::closedir(dir);    }};}}}}#endif //PROCESS_HANDLES_HPP
 |