various updates for arm

This commit is contained in:
Daniel Larimer 2012-12-30 15:16:00 -08:00
commit 0114f6e3e7
169 changed files with 60409 additions and 272 deletions

View file

@ -41,9 +41,8 @@ option( UNITY_BUILD OFF )
FIND_PACKAGE( OpenSSL )
include_directories( vendor/boost/process/include )
include_directories( vendor/libssh2-1.4.2/include )
include_directories( vendor/zlib-1.2.7/)
include_directories( vendor/libssh2-1.4.2/include )
include_directories( ${Boost_INCLUDE_DIR} )
include_directories( ${OPENSSL_INCLUDE_DIR} )
include_directories( include )
@ -95,13 +94,12 @@ set( sources
# src/program_options.cpp
)
add_subdirectory(vendor/libssh2-1.4.2)
add_subdirectory( vendor/zlib-1.2.7/)
add_subdirectory(vendor)
setup_library( fc SOURCES ${sources} )
setup_executable( json_rpc_test SOURCES tests/json_rpc_test.cpp LIBRARIES zlibstatic fc ${pthread_library} ${rt_library} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${rt_library} ${Boost_DATE_TIME_LIBRARY})
setup_executable( ssh_test SOURCES tests/ssh.cpp LIBRARIES fc ${pthread_library} ${rt_library} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${rt_library} ssh2 zlibstatic ${OPENSSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} ${ZLIB_LIBRARY} ${ALL_OPENSSL_LIBRARIES} ${Boost_DATE_TIME_LIBRARY})
#setup_executable( json_rpc_test SOURCES tests/json_rpc_test.cpp LIBRARIES fc ${pthread_library} ${rt_library} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${rt_library} ${Boost_DATE_TIME_LIBRARY})
#setup_executable( ssh_test SOURCES tests/ssh.cpp LIBRARIES fc ${pthread_library} ${rt_library} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${rt_library} ssh2 ${OPENSSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} ${ZLIB_LIBRARY} ${ALL_OPENSSL_LIBRARIES} ${Boost_DATE_TIME_LIBRARY})
#add_executable( test_vec tests/vector_test.cpp )
#target_link_libraries( test_vec fc ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} )

25
include/boost/process.hpp Normal file
View file

@ -0,0 +1,25 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process.hpp
*
* Convenience header that includes all public Boost.Process header files.
*/
#ifndef BOOST_PROCESS_HPP
#define BOOST_PROCESS_HPP
#include <boost/process/all.hpp>
#endif

View file

@ -0,0 +1,40 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/all.hpp
*
* Convenience header that includes all public Boost.Process header files.
*/
#ifndef BOOST_PROCESS_ALL_HPP
#define BOOST_PROCESS_ALL_HPP
#include <boost/process/child.hpp>
#include <boost/process/context.hpp>
#include <boost/process/environment.hpp>
#include <boost/process/handle.hpp>
#include <boost/process/operations.hpp>
#include <boost/process/pid_type.hpp>
#include <boost/process/pipe.hpp>
#include <boost/process/pistream.hpp>
#include <boost/process/postream.hpp>
#include <boost/process/process.hpp>
#include <boost/process/self.hpp>
#include <boost/process/status.hpp>
#include <boost/process/stream_behavior.hpp>
#include <boost/process/stream_ends.hpp>
#include <boost/process/stream_id.hpp>
#include <boost/process/stream_type.hpp>
#endif

View file

@ -0,0 +1,92 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/child.hpp
*
* Includes the declaration of the child class.
*/
#ifndef BOOST_PROCESS_CHILD_HPP
#define BOOST_PROCESS_CHILD_HPP
#include <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#else
# error "Unsupported platform."
#endif
#include <boost/process/process.hpp>
#include <boost/process/pid_type.hpp>
#include <boost/process/stream_id.hpp>
#include <boost/process/handle.hpp>
#include <map>
namespace boost {
namespace process {
/**
* The child class provides access to a child process.
*/
class child : public process
{
public:
/**
* Creates a new child object that represents the just spawned child
* process \a id.
*/
child(pid_type id, std::map<stream_id, handle> handles)
: process(id),
handles_(handles)
{
}
#if defined(BOOST_WINDOWS_API)
/**
* Creates a new child object that represents the just spawned child
* process \a id.
*
* This operation is only available on Windows systems.
*/
child(handle hprocess, std::map<stream_id, handle> handles)
: process(hprocess),
handles_(handles)
{
}
#endif
/**
* Gets a handle to a stream attached to the child.
*
* If the handle doesn't exist an invalid handle is returned.
*/
handle get_handle(stream_id id) const
{
std::map<stream_id, handle>::const_iterator it = handles_.find(id);
return (it != handles_.end()) ? it->second : handle();
}
private:
/**
* Handles providing access to streams attached to the child process.
*/
std::map<stream_id, handle> handles_;
};
}
}
#endif

View file

@ -0,0 +1,74 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/config.hpp
*
* Defines macros that are used by the library to determine the operating
* system it is running under and the features it supports.
*/
#ifndef BOOST_PROCESS_CONFIG_HPP
#define BOOST_PROCESS_CONFIG_HPP
#include <boost/config.hpp>
#include <boost/system/config.hpp>
#include <boost/system/system_error.hpp>
#include <boost/throw_exception.hpp>
#if defined(BOOST_POSIX_API)
# include <errno.h>
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#endif
#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN)
# if !defined(BOOST_PROCESS_POSIX_PATH_MAX) || defined(BOOST_PROCESS_DOXYGEN)
/**
* Specifies the system's maximal supported path length.
*
* The macro BOOST_PROCESS_POSIX_PATH_MAX is set to a positive integer
* value which specifies the system's maximal supported path length. It is
* only used if neither PATH_MAX nor _PC_PATH_MAX and HAVE_PATHCONF are defined.
* The maximal supported path length is required by
* boost::process::self::get_work_dir(). Please note that this function is
* also called by the constructor of boost::process::context.
*/
# define BOOST_PROCESS_POSIX_PATH_MAX 259
# endif
#endif
/** \cond */
#define BOOST_PROCESS_SOURCE_LOCATION \
"in file '" __FILE__ "', line " BOOST_STRINGIZE(__LINE__) ": "
#if defined(BOOST_POSIX_API)
# define BOOST_PROCESS_LAST_ERROR errno
#elif defined(BOOST_WINDOWS_API)
# define BOOST_PROCESS_LAST_ERROR GetLastError()
#endif
#define BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(what) \
boost::throw_exception(boost::system::system_error( \
boost::system::error_code(BOOST_PROCESS_LAST_ERROR, \
boost::system::get_system_category()), \
BOOST_PROCESS_SOURCE_LOCATION what))
#define BOOST_PROCESS_THROW_ERROR(error, what) \
boost::throw_exception(boost::system::system_error( \
boost::system::error_code(error, \
boost::system::get_system_category()), \
BOOST_PROCESS_SOURCE_LOCATION what))
/** \endcond */
#endif

View file

@ -0,0 +1,133 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/context.hpp
*
* Includes the declaration of the context class.
*/
#ifndef BOOST_PROCESS_CONTEXT_HPP
#define BOOST_PROCESS_CONTEXT_HPP
#include <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <unistd.h>
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#endif
#include <boost/process/stream_id.hpp>
#include <boost/process/stream_ends.hpp>
#include <boost/process/stream_type.hpp>
#include <boost/process/environment.hpp>
#include <boost/process/self.hpp>
#include <boost/process/stream_behavior.hpp>
#include <boost/function.hpp>
#include <string>
#include <map>
namespace boost {
namespace process {
/**
* Context class to define how a child process is created.
*
* The context class is used to configure streams, to set the work directory
* and define environment variables. It is also used to change a process
* name (the variable commonly known as argv[0]).
*/
struct context
{
typedef std::map<stream_id, boost::function<stream_ends (stream_type)> >
streams_t;
/**
* Streams.
*
* Streams of a child process can be configured through factory functions
* which return a pair of handles - one handle to use as a stream end
* in the child process and possibly another handle to use as a stream end
* in the parent process (if a pipe is setup both processes can communicate
* with each other).
*/
streams_t streams;
/**
* Process name.
*
* The child process can access the process name via a variable
* commonly known as argv[0].
*/
std::string process_name;
/**
* Work directory.
*/
std::string work_dir;
/**
* Environment variables.
*/
environment env;
/**
* Constructs a process context.
*
* The default behavior of standard streams is to inherit them. The current
* work directory is also the work directory of the child process. The child
* process also inherits all environment variables.
*/
context()
: work_dir(self::get_work_dir()),
env(self::get_environment())
{
#if 0 // this default behavior will throw in non-console apps
#if defined(BOOST_POSIX_API)
streams[stdin_id] = behavior::inherit(STDIN_FILENO);
streams[stdout_id] = behavior::inherit(STDOUT_FILENO);
streams[stderr_id] = behavior::inherit(STDERR_FILENO);
#elif defined(BOOST_WINDOWS_API)
streams[stdin_id] = behavior::inherit(GetStdHandle(STD_INPUT_HANDLE));
streams[stdout_id] = behavior::inherit(GetStdHandle(STD_OUTPUT_HANDLE));
streams[stderr_id] = behavior::inherit(GetStdHandle(STD_ERROR_HANDLE));
#endif
#endif
}
#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN)
/**
* Setups a child process.
*
* This is an extension point to support more configuration options for
* child processes. You can initialize \a setup with a user-defined function
* which is called when a child process is created.
*
* On POSIX platforms setup() is called in the child process. That's why in
* a multithreaded application only async-signal-safe functions must be
* called in the function \a setup is bound to.
*
* On Windows platforms setup() is called in the parent process. A
* reference to a STARTUPINFOA structure is passed as parameter.
*/
boost::function<void ()> setup;
#elif defined(BOOST_WINDOWS_API)
boost::function<void (STARTUPINFOA&)> setup;
#endif
};
}
}
#endif

View file

@ -0,0 +1,69 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/detail/basic_status.hpp
*
* Includes the declaration of the basic status class.
*/
#ifndef BOOST_PROCESS_DETAIL_BASIC_STATUS_HPP
#define BOOST_PROCESS_DETAIL_BASIC_STATUS_HPP
#include <boost/process/config.hpp>
#include <boost/process/pid_type.hpp>
#include <boost/asio.hpp>
namespace boost {
namespace process {
namespace detail {
/**
* The basic_status class to wait for processes to exit.
*
* The basic_status class is a Boost.Asio I/O object and supports synchronous
* and asynchronous wait operations. It must be instantiated with a Service.
*/
template <typename Service>
class basic_status
: public boost::asio::basic_io_object<Service>
{
public:
explicit basic_status(boost::asio::io_service &io_service)
: boost::asio::basic_io_object<Service>(io_service)
{
}
/**
* Waits synchronously for a process to exit.
*/
int wait(pid_type pid)
{
return this->service.wait(this->implementation, pid);
}
/**
* Waits asynchronously for a process to exit.
*/
template <typename Handler>
void async_wait(pid_type pid, Handler handler)
{
this->service.async_wait(this->implementation, pid, handler);
}
};
}
}
}
#endif

View file

@ -0,0 +1,318 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/detail/basic_status_service.hpp
*
* Includes the declaration of the basic status service class.
*/
#ifndef BOOST_PROCESS_DETAIL_BASIC_STATUS_SERVICE_HPP
#define BOOST_PROCESS_DETAIL_BASIC_STATUS_SERVICE_HPP
#include <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <boost/process/operations.hpp>
# include <string>
# include <sys/types.h>
# include <sys/wait.h>
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#else
# error "Unsupported platform."
#endif
#include <boost/process/pid_type.hpp>
#include <boost/process/detail/status_impl.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/system/error_code.hpp>
#include <boost/unordered_map.hpp>
#include <vector>
#include <algorithm>
namespace boost {
namespace process {
namespace detail {
/**
* The basic_status_service class provides the service to wait for processes
* synchronously and asynchronously.
*/
template <typename StatusImplementation = status_impl>
class basic_status_service
: public boost::asio::detail::service_base<StatusImplementation>
{
public:
explicit basic_status_service(boost::asio::io_service &io_service)
: boost::asio::detail::service_base<StatusImplementation>(io_service),
#if defined(BOOST_POSIX_API)
interrupt_pid_(-1),
pids_(0)
#elif defined(BOOST_WINDOWS_API)
run_(true)
#endif
{
#if defined(BOOST_WINDOWS_API)
handles_.push_back(CreateEvent(NULL, FALSE, FALSE, NULL));
if (handles_[0] == NULL)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateEvent() failed");
work_thread_ = boost::thread(
&basic_status_service<StatusImplementation>::work_thread, this);
#endif
}
~basic_status_service()
{
#if defined(BOOST_POSIX_API)
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
bool worker_thread_active = (pids_ != 0);
lock.unlock();
if (worker_thread_active)
{
stop_work_thread();
work_thread_.join();
}
#elif defined(BOOST_WINDOWS_API)
stop_work_thread();
work_thread_.join();
CloseHandle(handles_[0]);
#endif
}
typedef boost::shared_ptr<StatusImplementation> implementation_type;
void construct(implementation_type &impl)
{
impl = boost::make_shared<StatusImplementation>();
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
impls_.push_back(impl);
}
void destroy(implementation_type &impl)
{
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
typename std::vector<implementation_type>::iterator it =
std::find(impls_.begin(), impls_.end(), impl);
if (it != impls_.end())
impls_.erase(it);
#if defined(BOOST_WINDOWS_API)
interrupt_work_thread();
work_thread_cond_.wait(work_thread_mutex_);
impl->clear(handles_);
work_thread_cond_.notify_all();
#endif
impl.reset();
}
int wait(implementation_type &impl, pid_type pid)
{
boost::system::error_code ec;
int status = impl->wait(pid, ec);
#if defined(BOOST_POSIX_API)
if (ec.value() == ECHILD)
{
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
boost::unordered_map<pid_t, int>::iterator it = statuses_.find(pid);
if (it == statuses_.end())
{
work_thread_cond_.wait(work_thread_mutex_);
it = statuses_.find(pid);
}
if (it != statuses_.end())
{
status = it->second;
statuses_.erase(it);
ec.clear();
}
}
#endif
boost::asio::detail::throw_error(ec);
return status;
}
template <typename Handler>
void async_wait(implementation_type &impl, pid_type pid, Handler handler)
{
#if defined(BOOST_POSIX_API)
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
if (++pids_ == 1)
{
work_.reset(new boost::asio::io_service::work(
this->get_io_service()));
work_thread_ = boost::thread(
&basic_status_service<StatusImplementation>::work_thread,
this);
}
impl->async_wait(pid, this->get_io_service().wrap(handler));
#elif defined(BOOST_WINDOWS_API)
HANDLE handle = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
FALSE, pid);
if (handle == NULL)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
if (!work_)
work_.reset(new boost::asio::io_service::work(
this->get_io_service()));
interrupt_work_thread();
work_thread_cond_.wait(work_thread_mutex_);
handles_.push_back(handle);
impl->async_wait(handle, this->get_io_service().wrap(handler));
work_thread_cond_.notify_all();
#endif
}
private:
void shutdown_service()
{
#if defined(BOOST_WINDOWS_API)
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
work_.reset();
#endif
}
void work_thread()
{
#if defined(BOOST_POSIX_API)
for (;;)
{
int status;
pid_t pid = ::wait(&status);
if (pid == -1)
{
if (errno != EINTR)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("wait(2) failed");
}
else if (interrupted(pid))
{
// On POSIX the only reason to interrupt is to break out.
break;
}
else
{
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
bool regchild = false;
for (typename std::vector<implementation_type>::iterator it =
impls_.begin(); it != impls_.end(); ++it)
regchild |= (*it)->complete(pid, status);
if (regchild && --pids_ == 0)
{
work_.reset();
break;
}
else if (!regchild)
{
statuses_.insert(boost::unordered_map<pid_t, int>::
value_type(pid, status));
work_thread_cond_.notify_all();
}
}
}
#elif defined(BOOST_WINDOWS_API)
for (;;)
{
DWORD res = WaitForMultipleObjects(handles_.size(), &handles_[0],
FALSE, INFINITE);
if (res == WAIT_FAILED)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
"WaitForMultipleObjects() failed");
else if (res - WAIT_OBJECT_0 == 0)
{
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
if (!run_)
break;
work_thread_cond_.notify_all();
work_thread_cond_.wait(work_thread_mutex_);
}
else if (res - WAIT_OBJECT_0 > 0)
{
HANDLE handle = handles_[res - WAIT_OBJECT_0];
DWORD exit_code;
if (!GetExitCodeProcess(handle, &exit_code))
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
"GetExitCodeProcess() failed");
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
for (typename std::vector<implementation_type>::iterator it =
impls_.begin(); it != impls_.end(); ++it)
(*it)->complete(handle, exit_code);
std::vector<HANDLE>::iterator it = handles_.begin();
std::advance(it, res - WAIT_OBJECT_0);
handles_.erase(it);
if (handles_.size() == 1)
work_.reset();
}
}
#endif
}
void interrupt_work_thread()
{
#if defined(BOOST_POSIX_API)
// By creating a child process which immediately exits
// we interrupt wait().
std::vector<std::string> args;
args.push_back("-c");
args.push_back("'exit'");
interrupt_pid_ = create_child("/bin/sh", args).get_id();
#elif defined(BOOST_WINDOWS_API)
// By signaling the event in the first slot WaitForMultipleObjects()
// will return. The work thread won't do anything except checking if
// it should continue to run.
if (!SetEvent(handles_[0]))
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("SetEvent() failed");
#endif
}
#if defined(BOOST_POSIX_API)
bool interrupted(pid_t pid)
{
boost::mutex::scoped_lock lock(work_thread_mutex_);
return interrupt_pid_ == pid;
}
#endif
void stop_work_thread()
{
boost::mutex::scoped_lock lock(work_thread_mutex_);
#if defined(BOOST_WINDOWS_API)
// Access to run_ must be sychronized with running().
run_ = false;
#endif
// Access to interrupt_pid_ must be sychronized with interrupted().
interrupt_work_thread();
}
boost::scoped_ptr<boost::asio::io_service::work> work_;
std::vector<implementation_type> impls_;
boost::mutex work_thread_mutex_;
boost::thread work_thread_;
boost::condition_variable_any work_thread_cond_;
#if defined(BOOST_POSIX_API)
pid_t interrupt_pid_;
int pids_;
boost::unordered_map<pid_t, int> statuses_;
#elif defined(BOOST_WINDOWS_API)
bool run_;
std::vector<HANDLE> handles_;
#endif
};
}
}
}
#endif

View file

@ -0,0 +1,106 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/detail/posix_helpers.hpp
*
* Includes the declaration of helper functions for POSIX systems.
*/
#ifndef BOOST_PROCESS_POSIX_HELPERS_HPP
#define BOOST_PROCESS_POSIX_HELPERS_HPP
#include <boost/process/config.hpp>
#include <boost/process/environment.hpp>
#include <string>
#include <utility>
#include <cstring>
#include <cstddef>
namespace boost {
namespace process {
namespace detail {
/**
* Converts an environment to a char** table as used by execve().
*
* Converts the environment's contents to the format used by the
* execve() system call. The returned char** array is allocated
* in dynamic memory; the caller must free it when not used any
* more. Each entry is also allocated in dynamic memory and is a
* NULL-terminated string of the form var=value; these must also be
* released by the caller.
*
* This operation is only available on POSIX systems.
*
* \return The first argument of the pair is an integer that indicates
* how many strings are stored in the second argument. The
* second argument is a NULL-terminated, dynamically allocated
* array of dynamically allocated strings representing the
* enviroment's content. Each array entry is a NULL-terminated
* string of the form var=value. The caller is responsible for
* freeing them.
*/
inline std::pair<std::size_t, char**> environment_to_envp(const environment
&env)
{
std::size_t nargs = env.size();
char **envp = new char*[nargs + 1];
environment::size_type i = 0;
for (environment::const_iterator it = env.begin(); it != env.end(); ++it)
{
std::string s = it->first + "=" + it->second;
envp[i] = new char[s.size() + 1];
std::strncpy(envp[i], s.c_str(), s.size() + 1);
++i;
}
envp[i] = 0;
return std::pair<std::size_t, char**>(nargs, envp);
}
/**
* Converts the command line to an array of C strings.
*
* Converts the command line's list of arguments to the format expected
* by the \a argv parameter in the POSIX execve() system call.
*
* This operation is only available on POSIX systems.
*
* \return The first argument of the pair is an integer that indicates
* how many strings are stored in the second argument. The
* second argument is a NULL-terminated, dynamically allocated
* array of dynamically allocated strings holding the arguments
* to the executable. The caller is responsible for freeing them.
*/
template <class Arguments>
inline std::pair<std::size_t, char**> collection_to_argv(const Arguments &args)
{
std::size_t nargs = args.size();
char **argv = new char*[nargs + 1];
typename Arguments::size_type i = 0;
for (typename Arguments::const_iterator it = args.begin(); it != args.end();
++it)
{
argv[i] = new char[it->size() + 1];
std::strncpy(argv[i], it->c_str(), it->size() + 1);
++i;
}
argv[nargs] = 0;
return std::pair<std::size_t, char**>(nargs, argv);
}
}
}
}
#endif

View file

@ -0,0 +1,190 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/detail/status_impl.hpp
*
* Includes the declaration of the status implementation class.
*/
#ifndef BOOST_PROCESS_DETAIL_STATUS_IMPL_HPP
#define BOOST_PROCESS_DETAIL_STATUS_IMPL_HPP
#include <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <sys/types.h>
# include <signal.h>
# include <sys/wait.h>
# include <errno.h>
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#else
# error "Unsupported platform."
#endif
#include <boost/process/pid_type.hpp>
#include <boost/system/error_code.hpp>
#include <boost/ptr_container/ptr_unordered_map.hpp>
#include <algorithm>
namespace boost {
namespace process {
namespace detail {
#if defined(BOOST_POSIX_API)
typedef pid_t phandle;
#elif defined(BOOST_WINDOWS_API)
typedef HANDLE phandle;
#endif
struct operation
{
virtual ~operation(){}
virtual void operator()(int exit_code)
{
#if defined(BOOST_MSVC)
exit_code;
#endif
}
};
template <typename Handler>
class wrapped_handler : public operation
{
public:
wrapped_handler(Handler handler)
: handler_(handler)
{
}
void operator()(int exit_code)
{
handler_(boost::system::error_code(), exit_code);
}
private:
Handler handler_;
};
/**
* The status_impl class saves internal data of every status I/O object.
*/
class status_impl
{
public:
#if defined(BOOST_WINDOWS_API)
template <typename Container>
void clear(Container &handles)
{
for (operations_type::iterator it = ops_.begin(); it != ops_.end();
++it)
{
for (typename Container::iterator it2 = handles.begin(); it2 !=
handles.end(); ++it2)
{
if (*it2 == it->first)
{
handles.erase(it2);
break;
}
}
CloseHandle(it->first);
}
}
#endif
int wait(pid_type pid, boost::system::error_code &ec)
{
#if defined(BOOST_POSIX_API)
pid_t p;
int status;
do
{
p = waitpid(pid, &status, 0);
} while (p == -1 && errno == EINTR);
if (p == -1)
{
ec = boost::system::error_code(errno,
boost::system::get_system_category());
return -1;
}
return status;
#elif defined(BOOST_WINDOWS_API)
HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE,
pid);
if (h == NULL)
{
ec = boost::system::error_code(GetLastError(),
boost::system::get_system_category());
return -1;
}
if (WaitForSingleObject(h, INFINITE) == WAIT_FAILED)
{
CloseHandle(h);
ec = boost::system::error_code(GetLastError(),
boost::system::get_system_category());
return -1;
}
DWORD exit_code;
if (!GetExitCodeProcess(h, &exit_code))
{
CloseHandle(h);
ec = boost::system::error_code(GetLastError(),
boost::system::get_system_category());
return -1;
}
if (!CloseHandle(h))
{
ec = boost::system::error_code(GetLastError(),
boost::system::get_system_category());
return -1;
}
return exit_code;
#endif
}
template <typename Handler>
void async_wait(phandle ph, Handler handler)
{
ops_.insert(ph, new wrapped_handler<Handler>(handler));
}
bool complete(phandle ph, int exit_code)
{
boost::iterator_range<operations_type::iterator> r =
ops_.equal_range(ph);
if (r.empty())
return false;
for (operations_type::iterator it = r.begin(); it != r.end(); ++it)
(*it->second)(exit_code);
ops_.erase(r.begin(), r.end());
#if defined(BOOST_WINDOWS_API)
if (!CloseHandle(ph))
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
#endif
return true;
}
private:
typedef boost::ptr_unordered_multimap<phandle, operation> operations_type;
operations_type ops_;
};
}
}
}
#endif

View file

@ -0,0 +1,228 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/detail/systembuf.hpp
*
* Includes the declaration of the systembuf class.
*/
#ifndef BOOST_PROCESS_DETAIL_SYSTEMBUF_HPP
#define BOOST_PROCESS_DETAIL_SYSTEMBUF_HPP
#include <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <sys/types.h>
# include <unistd.h>
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#else
# error "Unsupported platform."
#endif
#include <boost/noncopyable.hpp>
#include <boost/scoped_array.hpp>
#include <boost/assert.hpp>
#include <streambuf>
#include <cstddef>
namespace boost {
namespace process {
class postream;
namespace detail {
/**
* std::streambuf implementation for handles.
*
* systembuf provides a std::streambuf implementation for handles.
* Contrarywise to the handle class, this class does \b not take
* ownership of the native handle; this should be taken care of
* somewhere else.
*
* This class follows the expected semantics of a std::streambuf object.
* However, it is not copyable to avoid introducing inconsistences with
* the on-disk file and the in-memory buffers.
*/
class systembuf : public std::streambuf, public boost::noncopyable
{
friend class boost::process::postream;
public:
#if defined(BOOST_PROCESS_DOXYGEN)
/**
* Opaque name for the native handle type.
*/
typedef NativeHandleType handle_type;
#elif defined(BOOST_POSIX_API)
typedef int handle_type;
#elif defined(BOOST_WINDOWS_API)
typedef HANDLE handle_type;
#endif
/**
* Constructs a new systembuf for the given handle.
*
* This constructor creates a new systembuf object that reads or
* writes data from/to the \a h native handle. This handle
* is \b not owned by the created systembuf object; the code
* should take care of it externally.
*
* This class buffers input and output; the buffer size may be
* tuned through the \a bufsize parameter, which defaults to 8192
* bytes.
*
* \see pistream and postream
*/
explicit systembuf(handle_type h, std::size_t bufsize = 8192)
: handle_(h),
bufsize_(bufsize),
read_buf_(new char[bufsize]),
write_buf_(new char[bufsize])
{
#if defined(BOOST_POSIX_API)
BOOST_ASSERT(handle_ >= 0);
#elif defined(BOOST_WINDOWS_API)
BOOST_ASSERT(handle_ != INVALID_HANDLE_VALUE);
#endif
BOOST_ASSERT(bufsize_ > 0);
setp(write_buf_.get(), write_buf_.get() + bufsize_);
}
protected:
/**
* Reads new data from the native handle.
*
* This operation is called by input methods when there is no more
* data in the input buffer. The function fills the buffer with new
* data, if available.
*
* \pre All input positions are exhausted (gptr() >= egptr()).
* \post The input buffer has new data, if available.
* \returns traits_type::eof() if a read error occurrs or there are
* no more data to be read. Otherwise returns
* traits_type::to_int_type(*gptr()).
*/
virtual int_type underflow()
{
BOOST_ASSERT(gptr() >= egptr());
bool ok;
#if defined(BOOST_POSIX_API)
ssize_t cnt = read(handle_, read_buf_.get(), bufsize_);
ok = (cnt != -1 && cnt != 0);
#elif defined(BOOST_WINDOWS_API)
DWORD cnt;
BOOL res = ReadFile(handle_, read_buf_.get(), bufsize_, &cnt, NULL);
ok = (res && cnt > 0);
#endif
if (!ok)
return traits_type::eof();
else
{
setg(read_buf_.get(), read_buf_.get(), read_buf_.get() + cnt);
return traits_type::to_int_type(*gptr());
}
}
/**
* Makes room in the write buffer for additional data.
*
* This operation is called by output methods when there is no more
* space in the output buffer to hold a new element. The function
* first flushes the buffer's contents to disk and then clears it to
* leave room for more characters. The given \a c character is
* stored at the beginning of the new space.
*
* \pre All output positions are exhausted (pptr() >= epptr()).
* \post The output buffer has more space if no errors occurred
* during the write to disk.
* \post *(pptr() - 1) is \a c.
* \returns traits_type::eof() if a write error occurrs. Otherwise
* returns traits_type::not_eof(c).
*/
virtual int_type overflow(int c)
{
BOOST_ASSERT(pptr() >= epptr());
if (sync() == -1)
return traits_type::eof();
if (!traits_type::eq_int_type(c, traits_type::eof()))
{
traits_type::assign(*pptr(), static_cast<traits_type::char_type>(
c));
pbump(1);
}
return traits_type::not_eof(c);
}
/**
* Flushes the output buffer to disk.
*
* Synchronizes the systembuf buffers with the contents of the file
* associated to this object through the native handle. The output buffer
* is flushed to disk and cleared to leave new room for more data.
*
* \returns 0 on success, -1 if an error occurred.
*/
virtual int sync()
{
#if defined(BOOST_POSIX_API)
ssize_t cnt = pptr() - pbase();
bool ok = (write(handle_, pbase(), cnt) == cnt);
if (ok)
pbump(-cnt);
return ok ? 0 : -1;
#elif defined(BOOST_WINDOWS_API)
long cnt = pptr() - pbase();
DWORD rcnt;
BOOL res = WriteFile(handle_, pbase(), cnt, &rcnt, NULL);
bool ok = (res && static_cast<long>(rcnt) == cnt);
if (ok)
pbump(-cnt);
return ok ? 0 : -1;
#endif
}
private:
/**
* Native handle used by the systembuf object.
*/
handle_type handle_;
/**
* Internal buffer size used during read and write operations.
*/
std::size_t bufsize_;
/**
* Internal buffer used during read operations.
*/
boost::scoped_array<char> read_buf_;
/**
* Internal buffer used during write operations.
*/
boost::scoped_array<char> write_buf_;
};
}
}
}
#endif

View file

@ -0,0 +1,138 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/detail/windows_helpers.hpp
*
* Includes the declaration of helper functions for Windows systems.
*/
#ifndef BOOST_PROCESS_WINDOWS_HELPERS_HPP
#define BOOST_PROCESS_WINDOWS_HELPERS_HPP
#include <boost/process/config.hpp>
#include <boost/process/environment.hpp>
#include <boost/shared_array.hpp>
#include <string>
#include <vector>
#include <cstddef>
#include <string.h>
#include <windows.h>
namespace boost {
namespace process {
namespace detail {
/**
* Converts an environment to a string used by CreateProcess().
*
* Converts the environment's contents to the format used by the
* CreateProcess() system call. The returned char* string is
* allocated in dynamic memory; the caller must free it when not
* used any more. This is enforced by the use of a shared pointer.
*
* This operation is only available on Windows systems.
*
* \return A dynamically allocated char* string that represents
* the environment's content. This string is of the form
* var1=value1\\0var2=value2\\0\\0.
*/
inline boost::shared_array<char> environment_to_windows_strings(environment
&env)
{
boost::shared_array<char> envp;
if (env.empty())
{
envp.reset(new char[2]);
ZeroMemory(envp.get(), 2);
}
else
{
std::string s;
for (environment::const_iterator it = env.begin(); it != env.end();
++it)
{
s += it->first + "=" + it->second;
s.push_back(0);
}
envp.reset(new char[s.size() + 1]);
#if (BOOST_MSVC >= 1400)
memcpy_s(envp.get(), s.size() + 1, s.c_str(), s.size() + 1);
#else
memcpy(envp.get(), s.c_str(), s.size() + 1);
#endif
}
return envp;
}
/**
* Converts the command line to a plain string.
*
* Converts the command line's list of arguments to the format expected by the
* \a lpCommandLine parameter in the CreateProcess() system call.
*
* This operation is only available on Windows systems.
*
* \return A dynamically allocated string holding the command line
* to be passed to the executable. It is returned in a
* shared_array object to ensure its release at some point.
*/
template <class Arguments>
inline boost::shared_array<char> collection_to_windows_cmdline(const Arguments
&args)
{
typedef std::vector<std::string> arguments_t;
arguments_t args2;
typename Arguments::size_type i = 0;
std::size_t size = 0;
for (typename Arguments::const_iterator it = args.begin(); it != args.end();
++it)
{
std::string arg = *it;
std::string::size_type pos = 0;
while ( (pos = arg.find('"', pos)) != std::string::npos)
{
arg.replace(pos, 1, "\\\"");
pos += 2;
}
if (arg.find(' ') != std::string::npos)
arg = '\"' + arg + '\"';
if (i++ != args.size() - 1)
arg += ' ';
args2.push_back(arg);
size += arg.size() + 1;
}
boost::shared_array<char> cmdline(new char[size]);
cmdline.get()[0] = '\0';
for (arguments_t::size_type i = 0; i < args.size(); ++i)
#if (BOOST_MSVC >= 1400)
strcat_s(cmdline.get(), size, args2[i].c_str());
#else
strncat(cmdline.get(), args2[i].c_str(), args2[i].size());
#endif
return cmdline;
}
}
}
}
#endif

View file

@ -0,0 +1,52 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/environment.hpp
*
* Includes the declaration of the environment class.
*/
#ifndef BOOST_PROCESS_ENVIRONMENT_HPP
#define BOOST_PROCESS_ENVIRONMENT_HPP
#include <map>
#include <string>
namespace boost {
namespace process {
/**
* Representation of a process' environment variables.
*
* The environment is a map that establishes an unidirectional
* association between variable names and their values and is
* represented by a string to string map.
*
* Variables may be defined to the empty string. Be aware that doing so
* is not portable: POSIX systems will treat such variables as being
* defined to the empty value, but Windows systems are not able to
* distinguish them from undefined variables.
*
* Neither POSIX nor Windows systems support a variable with no name.
*
* It is worthy to note that the environment is sorted alphabetically.
* This is provided for-free by the map container used to implement this
* type, and this behavior is required by Windows systems.
*/
typedef std::map<std::string, std::string> environment;
}
}
#endif

View file

@ -0,0 +1,231 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/handle.hpp
*
* Includes the declaration of the handle class.
*/
#ifndef BOOST_PROCESS_HANDLE_HPP
#define BOOST_PROCESS_HANDLE_HPP
#include <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <unistd.h>
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#else
# error "Unsupported platform."
#endif
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
namespace boost {
namespace process {
/**
* RAII model for handles.
*
* The \a handle class is a RAII model for native handles. This class wraps
* one of such handles grabbing its ownership, and automaticaly closes it
* upon destruction. It is used to avoid leaking open handles, shall an
* unexpected execution trace occur.
*/
class handle
{
public:
#if defined(BOOST_PROCESS_DOXYGEN)
/**
* Opaque name for the native handle type.
*
* On POSIX systems \a NativeSystemHandle is an integer type while it is
* a \a HANDLE on Windows systems.
*/
typedef NativeSystemHandle native_type;
#elif defined(BOOST_POSIX_API)
typedef int native_type;
#elif defined(BOOST_WINDOWS_API)
typedef HANDLE native_type;
#endif
/**
* Constructs an invalid handle.
*
* \see valid()
*/
handle()
{
}
/**
* RAII settings to specify if handle should be automatically closed.
*/
enum close_type { do_close, dont_close };
/**
* Constructs a handle from a native handle.
*
* This constructor creates a new \a handle object that takes
* ownership of the given \a native handle. If \a close is set to
* handle::dont_close the \a native handle is not closed upon destruction.
* The user must not close \a native if it is owned by a \a handle object.
* Ownership can be reclaimed using release().
*
* \see release()
*/
handle(native_type native, close_type close = handle::do_close)
: impl_(boost::make_shared<impl>(native, close))
{
}
/**
* Checks whether the handle is valid or not.
*
* \return true if the handle is valid; false otherwise.
*/
bool valid() const
{
return impl_ && impl_->valid();
}
/**
* Closes the handle.
*
* \post The handle is invalid.
* \post The native handle is closed.
*/
void close()
{
if (impl_)
impl_->close();
}
/**
* Gets the native handle.
*
* The caller can issue any operation on it except closing it.
* If closing is required, release() shall be used.
*
* \return The native handle.
*/
native_type native() const
{
return impl_ ? impl_->native() : invalid_handle();
}
/**
* Reclaims ownership of the native handle.
*
* The caller is responsible of closing the native handle.
*
* \post The handle is invalid.
* \return The native handle.
*/
native_type release()
{
return impl_ ? impl_->release() : invalid_handle();
}
private:
class impl
{
public:
typedef handle::native_type native_type;
impl(native_type native, close_type close)
: native_(native),
close_(close)
{
}
~impl()
{
if (valid() && close_ == handle::do_close)
{
#if defined(BOOST_POSIX_API)
::close(native_);
#elif defined(BOOST_WINDOWS_API)
CloseHandle(native_);
#endif
}
}
bool valid() const
{
return native_ != handle::invalid_handle();
}
void close()
{
if (valid())
{
#if defined(BOOST_POSIX_API)
::close(native_);
#elif defined(BOOST_WINDOWS_API)
CloseHandle(native_);
#endif
native_ = handle::invalid_handle();
}
}
native_type native() const
{
return native_;
}
native_type release()
{
native_type native = native_;
native_ = handle::invalid_handle();
return native;
}
private:
native_type native_;
close_type close_;
};
/**
* Implementation of handle to store native handle value.
*
* A shared pointer is used as handles represent system resources. If a
* handle is closed and becomes invalid the state of copies of the handle
* object will be updated as they all share the handle implementation.
*/
boost::shared_ptr<impl> impl_;
/**
* Constant function representing an invalid handle value.
*
* Returns the platform-specific handle value that represents an
* invalid handle. This is a constant function rather than a regular
* constant because, in the latter case, we cannot define it under
* Windows due to the value being of a complex type.
*/
static const native_type invalid_handle()
{
#if defined(BOOST_POSIX_API)
return -1;
#elif defined(BOOST_WINDOWS_API)
return INVALID_HANDLE_VALUE;
#endif
}
};
}
}
#endif

View file

@ -0,0 +1,433 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/operations.hpp
*
* Provides miscellaneous free functions.
*/
#ifndef BOOST_PROCESS_OPERATIONS_HPP
#define BOOST_PROCESS_OPERATIONS_HPP
#include <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <boost/process/detail/posix_helpers.hpp>
# include <utility>
# include <cstddef>
# include <stdlib.h>
# include <unistd.h>
# include <fcntl.h>
# if defined(__CYGWIN__)
# include <boost/scoped_array.hpp>
# include <sys/cygwin.h>
# endif
#elif defined(BOOST_WINDOWS_API)
# include <boost/process/detail/windows_helpers.hpp>
# include <boost/scoped_array.hpp>
# include <boost/shared_array.hpp>
# include <windows.h>
#else
# error "Unsupported platform."
#endif
#include <boost/process/child.hpp>
#include <boost/process/context.hpp>
#include <boost/process/stream_id.hpp>
#include <boost/process/stream_ends.hpp>
#include <boost/process/handle.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/system/system_error.hpp>
#include <boost/throw_exception.hpp>
#include <boost/assert.hpp>
#include <string>
#include <vector>
#include <map>
#include <utility>
namespace boost {
namespace process {
/**
* Locates the executable program \a file in all the directory components
* specified in \a path. If \a path is empty, the value of the PATH
* environment variable is used.
*
* The path variable is interpreted following the same conventions used
* to parse the PATH environment variable in the underlying platform.
*
* \throw boost::filesystem::filesystem_error If the file cannot be found
* in the path.
*/
inline std::string find_executable_in_path(const std::string &file,
std::string path = "")
{
#if defined(BOOST_POSIX_API)
BOOST_ASSERT(file.find('/') == std::string::npos);
#elif defined(BOOST_WINDOWS_API)
BOOST_ASSERT(file.find_first_of("\\/") == std::string::npos);
#endif
std::string result;
#if defined(BOOST_POSIX_API)
if (path.empty())
{
const char *envpath = getenv("PATH");
if (!envpath)
boost::throw_exception(boost::filesystem::filesystem_error(
BOOST_PROCESS_SOURCE_LOCATION "file not found", file,
boost::system::errc::make_error_code(
boost::system::errc::no_such_file_or_directory)));
path = envpath;
}
BOOST_ASSERT(!path.empty());
#if defined(__CYGWIN__)
if (!cygwin_posix_path_list_p(path.c_str()))
{
int size = cygwin_win32_to_posix_path_list_buf_size(path.c_str());
boost::scoped_array<char> cygpath(new char[size]);
cygwin_win32_to_posix_path_list(path.c_str(), cygpath.get());
path = cygpath.get();
}
#endif
std::string::size_type pos1 = 0, pos2;
do
{
pos2 = path.find(':', pos1);
std::string dir = (pos2 != std::string::npos) ?
path.substr(pos1, pos2 - pos1) : path.substr(pos1);
std::string f = dir +
(boost::algorithm::ends_with(dir, "/") ? "" : "/") + file;
if (!access(f.c_str(), X_OK))
result = f;
pos1 = pos2 + 1;
} while (pos2 != std::string::npos && result.empty());
#elif defined(BOOST_WINDOWS_API)
const char *exts[] = { "", ".exe", ".com", ".bat", NULL };
const char **ext = exts;
while (*ext)
{
char buf[MAX_PATH];
char *dummy;
DWORD size = SearchPathA(path.empty() ? NULL : path.c_str(),
file.c_str(), *ext, MAX_PATH, buf, &dummy);
BOOST_ASSERT(size < MAX_PATH);
if (size > 0)
{
result = buf;
break;
}
++ext;
}
#endif
if (result.empty())
boost::throw_exception(boost::filesystem::filesystem_error(
BOOST_PROCESS_SOURCE_LOCATION "file not found", file,
boost::system::errc::make_error_code(
boost::system::errc::no_such_file_or_directory)));
return result;
}
/**
* Extracts the program name from a given executable.
*
* \return The program name. On Windows the program name
* is returned without a file extension.
*/
inline std::string executable_to_progname(const std::string &exe)
{
std::string::size_type begin = 0;
std::string::size_type end = std::string::npos;
#if defined(BOOST_POSIX_API)
std::string::size_type slash = exe.rfind('/');
#elif defined(BOOST_WINDOWS_API)
std::string::size_type slash = exe.find_last_of("/\\");
#endif
if (slash != std::string::npos)
begin = slash + 1;
#if defined(BOOST_WINDOWS_API)
if (exe.size() > 4 && (boost::algorithm::iends_with(exe, ".exe") ||
boost::algorithm::iends_with(exe, ".com") ||
boost::algorithm::iends_with(exe, ".bat")))
end = exe.size() - 4;
#endif
return exe.substr(begin, end - begin);
}
/**
* Starts a new child process.
*
* Launches a new process based on the binary image specified by the
* executable, the set of arguments passed to it and the execution context.
*
* \remark Blocking remarks: This function may block if the device holding the
* executable blocks when loading the image. This might happen if, e.g.,
* the binary is being loaded from a network share.
*
* \return A handle to the new child process.
*/
template <typename Arguments, typename Context>
inline child create_child(const std::string &executable, Arguments args,
Context ctx)
{
typedef std::map<stream_id, stream_ends> handles_t;
handles_t handles;
typename Context::streams_t::iterator it = ctx.streams.begin();
for (; it != ctx.streams.end(); ++it)
{
if (it->first == stdin_id)
handles[it->first] = it->second(input_stream);
else if (it->first == stdout_id)
handles[it->first] = it->second(output_stream);
else if (it->first == stderr_id)
handles[it->first] = it->second(output_stream);
#if defined(BOOST_POSIX_API)
else
handles[it->first] = it->second(unknown_stream);
#endif
}
std::string p_name = ctx.process_name.empty() ?
executable_to_progname(executable) : ctx.process_name;
args.insert(args.begin(), p_name);
#if defined(BOOST_POSIX_API)
// Between fork() and execve() only async-signal-safe functions
// must be called if multithreaded applications should be supported.
// That's why the following code is executed before fork() is called.
#if defined(F_MAXFD)
int maxdescs = fcntl(-1, F_MAXFD, 0);
if (maxdescs == -1)
maxdescs = sysconf(_SC_OPEN_MAX);
#else
int maxdescs = sysconf(_SC_OPEN_MAX);
#endif
if (maxdescs == -1)
maxdescs = 1024;
std::vector<bool> closeflags(maxdescs, true);
std::pair<std::size_t, char**> argv = detail::collection_to_argv(args);
std::pair<std::size_t, char**> envp =
detail::environment_to_envp(ctx.env);
const char *work_dir = ctx.work_dir.c_str();
pid_t pid = fork();
if (pid == -1)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fork(2) failed");
else if (pid == 0)
{
if (chdir(work_dir) == -1)
{
write(STDERR_FILENO, "chdir() failed\n", 15);
_exit(127);
}
for (handles_t::iterator it = handles.begin(); it != handles.end();
++it)
{
if (it->second.child.valid())
{
handles_t::iterator it2 = it;
++it2;
for (; it2 != handles.end(); ++it2)
{
if (it2->second.child.native() == it->first)
{
int fd = fcntl(it2->second.child.native(), F_DUPFD,
it->first + 1);
if (fd == -1)
{
write(STDERR_FILENO, "fcntl() failed\n", 15);
_exit(127);
}
it2->second.child = fd;
}
}
if (dup2(it->second.child.native(), it->first) == -1)
{
write(STDERR_FILENO, "dup2() failed\n", 14);
_exit(127);
}
closeflags[it->first] = false;
}
}
if (ctx.setup)
ctx.setup();
for (std::size_t i = 0; i < closeflags.size(); ++i)
{
if (closeflags[i])
close(i);
}
execve(executable.c_str(), argv.second, envp.second);
// Actually we should delete argv and envp data. As we must not
// call any non-async-signal-safe functions though we simply exit.
write(STDERR_FILENO, "execve() failed\n", 16);
_exit(127);
}
else
{
BOOST_ASSERT(pid > 0);
for (std::size_t i = 0; i < argv.first; ++i)
delete[] argv.second[i];
delete[] argv.second;
for (std::size_t i = 0; i < envp.first; ++i)
delete[] envp.second[i];
delete[] envp.second;
std::map<stream_id, handle> parent_ends;
for (handles_t::iterator it = handles.begin(); it != handles.end();
++it)
parent_ends[it->first] = it->second.parent;
return child(pid, parent_ends);
}
#elif defined(BOOST_WINDOWS_API)
STARTUPINFOA startup_info;
ZeroMemory(&startup_info, sizeof(startup_info));
startup_info.cb = sizeof(startup_info);
startup_info.dwFlags |= STARTF_USESTDHANDLES;
startup_info.hStdInput = handles[stdin_id].child.native();
startup_info.hStdOutput = handles[stdout_id].child.native();
startup_info.hStdError = handles[stderr_id].child.native();
if (ctx.setup)
ctx.setup(startup_info);
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
boost::shared_array<char> cmdline =
detail::collection_to_windows_cmdline(args);
boost::scoped_array<char> exe(new char[executable.size() + 1]);
#if (BOOST_MSVC >= 1400)
strcpy_s(exe.get(), executable.size() + 1, executable.c_str());
#else
strcpy(exe.get(), executable.c_str());
#endif
boost::scoped_array<char> workdir(new char[ctx.work_dir.size() + 1]);
#if (BOOST_MSVC >= 1400)
strcpy_s(workdir.get(), ctx.work_dir.size() + 1, ctx.work_dir.c_str());
#else
strcpy(workdir.get(), ctx.work_dir.c_str());
#endif
boost::shared_array<char> envstrs =
detail::environment_to_windows_strings(ctx.env);
if (CreateProcessA(exe.get(), cmdline.get(), NULL, NULL, TRUE, 0,
envstrs.get(), workdir.get(), &startup_info, &pi) == 0)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateProcess() failed");
handle hprocess(pi.hProcess);
if (!CloseHandle(pi.hThread))
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
std::map<stream_id, handle> parent_ends;
parent_ends[stdin_id] = handles[stdin_id].parent;
parent_ends[stdout_id] = handles[stdout_id].parent;
parent_ends[stderr_id] = handles[stderr_id].parent;
return child(hprocess, parent_ends);
#endif
}
/**
* \overload
*/
inline child create_child(const std::string &executable)
{
return create_child(executable, std::vector<std::string>(), context());
}
/**
* \overload
*/
template <typename Arguments>
inline child create_child(const std::string &executable, Arguments args)
{
return create_child(executable, args, context());
}
/**
* Starts a shell-based command.
*
* Executes the given command through the default system shell. The
* command is subject to pattern expansion, redirection and pipelining.
* The shell is launched as described by the parameters in the context.
*
* This function behaves similarly to the system(3) system call. In a
* POSIX system, the command is fed to /bin/sh whereas under a Windows
* system, it is fed to cmd.exe. It is difficult to write portable
* commands, but this function comes in handy in multiple situations.
*
* \remark Blocking remarks: This function may block if the device holding the
* executable blocks when loading the image. This might happen if, e.g.,
* the binary is being loaded from a network share.
*
* \return A handle to the new child process.
*/
template <typename Context>
inline child shell(const std::string &command, Context ctx)
{
#if defined(BOOST_POSIX_API)
std::string executable = "/bin/sh";
std::vector<std::string> args;
args.push_back("-c");
args.push_back(command);
#elif defined(BOOST_WINDOWS_API)
char sysdir[MAX_PATH];
UINT size = GetSystemDirectoryA(sysdir, sizeof(sysdir));
if (!size)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("GetSystemDirectory() failed");
std::string executable = std::string(sysdir) +
(sysdir[size - 1] != '\\' ? "\\cmd.exe" : "cmd.exe");
std::vector<std::string> args;
args.push_back("/c");
args.push_back(command);
#endif
return create_child(executable, args, ctx);
}
/**
* \overload
*/
inline child shell(const std::string &command)
{
return shell(command, context());
}
}
}
#endif

View file

@ -0,0 +1,56 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/pid_type.hpp
*
* Includes the declaration of the pid type.
*/
#ifndef BOOST_PROCESS_PID_TYPE_HPP
#define BOOST_PROCESS_PID_TYPE_HPP
#include <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <sys/types.h>
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#endif
namespace boost {
namespace process {
#if defined(BOOST_PROCESS_DOXYGEN)
/**
* Opaque name for the process identifier type.
*
* Each operating system identifies processes using a specific type.
* The \a pid_type type is used to transparently refer to a process
* regardless of the operating system.
*
* This type is guaranteed to be an integral type on all supported
* platforms. On POSIX systems it is defined as pid_t, on Windows systems as
* DWORD.
*/
typedef NativeProcessId pid_type;
#elif defined(BOOST_POSIX_API)
typedef pid_t pid_type;
#elif defined(BOOST_WINDOWS_API)
typedef DWORD pid_type;
#endif
}
}
#endif

View file

@ -0,0 +1,49 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/pipe.hpp
*
* Includes the declaration of the pipe class.
*/
#ifndef BOOST_PROCESS_PIPE_HPP
#define BOOST_PROCESS_PIPE_HPP
#include <boost/process/config.hpp>
#include <boost/asio.hpp>
namespace boost {
namespace process {
#if defined(BOOST_PROCESS_DOXYGEN)
/**
* The pipe class is a type definition for stream-based classes defined by
* Boost.Asio.
*
* The type definition is provided for convenience. You can also use Boost.Asio
* classes directly for asynchronous I/O operations.
*/
typedef BoostAsioPipe pipe;
#elif defined(BOOST_POSIX_API)
typedef boost::asio::posix::stream_descriptor pipe;
#elif defined(BOOST_WINDOWS_API)
typedef boost::asio::windows::stream_handle pipe;
#else
# error "Unsupported platform."
#endif
}
}
#endif

View file

@ -0,0 +1,114 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/pistream.hpp
*
* Includes the declaration of the pistream class.
*/
#ifndef BOOST_PROCESS_PISTREAM_HPP
#define BOOST_PROCESS_PISTREAM_HPP
#include <boost/process/handle.hpp>
#include <boost/process/detail/systembuf.hpp>
#include <boost/noncopyable.hpp>
#include <istream>
namespace boost {
namespace process {
/**
* Child process' output stream.
*
* The pistream class represents an output communication channel with the
* child process. The child process writes data to this stream and the
* parent process can read it through the pistream object. In other
* words, from the child's point of view, the communication channel is an
* output one, but from the parent's point of view it is an input one;
* hence the confusing pistream name.
*
* pistream objects cannot be copied because they buffer data
* that flows through the communication channel.
*
* A pistream object behaves as a std::istream stream in all senses.
* The class is only provided because it must provide a method to let
* the caller explicitly close the communication channel.
*
* \remark Blocking remarks: Functions that read data from this
* stream can block if the associated handle blocks during
* the read. As this class is used to communicate with child
* processes through anonymous pipes, the most typical blocking
* condition happens when the child has no more data to send to
* the pipe's system buffer. When this happens, the buffer
* eventually empties and the system blocks until the writer
* generates some data.
*/
class pistream : public std::istream, public boost::noncopyable
{
public:
/**
* Creates a new process' output stream.
*/
explicit pistream(boost::process::handle h)
: std::istream(0),
handle_(h),
systembuf_(handle_.native())
{
rdbuf(&systembuf_);
}
/**
* Returns the handle managed by this stream.
*/
const boost::process::handle &handle() const
{
return handle_;
}
/**
* Returns the handle managed by this stream.
*/
boost::process::handle &handle()
{
return handle_;
}
/**
* Closes the handle managed by this stream.
*
* Explicitly closes the handle managed by this stream. This
* function can be used by the user to tell the child process it's
* not willing to receive more data.
*/
void close()
{
handle_.close();
}
private:
/**
* The handle managed by this stream.
*/
boost::process::handle handle_;
/**
* The systembuf object used to manage this stream's data.
*/
detail::systembuf systembuf_;
};
}
}
#endif

View file

@ -0,0 +1,115 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/postream.hpp
*
* Includes the declaration of the postream class.
*/
#ifndef BOOST_PROCESS_POSTREAM_HPP
#define BOOST_PROCESS_POSTREAM_HPP
#include <boost/process/handle.hpp>
#include <boost/process/detail/systembuf.hpp>
#include <boost/noncopyable.hpp>
#include <ostream>
namespace boost {
namespace process {
/**
* Child process' input stream.
*
* The postream class represents an input communication channel with the
* child process. The child process reads data from this stream and the
* parent process can write to it through the postream object. In other
* words, from the child's point of view, the communication channel is an
* input one, but from the parent's point of view it is an output one;
* hence the confusing postream name.
*
* postream objects cannot be copied because they buffer data that flows
* through the communication channel.
*
* A postream object behaves as a std::ostream stream in all senses.
* The class is only provided because it must provide a method to let
* the caller explicitly close the communication channel.
*
* \remark Blocking remarks: Functions that write data to this
* stream can block if the associated handle blocks during
* the write. As this class is used to communicate with child
* processes through anonymous pipes, the most typical blocking
* condition happens when the child is not processing the data
* in the pipe's system buffer. When this happens, the buffer
* eventually fills up and the system blocks until the reader
* consumes some data, leaving some new room.
*/
class postream : public std::ostream, public boost::noncopyable
{
public:
/**
* Creates a new process' input stream.
*/
explicit postream(boost::process::handle h)
: std::ostream(0),
handle_(h),
systembuf_(handle_.native())
{
rdbuf(&systembuf_);
}
/**
* Returns the handle managed by this stream.
*/
const boost::process::handle &handle() const
{
return handle_;
}
/**
* Returns the handle managed by this stream.
*/
boost::process::handle &handle()
{
return handle_;
}
/**
* Closes the handle managed by this stream.
*
* Explicitly closes the handle managed by this stream. This
* function can be used by the user to tell the child process there
* is no more data to send.
*/
void close()
{
systembuf_.sync();
handle_.close();
}
private:
/**
* The handle managed by this stream.
*/
boost::process::handle handle_;
/**
* The systembuf object used to manage this stream's data.
*/
detail::systembuf systembuf_;
};
}
}
#endif

View file

@ -0,0 +1,212 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/process.hpp
*
* Includes the declaration of the process class.
*/
#ifndef BOOST_PROCESS_PROCESS_HPP
#define BOOST_PROCESS_PROCESS_HPP
#include <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <unistd.h>
# include <sys/types.h>
# include <signal.h>
# include <sys/wait.h>
# include <errno.h>
#elif defined(BOOST_WINDOWS_API)
# include <boost/process/handle.hpp>
# include <cstdlib>
# include <windows.h>
#else
# error "Unsupported platform."
#endif
#include <boost/process/pid_type.hpp>
namespace boost {
namespace process {
/**
* Process class to represent any running process.
*/
class process
{
public:
/**
* Constructs a new process object.
*
* Creates a new process object that represents a running process
* within the system.
*
* On Windows the process is opened and a handle saved. This is required
* to avoid the operating system removing process resources when the
* process exits. The handle is closed when the process instance (and all
* of its copies) is destroyed.
*/
process(pid_type id)
: id_(id)
#if defined(BOOST_WINDOWS_API)
, handle_(open_process(id))
#endif
{
}
#if defined(BOOST_WINDOWS_API) || defined(BOOST_PROCESS_DOXYGEN)
/**
* Constructs a new process object.
*
* Creates a new process object that represents a running process
* within the system.
*
* This operation is only available on Windows systems. The handle is
* closed when the process instance (and all of its copies) is destroyed.
*/
process(handle h)
: id_(GetProcessId(h.native())),
handle_(h)
{
}
#endif
/**
* Returns the process identifier.
*/
pid_type get_id() const
{
return id_;
}
/**
* Terminates the process execution.
*
* Forces the termination of the process execution. Some platforms
* allow processes to ignore some external termination notifications
* or to capture them for a proper exit cleanup. You can set the
* \a force flag to true to force their termination regardless
* of any exit handler.
*
* After this call, accessing this object can be dangerous because the
* process identifier may have been reused by a different process. It
* might still be valid, though, if the process has refused to die.
*
* \throw boost::system::system_error If system calls used to terminate the
* process fail.
*/
void terminate(bool force = false) const
{
#if defined(BOOST_POSIX_API)
if (kill(id_, force ? SIGKILL : SIGTERM) == -1)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("kill(2) failed");
#elif defined(BOOST_WINDOWS_API)
#if defined(BOOST_MSVC)
force;
#endif
HANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, id_);
if (h == NULL)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
if (!TerminateProcess(h, EXIT_FAILURE))
{
CloseHandle(h);
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("TerminateProcess() failed");
}
if (!CloseHandle(h))
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
#endif
}
/**
* Blocks and waits for the process to terminate.
*
* Returns an exit code. The process object ceases to be valid after this
* call.
*
* \remark Blocking remarks: This call blocks if the process has not
* finalized execution and waits until it terminates.
*
* \throw boost::system::system_error If system calls used to wait for the
* process fail.
*/
int wait() const
{
#if defined(BOOST_POSIX_API)
pid_t p;
int status;
do
{
p = waitpid(id_, &status, 0);
} while (p == -1 && errno == EINTR);
if (p == -1)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("waitpid(2) failed");
return status;
#elif defined(BOOST_WINDOWS_API)
HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE,
id_);
if (h == NULL)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
if (WaitForSingleObject(h, INFINITE) == WAIT_FAILED)
{
CloseHandle(h);
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
"WaitForSingleObject() failed");
}
DWORD exit_code;
if (!GetExitCodeProcess(h, &exit_code))
{
CloseHandle(h);
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
"GetExitCodeProcess() failed");
}
if (!CloseHandle(h))
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
return exit_code;
#endif
}
private:
/**
* The process identifier.
*/
pid_type id_;
#if defined(BOOST_WINDOWS_API)
/**
* Opens a process and returns a handle.
*
* OpenProcess() returns NULL and not INVALID_HANDLE_VALUE on failure.
* That's why the return value is manually checked in this helper function
* instead of simply passing it to the constructor of the handle class.
*/
HANDLE open_process(pid_type id)
{
HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, id);
if (h == NULL)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
return h;
}
/**
* The process handle.
*/
handle handle_;
#endif
};
}
}
#endif

View file

@ -0,0 +1,188 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/self.hpp
*
* Includes the declaration of the self class.
*/
#ifndef BOOST_PROCESS_SELF_HPP
#define BOOST_PROCESS_SELF_HPP
#include <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <boost/scoped_array.hpp>
# include <errno.h>
# include <unistd.h>
# include <limits.h>
# if defined(__APPLE__)
# include <crt_externs.h>
# endif
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#else
# error "Unsupported platform."
#endif
#include <boost/process/process.hpp>
#include <boost/process/environment.hpp>
#include <boost/noncopyable.hpp>
#include <boost/assert.hpp>
#include <string>
#if defined(BOOST_POSIX_API)
extern "C"
{
extern char **environ;
}
#endif
namespace boost {
namespace process {
/**
* The self class provides access to the process itself.
*/
class self : public process, public boost::noncopyable
{
public:
/**
* Returns the self instance representing the caller's process.
*/
static self &get_instance()
{
static self *instance = 0;
if (!instance)
instance = new self;
return *instance;
}
/**
* Returns the current environment.
*
* Returns the current process environment variables. Modifying the
* returned object has no effect on the current environment.
*/
static environment get_environment()
{
environment e;
#if defined(BOOST_POSIX_API)
# if defined(__APPLE__)
char **env = *_NSGetEnviron();
# else
char **env = environ;
# endif
while (*env)
{
std::string s = *env;
std::string::size_type pos = s.find('=');
e.insert(environment::value_type(s.substr(0, pos),
s.substr(pos + 1)));
++env;
}
#elif defined(BOOST_WINDOWS_API)
# ifdef GetEnvironmentStrings
# undef GetEnvironmentStrings
# endif
char *ms_environ = GetEnvironmentStrings();
if (!ms_environ)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
"GetEnvironmentStrings() failed");
try
{
char *env = ms_environ;
while (*env)
{
std::string s = env;
std::string::size_type pos = s.find('=');
e.insert(environment::value_type(s.substr(0, pos),
s.substr(pos + 1)));
env += s.size() + 1;
}
}
catch (...)
{
FreeEnvironmentStringsA(ms_environ);
throw;
}
FreeEnvironmentStringsA(ms_environ);
#endif
return e;
}
/**
* Returns the current work directory.
*/
static std::string get_work_dir()
{
#if defined(BOOST_POSIX_API)
#if defined(PATH_MAX)
char buffer[PATH_MAX];
char *cwd = buffer;
long size = PATH_MAX;
#elif defined(_PC_PATH_MAX)
errno = 0;
long size = pathconf("/", _PC_PATH_MAX);
if (size == -1 && errno)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("pathconf(2) failed");
else if (size == -1)
size = BOOST_PROCESS_POSIX_PATH_MAX;
BOOST_ASSERT(size > 0);
boost::scoped_array<char> buffer(new char[size]);
char *cwd = buffer.get();
#else
char buffer[BOOST_PROCESS_POSIX_PATH_MAX];
char *cwd = buffer;
long size = BOOST_PROCESS_POSIX_PATH_MAX;
#endif
if (!getcwd(cwd, size))
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("getcwd(2) failed");
BOOST_ASSERT(cwd[0] != '\0');
return cwd;
#elif defined(BOOST_WINDOWS_API)
BOOST_ASSERT(MAX_PATH > 0);
char cwd[MAX_PATH];
if (!GetCurrentDirectoryA(sizeof(cwd), cwd))
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
"GetCurrentDirectory() failed");
BOOST_ASSERT(cwd[0] != '\0');
return cwd;
#endif
}
private:
/**
* Constructs a new self object.
*
* Creates a new self object that represents the current process.
*/
self() :
#if defined(BOOST_POSIX_API)
process(getpid())
#elif defined(BOOST_WINDOWS_API)
process(GetCurrentProcessId())
#endif
{
}
};
}
}
#endif

View file

@ -0,0 +1,41 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/status.hpp
*
* Includes the declaration of the status class.
*/
#ifndef BOOST_PROCESS_STATUS_HPP
#define BOOST_PROCESS_STATUS_HPP
#include <boost/process/config.hpp>
#include <boost/process/detail/basic_status.hpp>
#include <boost/process/detail/basic_status_service.hpp>
namespace boost {
namespace process {
/**
* The status class to wait for processes to exit.
*
* The status class is a Boost.Asio I/O object and supports synchronous
* and asynchronous wait operations.
*/
typedef detail::basic_status<detail::basic_status_service<> > status;
}
}
#endif

View file

@ -0,0 +1,326 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/stream_behavior.hpp
*
* Includes the declaration of stream behavior classes.
*/
#ifndef BOOST_PROCESS_STREAM_BEHAVIOR_HPP
#define BOOST_PROCESS_STREAM_BEHAVIOR_HPP
#include <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
# include <rpc.h>
#endif
#include <boost/process/stream_ends.hpp>
#include <boost/process/stream_type.hpp>
#include <boost/process/handle.hpp>
#include <string>
#include <algorithm>
namespace boost {
namespace process {
namespace behavior {
/**
* Stream behavior to close streams of a child process.
*
* A child process will not be able to use the stream.
*/
class close
{
public:
stream_ends operator()(stream_type) const
{
return stream_ends();
}
};
/**
* Stream behavior to make a child process inherit streams.
*
* A child process will use the very same stream of its parent process.
*/
class inherit
{
public:
inherit(handle::native_type h)
: h_(h, handle::dont_close)
{
#if defined(BOOST_WINDOWS_API)
if (h != INVALID_HANDLE_VALUE)
{
if (!SetHandleInformation(h_.native(), HANDLE_FLAG_INHERIT,
HANDLE_FLAG_INHERIT))
{
HANDLE proc = GetCurrentProcess();
HANDLE dup;
if (!DuplicateHandle(proc, h_.native(), proc, &dup, 0,
TRUE, DUPLICATE_SAME_ACCESS))
{
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
"DuplicateHandle() failed");
}
h_ = dup;
}
}
#endif
}
stream_ends operator()(stream_type) const
{
return stream_ends(h_, handle());
}
private:
handle h_;
};
/**
* Stream behavior to redirect streams with a pipe.
*
* A child process will be able to communicate with its parent process.
*/
class pipe
{
public:
#if defined(BOOST_POSIX_API)
pipe()
: stype_(unknown_stream)
{
}
pipe(stream_type stype)
: stype_(stype)
{
}
#endif
stream_ends operator()(stream_type stype) const
{
handle::native_type ends[2];
#if defined(BOOST_POSIX_API)
if (::pipe(ends) == -1)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("pipe(2) failed");
if (stype_ != unknown_stream)
stype = stype_;
#elif defined(BOOST_WINDOWS_API)
SECURITY_ATTRIBUTES sa;
ZeroMemory(&sa, sizeof(sa));
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = FALSE;
if (!CreatePipe(&ends[0], &ends[1], &sa, 0))
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreatePipe() failed");
#endif
handle child_end = ends[stype == input_stream ? 0 : 1];
handle parent_end = ends[stype == input_stream ? 1 : 0];
#if defined(BOOST_WINDOWS_API)
if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT,
HANDLE_FLAG_INHERIT))
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
"SetHandleInformation() failed");
#endif
return stream_ends(child_end, parent_end);
}
#if defined(BOOST_POSIX_API)
private:
stream_type stype_;
#endif
};
/**
* Stream behavior to redirect streams with a named pipe.
*
* A child process will be able to communicate with its parent process.
*/
class named_pipe
{
public:
named_pipe(const std::string &name)
: name_(name)
#if defined(BOOST_POSIX_API)
, stype_(unknown_stream)
#endif
{
}
#if defined(BOOST_POSIX_API)
named_pipe(const std::string &name, stream_type stype)
: name_(name),
stype_(stype)
{
}
#endif
stream_ends operator()(stream_type stype) const
{
#if defined(BOOST_POSIX_API)
if (mkfifo(name_.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("mkfifo(3) failed");
handle child_end = open(name_.c_str(), O_RDONLY | O_NONBLOCK);
if (!child_end.valid())
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
int opts = fcntl(child_end.native(), F_GETFL);
if (opts == -1)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fcntl(2) failed");
opts ^= O_NONBLOCK;
if (fcntl(child_end.native(), F_SETFL, opts) == -1)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fcntl(2) failed");
handle parent_end = open(name_.c_str(), O_WRONLY);
if (!parent_end.valid())
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
if (stype_ != unknown_stream)
stype = stype_;
#elif defined(BOOST_WINDOWS_API)
SECURITY_ATTRIBUTES sa;
ZeroMemory(&sa, sizeof(sa));
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
handle child_end = CreateNamedPipeA(name_.c_str(), PIPE_ACCESS_INBOUND |
FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, &sa);
if (!child_end.valid())
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateNamedPipe() failed");
handle parent_end = CreateFileA(name_.c_str(), GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (!parent_end.valid())
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed");
#endif
if (stype == output_stream)
std::swap(child_end, parent_end);
#if defined(BOOST_WINDOWS_API)
if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT,
HANDLE_FLAG_INHERIT))
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
"SetHandleInformation() failed");
#endif
return stream_ends(child_end, parent_end);
}
private:
std::string name_;
#if defined(BOOST_POSIX_API)
stream_type stype_;
#endif
};
/**
* Stream behavior to redirect streams with a pipe which supports asynchronous
* I/O.
*
* As platforms require different types of pipes for asynchronous I/O this
* stream behavior is provided for convenience. It uses the minimum required
* pipe type on a platform in order to be able to use asynchronous I/O.
*/
#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN)
typedef pipe async_pipe;
#elif defined(BOOST_WINDOWS_API)
class async_pipe
{
public:
stream_ends operator()(stream_type stype) const
{
UUID uuid;
RPC_STATUS s = UuidCreateSequential(&uuid);
if (s != RPC_S_OK && s != RPC_S_UUID_LOCAL_ONLY)
BOOST_PROCESS_THROW_ERROR(s, "UuidCreateSequential() failed");
unsigned char *c;
s = UuidToStringA(&uuid, &c);
if (s != RPC_S_OK)
BOOST_PROCESS_THROW_ERROR(s, "UuidToString() failed");
std::string name;
try
{
name = reinterpret_cast<char*>(c);
}
catch (...)
{
RpcStringFreeA(&c);
throw;
}
RpcStringFreeA(&c);
named_pipe p("\\\\.\\pipe\\boost_process_" + name);
return p(stype);
}
};
#endif
/**
* Stream behavior to mute streams.
*
* A child process will be able to use streams. But data written to an
* output stream is discarded and data read from an input stream is 0.
*/
class null
{
public:
#if defined(BOOST_POSIX_API)
null()
: stype_(unknown_stream)
{
}
null(stream_type stype)
: stype_(stype)
{
}
#endif
stream_ends operator()(stream_type stype) const
{
#if defined(BOOST_POSIX_API)
if (stype_ != unknown_stream)
stype = stype_;
std::string filename = (stype == input_stream) ? "/dev/zero" :
"/dev/null";
int flag = (stype == input_stream) ? O_RDONLY : O_WRONLY;
handle child_end = open(filename.c_str(), flag);
if (!child_end.valid())
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
#elif defined(BOOST_WINDOWS_API)
DWORD access = (stype == input_stream) ? GENERIC_READ : GENERIC_WRITE;
handle child_end = CreateFileA("NUL", access, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (!child_end.valid())
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed");
if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT,
HANDLE_FLAG_INHERIT))
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
"SetHandleInformation() failed");
#endif
return stream_ends(child_end, handle());
}
#if defined(BOOST_POSIX_API)
private:
stream_type stype_;
#endif
};
}
}
}
#endif

View file

@ -0,0 +1,68 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/stream_ends.hpp
*
* Includes the declaration of the stream_ends class.
*/
#ifndef BOOST_PROCESS_STREAM_ENDS_HPP
#define BOOST_PROCESS_STREAM_ENDS_HPP
#include <boost/process/config.hpp>
#include <boost/process/handle.hpp>
namespace boost {
namespace process {
/**
* A pair of handles to configure streams.
*
* Stream behaviors return a pair of handles to specify how a child's stream
* should be configured and possibly the opposite end of a child's end. This
* is the end remaining in the parent process and which can be used for example
* to communicate with a child process through its standard streams.
*/
struct stream_ends {
/**
* The child's end.
*/
handle child;
/**
* The parent's end.
*/
handle parent;
/**
* Standard constructor creating two invalid handles.
*/
stream_ends()
{
}
/**
* Helper constructor to easily initialize handles.
*/
stream_ends(handle c, handle p)
: child(c),
parent(p)
{
}
};
}
}
#endif

View file

@ -0,0 +1,50 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/stream_id.hpp
*
* Includes the declaration of the stream_id type.
*/
#ifndef BOOST_PROCESS_STREAM_ID_HPP
#define BOOST_PROCESS_STREAM_ID_HPP
#include <boost/process/config.hpp>
namespace boost {
namespace process {
/**
* Standard stream id to refer to standard streams in a cross-platform manner.
*/
enum std_stream_id { stdin_id, stdout_id, stderr_id };
#if defined(BOOST_PROCESS_DOXYGEN)
/**
* Stream id type.
*
* Depending on the platform the stream id type is defined to refer to standard
* streams only or to support more streams.
*/
typedef NativeStreamId stream_id;
#elif defined(BOOST_POSIX_API)
typedef int stream_id;
#elif defined(BOOST_WINDOWS_API)
typedef std_stream_id stream_id;
#endif
}
}
#endif

View file

@ -0,0 +1,45 @@
//
// Boost.Process
// ~~~~~~~~~~~~~
//
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
// Copyright (c) 2009 Boris Schaeling
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
//
// 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)
//
/**
* \file boost/process/stream_type.hpp
*
* Includes the declaration of the stream_type enumeration.
*/
#ifndef BOOST_PROCESS_STREAM_TYPE_HPP
#define BOOST_PROCESS_STREAM_TYPE_HPP
#include <boost/process/config.hpp>
namespace boost {
namespace process {
/**
* Stream type to differentiate between input and output streams.
*
* On POSIX systems another value unknown_stream is defined. It is passed
* to stream behaviors for file descriptors greater than 2.
*/
enum stream_type {
input_stream,
output_stream
#if defined(BOOST_POSIX_API)
, unknown_stream
#endif
};
}
}
#endif

View file

@ -1,9 +1,8 @@
#ifndef _FC_BASE58_HPP_
#define _FC_BASE58_HPP_
#pragma once
#include <fc/string.hpp>
namespace fc {
fc::string to_base58( const char* d, uint32_t s );
fc::string to_base58( const char* d, size_t s );
fc::vector<char> from_base58( const fc::string& base58_str );
size_t from_base58( const fc::string& base58_str, char* out_data, size_t out_data_len );
}
#endif // _FC_BASE58_HPP_

View file

@ -1,5 +1,4 @@
#ifndef _FC_DATASTREAM_HPP_
#define _FC_DATASTREAM_HPP_
#pragma once
#include <fc/utility.hpp>
#include <fc/error_report.hpp>
#include <string.h>
@ -16,26 +15,13 @@ namespace fc {
*/
template<typename T>
struct datastream {
datastream( T start, uint32_t s )
datastream( T start, size_t s )
:m_start(start),m_pos(start),m_end(start+s){};
template<typename DATA>
inline datastream& operator<<(const DATA& d) {
static_assert( !fc::is_class<DATA>::type::value, "no serialization defined" );
write( (const char*)&d, sizeof(d) );
return *this;
}
template<typename DATA>
inline datastream& operator>>(DATA& d) {
static_assert( !fc::is_class<DATA>::type::value, "no serialization defined" );
read((char*)&d, sizeof(d) );
return *this;
}
inline void skip( uint32_t s ){ m_pos += s; }
inline bool read( char* d, uint32_t s ) {
if( m_end - m_pos >= (int32_t)s ) {
inline void skip( size_t s ){ m_pos += s; }
inline bool read( char* d, size_t s ) {
if( size_t(m_end - m_pos) >= (size_t)s ) {
memcpy( d, m_pos, s );
m_pos += s;
return true;
@ -45,7 +31,7 @@ struct datastream {
return false;
}
inline bool write( const char* d, uint32_t s ) {
inline bool write( const char* d, size_t s ) {
if( m_end - m_pos >= (int32_t)s ) {
memcpy( m_pos, d, s );
m_pos += s;
@ -82,9 +68,9 @@ struct datastream {
T pos()const { return m_pos; }
inline bool valid()const { return m_pos <= m_end && m_pos >= m_start; }
inline bool seekp(uint32_t p) { m_pos = m_start + p; return m_pos <= m_end; }
inline uint32_t tellp()const { return m_pos - m_start; }
inline uint32_t remaining()const { return m_end - m_pos; }
inline bool seekp(size_t p) { m_pos = m_start + p; return m_pos <= m_end; }
inline size_t tellp()const { return m_pos - m_start; }
inline size_t remaining()const { return m_end - m_pos; }
private:
T m_start;
T m_pos;
@ -94,24 +80,117 @@ struct datastream {
template<>
struct datastream<size_t> {
datastream( size_t init_size = 0):m_size(init_size){};
template<typename DATA>
inline datastream& operator<<(const DATA& d) {
static_assert( !fc::is_class<DATA>::type::value, "no serialzation defined" );
m_size += sizeof(d);
return *this;
}
inline bool skip( uint32_t s ) { m_size += s; return true; }
inline bool write( const char* d, uint32_t s ) { m_size += s; return true; }
inline bool skip( size_t s ) { m_size += s; return true; }
inline bool write( const char* d,size_t s ) { m_size += s; return true; }
inline bool put(char c) { ++m_size; return true; }
inline bool valid()const { return true; }
inline bool seekp(uint32_t p) { m_size = p; return true; }
inline uint32_t tellp()const { return m_size; }
inline uint32_t remaining()const { return 0; }
inline bool seekp(size_t p) { m_size = p; return true; }
inline size_t tellp()const { return m_size; }
inline size_t remaining()const { return 0; }
private:
uint32_t m_size;
size_t m_size;
};
/*
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const size_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return *this;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, size_t& d) {
ds.read((char*)&d, sizeof(d) );
return *this;
}
*/
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int32_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int32_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint32_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint32_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int64_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int64_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint64_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint64_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int16_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int16_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint16_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint16_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int8_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int8_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint8_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint8_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
} // namespace fc
#endif

View file

@ -1,5 +1,4 @@
#ifndef _FC_FILESYSTEM_HPP_
#define _FC_FILESYSTEM_HPP_
#pragma once
#include <fc/string.hpp>
#include <fc/fwd.hpp>
@ -7,6 +6,7 @@ namespace boost {
namespace filesystem {
class path;
class directory_iterator;
class recursive_directory_iterator;
}
}
@ -32,12 +32,15 @@ namespace fc {
operator boost::filesystem::path& ();
operator const boost::filesystem::path& ()const;
void replace_extension( const fc::path& e );
fc::path stem()const;
fc::path extension()const;
fc::path filename()const;
fc::path parent_path()const;
fc::string string()const;
fc::string generic_string()const;
bool is_relative()const;
bool is_absolute()const;
private:
fwd<boost::filesystem::path,32> _p;
};
@ -57,19 +60,39 @@ namespace fc {
private:
fwd<boost::filesystem::directory_iterator,16> _p;
};
class recursive_directory_iterator {
public:
recursive_directory_iterator( const fc::path& p );
recursive_directory_iterator();
~recursive_directory_iterator();
fc::path operator*()const;
recursive_directory_iterator& operator++(int);
recursive_directory_iterator& operator++();
friend bool operator==( const recursive_directory_iterator&, const recursive_directory_iterator& );
friend bool operator!=( const recursive_directory_iterator&, const recursive_directory_iterator& );
private:
fwd<boost::filesystem::recursive_directory_iterator,16> _p;
};
bool exists( const path& p );
bool is_directory( const path& p );
bool is_regular_file( const path& p );
void create_directories( const path& p );
void remove_all( const path& p );
path absolute( const path& p );
path canonical( const path& p );
uint64_t file_size( const path& p );
bool remove( const path& p );
void copy( const path& from, const path& to );
void create_hard_link( const path& from, const path& to );
path unique_path();
path temp_directory_path();
class value;
void pack( fc::value& , const fc::path& );
void unpack( const fc::value& , fc::path& );
}
#endif // _FC_FILESYSTEM_HPP_

View file

@ -82,7 +82,7 @@ namespace fc {
template<typename T,unsigned int S,typename A>
fwd<T,S,A>::fwd() {
check_size<sizeof(T),sizeof(_store)>();
new (this) T();
new (this) T;
}
template<typename T,unsigned int S,typename A>
fwd<T,S,A>::fwd( const fwd<T,S,A>& f ){

View file

@ -32,6 +32,7 @@ namespace fc {
};
struct request {
fc::string get_header( const fc::string& key )const;
fc::string method;
fc::string domain;
fc::string path;
@ -39,6 +40,8 @@ namespace fc {
fc::vector<char> body;
};
fc::vector<header> parse_urlencoded_params( const fc::string& f );
/**
* Connections have reference semantics, all copies refer to the same
* underlying socket.

View file

@ -1,9 +1,9 @@
#pragma once
#include <fc/utility.hpp>
#include <fc/lexical_cast.hpp>
#include <fc/string.hpp>
namespace fc {
class string;
class istream {
public:
@ -44,6 +44,7 @@ namespace fc {
};
struct cin_t : virtual public istream {
~cin_t();
virtual size_t readsome( char* buf, size_t len );
virtual istream& read( char* buf, size_t len );
virtual bool eof()const;

View file

@ -103,7 +103,7 @@ namespace fc {
struct impl : public impl_base {
impl(T& i):st(i){}
virtual size_t readsome( char* buf, size_t len ) { return st.readsome(buf,len); }
virtual size_t readsome( char* buf, size_t len ) { return size_t(st.readsome(buf,len)); }
virtual void read( char* buf, size_t len ) {
st.read(buf,len);
}

View file

@ -1,5 +1,4 @@
#ifndef _FC_IP_HPP_
#define _FC_IP_HPP_
#pragma once
#include <fc/string.hpp>
namespace fc {
@ -36,7 +35,6 @@ namespace fc {
friend bool operator==( const endpoint& a, const endpoint& b );
private:
address _ip;
/**
* The compiler pads endpoint to a full 8 bytes, so while
* a port number is limited in range to 16 bits, we specify
@ -45,7 +43,10 @@ namespace fc {
* where they are stored.
*/
uint32_t _port;
address _ip;
};
}
class value;
void pack( fc::value& , const fc::ip::endpoint& );
void unpack( const fc::value& , fc::ip::endpoint& );
}
#endif // _FC_ENDPOINT_HPP_

View file

@ -19,6 +19,7 @@ namespace fc {
inline uint64_t to_uint64( uint64_t d ) { return d; }
fc::string to_string( double d );
fc::string to_string( size_t d );
fc::string to_string( uint64_t d );
fc::string to_string( uint32_t d );
fc::string to_string( uint16_t d );

View file

@ -1,5 +1,4 @@
#ifndef _FC_LOG_HPP_
#define _FC_LOG_HPP_
#pragma once
#include <fc/utility.hpp>
namespace boost { class mutex; }
@ -30,4 +29,3 @@ namespace fc {
#define elog(...) do { fc::log( CONSOLE_RED, __FILE__, __LINE__, __func__, __VA_ARGS__ ); }while(false)
#endif // _FC_LOG_HPP_

View file

@ -1,5 +1,4 @@
#ifndef FC_MUTEX_HPP_
#define FC_MUTEX_HPP_
#pragma once
#include <fc/time.hpp>
#include <fc/spin_yield_lock.hpp>
@ -107,4 +106,3 @@ namespace fc {
} // namespace fc
#endif // MACE_CMT_MUTEX_HPP_

View file

@ -36,7 +36,6 @@ namespace fc {
template<typename U>
optional& operator=( U&& u ) {
if( &u == &**this ) return *this;
if( !_valid ) {
new (&**this) T( fc::forward<U>(u) );
_valid = true;

View file

@ -1,7 +1,7 @@
#ifndef FC_PKE_HPP_
#define FC_PKE_HPP_
#pragma once
#include <fc/sha1.hpp>
#include <fc/vector.hpp>
#include <fc/reflect.hpp>
/**
* Define common crypto methods and data types to abstract underlying implementation.
@ -143,7 +143,13 @@ namespace fc {
typedef private_key<> private_key_t;
typedef signature<> signature_t;
class value;
void pack( fc::value& , const fc::signature_t& );
void unpack( const fc::value& , fc::signature_t& );
void pack( fc::value& , const fc::public_key_t& );
void unpack( const fc::value& , fc::private_key_t& );
void pack( fc::value& , const fc::private_key_t& );
void unpack( const fc::value& , fc::public_key_t& );
} // namespace fc
#endif

View file

@ -1,14 +1,16 @@
#pragma once
#include <fc/shared_impl.hpp>
#include <fc/future.hpp>
#include <fc/string.hpp>
namespace fc {
class istream;
class ostream;
class path;
class string;
template<typename> class vector;
fc::path find_executable_in_path( const fc::string name );
/**
* @brief start and manage an external process
*
@ -23,6 +25,7 @@ namespace fc {
open_stderr = 0x04,
open_all = open_stdin|open_stdout|open_stderr,
};
/**
* Return a new process executing the specified exe with the specified args.
*/

View file

@ -1,5 +1,4 @@
#ifndef _TORNET_RPC_RAW_HPP_
#define _TORNET_RPC_RAW_HPP_
#pragma once
#include <fc/reflect.hpp>
#include <fc/datastream.hpp>
#include <fc/varint.hpp>
@ -7,7 +6,6 @@
#include <fc/vector.hpp>
#include <fc/fwd.hpp>
#include <fc/array.hpp>
//#include <fc/value.hpp>
namespace fc {
class value;
@ -248,7 +246,7 @@ namespace fc {
raw::pack(ps,v );
fc::vector<char> vec(ps.tellp());
if( vec.size() ) {
datastream<char*> ds( vec.data(), vec.size() );
datastream<char*> ds( vec.data(), size_t(vec.size()) );
raw::pack(ds,v);
}
return vec;
@ -258,7 +256,7 @@ namespace fc {
inline T unpack( const fc::vector<char>& s ) {
T tmp;
if( s.size() ) {
datastream<const char*> ds( s.data(), s.size() );
datastream<const char*> ds( s.data(), size_t(s.size()) );
raw::unpack(ds,tmp);
}
return tmp;
@ -280,4 +278,3 @@ namespace fc {
} } // namespace fc::raw
#endif // BOOST_RPC_RAW_HPP

View file

@ -78,9 +78,11 @@ struct reflector{
#else
#define TEMPLATE
#endif
//#include <boost/typeof/typeof.hpp>
#define FC_REFLECT_VISIT_MEMBER( r, visitor, elem ) \
visitor.TEMPLATE operator()<decltype(((type*)0)->elem), type, &type::elem>( BOOST_PP_STRINGIZE(elem) );
{ typedef decltype(((type*)nullptr)->elem) member_type; \
visitor.TEMPLATE operator()<member_type,type,&type::elem>( BOOST_PP_STRINGIZE(elem) ); \
}
#define FC_REFLECT_BASE_MEMBER_COUNT( r, OP, elem ) \

View file

@ -0,0 +1,11 @@
#pragma once
namespace fc {
template<typename T>
class scoped_lock {
public:
scoped_lock( T& l ):_lock(l) { _lock.lock(); }
~scoped_lock() { _lock.unlock(); }
T& _lock;
};
}

View file

@ -14,8 +14,8 @@ shared_impl<T>::shared_impl( U&& u ):_impl(fc::forward<U>(u)){}
template<typename T>
shared_impl<T>::shared_impl( const shared_impl<T>& u ):_impl(u._impl){}
template<typename T>
shared_impl<T>::shared_impl( shared_impl<T>& u ):_impl(u._impl){}
//template<typename T>
//shared_impl<T>::shared_impl( shared_impl<T>& u ):_impl(u._impl){}
template<typename T>
shared_impl<T>::shared_impl( shared_impl<T>&& u ):_impl(fc::move(u._impl)){}
@ -57,8 +57,6 @@ TYPE::TYPE( TYPE&& c )\
:my(fc::move(c.my)){}\
TYPE::TYPE( const TYPE& c )\
:my(c.my){}\
TYPE::TYPE( TYPE& c )\
:my(c.my){}\
TYPE::TYPE() \
:my( new fc::shared_impl<TYPE>::impl( ) ){}\
TYPE::~TYPE(){}\

View file

@ -110,10 +110,10 @@ namespace fc {
bool operator !()const;
template<typename U>
shared_impl( U&& u );
explicit shared_impl( U&& u );
shared_impl( const shared_impl& u );
shared_impl( shared_impl& u );
// shared_impl( shared_impl& u );
shared_impl( shared_impl&& u );
shared_impl& operator=( shared_impl&& u );
shared_impl& operator=( const shared_impl& u );
@ -132,7 +132,6 @@ namespace fc {
TYPE( TYPE* ); \
TYPE( TYPE&& ); \
TYPE( const TYPE& ); \
TYPE( TYPE& ); \
template<typename A1> \
TYPE( A1&& ); \
template<typename A1,typename A2> \
@ -155,7 +154,8 @@ namespace fc {
#define FC_START_SHARED_IMPL( SCOPED_TYPE ) \
namespace fc { \
template<> \
struct fc::shared_impl<SCOPED_TYPE>::impl : public fc::retainable { \
class fc::shared_impl<SCOPED_TYPE>::impl : public fc::retainable { \
public:\
SCOPED_TYPE self() { return SCOPED_TYPE(this); } \

View file

@ -1,5 +1,6 @@
#pragma once
#include <fc/utility.hpp>
#include <fc/log.hpp>
namespace fc {
@ -28,39 +29,37 @@ namespace fc {
template<typename Other>
shared_ptr( const shared_ptr<Other>& o )
:_ptr(o.get()) {
if(_ptr) _ptr->retain();
if(_ptr != nullptr ) _ptr->retain();
}
shared_ptr( const shared_ptr& o )
:_ptr(o.get()) {
if(_ptr != nullptr ) _ptr->retain();
}
shared_ptr( T* t, bool inc = false )
:_ptr(t) { if( inc ) t->retain(); }
:_ptr(t) { if( inc && t != nullptr) t->retain(); }
shared_ptr():_ptr(nullptr){}
shared_ptr( const shared_ptr& p ) {
_ptr = p._ptr;
if( _ptr ) _ptr->retain();
}
shared_ptr( shared_ptr& p ) {
_ptr = p._ptr;
if( _ptr ) _ptr->retain();
}
shared_ptr( shared_ptr&& p ) {
_ptr = p._ptr;
p._ptr = nullptr;
}
~shared_ptr() { if( _ptr ) { _ptr->release(); } }
shared_ptr( shared_ptr&& p )
:_ptr(p._ptr){ p._ptr = nullptr; }
shared_ptr& reset( T* v = 0, bool inc = false ) {
~shared_ptr() { if( nullptr != _ptr ) { _ptr->release(); } }
shared_ptr& reset( T* v = nullptr, bool inc = false ) {
if( v == _ptr ) return *this;
if( _ptr ) _ptr->release();
if( inc && nullptr != v ) v->retain();
if( nullptr != _ptr ) _ptr->release();
_ptr = v;
if( _ptr && inc ) _ptr->retain();
return *this;
}
shared_ptr& operator=(const shared_ptr& p ) {
shared_ptr tmp(p);
fc_swap(tmp._ptr,_ptr);
if( _ptr == p._ptr ) return *this;
if( p._ptr != nullptr ) p._ptr->retain();
if( _ptr != nullptr ) _ptr->release();
_ptr = p._ptr;
return *this;
}
shared_ptr& operator=(shared_ptr&& p ) {

View file

@ -1,5 +1,4 @@
#ifndef _FC_SPIN_YIELD_LOCK_HPP_
#define _FC_SPIN_YIELD_LOCK_HPP_
#pragma once
namespace boost {
template<typename T> class atomic;
@ -38,4 +37,3 @@ namespace fc {
} // namespace fc
#endif // _FC_SPIN_YIELD_LOCK_HPP_

View file

@ -37,7 +37,7 @@ namespace fc {
struct file_attrib {
file_attrib();
size_t size;
uint64_t size;
uint32_t uid;
uint32_t gid;
uint32_t permissions;

View file

@ -6,7 +6,6 @@ namespace fc {
class istream;
class ostream;
class string;
namespace ssh {

View file

@ -22,6 +22,7 @@ namespace std {
}
namespace fc {
// typedef std::string string;
/**
* Including <string> results in 4000 lines of code
* that must be included to build your header. This
@ -55,17 +56,19 @@ namespace fc {
const_iterator begin()const;
const_iterator end()const;
char& operator[](uint64_t idx);
const char& operator[](uint64_t idx)const;
char& operator[](size_t idx);
const char& operator[](size_t idx)const;
string& operator =( const string& c );
string& operator =( string&& c );
void reserve( uint64_t );
uint64_t size()const;
uint64_t find( char c, uint64_t pos = 0 )const;
void reserve( size_t );
size_t size()const;
size_t find( char c, size_t pos = 0 )const;
size_t rfind( char c, size_t pos = 0 )const;
size_t rfind( const fc::string& c, size_t pos = 0 )const;
void resize( uint64_t s );
void resize( size_t s );
void clear();
const char* c_str()const;
@ -82,11 +85,11 @@ namespace fc {
friend string operator + ( const string&, const string& );
friend string operator + ( const string&, char c );
fc::string substr( int32_t start, int32_t len = 0x7fffffff )const;
fc::string substr( size_t start, size_t len = fc::string::npos )const;
private:
fc::fwd<std::string,32> my;
};
} // namespace FC
} // namespace fc

View file

@ -1,11 +1,9 @@
#ifndef _FC_SUPER_FAST_HASH_HPP_
#define _FC_SUPER_FAST_HASH_HPP_
#pragma once
#include <fc/string.hpp>
namespace fc {
class string;
uint32_t super_fast_hash (const char * data, int len);
uint32_t super_fast_hash (const fc::string& str );
}
#endif // _FC_SUPER_FAST_HASH_HPP_

View file

@ -2,9 +2,9 @@
#define _FC_THREAD_HPP_
#include <fc/task.hpp>
#include <fc/vector.hpp>
#include <fc/string.hpp>
namespace fc {
class string;
class time_point;
class microseconds;

View file

@ -1,7 +1,7 @@
#ifndef _FC_TIME_HPP_
#define _FC_TIME_HPP_
#pragma once
#include <stdint.h>
#include <fc/string.hpp>
#include <fc/raw.hpp>
namespace fc {
class microseconds {
@ -41,5 +41,16 @@ namespace fc {
private:
microseconds elapsed;
};
// forward declare io
class value;
void pack( fc::value& , const fc::time_point& );
void unpack( const fc::value& , fc::time_point& );
namespace raw {
template<typename Stream, typename T>
void unpack( Stream& s, fc::time_point& v );
template<typename Stream, typename T>
void pack( Stream& s, const fc::time_point& v );
}
}
#endif // _FC_TIME_HPP_

18
include/fc/time_io.hpp Normal file
View file

@ -0,0 +1,18 @@
#pragma once
#include <fc/time_point.hpp>
#include <fc/raw.hpp>
namespace fc {
namespace raw {
template<typename Stream, typename T>
void unpack( Stream& s, fc::time_point& v ) {
int64_t micro;
fc::raw::unpack(s, micro );
v = fc::time_point( fc::microseconds(micro);
}
template<typename Stream, typename T>
void pack( Stream& s, const fc::time_point& v ) {
fc::raw::pack( s, v.time_since_epoch().count() );
}
}
}

View file

@ -85,9 +85,8 @@ namespace fc {
struct tuple<BOOST_PP_ENUM_PARAMS(n,A)> { \
enum size_enum { size = n }; \
template<BOOST_PP_ENUM_PARAMS( n, typename AA)> \
tuple( BOOST_PP_ENUM(n, RREF_PARAMS, unused ) )BOOST_PP_IF(n,:,BOOST_PP_EMPTY())BOOST_PP_ENUM( n, ILIST_PARAMS,unused){} \
explicit tuple( BOOST_PP_ENUM(n, RREF_PARAMS, unused ) )BOOST_PP_IF(n,:,BOOST_PP_EMPTY())BOOST_PP_ENUM( n, ILIST_PARAMS,unused){} \
tuple( const tuple& t )BOOST_PP_IF(n,:,BOOST_PP_EMPTY())BOOST_PP_ENUM( n, ILIST_PARAMS_COPY,unused){} \
tuple( tuple& t )BOOST_PP_IF(n,:,BOOST_PP_EMPTY())BOOST_PP_ENUM( n, ILIST_PARAMS_COPY,unused){} \
tuple( tuple&& t )BOOST_PP_IF(n,:,BOOST_PP_EMPTY())BOOST_PP_ENUM( n, ILIST_PARAMS_COPY,unused){} \
tuple(){}\
template<typename V>\

View file

@ -1,6 +1,7 @@
#pragma once
#include <fc/string.hpp>
namespace fc {
class string;
class value;
template<typename T> class get_typename{};
template<> struct get_typename<int32_t> { static const char* name() { return "int32_t"; } };
template<> struct get_typename<int64_t> { static const char* name() { return "int64_t"; } };
@ -16,4 +17,5 @@ namespace fc {
template<> struct get_typename<char> { static const char* name() { return "char"; } };
template<> struct get_typename<void> { static const char* name() { return "char"; } };
template<> struct get_typename<string> { static const char* name() { return "string"; } };
template<> struct get_typename<value> { static const char* name() { return "value"; } };
}

View file

@ -3,6 +3,7 @@
#include <fc/string.hpp>
#include <fc/vector.hpp>
#include <fc/aligned.hpp>
#include <fc/typename.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
namespace fc {
@ -23,15 +24,16 @@ namespace fc {
*/
class value {
public:
struct key_val;
struct object {
class key_val;
class object {
public:
typedef fc::vector<key_val>::const_iterator const_iterator;
//fc::string type;
fc::vector<key_val> fields;
};
struct array {
class array {
public:
array( size_t s = 0 ):fields(s){}
//fc::string type;
fc::vector<value> fields;
};
@ -85,21 +87,31 @@ namespace fc {
value& operator=( value&& v );
value& operator=( const value& v );
value& operator=( value& v );
/**
* Include fc/value_cast.hpp for implementation
*/
template<typename T>
explicit value( T&& v );
explicit value( const T& v );
template<typename T>
value& operator=( T&& v ) {
value tmp(fc::forward<T>(v) );
fc_swap(*this,tmp);
return *this;
value& operator=( const T& v );
template<typename T>
T cast()const;
/*
{
slog("operator= %p", this);
value tmp(fc::forward<T>(v));
slog( "swap...tmp %p this %p", &tmp, this );
T tmp = fc::move(a);
a = fc::move(b);
b = fc::move(tmp);
slog( "return" );
return *this;
}
*/
/** used to iterate over object fields, use array index + size to iterate over array */
object::const_iterator find( const char* key )const;
@ -126,6 +138,7 @@ namespace fc {
/** gets the stored type **/
const char* type()const;
bool is_null()const;
bool is_string()const;
void visit( const_visitor&& v )const;
@ -145,30 +158,45 @@ namespace fc {
template<typename T>
friend T value_cast( const value& v );
aligned<24> holder;
aligned<40> holder;
};
bool operator == ( const value& v, std::nullptr_t );
bool operator != ( const value& v, std::nullptr_t );
struct value::key_val {
class value::key_val {
public:
key_val(){};
key_val( fc::string k, value v = value())
:key(fc::move(k)),val(fc::move(v)){}
key_val( fc::string k )
:key(fc::move(k)){}
// key_val( fc::string k, value v )
// :key(fc::move(k)),val(fc::move(v)){
// slog("key_val(key,val)");}
key_val( const fc::string& k, const value& v )
:key(k),val(v){}
key_val( key_val&& m )
:key(fc::move(m.key)),val(fc::move(m.val)){}
:key(fc::move(m.key)),val(fc::move(m.val)){ }
key_val( const key_val& m )
:key(m.key),val(m.val){}
~key_val(){ }
key_val& operator=( key_val&& k ) {
key = fc::move(k.key);
val = fc::move(k.val);
slog( "swap key");
fc_swap( key, k.key );
slog( "swap val");
fc_swap( val, k.val );
return *this;
}
key_val& operator=( const key_val& k ) {
slog( "copy key");
key = k.key;
slog( "copy val");
val = k.val;
return *this;
}

View file

@ -75,7 +75,7 @@ namespace fc {
virtual void operator()( const float& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const double& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const bool& v ){ m_out = v != 0 ? "true" : "false"; }
virtual void operator()( const fc::string& v ){ m_out = v; }
virtual void operator()( const fc::string& v ) { m_out = v; }
virtual void operator()( const value::object& ) { FC_THROW_MSG("bad cast"); }
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast"); }
virtual void operator()( ) { FC_THROW_MSG("bad cast"); }
@ -274,6 +274,7 @@ namespace fc {
virtual value_holder* copy_helper( char* c )const;
};
void new_value_holder_void( value* v );
} // namespace detail
@ -300,9 +301,19 @@ namespace fc {
}
template<typename T>
value::value( T&& v ) {
new (holder) detail::value_holder();
fc::pack( *this, fc::forward<T>(v) );
value::value( const T& v ) {
detail::new_value_holder_void(this);
fc::pack( *this, v);
}
template<typename T>
value& value::operator=( const T& v ) {
this->~value();
value tmp(v);
*this = fc::move(tmp);
return *this;
}
template<typename T>
T value::cast()const {
return value_cast<T>(*this);
}
}

View file

@ -45,7 +45,7 @@ namespace fc {
inline void pack( fc::value& jsv, const int16_t& v ) { jsv = v; }
inline void pack( fc::value& jsv, const int32_t& v ) { jsv = v; }
inline void pack( fc::value& jsv, const int64_t& v ) { jsv = v; }
inline void pack( fc::value& jsv, const fc::string& v ) { jsv = v; }
inline void pack( fc::value& jsv, const fc::string& v ) { jsv = value(v); }
inline void pack( fc::value& jsv, fc::string& v ) { jsv = v; }
inline void pack( fc::value& jsv, fc::string&& v ) { jsv = fc::move(v); }
inline void pack( fc::value& jsv, const char* v ) { jsv = fc::string(v); }
@ -93,7 +93,8 @@ namespace fc {
*/
template<typename T>
inline void pack_helper( const T& v, const char* name )const {
fc::pack( obj[name], v );
value* o = &obj[name];
fc::pack( *o, v );
}
template<typename T>
inline void pack_helper( const fc::optional<T>& v, const char* name )const {

View file

@ -10,11 +10,11 @@ namespace fc {
namespace detail {
template<typename T>
struct data {
uint64_t size;
uint64_t capacity;
size_t size;
size_t capacity;
T first;
static data* allocate( uint64_t cap ) {
static data* allocate( size_t cap ) {
data* d = nullptr;
if( cap ){
d = (data*)malloc(sizeof(data) + sizeof(T)*(static_cast<size_t>(cap)-1));
@ -26,7 +26,7 @@ namespace fc {
d->size = 0;
return d;
}
static data* reallocate( data* d, uint64_t cap ) {
static data* reallocate( data* d, size_t cap ) {
if( cap ){
d = (data*)realloc(d,sizeof(data) + sizeof(T)*(static_cast<size_t>(cap)-1));
d->capacity = static_cast<size_t>(cap);
@ -62,7 +62,7 @@ namespace fc {
resize(e-b);
if( size() ) memcpy( data(), b, static_cast<size_t>(size()) );
}
vector_impl(uint64_t s):_data(nullptr){
vector_impl(size_t s):_data(nullptr){
resize(s);
}
~vector_impl() {
@ -70,8 +70,8 @@ namespace fc {
}
uint64_t size()const { return _data ? _data->size : 0; }
uint64_t capacity()const { return _data ? _data->capacity : 0; }
size_t size()const { return _data ? _data->size : 0; }
size_t capacity()const { return _data ? _data->capacity : 0; }
T& back() { return (&_data->first)[-1+_data->size]; }
const T& back()const { return (&_data->first)[-1+_data->size]; }
@ -85,11 +85,11 @@ namespace fc {
iterator end() { return _data ? (&back())+1: 0;}
const_iterator end()const { return _data ? (&back())+1: 0;}
T& operator[]( uint64_t i ) { return (&_data->first)[i]; }
const T& operator[]( uint64_t i )const { return (&_data->first)[i]; }
T& operator[]( size_t i ) { return (&_data->first)[i]; }
const T& operator[]( size_t i )const { return (&_data->first)[i]; }
T& at( uint64_t i ) { return (&_data->first)[i]; }
const T& at( uint64_t i )const { return (&_data->first)[i]; }
T& at( size_t i ) { return (&_data->first)[i]; }
const T& at( size_t i )const { return (&_data->first)[i]; }
void pop_back() { erase( &back() ); }
@ -100,11 +100,11 @@ namespace fc {
_data = nullptr;
}
void reserve( uint64_t i ) {
void reserve( size_t i ) {
_data = detail::data<T>::reallocate( _data, i );
}
void resize( uint64_t i ) {
void resize( size_t i ) {
if( capacity() < i ) {
if( _data )
_data = detail::data<T>::reallocate( _data, i );
@ -122,7 +122,7 @@ namespace fc {
template<typename U>
iterator insert( const_iterator loc, U&& t ) {
uint64_t pos = loc - begin();
size_t pos = loc - begin();
resize( size()+1 );
char* src = &at(pos);
if( src != &back() )
@ -134,11 +134,11 @@ namespace fc {
iterator insert( iterator pos, const_iterator first, const_iterator last ) {
if( first >= last ) return pos;
uint64_t loc = pos - begin();
uint64_t right_size = size() - loc;
size_t loc = pos - begin();
size_t right_size = size() - loc;
resize( size() + (last-first) );
char* src = &at(loc);
uint64_t s = last-first;
size_t s = last-first;
memmove( src + s, src, right_size );
memcpy( src, first, s );
_data->size += (last-first);
@ -201,7 +201,7 @@ namespace fc {
}
}
vector_impl(uint64_t s):_data(nullptr){
vector_impl(size_t s):_data(nullptr){
resize(s);
}
~vector_impl() {
@ -209,8 +209,8 @@ namespace fc {
}
uint64_t size()const { return _data ? _data->size : 0; }
uint64_t capacity()const { return _data ? _data->capacity : 0; }
size_t size()const { return _data ? _data->size : 0; }
size_t capacity()const { return _data ? _data->capacity : 0; }
T& back() { return (&_data->first)[-1+_data->size]; }
const T& back()const { return (&_data->first)[-1+_data->size]; }
@ -223,11 +223,11 @@ namespace fc {
const_iterator begin()const { return _data ? &front() : 0;}
const_iterator end()const { return _data ? (&back())+1: 0;}
T& operator[]( uint64_t i ) { return (&_data->first)[i]; }
const T& operator[]( uint64_t i )const { return (&_data->first)[i]; }
T& operator[]( size_t i ) { return (&_data->first)[i]; }
const T& operator[]( size_t i )const { return (&_data->first)[i]; }
T& at( uint64_t i ) { return (&_data->first)[i]; }
const T& at( uint64_t i )const { return (&_data->first)[i]; }
T& at( size_t i ) { return (&_data->first)[i]; }
const T& at( size_t i )const { return (&_data->first)[i]; }
void pop_back() { erase( &back() ); }
@ -245,7 +245,7 @@ namespace fc {
this->_data = nullptr;
}
void reserve( uint64_t i ) {
void reserve( size_t i ) {
if( nullptr != this->_data && i <= this->_data->capacity )
return;
@ -264,7 +264,7 @@ namespace fc {
if( _ndata ) free(_ndata);
}
void resize( uint64_t i ) {
void resize( size_t i ) {
this->reserve(i);
while( i < this->_data->size ) {
this->back().~T();
@ -285,7 +285,7 @@ namespace fc {
template<typename U>
iterator insert( const_iterator loc, U&& t ) {
uint64_t pos = loc - this->begin();
size_t pos = loc - this->begin();
this->reserve( this->size()+1 );
loc = this->begin() + pos;
if( this->size() != 0 ) {
@ -351,7 +351,7 @@ namespace fc {
class vector : public detail::vector_impl<T, typename fc::is_class<T>::type> {
public:
vector(){}
vector( uint64_t s ):detail::vector_impl<T, typename fc::is_class<T>::type>(s){}
vector( size_t s ):detail::vector_impl<T, typename fc::is_class<T>::type>(s){}
vector( const vector& v ):detail::vector_impl<T, typename fc::is_class<T>::type>(v){}
vector( vector&& v ):detail::vector_impl<T, typename fc::is_class<T>::type>(fc::move(v)){}

View file

@ -606,10 +606,17 @@ inline bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vch
namespace fc {
fc::string to_base58( const char* d, uint32_t s ) {
fc::string to_base58( const char* d, size_t s ) {
return EncodeBase58( (const unsigned char*)d, (const unsigned char*)d+s ).c_str();
}
fc::vector<char> from_base58( const fc::string& base58_str ) {
std::vector<unsigned char> out;
if( !DecodeBase58( base58_str.c_str(), out ) ) {
FC_THROW_REPORT( "Unable to decode base58 string ${base58_str}", fc::value().set("base58_str",base58_str) );
}
return fc::vector<char>((const char*)out.data(), ((const char*)out.data())+out.size() );
}
/**
* @return the number of bytes decoded
*/

View file

@ -83,12 +83,12 @@ fc::string error_frame::to_detail_string()const {
}
fc::string error_frame::to_string()const {
fc::stringstream ss;
int64_t prev = 0;
size_t prev = 0;
auto next = desc.find( '$' );
while( prev != int64_t(fc::string::npos) && prev < int64_t(desc.size()) ) {
while( prev != size_t(fc::string::npos) && prev < size_t(desc.size()) ) {
// slog( "prev: %d next %d %s", prev, next, desc.substr(prev,next).c_str() );
// print everything from the last pos until the first '$'
ss << desc.substr( prev, next-prev );
ss << desc.substr( prev, size_t(next-prev) );
// if we got to the end, return it.
if( next == string::npos ) { return ss.str(); }
@ -107,7 +107,11 @@ fc::string error_frame::to_string()const {
if( meta ) {
auto itr = meta->find( key.c_str() );
if( itr != meta->end() ) {
ss << fc::json::to_string( itr->val );
if( itr->val.is_string() ) {
ss<<itr->val.cast<fc::string>();
} else {
ss << fc::json::to_string( itr->val );
}
} else {
ss << "???";
}
@ -128,14 +132,14 @@ fc::string error_frame::to_string()const {
}
fc::string error_report::to_string()const {
fc::stringstream ss;
for( int i = 0; i < stack.size(); ++i ) {
for( uint32_t i = 0; i < stack.size(); ++i ) {
ss << stack[i].to_string() << "\n";
}
return ss.str();
}
fc::string error_report::to_detail_string()const {
fc::stringstream ss;
for( int i = 0; i < stack.size(); ++i ) {
for( uint32_t i = 0; i < stack.size(); ++i ) {
ss << stack[i].to_detail_string() << "\n";
}
return ss.str();

View file

@ -1,9 +1,19 @@
//#define BOOST_NO_SCOPED_ENUMS
#include <fc/filesystem.hpp>
#include <fc/fwd_impl.hpp>
#include <fc/utility.hpp>
#include <boost/config.hpp>
#include <boost/filesystem.hpp>
#include <fc/value_cast.hpp>
#include <fc/error_report.hpp>
namespace fc {
void pack( fc::value& v, const fc::path& s ) {
v = s.generic_string();
}
void unpack( const fc::value& v, fc::path& s ) {
s = path(fc::value_cast<fc::string>(v));
}
path::path(){}
path::~path(){};
@ -59,6 +69,9 @@ namespace fc {
fc::path path::filename()const {
return _p->filename();
}
void path::replace_extension( const fc::path& e ) {
_p->replace_extension(e);
}
fc::path path::extension()const {
return _p->extension();
}
@ -68,6 +81,8 @@ namespace fc {
fc::path path::parent_path()const {
return _p->parent_path();
}
bool path::is_relative()const { return _p->is_relative(); }
bool path::is_absolute()const { return _p->is_absolute(); }
directory_iterator::directory_iterator( const fc::path& p )
:_p(p){}
@ -86,12 +101,49 @@ namespace fc {
return *r._p != *l._p;
}
recursive_directory_iterator::recursive_directory_iterator( const fc::path& p )
:_p(p){}
recursive_directory_iterator::recursive_directory_iterator(){}
recursive_directory_iterator::~recursive_directory_iterator(){}
fc::path recursive_directory_iterator::operator*()const { return boost::filesystem::path(*(*_p)); }
recursive_directory_iterator& recursive_directory_iterator::operator++(int) { (*_p)++; return *this; }
recursive_directory_iterator& recursive_directory_iterator::operator++() { (*_p)++; return *this; }
bool operator==( const recursive_directory_iterator& r, const recursive_directory_iterator& l) {
return *r._p == *l._p;
}
bool operator!=( const recursive_directory_iterator& r, const recursive_directory_iterator& l) {
return *r._p != *l._p;
}
bool exists( const path& p ) { return boost::filesystem::exists(p); }
void create_directories( const path& p ) { boost::filesystem::create_directories(p); }
void create_directories( const path& p ) {
try {
boost::filesystem::create_directories(p);
} catch ( ... ) {
FC_THROW_REPORT( "Unable to create directories ${path}", fc::value().set("path", p ).set("inner", fc::except_str() ) );
}
}
bool is_directory( const path& p ) { return boost::filesystem::is_directory(p); }
bool is_regular_file( const path& p ) { return boost::filesystem::is_regular_file(p); }
uint64_t file_size( const path& p ) { return boost::filesystem::file_size(p); }
void copy( const path& f, const path& t ) { boost::filesystem::copy( f, t ); }
void remove_all( const path& p ) { boost::filesystem::remove_all(p); }
void copy( const path& f, const path& t ) {
try {
boost::filesystem::copy( boost::filesystem::path(f), boost::filesystem::path(t) );
} catch ( boost::system::system_error& e ) {
FC_THROW_REPORT( "Copy from ${srcfile} to ${dstfile} failed because ${reason}",
fc::value().set("srcfile",f).set("dstfile",t).set("reason",e.what() ) );
} catch ( ... ) {
FC_THROW_REPORT( "Copy from ${srcfile} to ${dstfile} failed",
fc::value().set("srcfile",f).set("dstfile",t).set("inner", fc::except_str() ) );
}
}
void create_hard_link( const path& f, const path& t ) { boost::filesystem::create_hard_link( f, t ); }
bool remove( const path& f ) { return boost::filesystem::remove( f ); }
fc::path canonical( const fc::path& p ) { return boost::filesystem::canonical(p); }
fc::path absolute( const fc::path& p ) { return boost::filesystem::absolute(p); }

View file

@ -49,7 +49,7 @@ namespace fc {
my->ifs.open( file.string().c_str(), std::ios::binary );
}
size_t ifstream::readsome( char* buf, size_t len ) {
return my->ifs.readsome( buf, len );
return size_t(my->ifs.readsome( buf, len ));
}
ifstream& ifstream::read( char* buf, size_t len ) {
my->ifs.read(buf,len);
@ -61,6 +61,7 @@ namespace fc {
case cur: my->ifs.seekg( p, std::ios_base::cur ); return *this;
case end: my->ifs.seekg( p, std::ios_base::end ); return *this;
}
return *this;
}
void ifstream::close() { return my->ifs.close(); }

View file

@ -4,6 +4,8 @@
#include <fc/iostream.hpp>
#include <fc/exception.hpp>
#include <fc/ip.hpp>
#include <fc/error_report.hpp>
#include <fc/hex.hpp>
FC_START_SHARED_IMPL(fc::http::connection)
@ -154,4 +156,42 @@ http::request connection::read_request()const {
return req;
}
fc::string request::get_header( const fc::string& key )const {
for( auto itr = headers.begin(); itr != headers.end(); ++itr ) {
if( itr->key == key ) { return itr->val; }
}
return fc::string();
}
fc::vector<header> parse_urlencoded_params( const fc::string& f ) {
int num_args = 0;
for( size_t i = 0; i < f.size(); ++i ) {
if( f[i] == '=' ) ++num_args;
}
fc::vector<header> h(num_args);
int arg = 0;
for( size_t i = 0; i < f.size(); ++i ) {
while( f[i] != '=' && i < f.size() ) {
if( f[i] == '%' ) {
h[arg].key += char((fc::from_hex(f[i+1]) << 4) | fc::from_hex(f[i+2]));
i += 3;
} else {
h[arg].key += f[i];
++i;
}
}
++i;
while( i < f.size() && f[i] != '&' ) {
if( f[i] == '%' ) {
h[arg].val += char((fc::from_hex(f[i+1]) << 4) | fc::from_hex(f[i+2]));
i += 3;
} else {
h[arg].val += f[i] == '+' ? ' ' : f[i];
++i;
}
}
++arg;
}
return h;
}
} } // fc::http

View file

@ -4,7 +4,10 @@
#include <iostream>
#include <string.h>
#include <fc/log.hpp>
#include <fc/mutex.hpp>
#include <fc/scoped_lock.hpp>
#include <string>
#include <boost/thread/mutex.hpp>
namespace fc {
ostream& operator<<( ostream& o, const char* v ) {
@ -32,18 +35,27 @@ namespace fc {
buf[write_pos&0xfffff] = c;
++write_pos;
auto tmp = read_ready; // copy read_ready because it is accessed from multiple threads
fc::promise<void>::ptr tmp;
{ // copy read_ready because it is accessed from multiple threads
fc::scoped_lock<boost::mutex> lock( read_ready_mutex );
tmp = read_ready;
}
if( tmp && !tmp->ready() ) {
tmp->set_value();
}
std::cin.read(&c,1);
}
eof = true;
auto tmp = read_ready; // copy read_ready because it is accessed from multiple threads
fc::promise<void>::ptr tmp;
{ // copy read_ready because it is accessed from multiple threads
fc::scoped_lock<boost::mutex> lock( read_ready_mutex );
tmp = read_ready;
}
if( tmp && !tmp->ready() ) {
tmp->set_value();
}
}
boost::mutex read_ready_mutex;
fc::promise<void>::ptr read_ready;
fc::promise<void>::ptr write_ready;
@ -91,10 +103,10 @@ namespace fc {
size_t cin_t::readsome( char* buf, size_t len ) {
cin_buffer& b = get_cin_buffer();
size_t avail = b.write_pos - b.read_pos;
avail = (fc::min)(len,avail);
size_t u = 0;
while( avail && len ) {
int64_t avail = b.write_pos - b.read_pos;
avail = (fc::min)(int64_t(len),avail);
int64_t u = 0;
while( (avail>0) && (len>0) ) {
*buf = b.buf[b.read_pos&0xfffff];
++b.read_pos;
++buf;
@ -102,20 +114,36 @@ namespace fc {
--len;
++u;
}
return u;
return size_t(u);
}
cin_t::~cin_t() {
/*
cin_buffer& b = get_cin_buffer();
if( b.read_ready ) {
b.read_ready->wait();
}
*/
}
istream& cin_t::read( char* buf, size_t len ) {
cin_buffer& b = get_cin_buffer();
do {
while( !b.eof && (b.write_pos - b.read_pos)==0 ){
// wait for more...
fc::promise<void>::ptr rr( new fc::promise<void>() );
b.read_ready = rr;
// b.read_ready = rr;
{ // copy read_ready because it is accessed from multiple threads
fc::scoped_lock<boost::mutex> lock( b.read_ready_mutex );
b.read_ready = rr;
}
if( b.write_pos - b.read_pos == 0 ) {
rr->wait();
}
b.read_ready.reset();
{ // copy read_ready because it is accessed from multiple threads
fc::scoped_lock<boost::mutex> lock( b.read_ready_mutex );
b.read_ready.reset();
}
}
if( b.eof ) return *this;
size_t r = readsome( buf, len );

View file

@ -1,4 +1,5 @@
#include <fc/ip.hpp>
#include <fc/value_cast.hpp>
#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
#include <string>
@ -53,4 +54,12 @@ namespace fc { namespace ip {
return string(_ip) + ':' + fc::string(boost::lexical_cast<std::string>(_port).c_str());
}
} }
}
void pack( fc::value& v, const fc::ip::endpoint& s ) {
v = fc::string(s);
}
void unpack( const fc::value& v, fc::ip::endpoint& s ) {
s = fc::ip::endpoint::from_string(fc::value_cast<fc::string>(v));
}
}

View file

@ -6,6 +6,8 @@
#include <fc/interprocess/file_mapping.hpp>
#include <fc/error_report.hpp>
#include <map>
#include <vector>
#include <string>
namespace fc { namespace json {
@ -21,7 +23,7 @@ namespace fc { namespace json {
string(){}
string& operator=( const fc::string& s ) {
json_data = fc::vector<char>(s.begin(),s.end());
json_data = std::vector<char>(s.begin(),s.end());
return *this;
}
template<typename T>
@ -38,7 +40,7 @@ namespace fc { namespace json {
json_data = s.json_data;
return *this;
}
fc::vector<char> json_data;
std::vector<char> json_data;
};
} }
@ -444,6 +446,7 @@ struct temp_set {
* Warn on extra ',' or missing ','
*/
void read_values( fc::value::array& a, char* in, char* end, error_collector& ec ) {
if( in >= end ) return;
char* ve = 0;
char* v = read_value( in, end, ve );
while( *v == ',' ) {
@ -571,7 +574,7 @@ char* read_key_val( std::map<fc::string,fc::json::string>& obj, bool sc, char* i
temp_set ntemp(name_end,'\0');
temp_set vtemp(val_end,'\0');
//slog( "name: '%1%'", fc::string(name,name_end) );
obj[name] = fc::vector<char>(val,val_end);
obj[name] = std::vector<char>(val,val_end);
// obj.fields.push_back( key_val( name, to_value( val, val_end, ec ) ) );
return val_end;
}
@ -664,7 +667,6 @@ char* read_key_val( fc::value::object& obj, bool sc, char* in, char* end, error_
}
temp_set ntemp(name_end,'\0');
temp_set vtemp(val_end,'\0');
//slog( "name: '%1%'", fc::string(name,name_end) );
obj.fields.push_back( fc::value::key_val( name, to_value( val, val_end, ec ) ) );
return val_end;
}
@ -701,7 +703,7 @@ std::map<fc::string,fc::json::string> read_key_vals( char* in, char* end, error_
*/
fc::value to_value( fc::vector<char>&& v, error_collector& ec ) {
if( v.size() == 0 ) return fc::value();
return to_value( &v.front(), &v.front() + v.size(), ec );
return to_value( v.data(), v.data() + v.size(), ec );
}
/**
@ -945,7 +947,9 @@ fc::string pretty_print( fc::vector<char>&& v, uint8_t indent ) {
}
value from_string( const fc::string& s ) {
return from_string( s.c_str(), s.c_str() + s.size() );
std::vector<char> v(s.begin(),s.end());
//slog( "from_string( '%s' )", s.c_str() );
return from_string( v.data(), v.data()+v.size() );
}
value from_string( fc::vector<char>&& v ) {
error_collector ec;

View file

@ -80,8 +80,10 @@ namespace fc { namespace json {
send_error( id, error_object( "error report", fc::value(eo) ) );
}
} catch ( const fc::json::error_object& eo ) {
wlog( "%s", eo.message.c_str() );
send_error( id, eo );
} catch ( ... ) {
wlog( "%s", fc::except_str().c_str() );
send_error( id, error_object( fc::except_str(), fc::value() ) );
}
} else { // ignore exception + result

View file

@ -4,6 +4,8 @@
#include <fc/sstream.hpp>
#include <fc/thread.hpp>
#include <iostream>
namespace fc { namespace json {
class rpc_stream_connection::impl : public fc::retainable {
@ -32,6 +34,8 @@ namespace fc { namespace json {
fc::string line;
fc::getline( in, line );
while( !in.eof() ) {
// std::cerr<<"\n**line size: "<<line.size()<<"\n\n";
// slog( "line size: '%d'", line.size() );
try {
fc::value v= fc::json::from_string( line );
self.handle_message(v);
@ -52,10 +56,9 @@ namespace fc { namespace json {
rpc_stream_connection::rpc_stream_connection( fc::istream& i, fc::ostream& o )
:my( new impl(i,o,*this) ){
}
rpc_stream_connection::rpc_stream_connection(){ }
rpc_stream_connection::rpc_stream_connection(const rpc_stream_connection& c):my(c.my){}
rpc_stream_connection::rpc_stream_connection(){ slog( "%p...",this); }
rpc_stream_connection::rpc_stream_connection(const rpc_stream_connection& c):my(c.my){ slog( "%p",this); }
rpc_stream_connection::~rpc_stream_connection(){
// slog( "%p", my.get() );
}
// the life of the streams must exceed the life of all copies

View file

@ -15,7 +15,6 @@ namespace fc {
const char* thread_name();
void* thread_ptr();
/*
const char* short_name( const char* file_name ) {
const char* end = file_name + strlen(file_name);
--end;
@ -27,7 +26,9 @@ namespace fc {
}
return file_name;
}
*/
boost::mutex& log_mutex() {
static boost::mutex* m = new boost::mutex(); return *m;
}
#ifdef WIN32
#define isatty _isatty
@ -36,14 +37,13 @@ namespace fc {
void log( const char* color, const char* file_name, size_t line_num,
const char* method_name, const char* format, ... ) {
fc::unique_lock<boost::mutex> lock(log_mutex());
#ifndef WIN32
if(isatty(fileno(stderr)))
std::cerr<<"\r"<<color;
fprintf( stderr, "\r%s",color);
#endif
fprintf( stderr, "%-15s %-15s %-5zd %-15s ", thread_name(), fc::path(file_name).filename().generic_string().c_str(), line_num, method_name );
//std::cerr<<thread_ptr()<< thread_name()<< short_name(file_name)<< line_num<< method_name ;
fc::unique_lock<boost::mutex> lock(log_mutex());
// fc::string sname = fc::path(file_name).filename().generic_string();
fprintf( stderr, "%-15s %-15s %-5d %-15s ", thread_name(), short_name(file_name), int(line_num), method_name );
va_list args;
va_start(args,format);
vfprintf( stderr, format, args );
@ -54,6 +54,7 @@ namespace fc {
#endif
fprintf( stderr, "\n" );
fflush( stderr );
return;
}
/** used to add extra fields to be printed (thread,fiber,time,etc) */

View file

@ -1,6 +1,10 @@
#include <fc/pke.hpp>
#include <fc/error.hpp>
#include <fc/exception.hpp>
#include <fc/raw.hpp>
#include <fc/value.hpp>
#include <fc/value_cast.hpp>
#include <fc/base58.hpp>
#include <iostream>
#include <fc/sha1.hpp>
#include <openssl/rsa.h>
@ -10,6 +14,44 @@
#include <openssl/err.h>
namespace fc {
void pack( fc::value& v, const fc::public_key_t& s ) {
fc::vector<char> ve = fc::raw::pack( s );
v = to_base58( ve.data(), size_t(ve.size()) );
}
void unpack( const fc::value& v, fc::public_key_t& s ) {
try {
auto ve = from_base58(fc::value_cast<fc::string>(v));
s = fc::raw::unpack<public_key_t>(ve);
} catch ( ... ) {
wlog( "error unpacking signature" );
}
}
void pack( fc::value& v, const fc::private_key_t& s ) {
fc::vector<char> ve = fc::raw::pack( s );
v = to_base58( ve.data(), ve.size() );
}
void unpack( const fc::value& v, fc::private_key_t& s ) {
try {
auto ve = from_base58(fc::value_cast<fc::string>(v));
s = fc::raw::unpack<private_key_t>(ve);
} catch ( ... ) {
wlog( "error unpacking private_key" );
}
}
void pack( fc::value& v, const fc::signature_t& s ) {
fc::vector<char> ve = fc::raw::pack( s );
v = to_base58( ve.data(), ve.size() );
}
void unpack( const fc::value& v, fc::signature_t& s ) {
try {
auto ve = from_base58(fc::value_cast<fc::string>(v));
s = fc::raw::unpack<signature_t>(ve);
} catch ( ... ) {
wlog( "error unpacking signature" );
}
}
RSA* get_pub( const char* key, uint32_t key_size, uint32_t pe )
{
RSA* rsa = RSA_new();
@ -29,9 +71,9 @@ namespace fc {
bool verify_data( const char* key, uint32_t key_size, uint32_t pe, const sha1& digest, const char* sig )
{
RSA* pub = get_pub( key,key_size,pe);
bool v = RSA_verify( NID_sha1, (const uint8_t*)digest.data(), 20, (uint8_t*)sig, key_size, pub );
auto v = RSA_verify( NID_sha1, (const uint8_t*)digest.data(), 20, (uint8_t*)sig, key_size, pub );
RSA_free(pub);
return v;
return 0 != v;
}
bool sign_data( const fc::vector<char>& key, uint32_t key_size, uint32_t pe, const sha1& digest, char* sig )
{

View file

@ -4,14 +4,29 @@
#include <fc/asio.hpp>
#include <fc/filesystem.hpp>
#include <fc/vector.hpp>
#include <boost/process.hpp>
#include <fc/error_report.hpp>
#include <fc/value.hpp>
#include <boost/process/all.hpp>
#include <boost/iostreams/stream.hpp>
#include <cstdlib>
namespace fc {
namespace bp = boost::process;
namespace io = boost::iostreams;
fc::path find_executable_in_path( const fc::string name ) {
try {
return fc::string(bp::find_executable_in_path( std::string(name), "" ));
} catch (...) {
const char* p = std::getenv("PATH");
FC_THROW_REPORT( "Unable to find executable ${exe} in path.",
fc::value().set("exe", name)
.set("inner", fc::except_str() )
.set("PATH", fc::string(p!=nullptr?p:"") ) );
}
return fc::path();
}
class process_sink : public io::sink {
public:
struct category : io::sink::category, io::flushable_tag {};
@ -43,12 +58,13 @@ namespace fc {
try {
return static_cast<std::streamsize>(fc::asio::read_some( *m_pi, boost::asio::buffer( s, static_cast<size_t>(n) ) ));
} catch ( const boost::system::system_error& e ) {
wlog( "%s", fc::except_str().c_str() );
// wlog( "%s", fc::except_str().c_str() );
if( e.code() == boost::asio::error::eof )
return -1;
wlog( "%s", fc::except_str().c_str() );
throw;
} catch ( ... ) {
wlog( "%s", fc::except_str().c_str() );
//wlog( "%s", fc::except_str().c_str() );
return -1;
}
}
@ -74,8 +90,7 @@ FC_START_SHARED_IMPL( fc::process )
inp->close();
}
if( _exited.valid() && !_exited.ready()) {
slog( "terminate...");
child->terminate();
//child->terminate();
_exited.wait();
}
}catch(...) {
@ -132,7 +147,7 @@ fc::future<int> process::exec( const fc::path& exe, fc::vector<fc::string>&& arg
my->pctx.streams[boost::process::stdin_id] = bp::behavior::close();
std::vector<std::string> a;
a.reserve(args.size());
a.reserve(size_t(args.size()));
for( uint32_t i = 0; i < args.size(); ++i ) {
a.push_back( args[i] );
}

View file

@ -5,9 +5,12 @@
namespace fc {
retainable::retainable()
:_ref_count(1) { }
:_ref_count(1) {
static_assert( sizeof(_ref_count) == sizeof(boost::atomic<int32_t>), "failed to reserve enough space" );
}
retainable::~retainable() {
assert( _ref_count <= 0 );
assert( _ref_count == 0 );
}
void retainable::retain() {
@ -15,8 +18,8 @@ namespace fc {
}
void retainable::release() {
if( 1 == ((boost::atomic<int32_t>*)&_ref_count)->fetch_sub(1, boost::memory_order_release ) ) {
boost::atomic_thread_fence(boost::memory_order_acquire);
if( 1 == ((boost::atomic<int32_t>*)&_ref_count)->fetch_sub(1, boost::memory_order_release ) ) {
delete this;
}
}

View file

@ -478,7 +478,7 @@ namespace fc { namespace ssh {
}
}
try {
uint64_t wrote = 0;
size_t wrote = 0;
char* pos = reinterpret_cast<char*>(mr.get_address());
while( progress( wrote, fsize ) && wrote < fsize ) {
int r = libssh2_channel_write( chan, pos, fsize - wrote );
@ -800,7 +800,7 @@ namespace fc { namespace ssh {
}
bool detail::process_istream::eof()const {
return libssh2_channel_eof( proc.chan );
return 0 != libssh2_channel_eof( proc.chan );
}
ostream& detail::process_ostream::write( const char* buf, size_t len ) {

View file

@ -39,7 +39,7 @@ namespace fc {
return *this;
}
size_t stringstream::readsome( char* buf, size_t len ) {
return my->ss.readsome(buf,len);
return static_cast<size_t>(my->ss.readsome(buf,len));
}
istream& stringstream::read( char* buf, size_t len ) {
my->ss.read(buf,len);

View file

@ -12,8 +12,8 @@ namespace fc {
string::string(const char* s, int l) :my(s,l){ }
string::string(){}
string::string( const string& c ):my(c.my) { }
string::string( string&& m ):my(fc::move(m.my)) {}
string::string( const fc::string& c ):my(*c.my) { }
string::string( string&& m ):my(fc::move(*m.my)) {}
string::string( const char* c ):my(c){}
string::string( const_iterator b, const_iterator e ):my(b,e){}
string::string( const std::string& s ):my(s) {}
@ -27,16 +27,18 @@ namespace fc {
string::const_iterator string::begin()const { return my->c_str(); }
string::const_iterator string::end()const { return my->c_str() + my->size(); }
char& string::operator[](uint64_t idx) { return (*my)[idx]; }
const char& string::operator[](uint64_t idx)const { return (*my)[idx]; }
char& string::operator[](size_t idx) { return (*my)[idx]; }
const char& string::operator[](size_t idx)const { return (*my)[idx]; }
void string::reserve(uint64_t r) { my->reserve(r); }
uint64_t string::size()const { return my->size(); }
uint64_t string::find(char c, uint64_t p)const { return my->find(c,p); }
void string::reserve(size_t r) { my->reserve(r); }
size_t string::size()const { return my->size(); }
size_t string::find(char c, size_t p)const { return my->find(c,p); }
size_t string::rfind(char c, size_t p)const { return my->rfind(c,p); }
size_t string::rfind(const fc::string& c, size_t p)const { return my->rfind(c,p); }
void string::clear() { my->clear(); }
void string::resize( uint64_t s ) { my->resize(s); }
void string::resize( size_t s ) { my->resize(s); }
fc::string string::substr( int32_t start, int32_t len )const { return my->substr(start,len); }
fc::string string::substr( size_t start, size_t len )const { return my->substr(start,len); }
const char* string::c_str()const { return my->c_str(); }
bool string::operator == ( const char* s )const { return *my == s; }

View file

@ -9,9 +9,6 @@ namespace fc {
void* thread_ptr() {
return &thread::current();
}
boost::mutex& log_mutex() {
static boost::mutex m; return m;
}
thread*& current_thread() {
#ifdef _MSC_VER

View file

@ -1,5 +1,5 @@
#include <fc/url.hpp>
#include <fc/Value.hpp>
#include <fc/value.hpp>
#include <fc/error_report.hpp>
#include <fc/lexical_cast.hpp>
#include <fc/value_cast.hpp>

View file

@ -2,6 +2,7 @@
#include <fc/exception.hpp>
#include <fc/typename.hpp>
#include <string.h>
#include <fc/error_report.hpp>
namespace fc {
@ -32,6 +33,9 @@ namespace fc {
template<typename T>
struct value_holder_impl : value_holder {
static_assert( !fc::is_class<T>::value, "only fundamental types can be stored without specialization" );
value_holder_impl(){
static_assert( sizeof(value_holder_impl) <= 40, "Validate size" );
}
virtual const char* type()const { return fc::get_typename<T>::name(); }
virtual void visit( value::const_visitor&& v )const{ v(val); }
virtual void visit( value_visitor&& v ) { v(val); }
@ -53,14 +57,12 @@ namespace fc {
virtual void visit( value::const_visitor&& v )const{ v(); }
virtual void visit( value_visitor&& v ) { v(); }
// typedef void_t T;
/*
virtual const char* type()const { return "void"; }
virtual void clear() { }
virtual size_t size()const { return 0; }
// virtual const char* type()const { return "void"; }
// virtual void clear() { }
// virtual size_t size()const { return 0; }
virtual value_holder* move_helper( char* c ){ return new(c) value_holder_impl(); }
virtual value_holder* copy_helper( char* c )const{ return new(c) value_holder_impl();}
*/
virtual value_holder* move_helper( char* c ){ return new(c) value_holder_impl<void>(); }
virtual value_holder* copy_helper( char* c )const{ return new(c) value_holder_impl<void>();}
};
@ -68,7 +70,9 @@ namespace fc {
template<>
struct value_holder_impl<fc::string> : value_holder {
template<typename V>
value_holder_impl( V&& v ):val( fc::forward<V>(v) ){}
value_holder_impl( V&& v ):val( fc::forward<V>(v) ){
static_assert( sizeof(value_holder_impl<fc::string>) <= 40, "Validate size" );
}
virtual const char* type()const { return "string"; }
virtual void visit( value::const_visitor&& v )const { v(val); }
@ -124,12 +128,17 @@ namespace fc {
value::array val;
};
static_assert( sizeof( value_holder_impl<value::object> ) <= 40, "sanity check" );
static_assert( sizeof( value_holder_impl<value::array> ) <= 40, "sanity check" );
value_holder::~value_holder(){}
const char* value_holder::type()const { return "void"; }
value_holder* value_holder::move_helper( char* c ) { return new(c) value_holder(); }
value_holder* value_holder::copy_helper( char* c )const { return new(c) value_holder(); }
value_holder* value_holder::move_helper( char* c ) { return new(c) value_holder_impl<void>(); }
value_holder* value_holder::copy_helper( char* c )const { return new(c) value_holder_impl<void>(); }
void new_value_holder_void( value* v ) {
new (v) value_holder_impl<void>();
}
void value_holder::clear() {}
size_t value_holder::size()const { return 0; }
@ -150,7 +159,7 @@ namespace fc {
value_holder* value_holder_impl<value::array>::copy_helper( char* c )const{ return new(c) value_holder_impl(val); }
void value_holder_impl<value::array>::clear() { val.fields.clear(); }
size_t value_holder_impl<value::array>::size()const { return val.fields.size(); }
size_t value_holder_impl<value::array>::size()const { return static_cast<size_t>(val.fields.size()); }
void value_holder_impl<value::array>::visit( value::const_visitor&& v )const { v(val); }
void value_holder_impl<value::array>::visit( value_visitor&& v ) { v(val); }
void value_holder_impl<value::array>::push_back( value&& v ) { val.fields.push_back( fc::move(v) ); }
@ -158,19 +167,19 @@ namespace fc {
void value_holder_impl<value::object>::visit( value::const_visitor&& v )const { v(val); }
void value_holder_impl<value::object>::visit( value_visitor&& v ) { v(val); }
value_holder* value_holder_impl<value::object>::move_helper( char* c ) { return new(c) value_holder_impl( fc::move(val) ); }
value_holder* value_holder_impl<value::object>::copy_helper( char* c )const { return new(c) value_holder_impl(val); }
value_holder* value_holder_impl<value::object>::move_helper( char* c ) { return new(c) value_holder_impl<value::object>( fc::move(val) ); }
value_holder* value_holder_impl<value::object>::copy_helper( char* c )const { return new(c) value_holder_impl<value::object>(val); }
void value_holder_impl<value::object>::reserve( size_t s ) { val.fields.reserve(s); }
void value_holder_impl<value::object>::clear() { val = value::object(); }
size_t value_holder_impl<value::object>::size()const { return val.fields.size(); }
} // namespace detail
static detail::value_holder* gh( aligned<24>& h ) {
static detail::value_holder* gh( aligned<40>& h ) {
return (detail::value_holder*)h._store._data;
}
static const detail::value_holder* gh( const aligned<24>& h ) {
return (const detail::value_holder*)&h._store._data;
static const detail::value_holder* gh( const aligned<40>& h ) {
return (const detail::value_holder*)h._store._data;
}
value::value() {
@ -224,12 +233,15 @@ value::value( bool v){
new (holder) detail::value_holder_impl<bool>(v);
}
value::value( fc::string&& v){
static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl<fc::string> ), "size check" );
new (holder) detail::value_holder_impl<fc::string>(fc::move(v));
}
value::value( fc::string& v){
static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl<fc::string> ), "size check" );
new (holder) detail::value_holder_impl<fc::string>(v);
}
value::value( const fc::string& v){
static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl<fc::string> ), "size check" );
new (holder) detail::value_holder_impl<fc::string>(v);
}
value::value( value::object&& o ){
@ -276,15 +288,12 @@ value& value::operator=( const value& v ){
gh(v.holder)->copy_helper(holder);
return *this;
}
value& value::operator=( value& v ){
if( this == &v ) return *this;
gh(holder)->~value_holder();
gh(v.holder)->copy_helper(holder);
return *this;
}
bool value::is_null()const {
return strcmp(gh(holder)->type(), "void") == 0;
}
bool value::is_string()const {
return strcmp(gh(holder)->type(), "string") == 0;
}
value::object::const_iterator value::find( const char* key )const {
@ -297,40 +306,43 @@ value::object::const_iterator value::find( const char* key )const {
}
return o->val.fields.end();
}
FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() );
return nullptr;
//FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() );
return value::object::const_iterator();
}
value::object::const_iterator value::begin()const {
if( strcmp(gh(holder)->type(), "object") == 0 ) {
const detail::value_holder_impl<value::object>* o = static_cast<const detail::value_holder_impl<value::object>*>(gh(holder));
return o->val.fields.begin();
}
FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() );
return nullptr;
//// FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() );
return value::object::const_iterator();
//return nullptr;
}
value::object::const_iterator value::end()const {
if( strcmp(gh(holder)->type(), "object" ) == 0 ) {
const detail::value_holder_impl<value::object>* o = static_cast<const detail::value_holder_impl<value::object>*>(gh(holder));
return o->val.fields.end();
}
FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() );
return nullptr;
////FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() );
return value::object::const_iterator();
//return nullptr;
}
value& value::operator[]( const char* key ) {
if( strcmp(gh(holder)->type(), "object") == 0) {
detail::value_holder_impl<value::object>* o = static_cast<detail::value_holder_impl<value::object>*>(gh(holder));
detail::value_holder_impl<value::object>* o = dynamic_cast<detail::value_holder_impl<value::object>*>(gh(holder));
for( auto i = o->val.fields.begin();
i != o->val.fields.end(); ++i ) {
if( strcmp( i->key.c_str(), key ) == 0 )
return i->val;
}
o->val.fields.reserve(o->val.fields.size()+1);
o->val.fields.push_back( key_val(key) );
return o->val.fields.back().val;
} else if (strcmp(gh(holder)->type(), "void" ) == 0 ) {
new (holder) detail::value_holder_impl<value::object>(value::object());
new (gh(holder)) detail::value_holder_impl<value::object>(value::object());
return (*this)[key];
}
FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() );
FC_THROW_REPORT( "Bad cast of ${type} to object", fc::value().set("type",gh(holder)->type()) );
return *((value*)0);
}
value& value::operator[]( const fc::string& key ) { return (*this)[key.c_str()]; }

View file

@ -33,6 +33,21 @@ FC_STUB( test, (add)(namep_test)(sub)(sub1)(sub2)(sub3)(sub4)(sub5)(sub6)(sub7)(
int main( int argc, char** argv ) {
try {
slog( "Hello World\n" );
fc::value v = fc::string("goodbye");
slog(".");
fc::value v2;
slog("..");
v2["a"];
slog("........ v2[a] %p = v %p", &v2["a"], &v);
v2["a"] = v;
slog("...");
fc::value& b = v2["b"];
slog( "....");
b = fc::string("hello");
slog(".....");
return 0;
fc::ptr<test> t( new test() );
fc::json::rpc_tcp_server serv;
serv.add_interface( t );

3
vendor/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,3 @@
add_subdirectory( libssh2-1.4.2 )
add_subdirectory( zlib-1.2.7)
add_subdirectory( sigar )

48
vendor/libssh2-1.4.2/AUTHORS vendored Normal file
View file

@ -0,0 +1,48 @@
libssh2 is the result of many friendly people. This list is an attempt to
mention all contributors. If we've missed anyone, tell us!
This list of names is a-z sorted.
Adam Gobiowski
Alexander Holyapin
Alexander Lamaison
Ben Kibbey
Bjorn Stenborg
Carlo Bramini
Dan Casey
Dan Fandrich
Daniel Stenberg
David J Sullivan
David Robins
Edink Kadribasic
Erik Brossler
Francois Dupoux
Guenter Knauf
Heiner Steven
James Housleys
Jean-Louis Charton
Jussi Mononen
Mark McPherson
Markus Moeller
Mike Protts
Mikhail Gusarov
Neil Gierman
Olivier Hervieu
Paul Veldkamp
Peter Krempa
Peter O'Gorman
Peter Stuge
Romain Bondue
Sara Golemon
Satish Mittal
Sean Peterson
Selcuk Gueney
Simon Hart
Simon Josefsson
Steven Ayre
Steven Van Ingelgem
Tor Arntsen
Vincent Jaulin
Vlad Grachov
Wez Furlong
Yang Tse

28
vendor/libssh2-1.4.2/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,28 @@
include_directories(include)
include_directories( ${OPENSSL_INCLUDE_DIR} )
SET( sources
src/agent.c
src/channel.c
src/comp.c
src/crypt.c
src/global.c
src/hostkey.c
src/keepalive.c
src/kex.c
src/knownhost.c
src/libgcrypt.c
src/mac.c
src/misc.c
src/openssl.c
src/packet.c
src/pem.c
src/publickey.c
src/scp.c
src/session.c
src/sftp.c
src/transport.c
src/userauth.c
src/version.c
)
SETUP_LIBRARY( ssh2 SOURCES ${sources} LIBRARIES ${libraries} LIBRARY_TYPE STATIC )

42
vendor/libssh2-1.4.2/COPYING vendored Normal file
View file

@ -0,0 +1,42 @@
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2005,2006 Mikhail Gusarov <dottedmag@dottedmag.net>
* Copyright (c) 2006-2007 The Written Word, Inc.
* Copyright (c) 2007 Eli Fant <elifantu@mail.ru>
* Copyright (c) 2009 Daniel Stenberg
* Copyright (C) 2008, 2009 Simon Josefsson
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/

1
vendor/libssh2-1.4.2/ChangeLog vendored Normal file
View file

@ -0,0 +1 @@
see NEWS

13
vendor/libssh2-1.4.2/HACKING vendored Normal file
View file

@ -0,0 +1,13 @@
libssh2 source code style guide:
- 4 level indent
- spaces-only (no tabs)
- open braces on the if/for line:
if (banana) {
go_nuts();
}
- keep source lines shorter than 80 columns
- See libssh2-style.el for how to achieve this within Emacs

102
vendor/libssh2-1.4.2/README vendored Normal file
View file

@ -0,0 +1,102 @@
libssh2 - SSH2 library
======================
libssh2 is a library implementing the SSH2 protocol, available under
the revised BSD license.
Web site: http://www.libssh2.org/
Mailing list: http://cool.haxx.se/mailman/listinfo/libssh2-devel
The rest of this readme does not apply as the build system has been replaced
with CMake for use in mace on windows/linux and mac.
Generic installation instructions are in INSTALL. Some ./configure
options deserve additional comments:
* --enable-crypt-none
The SSH2 Transport allows for unencrypted data
transmission using the "none" cipher. Because this is
such a huge security hole, it is typically disabled on
SSH2 implementations and is disabled in libssh2 by
default as well.
Enabling this option will allow for "none" as a
negotiable method, however it still requires that the
method be advertized by the remote end and that no
more-preferable methods are available.
* --enable-mac-none
The SSH2 Transport also allows implementations to
forego a message authentication code. While this is
less of a security risk than using a "none" cipher, it
is still not recommended as disabling MAC hashes
removes a layer of security.
Enabling this option will allow for "none" as a
negotiable method, however it still requires that the
method be advertized by the remote end and that no
more-preferable methods are available.
* --disable-gex-new
The diffie-hellman-group-exchange-sha1 (dh-gex) key
exchange method originally defined an exchange
negotiation using packet type 30 to request a
generation pair based on a single target value. Later
refinement of dh-gex provided for range and target
values. By default libssh2 will use the newer range
method.
If you experience trouble connecting to an old SSH
server using dh-gex, try this option to fallback on
the older more reliable method.
* --with-libgcrypt
* --without-libgcrypt
* --with-libgcrypt-prefix=DIR
libssh2 can use the Libgcrypt library
(http://www.gnupg.org/) for cryptographic operations.
Either Libgcrypt or OpenSSL is required.
Configure will attempt to locate Libgcrypt
automatically.
If your installation of Libgcrypt is in another
location, specify it using --with-libgcrypt-prefix.
* --with-openssl
* --without-openssl
* --with-libssl-prefix=[DIR]
libssh2 can use the OpenSSL library
(http://www.openssl.org) for cryptographic operations.
Either Libgcrypt or OpenSSL is required.
Configure will attempt to locate OpenSSL in the
default location.
If your installation of OpenSSL is in another
location, specify it using --with-libssl-prefix.
* --with-libz
* --without-libz
* --with-libz-prefix=[DIR]
If present, libssh2 will attempt to use the zlib
(http://www.zlib.org) for payload compression, however
zlib is not required.
If your installation of Libz is in another location,
specify it using --with-libz-prefix.
* --enable-debug
Will make the build use more pedantic and strict compiler
options as well as enable the libssh2_trace() function (for
showing debug traces).

21
vendor/libssh2-1.4.2/RELEASE-NOTES vendored Normal file
View file

@ -0,0 +1,21 @@
libssh2 1.4.2
This release includes the following bugfixes:
o Return LIBSSH2_ERROR_SOCKET_DISCONNECT on EOF when reading banner
o userauth.c: fread() from public key file to correctly detect any errors
o configure.ac: Add option to disable build of the example applications
o Added 'Requires.private:' line to libssh2.pc
o SFTP: filter off incoming "zombie" responses
o gettimeofday: no need for a replacement under cygwin
o SSH_MSG_CHANNEL_REQUEST: default to want_reply
o win32/libssh2_config.h: Remove hardcoded #define LIBSSH2_HAVE_ZLIB
This release would not have looked like this without help, code, reports and
advice from friends like these:
Alexander Lamaison, Rafael Kitover, Guenter Knauf, Peter Stuge,
Oleksiy Zagorskyi
Thanks! (and sorry if I forgot to mention someone)

1188
vendor/libssh2-1.4.2/include/libssh2.h vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,118 @@
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
/* Note: This include file is only needed for using the
* publickey SUBSYSTEM which is not the same as publickey
* authentication. For authentication you only need libssh2.h
*
* For more information on the publickey subsystem,
* refer to IETF draft: secsh-publickey
*/
#ifndef LIBSSH2_PUBLICKEY_H
#define LIBSSH2_PUBLICKEY_H 1
#include "libssh2.h"
typedef struct _LIBSSH2_PUBLICKEY LIBSSH2_PUBLICKEY;
typedef struct _libssh2_publickey_attribute {
const char *name;
unsigned long name_len;
const char *value;
unsigned long value_len;
char mandatory;
} libssh2_publickey_attribute;
typedef struct _libssh2_publickey_list {
unsigned char *packet; /* For freeing */
const unsigned char *name;
unsigned long name_len;
const unsigned char *blob;
unsigned long blob_len;
unsigned long num_attrs;
libssh2_publickey_attribute *attrs; /* free me */
} libssh2_publickey_list;
/* Generally use the first macro here, but if both name and value are string literals, you can use _fast() to take advantage of preprocessing */
#define libssh2_publickey_attribute(name, value, mandatory) \
{ (name), strlen(name), (value), strlen(value), (mandatory) },
#define libssh2_publickey_attribute_fast(name, value, mandatory) \
{ (name), sizeof(name) - 1, (value), sizeof(value) - 1, (mandatory) },
#ifdef __cplusplus
extern "C" {
#endif
/* Publickey Subsystem */
LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session);
LIBSSH2_API int libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey,
const unsigned char *name,
unsigned long name_len,
const unsigned char *blob,
unsigned long blob_len, char overwrite,
unsigned long num_attrs,
const libssh2_publickey_attribute attrs[]);
#define libssh2_publickey_add(pkey, name, blob, blob_len, overwrite, \
num_attrs, attrs) \
libssh2_publickey_add_ex((pkey), (name), strlen(name), (blob), (blob_len), \
(overwrite), (num_attrs), (attrs))
LIBSSH2_API int libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY *pkey,
const unsigned char *name,
unsigned long name_len,
const unsigned char *blob,
unsigned long blob_len);
#define libssh2_publickey_remove(pkey, name, blob, blob_len) \
libssh2_publickey_remove_ex((pkey), (name), strlen(name), (blob), (blob_len))
LIBSSH2_API int
libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey,
unsigned long *num_keys,
libssh2_publickey_list **pkey_list);
LIBSSH2_API void libssh2_publickey_list_free(LIBSSH2_PUBLICKEY *pkey,
libssh2_publickey_list *pkey_list);
LIBSSH2_API int libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY *pkey);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* ifndef: LIBSSH2_PUBLICKEY_H */

View file

@ -0,0 +1,345 @@
/* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#ifndef LIBSSH2_SFTP_H
#define LIBSSH2_SFTP_H 1
#include "libssh2.h"
#ifndef WIN32
#include <unistd.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Note: Version 6 was documented at the time of writing
* However it was marked as "DO NOT IMPLEMENT" due to pending changes
*
* Let's start with Version 3 (The version found in OpenSSH) and go from there
*/
#define LIBSSH2_SFTP_VERSION 3
typedef struct _LIBSSH2_SFTP LIBSSH2_SFTP;
typedef struct _LIBSSH2_SFTP_HANDLE LIBSSH2_SFTP_HANDLE;
typedef struct _LIBSSH2_SFTP_ATTRIBUTES LIBSSH2_SFTP_ATTRIBUTES;
typedef struct _LIBSSH2_SFTP_STATVFS LIBSSH2_SFTP_STATVFS;
/* Flags for open_ex() */
#define LIBSSH2_SFTP_OPENFILE 0
#define LIBSSH2_SFTP_OPENDIR 1
/* Flags for rename_ex() */
#define LIBSSH2_SFTP_RENAME_OVERWRITE 0x00000001
#define LIBSSH2_SFTP_RENAME_ATOMIC 0x00000002
#define LIBSSH2_SFTP_RENAME_NATIVE 0x00000004
/* Flags for stat_ex() */
#define LIBSSH2_SFTP_STAT 0
#define LIBSSH2_SFTP_LSTAT 1
#define LIBSSH2_SFTP_SETSTAT 2
/* Flags for symlink_ex() */
#define LIBSSH2_SFTP_SYMLINK 0
#define LIBSSH2_SFTP_READLINK 1
#define LIBSSH2_SFTP_REALPATH 2
/* SFTP attribute flag bits */
#define LIBSSH2_SFTP_ATTR_SIZE 0x00000001
#define LIBSSH2_SFTP_ATTR_UIDGID 0x00000002
#define LIBSSH2_SFTP_ATTR_PERMISSIONS 0x00000004
#define LIBSSH2_SFTP_ATTR_ACMODTIME 0x00000008
#define LIBSSH2_SFTP_ATTR_EXTENDED 0x80000000
/* SFTP statvfs flag bits */
#define LIBSSH2_SFTP_ST_RDONLY 0x00000001
#define LIBSSH2_SFTP_ST_NOSUID 0x00000002
struct _LIBSSH2_SFTP_ATTRIBUTES {
/* If flags & ATTR_* bit is set, then the value in this struct will be
* meaningful Otherwise it should be ignored
*/
unsigned long flags;
libssh2_uint64_t filesize;
unsigned long uid, gid;
unsigned long permissions;
unsigned long atime, mtime;
};
struct _LIBSSH2_SFTP_STATVFS {
libssh2_uint64_t f_bsize; /* file system block size */
libssh2_uint64_t f_frsize; /* fragment size */
libssh2_uint64_t f_blocks; /* size of fs in f_frsize units */
libssh2_uint64_t f_bfree; /* # free blocks */
libssh2_uint64_t f_bavail; /* # free blocks for non-root */
libssh2_uint64_t f_files; /* # inodes */
libssh2_uint64_t f_ffree; /* # free inodes */
libssh2_uint64_t f_favail; /* # free inodes for non-root */
libssh2_uint64_t f_fsid; /* file system ID */
libssh2_uint64_t f_flag; /* mount flags */
libssh2_uint64_t f_namemax; /* maximum filename length */
};
/* SFTP filetypes */
#define LIBSSH2_SFTP_TYPE_REGULAR 1
#define LIBSSH2_SFTP_TYPE_DIRECTORY 2
#define LIBSSH2_SFTP_TYPE_SYMLINK 3
#define LIBSSH2_SFTP_TYPE_SPECIAL 4
#define LIBSSH2_SFTP_TYPE_UNKNOWN 5
#define LIBSSH2_SFTP_TYPE_SOCKET 6
#define LIBSSH2_SFTP_TYPE_CHAR_DEVICE 7
#define LIBSSH2_SFTP_TYPE_BLOCK_DEVICE 8
#define LIBSSH2_SFTP_TYPE_FIFO 9
/*
* Reproduce the POSIX file modes here for systems that are not POSIX
* compliant.
*
* These is used in "permissions" of "struct _LIBSSH2_SFTP_ATTRIBUTES"
*/
/* File type */
#define LIBSSH2_SFTP_S_IFMT 0170000 /* type of file mask */
#define LIBSSH2_SFTP_S_IFIFO 0010000 /* named pipe (fifo) */
#define LIBSSH2_SFTP_S_IFCHR 0020000 /* character special */
#define LIBSSH2_SFTP_S_IFDIR 0040000 /* directory */
#define LIBSSH2_SFTP_S_IFBLK 0060000 /* block special */
#define LIBSSH2_SFTP_S_IFREG 0100000 /* regular */
#define LIBSSH2_SFTP_S_IFLNK 0120000 /* symbolic link */
#define LIBSSH2_SFTP_S_IFSOCK 0140000 /* socket */
/* File mode */
/* Read, write, execute/search by owner */
#define LIBSSH2_SFTP_S_IRWXU 0000700 /* RWX mask for owner */
#define LIBSSH2_SFTP_S_IRUSR 0000400 /* R for owner */
#define LIBSSH2_SFTP_S_IWUSR 0000200 /* W for owner */
#define LIBSSH2_SFTP_S_IXUSR 0000100 /* X for owner */
/* Read, write, execute/search by group */
#define LIBSSH2_SFTP_S_IRWXG 0000070 /* RWX mask for group */
#define LIBSSH2_SFTP_S_IRGRP 0000040 /* R for group */
#define LIBSSH2_SFTP_S_IWGRP 0000020 /* W for group */
#define LIBSSH2_SFTP_S_IXGRP 0000010 /* X for group */
/* Read, write, execute/search by others */
#define LIBSSH2_SFTP_S_IRWXO 0000007 /* RWX mask for other */
#define LIBSSH2_SFTP_S_IROTH 0000004 /* R for other */
#define LIBSSH2_SFTP_S_IWOTH 0000002 /* W for other */
#define LIBSSH2_SFTP_S_IXOTH 0000001 /* X for other */
/* macros to check for specific file types, added in 1.2.5 */
#define LIBSSH2_SFTP_S_ISLNK(m) \
(((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFLNK)
#define LIBSSH2_SFTP_S_ISREG(m) \
(((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFREG)
#define LIBSSH2_SFTP_S_ISDIR(m) \
(((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFDIR)
#define LIBSSH2_SFTP_S_ISCHR(m) \
(((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFCHR)
#define LIBSSH2_SFTP_S_ISBLK(m) \
(((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFBLK)
#define LIBSSH2_SFTP_S_ISFIFO(m) \
(((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFIFO)
#define LIBSSH2_SFTP_S_ISSOCK(m) \
(((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFSOCK)
/* SFTP File Transfer Flags -- (e.g. flags parameter to sftp_open())
* Danger will robinson... APPEND doesn't have any effect on OpenSSH servers */
#define LIBSSH2_FXF_READ 0x00000001
#define LIBSSH2_FXF_WRITE 0x00000002
#define LIBSSH2_FXF_APPEND 0x00000004
#define LIBSSH2_FXF_CREAT 0x00000008
#define LIBSSH2_FXF_TRUNC 0x00000010
#define LIBSSH2_FXF_EXCL 0x00000020
/* SFTP Status Codes (returned by libssh2_sftp_last_error() ) */
#define LIBSSH2_FX_OK 0
#define LIBSSH2_FX_EOF 1
#define LIBSSH2_FX_NO_SUCH_FILE 2
#define LIBSSH2_FX_PERMISSION_DENIED 3
#define LIBSSH2_FX_FAILURE 4
#define LIBSSH2_FX_BAD_MESSAGE 5
#define LIBSSH2_FX_NO_CONNECTION 6
#define LIBSSH2_FX_CONNECTION_LOST 7
#define LIBSSH2_FX_OP_UNSUPPORTED 8
#define LIBSSH2_FX_INVALID_HANDLE 9
#define LIBSSH2_FX_NO_SUCH_PATH 10
#define LIBSSH2_FX_FILE_ALREADY_EXISTS 11
#define LIBSSH2_FX_WRITE_PROTECT 12
#define LIBSSH2_FX_NO_MEDIA 13
#define LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM 14
#define LIBSSH2_FX_QUOTA_EXCEEDED 15
#define LIBSSH2_FX_UNKNOWN_PRINCIPLE 16 /* Initial mis-spelling */
#define LIBSSH2_FX_UNKNOWN_PRINCIPAL 16
#define LIBSSH2_FX_LOCK_CONFlICT 17 /* Initial mis-spelling */
#define LIBSSH2_FX_LOCK_CONFLICT 17
#define LIBSSH2_FX_DIR_NOT_EMPTY 18
#define LIBSSH2_FX_NOT_A_DIRECTORY 19
#define LIBSSH2_FX_INVALID_FILENAME 20
#define LIBSSH2_FX_LINK_LOOP 21
/* Returned by any function that would block during a read/write opperation */
#define LIBSSH2SFTP_EAGAIN LIBSSH2_ERROR_EAGAIN
/* SFTP API */
LIBSSH2_API LIBSSH2_SFTP *libssh2_sftp_init(LIBSSH2_SESSION *session);
LIBSSH2_API int libssh2_sftp_shutdown(LIBSSH2_SFTP *sftp);
LIBSSH2_API unsigned long libssh2_sftp_last_error(LIBSSH2_SFTP *sftp);
LIBSSH2_API LIBSSH2_CHANNEL *libssh2_sftp_get_channel(LIBSSH2_SFTP *sftp);
/* File / Directory Ops */
LIBSSH2_API LIBSSH2_SFTP_HANDLE *libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp,
const char *filename,
unsigned int filename_len,
unsigned long flags,
long mode, int open_type);
#define libssh2_sftp_open(sftp, filename, flags, mode) \
libssh2_sftp_open_ex((sftp), (filename), strlen(filename), (flags), \
(mode), LIBSSH2_SFTP_OPENFILE)
#define libssh2_sftp_opendir(sftp, path) \
libssh2_sftp_open_ex((sftp), (path), strlen(path), 0, 0, \
LIBSSH2_SFTP_OPENDIR)
LIBSSH2_API ssize_t libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle,
char *buffer, size_t buffer_maxlen);
LIBSSH2_API int libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *handle, \
char *buffer, size_t buffer_maxlen,
char *longentry,
size_t longentry_maxlen,
LIBSSH2_SFTP_ATTRIBUTES *attrs);
#define libssh2_sftp_readdir(handle, buffer, buffer_maxlen, attrs) \
libssh2_sftp_readdir_ex((handle), (buffer), (buffer_maxlen), NULL, 0, \
(attrs))
LIBSSH2_API ssize_t libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle,
const char *buffer, size_t count);
LIBSSH2_API int libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle);
#define libssh2_sftp_close(handle) libssh2_sftp_close_handle(handle)
#define libssh2_sftp_closedir(handle) libssh2_sftp_close_handle(handle)
LIBSSH2_API void libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE *handle, size_t offset);
LIBSSH2_API void libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE *handle,
libssh2_uint64_t offset);
#define libssh2_sftp_rewind(handle) libssh2_sftp_seek64((handle), 0)
LIBSSH2_API size_t libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE *handle);
LIBSSH2_API libssh2_uint64_t libssh2_sftp_tell64(LIBSSH2_SFTP_HANDLE *handle);
LIBSSH2_API int libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE *handle,
LIBSSH2_SFTP_ATTRIBUTES *attrs,
int setstat);
#define libssh2_sftp_fstat(handle, attrs) \
libssh2_sftp_fstat_ex((handle), (attrs), 0)
#define libssh2_sftp_fsetstat(handle, attrs) \
libssh2_sftp_fstat_ex((handle), (attrs), 1)
/* Miscellaneous Ops */
LIBSSH2_API int libssh2_sftp_rename_ex(LIBSSH2_SFTP *sftp,
const char *source_filename,
unsigned int srouce_filename_len,
const char *dest_filename,
unsigned int dest_filename_len,
long flags);
#define libssh2_sftp_rename(sftp, sourcefile, destfile) \
libssh2_sftp_rename_ex((sftp), (sourcefile), strlen(sourcefile), \
(destfile), strlen(destfile), \
LIBSSH2_SFTP_RENAME_OVERWRITE | \
LIBSSH2_SFTP_RENAME_ATOMIC | \
LIBSSH2_SFTP_RENAME_NATIVE)
LIBSSH2_API int libssh2_sftp_unlink_ex(LIBSSH2_SFTP *sftp,
const char *filename,
unsigned int filename_len);
#define libssh2_sftp_unlink(sftp, filename) \
libssh2_sftp_unlink_ex((sftp), (filename), strlen(filename))
LIBSSH2_API int libssh2_sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle,
LIBSSH2_SFTP_STATVFS *st);
LIBSSH2_API int libssh2_sftp_statvfs(LIBSSH2_SFTP *sftp,
const char *path,
size_t path_len,
LIBSSH2_SFTP_STATVFS *st);
LIBSSH2_API int libssh2_sftp_mkdir_ex(LIBSSH2_SFTP *sftp,
const char *path,
unsigned int path_len, long mode);
#define libssh2_sftp_mkdir(sftp, path, mode) \
libssh2_sftp_mkdir_ex((sftp), (path), strlen(path), (mode))
LIBSSH2_API int libssh2_sftp_rmdir_ex(LIBSSH2_SFTP *sftp,
const char *path,
unsigned int path_len);
#define libssh2_sftp_rmdir(sftp, path) \
libssh2_sftp_rmdir_ex((sftp), (path), strlen(path))
LIBSSH2_API int libssh2_sftp_stat_ex(LIBSSH2_SFTP *sftp,
const char *path,
unsigned int path_len,
int stat_type,
LIBSSH2_SFTP_ATTRIBUTES *attrs);
#define libssh2_sftp_stat(sftp, path, attrs) \
libssh2_sftp_stat_ex((sftp), (path), strlen(path), LIBSSH2_SFTP_STAT, \
(attrs))
#define libssh2_sftp_lstat(sftp, path, attrs) \
libssh2_sftp_stat_ex((sftp), (path), strlen(path), LIBSSH2_SFTP_LSTAT, \
(attrs))
#define libssh2_sftp_setstat(sftp, path, attrs) \
libssh2_sftp_stat_ex((sftp), (path), strlen(path), LIBSSH2_SFTP_SETSTAT, \
(attrs))
LIBSSH2_API int libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp,
const char *path,
unsigned int path_len,
char *target,
unsigned int target_len, int link_type);
#define libssh2_sftp_symlink(sftp, orig, linkpath) \
libssh2_sftp_symlink_ex((sftp), (orig), strlen(orig), (linkpath), \
strlen(linkpath), LIBSSH2_SFTP_SYMLINK)
#define libssh2_sftp_readlink(sftp, path, target, maxlen) \
libssh2_sftp_symlink_ex((sftp), (path), strlen(path), (target), (maxlen), \
LIBSSH2_SFTP_READLINK)
#define libssh2_sftp_realpath(sftp, path, target, maxlen) \
libssh2_sftp_symlink_ex((sftp), (path), strlen(path), (target), (maxlen), \
LIBSSH2_SFTP_REALPATH)
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* LIBSSH2_SFTP_H */

BIN
vendor/libssh2-1.4.2/libssh2_debug.a vendored Normal file

Binary file not shown.

793
vendor/libssh2-1.4.2/src/agent.c vendored Normal file
View file

@ -0,0 +1,793 @@
/*
* Copyright (c) 2009 by Daiki Ueno
* Copyright (C) 2010 by Daniel Stenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#include "libssh2_priv.h"
#include "misc.h"
#include <errno.h>
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#else
/* Use the existence of sys/un.h as a test if Unix domain socket is
supported. winsock*.h define PF_UNIX/AF_UNIX but do not actually
support them. */
#undef PF_UNIX
#endif
#include "userauth.h"
#include "session.h"
/* Requests from client to agent for protocol 1 key operations */
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
#define SSH_AGENTC_RSA_CHALLENGE 3
#define SSH_AGENTC_ADD_RSA_IDENTITY 7
#define SSH_AGENTC_REMOVE_RSA_IDENTITY 8
#define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9
#define SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24
/* Requests from client to agent for protocol 2 key operations */
#define SSH2_AGENTC_REQUEST_IDENTITIES 11
#define SSH2_AGENTC_SIGN_REQUEST 13
#define SSH2_AGENTC_ADD_IDENTITY 17
#define SSH2_AGENTC_REMOVE_IDENTITY 18
#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
#define SSH2_AGENTC_ADD_ID_CONSTRAINED 25
/* Key-type independent requests from client to agent */
#define SSH_AGENTC_ADD_SMARTCARD_KEY 20
#define SSH_AGENTC_REMOVE_SMARTCARD_KEY 21
#define SSH_AGENTC_LOCK 22
#define SSH_AGENTC_UNLOCK 23
#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
/* Generic replies from agent to client */
#define SSH_AGENT_FAILURE 5
#define SSH_AGENT_SUCCESS 6
/* Replies from agent to client for protocol 1 key operations */
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
#define SSH_AGENT_RSA_RESPONSE 4
/* Replies from agent to client for protocol 2 key operations */
#define SSH2_AGENT_IDENTITIES_ANSWER 12
#define SSH2_AGENT_SIGN_RESPONSE 14
/* Key constraint identifiers */
#define SSH_AGENT_CONSTRAIN_LIFETIME 1
#define SSH_AGENT_CONSTRAIN_CONFIRM 2
/* non-blocking mode on agent connection is not yet implemented, but
for future use. */
typedef enum {
agent_NB_state_init = 0,
agent_NB_state_request_created,
agent_NB_state_request_length_sent,
agent_NB_state_request_sent,
agent_NB_state_response_length_received,
agent_NB_state_response_received
} agent_nonblocking_states;
typedef struct agent_transaction_ctx {
unsigned char *request;
size_t request_len;
unsigned char *response;
size_t response_len;
agent_nonblocking_states state;
} *agent_transaction_ctx_t;
typedef int (*agent_connect_func)(LIBSSH2_AGENT *agent);
typedef int (*agent_transact_func)(LIBSSH2_AGENT *agent,
agent_transaction_ctx_t transctx);
typedef int (*agent_disconnect_func)(LIBSSH2_AGENT *agent);
struct agent_publickey {
struct list_node node;
/* this is the struct we expose externally */
struct libssh2_agent_publickey external;
};
struct agent_ops {
agent_connect_func connect;
agent_transact_func transact;
agent_disconnect_func disconnect;
};
struct _LIBSSH2_AGENT
{
LIBSSH2_SESSION *session; /* the session this "belongs to" */
libssh2_socket_t fd;
struct agent_ops *ops;
struct agent_transaction_ctx transctx;
struct agent_publickey *identity;
struct list_head head; /* list of public keys */
};
#ifdef PF_UNIX
static int
agent_connect_unix(LIBSSH2_AGENT *agent)
{
const char *path;
struct sockaddr_un s_un;
path = getenv("SSH_AUTH_SOCK");
if (!path)
return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE,
"no auth sock variable");
agent->fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (agent->fd < 0)
return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_SOCKET,
"failed creating socket");
s_un.sun_family = AF_UNIX;
strncpy (s_un.sun_path, path, sizeof s_un.sun_path);
if (connect(agent->fd, (struct sockaddr*)(&s_un), sizeof s_un) != 0) {
close (agent->fd);
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"failed connecting with agent");
}
return LIBSSH2_ERROR_NONE;
}
static int
agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
{
unsigned char buf[4];
int rc;
/* Send the length of the request */
if (transctx->state == agent_NB_state_request_created) {
_libssh2_htonu32(buf, transctx->request_len);
rc = LIBSSH2_SEND_FD(agent->session, agent->fd, buf, sizeof buf, 0);
if (rc == -EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
else if (rc < 0)
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND,
"agent send failed");
transctx->state = agent_NB_state_request_length_sent;
}
/* Send the request body */
if (transctx->state == agent_NB_state_request_length_sent) {
rc = LIBSSH2_SEND_FD(agent->session, agent->fd, transctx->request,
transctx->request_len, 0);
if (rc == -EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
else if (rc < 0)
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND,
"agent send failed");
transctx->state = agent_NB_state_request_sent;
}
/* Receive the length of a response */
if (transctx->state == agent_NB_state_request_sent) {
rc = LIBSSH2_RECV_FD(agent->session, agent->fd, buf, sizeof buf, 0);
if (rc < 0) {
if (rc == -EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_RECV,
"agent recv failed");
}
transctx->response_len = _libssh2_ntohu32(buf);
transctx->response = LIBSSH2_ALLOC(agent->session,
transctx->response_len);
if (!transctx->response)
return LIBSSH2_ERROR_ALLOC;
transctx->state = agent_NB_state_response_length_received;
}
/* Receive the response body */
if (transctx->state == agent_NB_state_response_length_received) {
rc = LIBSSH2_RECV_FD(agent->session, agent->fd, transctx->response,
transctx->response_len, 0);
if (rc < 0) {
if (rc == -EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND,
"agent recv failed");
}
transctx->state = agent_NB_state_response_received;
}
return 0;
}
static int
agent_disconnect_unix(LIBSSH2_AGENT *agent)
{
int ret;
ret = close(agent->fd);
if(ret == -1)
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
"failed closing the agent socket");
return LIBSSH2_ERROR_NONE;
}
struct agent_ops agent_ops_unix = {
agent_connect_unix,
agent_transact_unix,
agent_disconnect_unix
};
#endif /* PF_UNIX */
#ifdef WIN32
/* Code to talk to Pageant was taken from PuTTY.
*
* Portions copyright Robert de Bath, Joris van Rantwijk, Delian
* Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas
* Barry, Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa,
* Markus Kuhn, Colin Watson, and CORE SDI S.A.
*/
#define PAGEANT_COPYDATA_ID 0x804e50ba /* random goop */
#define PAGEANT_MAX_MSGLEN 8192
static int
agent_connect_pageant(LIBSSH2_AGENT *agent)
{
HWND hwnd;
hwnd = FindWindow("Pageant", "Pageant");
if (!hwnd)
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"failed connecting agent");
agent->fd = 0; /* Mark as the connection has been established */
return LIBSSH2_ERROR_NONE;
}
static int
agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
{
HWND hwnd;
char mapname[23];
HANDLE filemap;
unsigned char *p;
unsigned char *p2;
int id;
COPYDATASTRUCT cds;
if (!transctx || 4 + transctx->request_len > PAGEANT_MAX_MSGLEN)
return _libssh2_error(agent->session, LIBSSH2_ERROR_INVAL,
"illegal input");
hwnd = FindWindow("Pageant", "Pageant");
if (!hwnd)
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"found no pageant");
sprintf(mapname, "PageantRequest%08x", (unsigned)GetCurrentThreadId());
filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
0, PAGEANT_MAX_MSGLEN, mapname);
if (filemap == NULL || filemap == INVALID_HANDLE_VALUE)
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"failed setting up pageant filemap");
p2 = p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
_libssh2_store_str(&p2, (const char *)transctx->request,
transctx->request_len);
cds.dwData = PAGEANT_COPYDATA_ID;
cds.cbData = 1 + strlen(mapname);
cds.lpData = mapname;
id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds);
if (id > 0) {
transctx->response_len = _libssh2_ntohu32(p);
if (transctx->response_len > PAGEANT_MAX_MSGLEN) {
UnmapViewOfFile(p);
CloseHandle(filemap);
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"agent setup fail");
}
transctx->response = LIBSSH2_ALLOC(agent->session,
transctx->response_len);
if (!transctx->response) {
UnmapViewOfFile(p);
CloseHandle(filemap);
return _libssh2_error(agent->session, LIBSSH2_ERROR_ALLOC,
"agent malloc");
}
memcpy(transctx->response, p + 4, transctx->response_len);
}
UnmapViewOfFile(p);
CloseHandle(filemap);
return 0;
}
static int
agent_disconnect_pageant(LIBSSH2_AGENT *agent)
{
agent->fd = LIBSSH2_INVALID_SOCKET;
return 0;
}
struct agent_ops agent_ops_pageant = {
agent_connect_pageant,
agent_transact_pageant,
agent_disconnect_pageant
};
#endif /* WIN32 */
static struct {
const char *name;
struct agent_ops *ops;
} supported_backends[] = {
#ifdef WIN32
{"Pageant", &agent_ops_pageant},
#endif /* WIN32 */
#ifdef PF_UNIX
{"Unix", &agent_ops_unix},
#endif /* PF_UNIX */
{NULL, NULL}
};
static int
agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
const unsigned char *data, size_t data_len, void **abstract)
{
LIBSSH2_AGENT *agent = (LIBSSH2_AGENT *) (*abstract);
agent_transaction_ctx_t transctx = &agent->transctx;
struct agent_publickey *identity = agent->identity;
ssize_t len = 1 + 4 + identity->external.blob_len + 4 + data_len + 4;
ssize_t method_len;
unsigned char *s;
int rc;
/* Create a request to sign the data */
if (transctx->state == agent_NB_state_init) {
s = transctx->request = LIBSSH2_ALLOC(session, len);
if (!transctx->request)
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"out of memory");
*s++ = SSH2_AGENTC_SIGN_REQUEST;
/* key blob */
_libssh2_store_str(&s, (const char *)identity->external.blob,
identity->external.blob_len);
/* data */
_libssh2_store_str(&s, (const char *)data, data_len);
/* flags */
_libssh2_store_u32(&s, 0);
transctx->request_len = s - transctx->request;
transctx->state = agent_NB_state_request_created;
}
/* Make sure to be re-called as a result of EAGAIN. */
if (*transctx->request != SSH2_AGENTC_SIGN_REQUEST)
return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
"illegal request");
if (!agent->ops)
/* if no agent has been connected, bail out */
return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
"agent not connected");
rc = agent->ops->transact(agent, transctx);
if (rc) {
goto error;
}
LIBSSH2_FREE(session, transctx->request);
transctx->request = NULL;
len = transctx->response_len;
s = transctx->response;
len--;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
if (*s != SSH2_AGENT_SIGN_RESPONSE) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
s++;
/* Skip the entire length of the signature */
len -= 4;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
s += 4;
/* Skip signing method */
len -= 4;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
method_len = _libssh2_ntohu32(s);
s += 4;
len -= method_len;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
s += method_len;
/* Read the signature */
len -= 4;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
*sig_len = _libssh2_ntohu32(s);
s += 4;
len -= *sig_len;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
*sig = LIBSSH2_ALLOC(session, *sig_len);
if (!*sig) {
rc = LIBSSH2_ERROR_ALLOC;
goto error;
}
memcpy(*sig, s, *sig_len);
error:
LIBSSH2_FREE(session, transctx->request);
transctx->request = NULL;
LIBSSH2_FREE(session, transctx->response);
transctx->response = NULL;
return _libssh2_error(session, rc, "agent sign failure");
}
static int
agent_list_identities(LIBSSH2_AGENT *agent)
{
agent_transaction_ctx_t transctx = &agent->transctx;
ssize_t len, num_identities;
unsigned char *s;
int rc;
unsigned char c = SSH2_AGENTC_REQUEST_IDENTITIES;
/* Create a request to list identities */
if (transctx->state == agent_NB_state_init) {
transctx->request = &c;
transctx->request_len = 1;
transctx->state = agent_NB_state_request_created;
}
/* Make sure to be re-called as a result of EAGAIN. */
if (*transctx->request != SSH2_AGENTC_REQUEST_IDENTITIES)
return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE,
"illegal agent request");
if (!agent->ops)
/* if no agent has been connected, bail out */
return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE,
"agent not connected");
rc = agent->ops->transact(agent, transctx);
if (rc) {
goto error;
}
transctx->request = NULL;
len = transctx->response_len;
s = transctx->response;
len--;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
if (*s != SSH2_AGENT_IDENTITIES_ANSWER) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
s++;
/* Read the length of identities */
len -= 4;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
num_identities = _libssh2_ntohu32(s);
s += 4;
while (num_identities--) {
struct agent_publickey *identity;
ssize_t comment_len;
identity = LIBSSH2_ALLOC(agent->session, sizeof *identity);
if (!identity) {
rc = LIBSSH2_ERROR_ALLOC;
goto error;
}
/* Read the length of the blob */
len -= 4;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
identity->external.blob_len = _libssh2_ntohu32(s);
s += 4;
/* Read the blob */
len -= identity->external.blob_len;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
identity->external.blob = LIBSSH2_ALLOC(agent->session,
identity->external.blob_len);
if (!identity->external.blob) {
rc = LIBSSH2_ERROR_ALLOC;
goto error;
}
memcpy(identity->external.blob, s, identity->external.blob_len);
s += identity->external.blob_len;
/* Read the length of the comment */
len -= 4;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
comment_len = _libssh2_ntohu32(s);
s += 4;
/* Read the comment */
len -= comment_len;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
identity->external.comment = LIBSSH2_ALLOC(agent->session,
comment_len + 1);
if (!identity->external.comment) {
rc = LIBSSH2_ERROR_ALLOC;
goto error;
}
identity->external.comment[comment_len] = '\0';
memcpy(identity->external.comment, s, comment_len);
s += comment_len;
_libssh2_list_add(&agent->head, &identity->node);
}
error:
LIBSSH2_FREE(agent->session, transctx->response);
transctx->response = NULL;
return _libssh2_error(agent->session, rc,
"agent list id failed");
}
static void
agent_free_identities(LIBSSH2_AGENT *agent) {
struct agent_publickey *node;
struct agent_publickey *next;
for (node = _libssh2_list_first(&agent->head); node; node = next) {
next = _libssh2_list_next(&node->node);
LIBSSH2_FREE(agent->session, node->external.blob);
LIBSSH2_FREE(agent->session, node->external.comment);
LIBSSH2_FREE(agent->session, node);
}
_libssh2_list_init(&agent->head);
}
#define AGENT_PUBLICKEY_MAGIC 0x3bdefed2
/*
* agent_publickey_to_external()
*
* Copies data from the internal to the external representation struct.
*
*/
static struct libssh2_agent_publickey *
agent_publickey_to_external(struct agent_publickey *node)
{
struct libssh2_agent_publickey *ext = &node->external;
ext->magic = AGENT_PUBLICKEY_MAGIC;
ext->node = node;
return ext;
}
/*
* libssh2_agent_init
*
* Init an ssh-agent handle. Returns the pointer to the handle.
*
*/
LIBSSH2_API LIBSSH2_AGENT *
libssh2_agent_init(LIBSSH2_SESSION *session)
{
LIBSSH2_AGENT *agent;
agent = LIBSSH2_ALLOC(session, sizeof *agent);
if (!agent) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate space for agent connection");
return NULL;
}
memset(agent, 0, sizeof *agent);
agent->session = session;
_libssh2_list_init(&agent->head);
return agent;
}
/*
* libssh2_agent_connect()
*
* Connect to an ssh-agent.
*
* Returns 0 if succeeded, or a negative value for error.
*/
LIBSSH2_API int
libssh2_agent_connect(LIBSSH2_AGENT *agent)
{
int i, rc = -1;
for (i = 0; supported_backends[i].name; i++) {
agent->ops = supported_backends[i].ops;
rc = agent->ops->connect(agent);
if (!rc)
return 0;
}
return rc;
}
/*
* libssh2_agent_list_identities()
*
* Request ssh-agent to list identities.
*
* Returns 0 if succeeded, or a negative value for error.
*/
LIBSSH2_API int
libssh2_agent_list_identities(LIBSSH2_AGENT *agent)
{
memset(&agent->transctx, 0, sizeof agent->transctx);
/* Abondon the last fetched identities */
agent_free_identities(agent);
return agent_list_identities(agent);
}
/*
* libssh2_agent_get_identity()
*
* Traverse the internal list of public keys. Pass NULL to 'prev' to get
* the first one. Or pass a poiner to the previously returned one to get the
* next.
*
* Returns:
* 0 if a fine public key was stored in 'store'
* 1 if end of public keys
* [negative] on errors
*/
LIBSSH2_API int
libssh2_agent_get_identity(LIBSSH2_AGENT *agent,
struct libssh2_agent_publickey **ext,
struct libssh2_agent_publickey *oprev)
{
struct agent_publickey *node;
if (oprev && oprev->node) {
/* we have a starting point */
struct agent_publickey *prev = oprev->node;
/* get the next node in the list */
node = _libssh2_list_next(&prev->node);
}
else
node = _libssh2_list_first(&agent->head);
if (!node)
/* no (more) node */
return 1;
*ext = agent_publickey_to_external(node);
return 0;
}
/*
* libssh2_agent_userauth()
*
* Do publickey user authentication with the help of ssh-agent.
*
* Returns 0 if succeeded, or a negative value for error.
*/
LIBSSH2_API int
libssh2_agent_userauth(LIBSSH2_AGENT *agent,
const char *username,
struct libssh2_agent_publickey *identity)
{
void *abstract = agent;
int rc;
if (agent->session->userauth_pblc_state == libssh2_NB_state_idle) {
memset(&agent->transctx, 0, sizeof agent->transctx);
agent->identity = identity->node;
}
BLOCK_ADJUST(rc, agent->session,
_libssh2_userauth_publickey(agent->session, username,
strlen(username),
identity->blob,
identity->blob_len,
agent_sign,
&abstract));
return rc;
}
/*
* libssh2_agent_disconnect()
*
* Close a connection to an ssh-agent.
*
* Returns 0 if succeeded, or a negative value for error.
*/
LIBSSH2_API int
libssh2_agent_disconnect(LIBSSH2_AGENT *agent)
{
if (agent->ops && agent->fd != LIBSSH2_INVALID_SOCKET)
return agent->ops->disconnect(agent);
return 0;
}
/*
* libssh2_agent_free()
*
* Free an ssh-agent handle. This function also frees the internal
* collection of public keys.
*/
LIBSSH2_API void
libssh2_agent_free(LIBSSH2_AGENT *agent) {
/* Allow connection freeing when the socket has lost its connection */
if (agent->fd != LIBSSH2_INVALID_SOCKET) {
libssh2_agent_disconnect(agent);
}
agent_free_identities(agent);
LIBSSH2_FREE(agent->session, agent);
}

2570
vendor/libssh2-1.4.2/src/channel.c vendored Normal file

File diff suppressed because it is too large Load diff

141
vendor/libssh2-1.4.2/src/channel.h vendored Normal file
View file

@ -0,0 +1,141 @@
#ifndef __LIBSSH2_CHANNEL_H
#define __LIBSSH2_CHANNEL_H
/* Copyright (c) 2008-2010 by Daniel Stenberg
*
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
/*
* _libssh2_channel_receive_window_adjust
*
* Adjust the receive window for a channel by adjustment bytes. If the amount
* to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
* adjustment amount will be queued for a later packet.
*
* Always non-blocking.
*/
int _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
uint32_t adjustment,
unsigned char force,
unsigned int *store);
/*
* _libssh2_channel_flush
*
* Flush data from one (or all) stream
* Returns number of bytes flushed, or negative on failure
*/
int _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid);
/*
* _libssh2_channel_free
*
* Make sure a channel is closed, then remove the channel from the session
* and free its resource(s)
*
* Returns 0 on success, negative on failure
*/
int _libssh2_channel_free(LIBSSH2_CHANNEL *channel);
int
_libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode);
/*
* _libssh2_channel_write
*
* Send data to a channel
*/
ssize_t
_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
const unsigned char *buf, size_t buflen);
/*
* _libssh2_channel_open
*
* Establish a generic session channel
*/
LIBSSH2_CHANNEL *
_libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
uint32_t channel_type_len,
uint32_t window_size,
uint32_t packet_size,
const unsigned char *message, size_t message_len);
/*
* _libssh2_channel_process_startup
*
* Primitive for libssh2_channel_(shell|exec|subsystem)
*/
int
_libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
const char *request, size_t request_len,
const char *message, size_t message_len);
/*
* _libssh2_channel_read
*
* Read data from a channel
*
* It is important to not return 0 until the currently read channel is
* complete. If we read stuff from the wire but it was no payload data to fill
* in the buffer with, we MUST make sure to return PACKET_EAGAIN.
*/
ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
char *buf, size_t buflen);
uint32_t _libssh2_channel_nextid(LIBSSH2_SESSION * session);
LIBSSH2_CHANNEL *_libssh2_channel_locate(LIBSSH2_SESSION * session,
uint32_t channel_id);
size_t _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel,
int stream_id);
int _libssh2_channel_close(LIBSSH2_CHANNEL * channel);
/*
* _libssh2_channel_forward_cancel
*
* Stop listening on a remote port and free the listener
* Toss out any pending (un-accept()ed) connections
*
* Return 0 on success, LIBSSH2_ERROR_EAGAIN if would block, -1 on error
*/
int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener);
#endif /* __LIBSSH2_CHANNEL_H */

390
vendor/libssh2-1.4.2/src/comp.c vendored Normal file
View file

@ -0,0 +1,390 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2010, Daniel Stenberg <daniel@haxx.se>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#include "libssh2_priv.h"
#ifdef LIBSSH2_HAVE_ZLIB
# include <zlib.h>
#endif
#include "comp.h"
/* ********
* none *
******** */
/*
* comp_method_none_comp
*
* Minimalist compression: Absolutely none
*/
static int
comp_method_none_comp(LIBSSH2_SESSION *session,
unsigned char *dest,
size_t *dest_len,
const unsigned char *src,
size_t src_len,
void **abstract)
{
(void) session;
(void) abstract;
(void) dest;
(void) dest_len;
(void) src;
(void) src_len;
return 0;
}
/*
* comp_method_none_decomp
*
* Minimalist decompression: Absolutely none
*/
static int
comp_method_none_decomp(LIBSSH2_SESSION * session,
unsigned char **dest,
size_t *dest_len,
size_t payload_limit,
const unsigned char *src,
size_t src_len, void **abstract)
{
(void) session;
(void) payload_limit;
(void) abstract;
*dest = (unsigned char *) src;
*dest_len = src_len;
return 0;
}
static const LIBSSH2_COMP_METHOD comp_method_none = {
"none",
0, /* not really compressing */
NULL,
comp_method_none_comp,
comp_method_none_decomp,
NULL
};
#ifdef LIBSSH2_HAVE_ZLIB
/* ********
* zlib *
******** */
/* Memory management wrappers
* Yes, I realize we're doing a callback to a callback,
* Deal...
*/
static voidpf
comp_method_zlib_alloc(voidpf opaque, uInt items, uInt size)
{
LIBSSH2_SESSION *session = (LIBSSH2_SESSION *) opaque;
return (voidpf) LIBSSH2_ALLOC(session, items * size);
}
static void
comp_method_zlib_free(voidpf opaque, voidpf address)
{
LIBSSH2_SESSION *session = (LIBSSH2_SESSION *) opaque;
LIBSSH2_FREE(session, address);
}
/* libssh2_comp_method_zlib_init
* All your bandwidth are belong to us (so save some)
*/
static int
comp_method_zlib_init(LIBSSH2_SESSION * session, int compr,
void **abstract)
{
z_stream *strm;
int status;
strm = LIBSSH2_ALLOC(session, sizeof(z_stream));
if (!strm) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"zlib compression/decompression");
}
memset(strm, 0, sizeof(z_stream));
strm->opaque = (voidpf) session;
strm->zalloc = (alloc_func) comp_method_zlib_alloc;
strm->zfree = (free_func) comp_method_zlib_free;
if (compr) {
/* deflate */
status = deflateInit(strm, Z_DEFAULT_COMPRESSION);
} else {
/* inflate */
status = inflateInit(strm);
}
if (status != Z_OK) {
LIBSSH2_FREE(session, strm);
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"unhandled zlib error %d", status);
return LIBSSH2_ERROR_COMPRESS;
}
*abstract = strm;
return LIBSSH2_ERROR_NONE;
}
/*
* libssh2_comp_method_zlib_comp
*
* Compresses source to destination. Without allocation.
*/
static int
comp_method_zlib_comp(LIBSSH2_SESSION *session,
unsigned char *dest,
/* dest_len is a pointer to allow this function to
update it with the final actual size used */
size_t *dest_len,
const unsigned char *src,
size_t src_len,
void **abstract)
{
z_stream *strm = *abstract;
int out_maxlen = *dest_len;
int status;
strm->next_in = (unsigned char *) src;
strm->avail_in = src_len;
strm->next_out = dest;
strm->avail_out = out_maxlen;
status = deflate(strm, Z_PARTIAL_FLUSH);
if (status != Z_OK) {
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"unhandled zlib compression error %d", status);
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"compression failure");
}
*dest_len = out_maxlen - strm->avail_out;
return 0;
}
/*
* libssh2_comp_method_zlib_decomp
*
* Decompresses source to destination. Allocates the output memory.
*/
static int
comp_method_zlib_decomp(LIBSSH2_SESSION * session,
unsigned char **dest,
size_t *dest_len,
size_t payload_limit,
const unsigned char *src,
size_t src_len, void **abstract)
{
z_stream *strm = *abstract;
/* A short-term alloc of a full data chunk is better than a series of
reallocs */
char *out;
int out_maxlen = 8 * src_len;
int limiter = 0;
/* If strm is null, then we have not yet been initialized. */
if (strm == NULL)
return _libssh2_error(session, LIBSSH2_ERROR_COMPRESS,
"decompression unitilized");;
/* In practice they never come smaller than this */
if (out_maxlen < 25)
out_maxlen = 25;
if (out_maxlen > (int) payload_limit)
out_maxlen = payload_limit;
strm->next_in = (unsigned char *) src;
strm->avail_in = src_len;
strm->next_out = (unsigned char *) LIBSSH2_ALLOC(session, out_maxlen);
out = (char *) strm->next_out;
strm->avail_out = out_maxlen;
if (!strm->next_out)
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate decompression buffer");
while (strm->avail_in) {
int status;
status = inflate(strm, Z_PARTIAL_FLUSH);
if (status != Z_OK) {
LIBSSH2_FREE(session, out);
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"unhandled zlib error %d", status);
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"decompression failure");
}
if (strm->avail_in) {
size_t out_ofs = out_maxlen - strm->avail_out;
char *newout;
out_maxlen += 8 * strm->avail_in;
if ((out_maxlen > (int) payload_limit) && limiter++) {
LIBSSH2_FREE(session, out);
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"Excessive growth in decompression phase");
}
newout = LIBSSH2_REALLOC(session, out, out_maxlen);
if (!newout) {
LIBSSH2_FREE(session, out);
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to expand decompression buffer");
}
out = newout;
strm->next_out = (unsigned char *) out + out_ofs;
strm->avail_out += 8 * strm->avail_in;
} else
while (!strm->avail_out) {
/* Done with input, might be a byte or two in internal buffer
* during compress. Or potentially many bytes if it's a
* decompress
*/
int grow_size = 2048;
char *newout;
if (out_maxlen >= (int) payload_limit) {
LIBSSH2_FREE(session, out);
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"Excessive growth in decompression "
"phase");
}
if (grow_size > (int) (payload_limit - out_maxlen)) {
grow_size = payload_limit - out_maxlen;
}
out_maxlen += grow_size;
strm->avail_out = grow_size;
newout = LIBSSH2_REALLOC(session, out, out_maxlen);
if (!newout) {
LIBSSH2_FREE(session, out);
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to expand final "
"decompress buffer");
}
out = newout;
strm->next_out = (unsigned char *) out + out_maxlen -
grow_size;
status = inflate(strm, Z_PARTIAL_FLUSH);
if (status != Z_OK) {
LIBSSH2_FREE(session, out);
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"unhandled zlib error %d", status);
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"decompression failure");
}
}
}
*dest = (unsigned char *) out;
*dest_len = out_maxlen - strm->avail_out;
return 0;
}
/* libssh2_comp_method_zlib_dtor
* All done, no more compression for you
*/
static int
comp_method_zlib_dtor(LIBSSH2_SESSION *session, int compr, void **abstract)
{
z_stream *strm = *abstract;
if (strm) {
if (compr)
deflateEnd(strm);
else
inflateEnd(strm);
LIBSSH2_FREE(session, strm);
}
*abstract = NULL;
return 0;
}
static const LIBSSH2_COMP_METHOD comp_method_zlib = {
"zlib",
1, /* yes, this compresses */
comp_method_zlib_init,
comp_method_zlib_comp,
comp_method_zlib_decomp,
comp_method_zlib_dtor,
};
#endif /* LIBSSH2_HAVE_ZLIB */
/* If compression is enabled by the API, then this array is used which then
may allow compression if zlib is available at build time */
static const LIBSSH2_COMP_METHOD *comp_methods[] = {
#ifdef LIBSSH2_HAVE_ZLIB
&comp_method_zlib,
#endif /* LIBSSH2_HAVE_ZLIB */
&comp_method_none,
NULL
};
/* If compression is disabled by the API, then this array is used */
static const LIBSSH2_COMP_METHOD *no_comp_methods[] = {
&comp_method_none,
NULL
};
const LIBSSH2_COMP_METHOD **
_libssh2_comp_methods(LIBSSH2_SESSION *session)
{
if(session->flag.compress)
return comp_methods;
else
return no_comp_methods;
}

45
vendor/libssh2-1.4.2/src/comp.h vendored Normal file
View file

@ -0,0 +1,45 @@
#ifndef __LIBSSH2_COMP_H
#define __LIBSSH2_COMP_H
/* Copyright (C) 2009-2010 by Daniel Stenberg
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
*/
#include "libssh2_priv.h"
const LIBSSH2_COMP_METHOD **_libssh2_comp_methods(LIBSSH2_SESSION *session);
#endif /* __LIBSSH2_COMP_H */

334
vendor/libssh2-1.4.2/src/crypt.c vendored Normal file
View file

@ -0,0 +1,334 @@
/* Copyright (c) 2009, 2010 Simon Josefsson <simon@josefsson.org>
* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#include "libssh2_priv.h"
#ifdef LIBSSH2_CRYPT_NONE
/* crypt_none_crypt
* Minimalist cipher: VERY secure *wink*
*/
static int
crypt_none_crypt(LIBSSH2_SESSION * session, unsigned char *buf,
void **abstract)
{
/* Do nothing to the data! */
return 0;
}
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_none = {
"none",
8, /* blocksize (SSH2 defines minimum blocksize as 8) */
0, /* iv_len */
0, /* secret_len */
0, /* flags */
NULL,
crypt_none_crypt,
NULL
};
#endif /* LIBSSH2_CRYPT_NONE */
struct crypt_ctx
{
int encrypt;
_libssh2_cipher_type(algo);
_libssh2_cipher_ctx h;
};
static int
crypt_init(LIBSSH2_SESSION * session,
const LIBSSH2_CRYPT_METHOD * method,
unsigned char *iv, int *free_iv,
unsigned char *secret, int *free_secret,
int encrypt, void **abstract)
{
struct crypt_ctx *ctx = LIBSSH2_ALLOC(session,
sizeof(struct crypt_ctx));
if (!ctx)
return LIBSSH2_ERROR_ALLOC;
ctx->encrypt = encrypt;
ctx->algo = method->algo;
if (_libssh2_cipher_init(&ctx->h, ctx->algo, iv, secret, encrypt)) {
LIBSSH2_FREE(session, ctx);
return -1;
}
*abstract = ctx;
*free_iv = 1;
*free_secret = 1;
return 0;
}
static int
crypt_encrypt(LIBSSH2_SESSION * session, unsigned char *block,
void **abstract)
{
struct crypt_ctx *cctx = *(struct crypt_ctx **) abstract;
(void) session;
return _libssh2_cipher_crypt(&cctx->h, cctx->algo, cctx->encrypt, block);
}
static int
crypt_dtor(LIBSSH2_SESSION * session, void **abstract)
{
struct crypt_ctx **cctx = (struct crypt_ctx **) abstract;
if (cctx && *cctx) {
_libssh2_cipher_dtor(&(*cctx)->h);
LIBSSH2_FREE(session, *cctx);
*abstract = NULL;
}
return 0;
}
#if LIBSSH2_AES_CTR
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_ctr = {
"aes128-ctr",
16, /* blocksize */
16, /* initial value length */
16, /* secret length -- 16*8 == 128bit */
0, /* flags */
&crypt_init,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_aes128ctr
};
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_ctr = {
"aes192-ctr",
16, /* blocksize */
16, /* initial value length */
24, /* secret length -- 24*8 == 192bit */
0, /* flags */
&crypt_init,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_aes192ctr
};
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_ctr = {
"aes256-ctr",
16, /* blocksize */
16, /* initial value length */
32, /* secret length -- 32*8 == 256bit */
0, /* flags */
&crypt_init,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_aes256ctr
};
#endif
#if LIBSSH2_AES
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_cbc = {
"aes128-cbc",
16, /* blocksize */
16, /* initial value length */
16, /* secret length -- 16*8 == 128bit */
0, /* flags */
&crypt_init,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_aes128
};
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_cbc = {
"aes192-cbc",
16, /* blocksize */
16, /* initial value length */
24, /* secret length -- 24*8 == 192bit */
0, /* flags */
&crypt_init,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_aes192
};
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_cbc = {
"aes256-cbc",
16, /* blocksize */
16, /* initial value length */
32, /* secret length -- 32*8 == 256bit */
0, /* flags */
&crypt_init,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_aes256
};
/* rijndael-cbc@lysator.liu.se == aes256-cbc */
static const LIBSSH2_CRYPT_METHOD
libssh2_crypt_method_rijndael_cbc_lysator_liu_se = {
"rijndael-cbc@lysator.liu.se",
16, /* blocksize */
16, /* initial value length */
32, /* secret length -- 32*8 == 256bit */
0, /* flags */
&crypt_init,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_aes256
};
#endif /* LIBSSH2_AES */
#if LIBSSH2_BLOWFISH
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_blowfish_cbc = {
"blowfish-cbc",
8, /* blocksize */
8, /* initial value length */
16, /* secret length */
0, /* flags */
&crypt_init,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_blowfish
};
#endif /* LIBSSH2_BLOWFISH */
#if LIBSSH2_RC4
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour = {
"arcfour",
8, /* blocksize */
8, /* initial value length */
16, /* secret length */
0, /* flags */
&crypt_init,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_arcfour
};
static int
crypt_init_arcfour128(LIBSSH2_SESSION * session,
const LIBSSH2_CRYPT_METHOD * method,
unsigned char *iv, int *free_iv,
unsigned char *secret, int *free_secret,
int encrypt, void **abstract)
{
int rc;
rc = crypt_init (session, method, iv, free_iv, secret, free_secret,
encrypt, abstract);
if (rc == 0) {
struct crypt_ctx *cctx = *(struct crypt_ctx **) abstract;
unsigned char block[8];
size_t discard = 1536;
for (; discard; discard -= 8)
_libssh2_cipher_crypt(&cctx->h, cctx->algo, cctx->encrypt, block);
}
return rc;
}
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour128 = {
"arcfour128",
8, /* blocksize */
8, /* initial value length */
16, /* secret length */
0, /* flags */
&crypt_init_arcfour128,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_arcfour
};
#endif /* LIBSSH2_RC4 */
#if LIBSSH2_CAST
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_cast128_cbc = {
"cast128-cbc",
8, /* blocksize */
8, /* initial value length */
16, /* secret length */
0, /* flags */
&crypt_init,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_cast5
};
#endif /* LIBSSH2_CAST */
#if LIBSSH2_3DES
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_3des_cbc = {
"3des-cbc",
8, /* blocksize */
8, /* initial value length */
24, /* secret length */
0, /* flags */
&crypt_init,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_3des
};
#endif
static const LIBSSH2_CRYPT_METHOD *_libssh2_crypt_methods[] = {
#if LIBSSH2_AES_CTR
&libssh2_crypt_method_aes128_ctr,
&libssh2_crypt_method_aes192_ctr,
&libssh2_crypt_method_aes256_ctr,
#endif /* LIBSSH2_AES */
#if LIBSSH2_AES
&libssh2_crypt_method_aes256_cbc,
&libssh2_crypt_method_rijndael_cbc_lysator_liu_se, /* == aes256-cbc */
&libssh2_crypt_method_aes192_cbc,
&libssh2_crypt_method_aes128_cbc,
#endif /* LIBSSH2_AES */
#if LIBSSH2_BLOWFISH
&libssh2_crypt_method_blowfish_cbc,
#endif /* LIBSSH2_BLOWFISH */
#if LIBSSH2_RC4
&libssh2_crypt_method_arcfour128,
&libssh2_crypt_method_arcfour,
#endif /* LIBSSH2_RC4 */
#if LIBSSH2_CAST
&libssh2_crypt_method_cast128_cbc,
#endif /* LIBSSH2_CAST */
#if LIBSSH2_3DES
&libssh2_crypt_method_3des_cbc,
#endif /* LIBSSH2_DES */
#ifdef LIBSSH2_CRYPT_NONE
&libssh2_crypt_method_none,
#endif
NULL
};
/* Expose to kex.c */
const LIBSSH2_CRYPT_METHOD **
libssh2_crypt_methods(void)
{
return _libssh2_crypt_methods;
}

118
vendor/libssh2-1.4.2/src/crypto.h vendored Normal file
View file

@ -0,0 +1,118 @@
/* Copyright (C) 2009, 2010 Simon Josefsson
* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
* Copyright (C) 2010 Daniel Stenberg
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#ifndef LIBSSH2_CRYPTO_H
#define LIBSSH2_CRYPTO_H
#ifdef LIBSSH2_LIBGCRYPT
#include "libgcrypt.h"
#else
#include "openssl.h"
#endif
int _libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
const unsigned char *edata,
unsigned long elen,
const unsigned char *ndata,
unsigned long nlen,
const unsigned char *ddata,
unsigned long dlen,
const unsigned char *pdata,
unsigned long plen,
const unsigned char *qdata,
unsigned long qlen,
const unsigned char *e1data,
unsigned long e1len,
const unsigned char *e2data,
unsigned long e2len,
const unsigned char *coeffdata, unsigned long coefflen);
int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
LIBSSH2_SESSION * session,
const char *filename,
unsigned const char *passphrase);
int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
const unsigned char *sig,
unsigned long sig_len,
const unsigned char *m, unsigned long m_len);
int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
libssh2_rsa_ctx * rsactx,
const unsigned char *hash,
size_t hash_len,
unsigned char **signature,
size_t *signature_len);
int _libssh2_dsa_new(libssh2_dsa_ctx ** dsa,
const unsigned char *pdata,
unsigned long plen,
const unsigned char *qdata,
unsigned long qlen,
const unsigned char *gdata,
unsigned long glen,
const unsigned char *ydata,
unsigned long ylen,
const unsigned char *x, unsigned long x_len);
int _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
LIBSSH2_SESSION * session,
const char *filename,
unsigned const char *passphrase);
int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
const unsigned char *sig,
const unsigned char *m, unsigned long m_len);
int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
const unsigned char *hash,
unsigned long hash_len, unsigned char *sig);
int _libssh2_cipher_init(_libssh2_cipher_ctx * h,
_libssh2_cipher_type(algo),
unsigned char *iv,
unsigned char *secret, int encrypt);
int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
_libssh2_cipher_type(algo),
int encrypt, unsigned char *block);
int _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
unsigned char **method,
size_t *method_len,
unsigned char **pubkeydata,
size_t *pubkeydata_len,
const char *privatekey,
const char *passphrase);
void _libssh2_init_aes_ctr(void);
#endif

Some files were not shown because too many files have changed in this diff Show more