Compare commits

..

11 commits

Author SHA1 Message Date
pravin-battu
b7d4e4e37b Revert "updated to editline changes, brought all updates"
This reverts commit 8fe703c35a.
2020-10-15 09:54:05 -03:00
pravin-battu
252e3df0c4 updates to include boost regex 2020-10-14 11:07:34 -03:00
pravin-battu
8fe703c35a updated to editline changes, brought all updates 2020-10-13 17:32:28 -03:00
pravin-battu
1e1a8cb30a changes to convert from readline to editline 2020-10-13 12:36:31 -03:00
Bobinson K B
fb27454cdf Merge branch 'ws-fc-updates' into 'latest-fc'
ws-updates

See merge request PBSA/PeerplaysIO/tools-libs/peerplays-fc!18
2020-08-12 13:00:39 +00:00
blockc p
917e4d348b ws-updates 2020-08-12 13:00:39 +00:00
Bobinson K B
8dd2fbe1b6 Merge branch 'issue-13-fix-websocket' into 'latest-fc'
Issue-13-fix (websocket shutdown)

See merge request PBSA/PeerplaysIO/tools-libs/peerplays-fc!17
2020-08-11 14:53:56 +00:00
Roshan Syed
b99585ca69 Added .gitlab-ci.yml 2020-07-09 13:11:09 +00:00
pravin-battu
c1e362a8dd websocket issue 2020-07-05 22:23:29 -03:00
blockc p
13b7cfaec7 Revert "websocket fix, issue 13"
This reverts commit 0cf6f461b6
2020-07-02 17:07:12 +00:00
pravin-battu
0cf6f461b6 websocket fix, issue 13 2020-07-02 13:34:29 -03:00
81 changed files with 5820 additions and 269 deletions

10
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,10 @@
include:
- template: Jobs/Code-Quality.gitlab-ci.yml
stages:
- test
trigger_build_peerplays:
stage: test
script:
- "curl -X POST -F token=$CI_JOB_TOKEN -F ref=$REF_NAME https://gitlab.com/api/v4/projects/10735589/trigger/pipeline"

View file

@ -40,7 +40,7 @@ endif()
SET (ORIGINAL_LIB_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) SET (ORIGINAL_LIB_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
SET(BOOST_COMPONENTS) SET(BOOST_COMPONENTS)
LIST(APPEND BOOST_COMPONENTS thread date_time filesystem system program_options signals serialization chrono unit_test_framework context locale iostreams) LIST(APPEND BOOST_COMPONENTS thread date_time filesystem system program_options signals serialization chrono unit_test_framework context locale iostreams regex)
SET( Boost_USE_STATIC_LIBS ON CACHE STRING "ON or OFF" ) SET( Boost_USE_STATIC_LIBS ON CACHE STRING "ON or OFF" )
IF( ECC_IMPL STREQUAL openssl ) IF( ECC_IMPL STREQUAL openssl )
@ -108,6 +108,54 @@ else ( MSVC )
endif ( MSVC ) endif ( MSVC )
# End configure secp256k1-zkp # End configure secp256k1-zkp
# Configure editline
if ( MSVC )
# autoconf won't work here, hard code the defines
set( EDITLINE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline" )
file( GLOB EDITLINE_SOURCES "${EDITLINE_DIR}/src/editline.c" )
add_library( editline ${EDITLINE_SOURCES} )
target_include_directories( editline PRIVATE "${EDITLINE_DIR}" PUBLIC "${EDITLINE_DIR}/include" )
set_target_properties( editline PROPERTIES COMPILE_DEFINITIONS LINKER_LANGUAGE C )
else ( MSVC )
include(ExternalProject)
if ( MINGW )
ExternalProject_Add( project_editline
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/editline --host=x86_64-w64-mingw32
BUILD_COMMAND make
INSTALL_COMMAND true
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline/src/project_editline-build/.libs/libeditline.a
)
else ( MINGW )
ExternalProject_Add( project_editline
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/editline
BUILD_COMMAND make
INSTALL_COMMAND true
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline/src/project_editline-build/.libs/libeditline.a
)
endif ( MINGW )
ExternalProject_Add_Step(project_editline autogen
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/autogen.sh
DEPENDERS configure
)
ExternalProject_Get_Property(project_editline binary_dir)
add_library(editline STATIC IMPORTED)
set_property(TARGET editline PROPERTY IMPORTED_LOCATION ${binary_dir}/src/.libs/libeditline${CMAKE_STATIC_LIBRARY_SUFFIX})
set_property(TARGET editline PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/include)
add_dependencies(editline project_editline)
install( FILES ${binary_dir}/src/.libs/libeditline${CMAKE_STATIC_LIBRARY_SUFFIX} DESTINATION lib/cryptonomex )
endif ( MSVC )
# End configure editline
IF( WIN32 ) IF( WIN32 )
MESSAGE(STATUS "Configuring fc to build on Win32") MESSAGE(STATUS "Configuring fc to build on Win32")
@ -258,27 +306,17 @@ add_subdirectory( vendor/websocketpp EXCLUDE_FROM_ALL )
setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC ) setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC )
install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION include ) install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION include )
# begin readline stuff # begin editline stuff
find_package(Curses)
find_package(Readline)
file(GLOB HEADERS "include/bts/cli/*.hpp")
if (READLINE_FOUND)
target_compile_definitions (fc PRIVATE HAVE_READLINE)
set(readline_libraries ${Readline_LIBRARY})
if (CURSES_FOUND)
list(APPEND readline_libraries ${CURSES_LIBRARY})
endif()
set(readline_includes ${Readline_INCLUDE_DIR})
endif()
if(WIN32) if(WIN32)
target_compile_definitions( fc PRIVATE _CRT_NONSTDC_NO_DEPRECATE ) target_compile_definitions( fc PRIVATE _CRT_NONSTDC_NO_DEPRECATE )
else(WIN32)
target_compile_definitions( fc PRIVATE HAVE_EDITLINE )
set( editline_libraries editline )
endif(WIN32) endif(WIN32)
# end readline stuff # end editline stuff
if( NOT CPP_STANDARD ) if( NOT CPP_STANDARD )
set( CPP_STANDARD, "-std=c++11" ) set( CPP_STANDARD "-std=c++11" )
endif() endif()
IF(WIN32) IF(WIN32)
@ -360,7 +398,6 @@ target_include_directories(fc
${OPENSSL_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR}
"vendor/diff-match-patch-cpp-stl" "vendor/diff-match-patch-cpp-stl"
${CMAKE_CURRENT_SOURCE_DIR}/vendor/websocketpp ${CMAKE_CURRENT_SOURCE_DIR}/vendor/websocketpp
"${readline_includes}"
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp
@ -370,7 +407,7 @@ target_include_directories(fc
IF(NOT WIN32) IF(NOT WIN32)
set(LINK_USR_LOCAL_LIB -L/usr/local/lib) set(LINK_USR_LOCAL_LIB -L/usr/local/lib)
ENDIF() ENDIF()
target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${readline_libraries} ${ECC_LIB} ) target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${editline_libraries} ${ECC_LIB} )
if(MSVC) if(MSVC)
set_source_files_properties( src/network/http/websocket.cpp PROPERTIES COMPILE_FLAGS "/bigobj" ) set_source_files_properties( src/network/http/websocket.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )

View file

@ -1,47 +0,0 @@
# - Try to find readline include dirs and libraries
#
# Usage of this module as follows:
#
# find_package(Readline)
#
# Variables used by this module, they can change the default behaviour and need
# to be set before calling find_package:
#
# Readline_ROOT_DIR Set this variable to the root installation of
# readline if the module has problems finding the
# proper installation path.
#
# Variables defined by this module:
#
# READLINE_FOUND System has readline, include and lib dirs found
# Readline_INCLUDE_DIR The readline include directories.
# Readline_LIBRARY The readline library.
find_path(Readline_ROOT_DIR
NAMES include/readline/readline.h
)
find_path(Readline_INCLUDE_DIR
NAMES readline/readline.h
HINTS ${Readline_ROOT_DIR}/include
)
find_library(Readline_LIBRARY
NAMES readline
HINTS ${Readline_ROOT_DIR}/lib
)
if(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
set(READLINE_FOUND TRUE)
else(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
FIND_LIBRARY(Readline_LIBRARY NAMES readline)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Readline DEFAULT_MSG Readline_INCLUDE_DIR Readline_LIBRARY )
MARK_AS_ADVANCED(Readline_INCLUDE_DIR Readline_LIBRARY)
endif(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
mark_as_advanced(
Readline_ROOT_DIR
Readline_INCLUDE_DIR
Readline_LIBRARY
)

View file

@ -2,7 +2,7 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <string> #include <string>
#include <fc/any.hpp> #include <boost/any.hpp>
#include <fc/network/ip.hpp> #include <fc/network/ip.hpp>
#include <fc/signals.hpp> #include <fc/signals.hpp>
@ -26,14 +26,14 @@ namespace fc { namespace http {
void on_message_handler( const std::function<void(const std::string&)>& h ) { _on_message = h; } void on_message_handler( const std::function<void(const std::string&)>& h ) { _on_message = h; }
void on_http_handler( const std::function<std::string(const std::string&)>& h ) { _on_http = h; } void on_http_handler( const std::function<std::string(const std::string&)>& h ) { _on_http = h; }
void set_session_data( fc::any d ){ _session_data = std::move(d); } void set_session_data( boost::any d ){ _session_data = std::move(d); }
fc::any& get_session_data() { return _session_data; } boost::any& get_session_data() { return _session_data; }
virtual std::string get_request_header(const std::string& key) = 0; virtual std::string get_request_header(const std::string& key) = 0;
fc::signal<void()> closed; fc::signal<void()> closed;
private: private:
fc::any _session_data; boost::any _session_data;
std::function<void(const std::string&)> _on_message; std::function<void(const std::string&)> _on_message;
std::function<string(const std::string&)> _on_http; std::function<string(const std::string&)> _on_http;
}; };
@ -53,6 +53,8 @@ namespace fc { namespace http {
uint16_t get_listening_port(); uint16_t get_listening_port();
void start_accept(); void start_accept();
void stop_listening();
void close();
private: private:
friend class detail::websocket_server_impl; friend class detail::websocket_server_impl;
std::unique_ptr<detail::websocket_server_impl> my; std::unique_ptr<detail::websocket_server_impl> my;
@ -84,6 +86,10 @@ namespace fc { namespace http {
websocket_connection_ptr connect( const std::string& uri ); websocket_connection_ptr connect( const std::string& uri );
websocket_connection_ptr secure_connect( const std::string& uri ); websocket_connection_ptr secure_connect( const std::string& uri );
void close();
void synchronous_close();
private: private:
std::unique_ptr<detail::websocket_client_impl> my; std::unique_ptr<detail::websocket_client_impl> my;
std::unique_ptr<detail::websocket_tls_client_impl> smy; std::unique_ptr<detail::websocket_tls_client_impl> smy;

View file

@ -10,7 +10,7 @@ namespace fc { namespace rpc {
class websocket_api_connection : public api_connection class websocket_api_connection : public api_connection
{ {
public: public:
websocket_api_connection( fc::http::websocket_connection& c, uint32_t max_conversion_depth ); websocket_api_connection(const std::shared_ptr<fc::http::websocket_connection> &c, uint32_t max_conversion_depth );
~websocket_api_connection(); ~websocket_api_connection();
virtual variant send_call( virtual variant send_call(
@ -29,7 +29,7 @@ namespace fc { namespace rpc {
const std::string& message, const std::string& message,
bool send_message = true ); bool send_message = true );
fc::http::websocket_connection& _connection; std::shared_ptr<fc::http::websocket_connection> _connection;
fc::rpc::state _rpc_state; fc::rpc::state _rpc_state;
}; };

View file

@ -132,14 +132,10 @@ namespace fc { namespace http {
typedef websocketpp::transport::asio::tls_socket::endpoint socket_type; typedef websocketpp::transport::asio::tls_socket::endpoint socket_type;
}; };
typedef websocketpp::transport::asio::endpoint<transport_config> typedef websocketpp::transport::asio::endpoint<transport_config> transport_type;
transport_type;
}; };
using websocketpp::connection_hdl; using websocketpp::connection_hdl;
typedef websocketpp::server<asio_with_stub_log> websocket_server_type; typedef websocketpp::server<asio_with_stub_log> websocket_server_type;
typedef websocketpp::server<asio_tls_stub_log> websocket_tls_server_type; typedef websocketpp::server<asio_tls_stub_log> websocket_tls_server_type;
@ -152,7 +148,7 @@ namespace fc { namespace http {
:_ws_connection(con){ :_ws_connection(con){
} }
~websocket_connection_impl() virtual ~websocket_connection_impl()
{ {
} }
@ -399,35 +395,26 @@ namespace fc { namespace http {
}; };
typedef websocketpp::client<asio_with_stub_log> websocket_client_type; typedef websocketpp::client<asio_with_stub_log> websocket_client_type;
typedef websocketpp::client<asio_tls_stub_log> websocket_tls_client_type; typedef websocketpp::client<asio_tls_stub_log> websocket_tls_client_type;
typedef websocket_client_type::connection_ptr websocket_client_connection_type; typedef websocket_client_type::connection_ptr websocket_client_connection_type;
typedef websocket_tls_client_type::connection_ptr websocket_tls_client_connection_type; typedef websocket_tls_client_type::connection_ptr websocket_tls_client_connection_type;
class websocket_client_impl using websocketpp::connection_hdl;
template<typename T>
class generic_websocket_client_impl
{ {
public: public:
typedef websocket_client_type::message_ptr message_ptr; generic_websocket_client_impl()
websocket_client_impl()
:_client_thread( fc::thread::current() ) :_client_thread( fc::thread::current() )
{ {
_client.clear_access_channels( websocketpp::log::alevel::all ); _client.clear_access_channels( websocketpp::log::alevel::all );
_client.set_message_handler( [&]( connection_hdl hdl, message_ptr msg ){ _client.set_message_handler( [&]( connection_hdl hdl,
typename websocketpp::client<T>::message_ptr msg ){
_client_thread.async( [&](){ _client_thread.async( [&](){
idump((msg->get_payload())); wdump((msg->get_payload()));
//std::cerr<<"recv: "<<msg->get_payload()<<"\n"; //std::cerr<<"recv: "<<msg->get_payload()<<"\n";
auto received = msg->get_payload(); auto received = msg->get_payload();
fc::async( [=](){ fc::async( [=](){
@ -453,73 +440,40 @@ namespace fc { namespace http {
_client.init_asio( &fc::asio::default_io_service() ); _client.init_asio( &fc::asio::default_io_service() );
} }
~websocket_client_impl() virtual ~generic_websocket_client_impl()
{ {
if(_connection ) if( _connection )
{ {
_connection->close(0, "client closed"); _connection->close(0, "client closed");
_connection.reset(); _connection.reset();
_closed->wait();
} }
if( _closed )
_closed->wait();
} }
fc::promise<void>::ptr _connected; fc::promise<void>::ptr _connected;
fc::promise<void>::ptr _closed; fc::promise<void>::ptr _closed;
fc::thread& _client_thread; fc::thread& _client_thread;
websocket_client_type _client; websocketpp::client<T> _client;
websocket_connection_ptr _connection; websocket_connection_ptr _connection;
std::string _uri; std::string _uri;
fc::optional<connection_hdl> _hdl;
}; };
class websocket_client_impl : public generic_websocket_client_impl<asio_with_stub_log>
{};
class websocket_tls_client_impl : public generic_websocket_client_impl<asio_tls_stub_log>
class websocket_tls_client_impl
{ {
public: public:
typedef websocket_tls_client_type::message_ptr message_ptr;
websocket_tls_client_impl( const std::string& ca_filename ) websocket_tls_client_impl( const std::string& ca_filename )
:_client_thread( fc::thread::current() ) : generic_websocket_client_impl()
{ {
// ca_filename has special values: // ca_filename has special values:
// "_none" disables cert checking (potentially insecure!) // "_none" disables cert checking (potentially insecure!)
// "_default" uses default CA's provided by OS // "_default" uses default CA's provided by OS
_client.clear_access_channels( websocketpp::log::alevel::all );
_client.set_message_handler( [&]( connection_hdl hdl, message_ptr msg ){
_client_thread.async( [&](){
idump((msg->get_payload()));
_connection->on_message( msg->get_payload() );
}).wait();
});
_client.set_close_handler( [=]( connection_hdl hdl ){
if( _connection )
{
try {
_client_thread.async( [&](){
ilog(". ${p}", ("p",uint64_t(_connection.get())));
if( !_shutting_down && !_closed && _connection )
_connection->closed();
_connection.reset();
} ).wait();
} catch ( const fc::exception& e )
{
if( _closed ) _closed->set_exception( e.dynamic_copy_exception() );
}
if( _closed ) _closed->set_value();
}
});
_client.set_fail_handler( [=]( connection_hdl hdl ){
elog( "." );
auto con = _client.get_con_from_hdl(hdl);
auto message = con->get_ec().message();
if( _connection )
_client_thread.async( [&](){ if( _connection ) _connection->closed(); _connection.reset(); } ).wait();
if( _connected && !_connected->ready() )
_connected->set_exception( exception_ptr( new FC_EXCEPTION( exception, "${message}", ("message",message)) ) );
if( _closed )
_closed->set_value();
});
// //
// We need ca_filename to be copied into the closure, as the referenced object might be destroyed by the caller by the time // We need ca_filename to be copied into the closure, as the referenced object might be destroyed by the caller by the time
// tls_init_handler() is called. According to [1], capture-by-value results in the desired behavior (i.e. creation of // tls_init_handler() is called. According to [1], capture-by-value results in the desired behavior (i.e. creation of
@ -552,18 +506,8 @@ namespace fc { namespace http {
return ctx; return ctx;
}); });
_client.init_asio( &fc::asio::default_io_service() );
}
~websocket_tls_client_impl()
{
if(_connection )
{
ilog(".");
_shutting_down = true;
_connection->close(0, "client closed");
_closed->wait();
}
} }
virtual ~websocket_tls_client_impl() {}
std::string get_host()const std::string get_host()const
{ {
@ -576,20 +520,19 @@ namespace fc { namespace http {
return; return;
ctx->set_verify_mode( boost::asio::ssl::verify_peer ); ctx->set_verify_mode( boost::asio::ssl::verify_peer );
if( ca_filename == "_default" ) if( ca_filename == "_default" )
{
#if WIN32
add_windows_root_certs( *ctx );
#else
ctx->set_default_verify_paths(); ctx->set_default_verify_paths();
#endif
}
else else
ctx->load_verify_file( ca_filename ); ctx->load_verify_file( ca_filename );
ctx->set_verify_depth(10); ctx->set_verify_depth(10);
ctx->set_verify_callback( boost::asio::ssl::rfc2818_verification( get_host() ) ); ctx->set_verify_callback( boost::asio::ssl::rfc2818_verification( get_host() ) );
} }
bool _shutting_down = false;
fc::promise<void>::ptr _connected;
fc::promise<void>::ptr _closed;
fc::thread& _client_thread;
websocket_tls_client_type _client;
websocket_connection_ptr _connection;
std::string _uri;
}; };
@ -622,8 +565,16 @@ namespace fc { namespace http {
my->_server.start_accept(); my->_server.start_accept();
} }
void websocket_server::stop_listening()
{
my->_server.stop_listening();
}
void websocket_server::close()
{
for (auto& connection : my->_connections)
my->_server.close(connection.first, websocketpp::close::status::normal, "Goodbye");
}
websocket_tls_server::websocket_tls_server( const string& server_pem, const string& ssl_password ):my( new detail::websocket_tls_server_impl(server_pem, ssl_password) ) {} websocket_tls_server::websocket_tls_server( const string& server_pem, const string& ssl_password ):my( new detail::websocket_tls_server_impl(server_pem, ssl_password) ) {}
websocket_tls_server::~websocket_tls_server(){} websocket_tls_server::~websocket_tls_server(){}
@ -646,7 +597,6 @@ namespace fc { namespace http {
my->_server.start_accept(); my->_server.start_accept();
} }
websocket_tls_client::websocket_tls_client( const std::string& ca_filename ):my( new detail::websocket_tls_client_impl( ca_filename ) ) {} websocket_tls_client::websocket_tls_client( const std::string& ca_filename ):my( new detail::websocket_tls_client_impl( ca_filename ) ) {}
websocket_tls_client::~websocket_tls_client(){ } websocket_tls_client::~websocket_tls_client(){ }
@ -659,7 +609,7 @@ namespace fc { namespace http {
{ try { { try {
if( uri.substr(0,4) == "wss:" ) if( uri.substr(0,4) == "wss:" )
return secure_connect(uri); return secure_connect(uri);
FC_ASSERT( uri.substr(0,3) == "ws:" ); FC_ASSERT( uri.substr(0,4) == "wss:" || uri.substr(0,3) == "ws:", "Unsupported protocol" );
// wlog( "connecting to ${uri}", ("uri",uri)); // wlog( "connecting to ${uri}", ("uri",uri));
websocketpp::lib::error_code ec; websocketpp::lib::error_code ec;
@ -687,7 +637,8 @@ namespace fc { namespace http {
{ try { { try {
if( uri.substr(0,3) == "ws:" ) if( uri.substr(0,3) == "ws:" )
return connect(uri); return connect(uri);
FC_ASSERT( uri.substr(0,4) == "wss:" ); FC_ASSERT( uri.substr(0,4) == "wss:" || uri.substr(0,3) == "ws:", "Unsupported protocol" );
// wlog( "connecting to ${uri}", ("uri",uri)); // wlog( "connecting to ${uri}", ("uri",uri));
websocketpp::lib::error_code ec; websocketpp::lib::error_code ec;
@ -709,6 +660,19 @@ namespace fc { namespace http {
return smy->_connection; return smy->_connection;
} FC_CAPTURE_AND_RETHROW( (uri) ) } } FC_CAPTURE_AND_RETHROW( (uri) ) }
void websocket_client::close()
{
if (my->_hdl)
my->_client.close(*my->_hdl, websocketpp::close::status::normal, "Goodbye");
}
void websocket_client::synchronous_close()
{
close();
if (my->_closed)
my->_closed->wait();
}
websocket_connection_ptr websocket_tls_client::connect( const std::string& uri ) websocket_connection_ptr websocket_tls_client::connect( const std::string& uri )
{ try { { try {
// wlog( "connecting to ${uri}", ("uri",uri)); // wlog( "connecting to ${uri}", ("uri",uri));

View file

@ -7,22 +7,8 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
#ifdef HAVE_READLINE #ifdef HAVE_EDITLINE
# include <readline/readline.h> # include "editline.h"
# include <readline/history.h>
// I don't know exactly what version of readline we need. I know the 4.2 version that ships on some macs is
// missing some functions we require. We're developing against 6.3, but probably anything in the 6.x
// series is fine
# if RL_VERSION_MAJOR < 6
# ifdef _MSC_VER
# pragma message("You have an old version of readline installed that might not support some of the features we need")
# pragma message("Readline support will not be compiled in")
# else
# warning "You have an old version of readline installed that might not support some of the features we need"
# warning "Readline support will not be compiled in"
# endif
# undef HAVE_READLINE
# endif
# ifdef WIN32 # ifdef WIN32
# include <io.h> # include <io.h>
# endif # endif
@ -131,61 +117,90 @@ void cli::run()
} }
char * dupstr (const char* s) { /****
char *r; * @brief loop through list of commands, attempting to find a match
* @param token what the user typed
r = (char*) malloc ((strlen (s) + 1)); * @param match sets to 1 if only 1 match was found
strcpy (r, s); * @returns the remaining letters of the name of the command or NULL if 1 match not found
return (r); */
} static char *my_rl_complete(char *token, int *match)
char* my_generator(const char* text, int state)
{ {
static int list_index, len; bool have_one = false;
const char *name; std::string method_name;
if (!state) {
list_index = 0;
len = strlen (text);
}
auto& cmd = cli_commands(); auto& cmd = cli_commands();
int partlen = strlen (token); /* Part of token */
while( list_index < cmd.size() ) for (const std::string& it : cmd)
{ {
name = cmd[list_index].c_str(); if (it.compare(0, partlen, token) == 0)
list_index++; {
if (have_one) {
if (strncmp (name, text, len) == 0) // we can only have 1, but we found a second
return (dupstr(name)); return NULL;
}
else
{
method_name = it;
have_one = true;
}
}
} }
/* If no names matched, then return NULL. */ if (have_one)
return ((char *)NULL); {
*match = 1;
method_name += " ";
return strdup (method_name.c_str() + partlen);
}
return NULL;
} }
/***
static char** cli_completion( const char * text , int start, int end) * @brief return an array of matching commands
* @param token the incoming text
* @param array the resultant array of possible matches
* @returns the number of matches
*/
static int cli_completion(char *token, char ***array)
{ {
char **matches; auto& cmd = cli_commands();
matches = (char **)NULL; int num_commands = cmd.size();
#ifdef HAVE_READLINE char **copy = (char **) malloc (num_commands * sizeof(char *));
if (start == 0) if (copy == NULL)
matches = rl_completion_matches ((char*)text, &my_generator); {
else // possible out of memory
rl_bind_key('\t',rl_abort); return 0;
#endif }
int total_matches = 0;
return (matches); int partlen = strlen(token);
for (const std::string& it : cmd)
{
if ( it.compare(0, partlen, token) == 0)
{
copy[total_matches] = strdup ( it.c_str() );
++total_matches;
}
}
*array = copy;
return total_matches;
} }
/***
* @brief Read input from the user
* @param prompt the prompt to display
* @param line what the user typed
*/
void cli::getline( const fc::string& prompt, fc::string& line) void cli::getline( const fc::string& prompt, fc::string& line)
{ {
// getting file descriptor for C++ streams is near impossible // getting file descriptor for C++ streams is near impossible
// so we just assume it's the same as the C stream... // so we just assume it's the same as the C stream...
#ifdef HAVE_READLINE #ifdef HAVE_EDITLINE
#ifndef WIN32 #ifndef WIN32
if( isatty( fileno( stdin ) ) ) if( isatty( fileno( stdin ) ) )
#else #else
@ -197,8 +212,9 @@ void cli::getline( const fc::string& prompt, fc::string& line)
if( _isatty( _fileno( stdin ) ) ) if( _isatty( _fileno( stdin ) ) )
#endif #endif
{ {
rl_attempted_completion_function = cli_completion; rl_set_complete_func(my_rl_complete);
rl_set_list_possib_func(cli_completion);
jjkkljk;
static fc::thread getline_thread("getline"); static fc::thread getline_thread("getline");
getline_thread.async( [&](){ getline_thread.async( [&](){
char* line_read = nullptr; char* line_read = nullptr;
@ -206,10 +222,17 @@ void cli::getline( const fc::string& prompt, fc::string& line)
line_read = readline(prompt.c_str()); line_read = readline(prompt.c_str());
if( line_read == nullptr ) if( line_read == nullptr )
FC_THROW_EXCEPTION( fc::eof_exception, "" ); FC_THROW_EXCEPTION( fc::eof_exception, "" );
rl_bind_key( '\t', rl_complete );
if( *line_read )
add_history(line_read);
line = line_read; line = line_read;
try
{
if (*line_read)
add_history(line_read);
}
catch(...)
{
free(line_read);
throw;
}
free(line_read); free(line_read);
}).wait(); }).wait();
} }

View file

@ -7,7 +7,7 @@ websocket_api_connection::~websocket_api_connection()
{ {
} }
websocket_api_connection::websocket_api_connection( fc::http::websocket_connection& c, uint32_t max_depth ) websocket_api_connection::websocket_api_connection(const std::shared_ptr<fc::http::websocket_connection>& c, uint32_t max_depth )
: api_connection(max_depth),_connection(c) : api_connection(max_depth),_connection(c)
{ {
_rpc_state.add_method( "call", [this]( const variants& args ) -> variant _rpc_state.add_method( "call", [this]( const variants& args ) -> variant
@ -47,9 +47,12 @@ websocket_api_connection::websocket_api_connection( fc::http::websocket_connecti
return this->receive_call( 0, method_name, args ); return this->receive_call( 0, method_name, args );
} ); } );
_connection.on_message_handler( [&]( const std::string& msg ){ on_message(msg,true); } ); _connection->on_message_handler( [&]( const std::string& msg ){ on_message(msg,true); } );
_connection.on_http_handler( [&]( const std::string& msg ){ return on_message(msg,false); } ); _connection->on_http_handler( [&]( const std::string& msg ){ return on_message(msg,false); } );
_connection.closed.connect( [this](){ closed(); } ); _connection->closed.connect( [this](){
closed();
_connection = nullptr;
} );
} }
variant websocket_api_connection::send_call( variant websocket_api_connection::send_call(
@ -58,7 +61,7 @@ variant websocket_api_connection::send_call(
variants args /* = variants() */ ) variants args /* = variants() */ )
{ {
auto request = _rpc_state.start_remote_call( "call", {api_id, std::move(method_name), std::move(args) } ); auto request = _rpc_state.start_remote_call( "call", {api_id, std::move(method_name), std::move(args) } );
_connection.send_message( fc::json::to_string(fc::variant(request, _max_conversion_depth), _connection->send_message( fc::json::to_string(fc::variant(request, _max_conversion_depth),
fc::json::stringify_large_ints_and_doubles, _max_conversion_depth ) ); fc::json::stringify_large_ints_and_doubles, _max_conversion_depth ) );
return _rpc_state.wait_for_response( *request.id ); return _rpc_state.wait_for_response( *request.id );
} }
@ -68,7 +71,7 @@ variant websocket_api_connection::send_callback(
variants args /* = variants() */ ) variants args /* = variants() */ )
{ {
auto request = _rpc_state.start_remote_call( "callback", {callback_id, std::move(args) } ); auto request = _rpc_state.start_remote_call( "callback", {callback_id, std::move(args) } );
_connection.send_message( fc::json::to_string(fc::variant(request, _max_conversion_depth), _connection->send_message( fc::json::to_string(fc::variant(request, _max_conversion_depth),
fc::json::stringify_large_ints_and_doubles, _max_conversion_depth ) ); fc::json::stringify_large_ints_and_doubles, _max_conversion_depth ) );
return _rpc_state.wait_for_response( *request.id ); return _rpc_state.wait_for_response( *request.id );
} }
@ -78,7 +81,7 @@ void websocket_api_connection::send_notice(
variants args /* = variants() */ ) variants args /* = variants() */ )
{ {
fc::rpc::request req{ optional<uint64_t>(), "notice", {callback_id, std::move(args)}}; fc::rpc::request req{ optional<uint64_t>(), "notice", {callback_id, std::move(args)}};
_connection.send_message( fc::json::to_string(fc::variant(req, _max_conversion_depth), _connection->send_message( fc::json::to_string(fc::variant(req, _max_conversion_depth),
fc::json::stringify_large_ints_and_doubles, _max_conversion_depth ) ); fc::json::stringify_large_ints_and_doubles, _max_conversion_depth ) );
} }
@ -118,7 +121,7 @@ std::string websocket_api_connection::on_message(
{ {
auto reply = fc::json::to_string( response( *call.id, result, "2.0" ), fc::json::stringify_large_ints_and_doubles, _max_conversion_depth ); auto reply = fc::json::to_string( response( *call.id, result, "2.0" ), fc::json::stringify_large_ints_and_doubles, _max_conversion_depth );
if( send_message ) if( send_message )
_connection.send_message( reply ); _connection->send_message( reply );
return reply; return reply;
} }
} }
@ -136,7 +139,7 @@ std::string websocket_api_connection::on_message(
auto reply = fc::json::to_string( variant(response( *call.id, error_object{ 1, optexcept->to_string(), fc::variant(*optexcept, _max_conversion_depth)}, "2.0" ), _max_conversion_depth ), auto reply = fc::json::to_string( variant(response( *call.id, error_object{ 1, optexcept->to_string(), fc::variant(*optexcept, _max_conversion_depth)}, "2.0" ), _max_conversion_depth ),
fc::json::stringify_large_ints_and_doubles, _max_conversion_depth ); fc::json::stringify_large_ints_and_doubles, _max_conversion_depth );
if( send_message ) if( send_message )
_connection.send_message( reply ); _connection->send_message( reply );
return reply; return reply;
} }

View file

@ -61,7 +61,7 @@ int main( int argc, char** argv )
fc::http::websocket_server server; fc::http::websocket_server server;
server.on_connection([&]( const websocket_connection_ptr& c ){ server.on_connection([&]( const websocket_connection_ptr& c ){
auto wsc = std::make_shared<websocket_api_connection>(*c, MAX_DEPTH); auto wsc = std::make_shared<websocket_api_connection>(c, MAX_DEPTH);
auto login = std::make_shared<login_api>(); auto login = std::make_shared<login_api>();
login->calc = calc_api; login->calc = calc_api;
wsc->register_api(fc::api<login_api>(login)); wsc->register_api(fc::api<login_api>(login));
@ -76,7 +76,7 @@ int main( int argc, char** argv )
try { try {
fc::http::websocket_client client; fc::http::websocket_client client;
auto con = client.connect( "ws://localhost:8090" ); auto con = client.connect( "ws://localhost:8090" );
auto apic = std::make_shared<websocket_api_connection>(*con, MAX_DEPTH); auto apic = std::make_shared<websocket_api_connection>(con, MAX_DEPTH);
auto remote_login_api = apic->get_remote_api<login_api>(); auto remote_login_api = apic->get_remote_api<login_api>();
auto remote_calc = remote_login_api->get_calc(); auto remote_calc = remote_login_api->get_calc();
remote_calc->on_result( []( uint32_t r ) { elog( "callback result ${r}", ("r",r) ); } ); remote_calc->on_result( []( uint32_t r ) { elog( "callback result ${r}", ("r",r) ); } );

29
vendor/editline/.gitignore vendored Normal file
View file

@ -0,0 +1,29 @@
*~
*/.libs/
*.lo
*.o
*.pc
.deps
.testit_history
GPATH
GRTAGS
GTAGS
Makefile
Makefile.in
aclocal.m4
archive
autom4te.cache
compile
config.guess
config.h
config.h.in
config.log
config.status
config.sub
configure
depcomp
install-sh
libtool
ltmain.sh
missing
stamp-h1

34
vendor/editline/.travis.yml vendored Normal file
View file

@ -0,0 +1,34 @@
# Travis CI integration
# Defaults to GNU GCC and autotools: ./configure && make && make test
language: c
# We don't need to install packages, use dockerized build, quicker
sudo: false
# Test build with both GCC and Clang (LLVM)
compiler:
- gcc
- clang
env:
global:
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
# via the "travis encrypt" command using the project repo's public key
- secure: "iFll6pD0lzVYVRUlbPBGOTB0xqoEsC0BeUdftfRQdnEssruWOEKtf3VH6gSNRu8QMPeTCNhl4fsWUJhnowZgoobi/XcsXxFv/oJQZ1sa7cQUXizeEYUmsDZxUiw/sNsWlUz6dBKPepQStYyOK/tJLQ1GfLi1ESTPt6anokMVDbk="
addons:
coverity_scan:
project:
name: "troglobit/editline"
description: "A small line editing library"
notification_email: troglobit@gmail.com
build_command_prepend: "./autogen.sh && ./configure --enable-sigstop --enable-terminal-bell"
build_command: "make -j5"
branch_pattern: dev
# We don't store generated files (configure and Makefile) in GIT,
# so we must customize the default build script to run ./autogen.sh
script:
- ./autogen.sh
- ./configure --enable-sigstop --enable-terminal-bell
- make -j5

241
vendor/editline/ChangeLog.md vendored Normal file
View file

@ -0,0 +1,241 @@
Change Log
==========
All notable changes to the project are documented in this file.
[1.16.1][UNRELEASED]
--------------------
### Changes
- Major updates to the `editline.3` man page
### Fixes
- Fix #20: `configure --disable-eof` does not bite
- Fix #23: Make Ctrl-L clear the screan instead of starting a new line
- Fix #24: Fix behavior when TTY is narrower than column width, by Will Dietz
[1.16.0][] - 2018-09-16
-----------------------
Event loop callback support.
### Changes
- `rl_unintialize()`, new function to free all memory, by Claus Fischer
- `rl_insert_text()`, new GNU Readline compat function
- `rl_refresh_line()`, new GNU Readline compat function
- `rl_callback_*()`, alternate interface to plain `readline()` for event
loops. Modeled after the GNU Readline API
- `rl_completion_entry_function`, and `rl_attempted_completion_function`
are two new GNU Readline compat user hooks for the completion framework
- `rl_completion_matches()` and `rl_filename_completion_function()`
are two new GNU Readline compat functions
- Add new example: `fileman.c` from GNU Readline to demonstrate the
level of compatibility of the revamped completion framework
- Add support for Ctrl-Right and Ctrl-Left, forward/backward word
- Add .deb package to official release target
### Fixes
- Fixed header guards, avoid using leading `__`
- Spell check fixes
- Remove duplicate code in history check
- Use `NULL` instead of `0`, and `-1` instead of `NULL`, where applicable
- Misc. minor Coverity Scan fixes
- Misc. minor fixes to `testit.c` example code
- Add `-Wextra` to std `CFLAGS`
- Check `fclose()` return value in in `write_history()` and `read_history()`
- Initialize global variables and reset to `NULL` on `free()`
- Fix off-by-one in forward kill word, avoid deleting too much
- Skip (or kill) leading whitespace when skipping (or killing) forwards
[1.15.3][] - 2017-09-07
-----------------------
Bug fix release.
### Changes
- Refactor all enable/disable configure options, same problem as in #7
### Fixes
- Fix #7: `--enable-termcap` configure option does not work. The script
enabled termcap by default rather than the other way around.
Also, check for terminfo as well, when `--enable-termcap` is selected.
[1.15.2][] - 2016-06-06
-----------------------
Bug fixes and minor feature creep in `pkg-config` support.
### Changes
- Prevent mangling of symbols when linking with C++. Patch courtesy of
Jakub Pawlowski
- Add `libeditline.pc` for `pkg-config`
### Fixes
- Do not assume a termcap library exists, check for `tgetent()` in
curses, ncurses, tinfo and termcap libraries
- Call `tty_flush()` when user calls `rl_forced_update_display()`
to prevent screen becoming garbled. Patch by Jakub Pawlowski
[1.15.1][] - 2015-11-16
-----------------------
Bug fixes only.
### Changes
- Update README with origin of this version of editline
### Fixes
- Fix build system, don't force automake v1.11, require at least v1.11
- Fix build problem with examples using `--enable-termcap`
[1.15.0][] - 2015-09-10
-----------------------
### Changes
- Add support for `--disable-eof` and `--disable-sigint` to disable
default Ctrl-D and Ctrl-C behavior
- Add support for `el_no_hist` to disable access to and auto-save of history
- GNU readline compat functions for prompt handling and redisplay
- Refactor: replace variables named 'new' with non-reserved word
- Add support for [Travis-CI][], continuous integration with GitHub
- Add support for [Coverity Scan][], the best static code analyzer,
integrated with [Travis-CI][] -- scan runs for each push to master
- Rename NEWS.md --> ChangeLog.md, with symlinks for <kbd>make install</kbd>
- Attempt to align with http://keepachangelog.com/ for this file
- Cleanup and improve Markdown syntax in [README.md][]
- Add API and example to [README.md][], inspired by [libuEv][]
- Removed generated files from version control. Use `./autogen.sh`
to generate the `configure` script when working from GIT. This
does not affect distributed tarballs
### Fixes
- Fix issue #2, regression in Ctrl-D (EOF) behavior. Regression
introduced in [1.14.1][]. Fixed by @TobyGoodwin
- Fix memory leak in completion handler. Found by [Coverity Scan][].
- Fix suspicious use of `sizeof(char **)`, same as `sizeof(char *)` but
non-portable. Found by [Coverity Scan][]
- Fix out-of-bounds access in user key binding routines
Found by [Coverity Scan][].
- Fix invisible example code in man page
[1.14.2][] - 2014-09-14
-----------------------
Bug fixes only.
### Fixes
- Fix `el_no_echo` bug causing secrets to leak when disabling no-echo
- Handle `EINTR` in syscalls better
[1.14.1][] - 2014-09-14
-----------------------
Minor fixes and additions.
### Changes
- Don't print status message on `stderr` in key binding funcions
- Export `el_del_char()`
- Check for and return pending signals when detected
- Allow custom key bindings ...
### Fixes
- Bug fixes ...
[1.14.0][] - 2010-08-10
-----------------------
Major cleanups and further merges with Debian editline package.
### Changes
- Merge in changes to `debian/` from `editline_1.12-6.debian.tar.gz`
- Migrate to use libtool
- Make `UNIQUE_HISTORY` configurable
- Make scrollback history (`HIST_SIZE`) configurable
- Configure options for toggling terminal bell and `SIGSTOP` (Ctrl-Z)
- Configure option for using termcap to read/control terminal size
- Rename Signal to `el_intr_pending`, from Festival speech-tools
- Merge support for capitalizing words (`M-c`) from Festival
speech-tools by Alan W Black <mailto:awb()cstr!ed!ac!uk>
- Fallback backspace handling, in case `tgetstr("le")` fails
### Fixes
- Cleanups and fixes thanks to the Sparse static code analysis tool
- Merge `el_no_echo` patch from Festival speech-tools
- Merge fixes from Heimdal project
- Completely refactor `rl_complete()` and `rl_list_possib()` with
fixes from the Heimdal project. Use `rl_set_complete_func()` and
`rl_set_list_possib_func()`. Default completion callbacks are now
available as a configure option `--enable-default-complete`
- Memory leak fixes
- Actually fix 8-bit handling by reverting old Debian patch
- Merge patch to improve compatibility with GNU readline, thanks to
Steve Tell from way back in 1997 and 1998
[1.13.0][] - 2010-03-09
-----------------------
Adaptations to Debian editline package.
### Changes
- Major version number bump, adapt to Jim Studt's v1.12
- Import `debian/` directory and adapt it to configure et al.
- Change library name to libeditline to distinguish it from BSD libedit
[0.3.0][] - 2009-02-08
----------------------
### Changes
- Support for ANSI arrow keys using <kbd>configure --enable-arrow-keys</kbd>
[0.2.3][] - 2008-12-02
----------------------
### Changes
- Patches from Debian package merged
- Support for custom command completion
[0.1.0][] - 2008-06-07
----------------------
### Changes
- First version, forked from Minix current 2008-06-06
[UNRELEASED]: https://github.com/troglobit/finit/compare/1.16.0...HEAD
[1.16.1]: https://github.com/troglobit/finit/compare/1.16.0...1.16.1
[1.16.0]: https://github.com/troglobit/finit/compare/1.15.3...1.16.0
[1.15.3]: https://github.com/troglobit/finit/compare/1.15.2...1.15.3
[1.15.2]: https://github.com/troglobit/finit/compare/1.15.1...1.15.2
[1.15.1]: https://github.com/troglobit/finit/compare/1.15.0...1.15.1
[1.15.0]: https://github.com/troglobit/finit/compare/1.14.2...1.15.0
[1.14.2]: https://github.com/troglobit/finit/compare/1.14.1...1.14.2
[1.14.1]: https://github.com/troglobit/finit/compare/1.14.0...1.14.1
[1.14.0]: https://github.com/troglobit/finit/compare/1.13.0...1.14.0
[1.13.0]: https://github.com/troglobit/finit/compare/0.3.0...1.13.0
[0.3.0]: https://github.com/troglobit/finit/compare/0.2.3...0.3.0
[0.2.3]: https://github.com/troglobit/finit/compare/0.1.0...0.2.3
[0.1.0]: https://github.com/troglobit/finit/compare/0.0.0...0.1.0
[libuEv]: http://github.com/troglobit/libuev
[Travis-CI]: https://travis-ci.org/troglobit/uftpd
[Coverity Scan]: https://scan.coverity.com/projects/2947
[README.md]: https://github.com/troglobit/editline/blob/master/README.md
<!--
-- Local Variables:
-- mode: markdown
-- End:
-->

46
vendor/editline/INSTALL.md vendored Normal file
View file

@ -0,0 +1,46 @@
HowTo Build Minix Editline
==========================
Minix editline use the GNU configure tools, which includes autoconf,
automake and libtool. This enables high levels of portability and ease
of use. In most cases all you need to do is unpack the tarball, enter
the directory and type:
./configure
There are are, however, more options available. For instance, sometimes
it is useful to build editline as a static library, type:
./configure --disable-shared
By default editline employs a default handler for the TAB key, pressing
it once completes to the nearest matching filename in the current
working directory, or it can display a listing of possible completions.
For some uses this default is not desirable at all, type:
./configure --disable-default-complete
An even more common desire is to change the default install location.
By default all configure scripts setup /usr/local as the install
"prefix", to change this type:
./configure --prefix=/home/troglobit/tmp
Advanced users are encouraged to read up on --libdir, --mandir, etc. in
the GNU Configure and Build System.
For more available options, type:
./configure --help
To build and install, simply type:
make
followed by
sudo make install
Good Luck!
//Joachim

18
vendor/editline/LICENSE vendored Normal file
View file

@ -0,0 +1,18 @@
Copyright 1992,1993 Simmule Turner and Rich Salz
All rights reserved.
This software is not subject to any license of the American Telephone
and Telegraph Company or of the Regents of the University of California.
Permission is granted to anyone to use this software for any purpose on
any computer system, and to alter it and redistribute it freely, subject
to the following restrictions:
1. The authors are not responsible for the consequences of use of this
software, no matter how awful, even if they arise from flaws in it.
2. The origin of this software must not be misrepresented, either by
explicit claim or by omission. Since few users ever read sources,
credits must appear in the documentation.
3. Altered versions must be plainly marked as such, and must not be
misrepresented as being the original software. Since few users
ever read sources, credits must appear in the documentation.
4. This notice may not be removed or altered.

19
vendor/editline/Make.os9 vendored Normal file
View file

@ -0,0 +1,19 @@
## $Revision: 1.2 $
##
## OS-9 makefile for editline library.
##
.SUFFIXES:
RFILES = editline.r complete.r sysos9.r
%.r: %.c
cc68 -r -Dstrchr=index -Dstrrchr=rindex -DNEED_STRDUP -DSYS_OS9 $*.c
testit: testit.r editline.lib
cc68 -f=testit testit.r -l=editline.lib
$(RFILES): $(RFILES:%.r=%.c)
editline.lib: $(RFILES)
cat $(RFILES) >$@

52
vendor/editline/Makefile.am vendored Normal file
View file

@ -0,0 +1,52 @@
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libeditline.pc
doc_DATA = README.md LICENSE
EXTRA_DIST = README.md LICENSE ChangeLog.md INSTALL.md
SUBDIRS = src include man examples
## Generate .deb package
package build-deb:
@dpkg-buildpackage -uc -us
## Generate MD5 checksum file
MD5 = md5sum
md5-dist:
@for file in $(DIST_ARCHIVES); do \
$(MD5) $$file > ../$$file.md5; \
mv $$file ../; \
done
## Check if tagged in git
release-hook:
if [ ! `git tag | grep $(PACKAGE_VERSION)` ]; then \
echo; \
printf "\e[1m\e[41mCannot find release tag $(PACKAGE_VERSION)\e[0m\n"; \
printf "\e[1m\e[5mDo release anyway?\e[0m "; read yorn; \
if [ "$$yorn" != "y" -a "$$yorn" != "Y" ]; then \
printf "OK, aborting release.\n"; \
exit 1; \
fi; \
echo; \
else \
echo; \
printf "\e[1m\e[42mFound GIT release tag $(PACKAGE_VERSION)\e[0m\n"; \
printf "\e[1m\e[44m>>Remember to push tags!\e[0m\n"; \
echo; \
fi
# lintian --profile debian -i -I --show-overrides ../$PKG.changes
package:
dpkg-buildpackage -uc -us -B
## Target to run when building a release
release: distcheck release-hook md5-dist package
@echo
@echo "Resulting release files:"
@echo "========================================================================="
@for file in $(DIST_ARCHIVES); do \
printf "%-40s Distribution tarball\n" $$file; \
printf "%-40s " $$file.md5; cat ../$$file.md5 | cut -f1 -d' '; \
done
@for file in `cd ..; ls *$(PACKAGE)*_$(subst _,.,$(VERSION))*`; do \
printf "%-40s Debian/Ubuntu package file\n" $$file; \
done

271
vendor/editline/README.md vendored Normal file
View file

@ -0,0 +1,271 @@
Editline
========
[![License Badge][]][License] [![Travis Status]][Travis] [![Coverity Status]][Coverity Scan]
Table of Contents
-----------------
* [Introduction](#introduction)
* [API](#api)
* [Example](#example)
* [Build & Install](#build--install)
* [Origin & References](#origin--references)
Introduction
------------
This is a small [line editing][] library. It can be linked into almost
any program to provide command line editing and history functions. It
is call compatible with the [FSF readline][] library, but at a fraction
of the size, and as a result fewer features. It is also distributed
under a much more liberal [License][].
The small size (<30k), lack of dependencies (ncurses not needed!), and
the free license should make this library interesting to many embedded
developers.
Editline has several optional build-time features that can be enabled by
supplying different options to the GNU configure script. See the output
from <kbd>configure --help</kbd> for details. Some useful hints on how
to use the library is available in the `examples/` directory.
Editline is maintained collaboratively at [GitHub][].
Example
-------
Below follows a brief example to illustrate how one can use Editline to
create a simple CLI, use Ctrl-D to exit the program. For a slightly
more advanced example, see <https://github.com/troglobit/jush/>. The
Editline sources also include an `examples/` sub-directory.
1. Build and install the library, preferably using a [release tarball][]
The configure script defaults to a `/usr/local` prefix.
tar xf editline-1.15.3.tar.xz
cd editline-1.15.3/
./configure --prefix=/usr
make all
sudo make install
2. Place the below source code in a separate project directory,
e.g. `~/src/example.c`
```C
#include <stdlib.h>
#include <editline.h>
int main(void)
{
char *p;
while ((p = readline("CLI> ")) != NULL) {
puts(p);
free(p);
}
return 0;
}
```
3. Compile the example:
cd ~/src/
make LDLIBS=-leditline example
Here I use `make` and rely on its implicit (built-in) rules to handle
all the compiler magic, but you may want to create your own Makefile for
the project. In particular if you don't change the default prefix
(above), because then you need to specify the search path for the
include file(s) and the library manually.
A simple `~/src/Makefile` could look like this:
CFLAGS = -I/usr/local/include
LDFLAGS = -L/usr/local/lib
LDLIBS = -leditline
EXEC = example
OBJS = example.o
all: $(EXEC)
$(EXEC): $(OBJS)
clean:
$(RM) $(OBJS) $(EXEC)
distclean: clean
$(RM) *.o *~ *.bak
Then simply type `make` from your `~/src/` directory. You can also use
`pkg-config` for your `~/src/Makefile`, replace the following lines:
CFLAGS = $(shell pkg-config --cflags libeditline)
LDFLAGS = $(shell pkg-config --libs-only-L libeditline)
LDLIBS = $(shell pkg-config --libs-only-l libeditline)
Then simply type <kbd>make</kbd>, like above.
However, most `.rpm` based distributions `pkg-config` doesn't search in
`/usr/local` anymore, so you need to call make like this:
PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig make
Debian/Ubuntu based systems do not have this problem.
API
---
Here is the libeditline interfaces. It has a small compatibility layer
to [FSF readline][], which may not be entirely up-to-date.
```C
/* Editline specific global variables. */
int el_no_echo; /* Do not echo input characters */
int el_no_hist; /* Disable auto-save of and access to history,
* e.g. for password prompts or wizards */
int el_hist_size; /* Size of history scrollback buffer, default: 15 */
/* Editline specific functions. */
char * el_find_word (void);
void el_print_columns (int ac, char **av);
el_status_t el_ring_bell (void);
el_status_t el_del_char (void);
/* Callback function for key binding */
typedef el_status_t el_keymap_func_t(void);
/* Bind key to a callback, use CTL('f') to change Ctrl-F, for example */
el_status_t el_bind_key (int key, el_keymap_func_t function);
el_status_t el_bind_key_in_metamap (int key, el_keymap_func_t function);
/* For compatibility with FSF readline. */
int rl_point;
int rl_mark;
int rl_end;
int rl_inhibit_complete;
char *rl_line_buffer;
const char *rl_readline_name;
void (*rl_deprep_term_function)(void);
void rl_deprep_terminal (void);
void rl_reset_terminal (const char *terminal_name);
void rl_initialize (void);
void rl_uninitialize (void); /* Free all internal memory */
void rl_save_prompt (void);
void rl_restore_prompt (void);
void rl_set_prompt (const char *prompt);
void rl_clear_message (void);
void rl_forced_update_display (void);
/* Main function to use, saves history by default */
char *readline (const char *prompt);
/* Use to save a read line to history, when el_no_hist is set */
void add_history (const char *line);
/* Load and save editline history from/to a file. */
int read_history (const char *filename);
int write_history (const char *filename);
/* Magic completion API, see examples/cli.c for more info */
rl_complete_func_t *rl_set_complete_func (rl_complete_func_t *func);
rl_list_possib_func_t *rl_set_list_possib_func (rl_list_possib_func_t *func);
/* Alternate interface to plain readline(), for event loops */
void rl_callback_handler_install (const char *prompt, rl_vcpfunc_t *lhandler);
void rl_callback_read_char (void);
void rl_callback_handler_remove (void);
```
Build & Install
---------------
Editline was originally designed for older UNIX systems and Plan 9. The
current maintainer works exclusively on GNU/Linux systems, so it may use
GCC and GNU Make specific extensions here and there. This is not on
purpose and patches or pull requests to correct this are most welcome!
1. Configure editline with default features: <kbd>./configure</kbd>
2. Build the library and examples: <kbd>make all</kbd>
3. Install using <kbd>make install</kbd>
The `$DESTDIR` environment variable is honored at install. For more
options, see <kbd>./configure --help</kbd>
Remember to run `ldconfig` after install to update the linker cache. If
you've installed to a non-standard location (`--prefix`) you may also
have to update your `/etc/ld.so.conf`, or use `pkg-confg` to build your
application (above).
**NOTE:** RedHat/Fedora/CentOS and other `.rpm`-based distributions do
not consider `/usr/local` as standard path anymore. So make sure to
`./configure --prefix=/usr`, otherwise the build system use the GNU
default, which is `/usr/local`. The Debian based distributions, like
Ubuntu, do not have this problem.
Origin & References
--------------------
This [line editing][] library was created by [Rich Salz][] and Simmule
Turner and in 1992. It is distributed with a “[C News][]-like” license,
similar to the [BSD license][]. Rich's current version is however under
the Apache license. For details on the licensing terms of this version
of the software, see [License][].
This version of the editline library was forked from the [Minix 2][]
source tree and is *not* related to the similarily named NetBSD version
that [Jess Thrysøe][jess] disitributes to the world outside *BSD. The
libraries have much in common, but the latter is heavily refactored and
also relies on libtermcap (usually supplied by ncurses), whereas this
library only uses termios from the standard C library.
Patches and bug fixes from the following forks, based on the original
[comp.sources.unix][] posting, have been merged:
* Debian [libeditline][]
* [Heimdal][]
* [Festival][] speech-tools
* [Steve Tell][]'s editline patches
The version numbering scheme today follows that of the Debian version,
details available in the [ChangeLog.md][]. The current [maintainer][]
was unaware of the Debian version for quite some time, so a different
name and versioning scheme was used. In June 2009 this was changed to
line up alongside Debian, with the intent is to eventually merge the
efforts.
Outstanding issues are listed in the [TODO.md][] file.
[GitHub]: https://github.com/troglobit/editline
[line editing]: https://github.com/troglobit/editline/blob/master/docs/README
[release tarball]: https://github.com/troglobit/editline/releases
[maintainer]: http://troglobit.com
[C News]: https://en.wikipedia.org/wiki/C_News
[TODO.md]: https://github.com/troglobit/editline/blob/master/docs/TODO.md
[ChangeLog.md]: https://github.com/troglobit/editline/blob/master/ChangeLog.md
[FSF readline]: http://www.gnu.org/software/readline/
[Rich Salz]: https://github.com/richsalz/editline/
[comp.sources.unix]: http://ftp.cs.toronto.edu/pub/white/pub/rc/editline.shar
[Minix 2]: http://www.cise.ufl.edu/~cop4600/cgi-bin/lxr/http/source.cgi/lib/editline/
[jess]: http://thrysoee.dk/editline/
[BSD license]: http://en.wikipedia.org/wiki/BSD_licenses
[libeditline]: http://packages.qa.debian.org/e/editline.html
[Heimdal]: http://www.h5l.org
[Festival]: http://festvox.org/festival/
[Steve Tell]: http://www.cs.unc.edu/~tell/dist.html
[License]: https://github.com/troglobit/editline/blob/master/LICENSE
[License Badge]: https://img.shields.io/badge/License-C%20News-orange.svg
[Travis]: https://travis-ci.org/troglobit/editline
[Travis Status]: https://travis-ci.org/troglobit/editline.png?branch=master
[Coverity Scan]: https://scan.coverity.com/projects/2982
[Coverity Status]: https://scan.coverity.com/projects/2982/badge.svg

3
vendor/editline/autogen.sh vendored Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
autoreconf -W portability -visfm

99
vendor/editline/configure.ac vendored Normal file
View file

@ -0,0 +1,99 @@
AC_INIT(editline, 1.16.1-dev, https://github.com/troglobit/editline/issues)
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
AM_SILENT_RULES([yes])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([src/editline.c])
AC_CONFIG_HEADER([config.h])
AC_CONFIG_FILES([Makefile libeditline.pc src/Makefile include/Makefile man/Makefile examples/Makefile])
# Checks for programs.
AC_PROG_CC
AC_PROG_INSTALL
# Checks for libraries.
LT_INIT
# Checks for header files.
AC_HEADER_DIRENT
AC_HEADER_STAT
AC_HEADER_STDC
# Check for malloc.h instead of AC_FUNC_MALLOC/REALLOC AIX and others
# mess up the traditional malloc check.
AC_CHECK_HEADERS([malloc.h signal.h stdlib.h string.h termcap.h termio.h termios.h sgtty.h unistd.h])
# In termios.h or in sys/ioctl.g?
AC_HEADER_TIOCGWINSZ
# Overrides and types, should be a check.
AC_DEFINE([SYS_UNIX], [1], [Default to UNIX backend, should be detected.])
AC_TYPE_SIZE_T
# Checks for library functions.
AC_FUNC_CLOSEDIR_VOID
AC_PROG_GCC_TRADITIONAL
AC_FUNC_STAT
AC_CHECK_FUNCS([strchr strdup strrchr tcgetattr perror])
#
# Available features
#
AC_ARG_ENABLE(unique-history,
[AS_HELP_STRING([--disable-unique-history],
[Disable uniqify of scrollback. Default: duplicate entries are ignored. Use this to save dupes.])])
AC_ARG_ENABLE(arrow-keys,
[AS_HELP_STRING([--disable-arrow-keys], [Disable ANSI arrow keys.])])
AC_ARG_ENABLE(eof,
[AS_HELP_STRING([--disable-eof], [Disable default EOF (Ctrl-D) behavior.])])
AC_ARG_ENABLE(sigint,
[AS_HELP_STRING([--disable-sigint], [Disable default SIGINT (Ctrl-C) behavior.])])
AC_ARG_ENABLE(sigstop,
[AS_HELP_STRING([--enable-sigstop], [Enable SIGSTOP (Ctrl-Z) behavior.])])
AC_ARG_ENABLE(terminal-bell,
[AS_HELP_STRING([--enable-terminal-bell], [Enable terminal bell on completion.])])
AC_ARG_ENABLE(termcap,
AS_HELP_STRING([--enable-termcap], [Use termcap library to query terminal size.]))
#
# Check what features have been enabled
#
AS_IF([test "x$enable_unique_history" != "xno"],
AC_DEFINE(CONFIG_UNIQUE_HISTORY, 1, [Define to skip duplicate lines in the scrollback history.]))
AS_IF([test "x$enable_terminal_bell" != "xno"],
AC_DEFINE(CONFIG_ANSI_ARROWS, 1, [Define to include ANSI arrow keys support.]))
AS_IF([test "x$enable_eof" != "xno"],
AC_DEFINE(CONFIG_EOF, 1, [Define to enable EOF (Ctrl-D) key.]))
AS_IF([test "x$enable_sigint" != "xno"],
AC_DEFINE(CONFIG_SIGINT, 1, [Define to enable SIGINT (Ctrl-C) key.]))
AS_IF([test "x$enable_sigstop" = "xyes"],
AC_DEFINE(CONFIG_SIGSTOP, 1, [Define to enable SIGSTOP (Ctrl-Z) key.]))
AS_IF([test "x$enable_terminal_bell" = "xyes"],
AC_DEFINE(CONFIG_TERMINAL_BELL, 1, [Define to enable terminal bell on completion.]))
# Check for a termcap compatible library if enabled
AS_IF([test "x$enable_termcap" = "xyes"],
AC_DEFINE(CONFIG_USE_TERMCAP, 1, [Define to use the termcap library for terminal size.])
AC_CHECK_LIB(terminfo, tgetent, , [
AC_CHECK_LIB(termcap, tgetent, , [
AC_CHECK_LIB(tinfo, tgetent, , [
AC_CHECK_LIB(curses, tgetent, , [
AC_CHECK_LIB(ncurses, tgetent, , [
AC_MSG_ERROR([Cannot find a termcap capable library, try installing Ncurses.])])
])
])
])
]))
# Generate all files
AC_OUTPUT

10
vendor/editline/debian/.gitignore vendored Normal file
View file

@ -0,0 +1,10 @@
*.log
*.debhelper
*.substvars
autoreconf.*
debhelper-build-stamp
files
tmp/*
libeditline-dev/*
libeditline0/*
libeditline1/*

9
vendor/editline/debian/README.Debian vendored Normal file
View file

@ -0,0 +1,9 @@
editline for Debian
----------------------
This is packaged in typical Debian form with a shared library version and
a static library version. It will be a rare package that wishes to
use the shared library form, the static one is only adds about 12.5kb
to your program.
-- Jim Studt <jim@federated.com>, Fri, 5 May 2000 13:25:51 -0500

122
vendor/editline/debian/changelog vendored Normal file
View file

@ -0,0 +1,122 @@
editline (1.16.1) unstable; urgency=medium
* Minor bug fix and documentation update release.
-- Joachim Nilsson <troglobit@gmail.com> Sat, 27 Apr 2019 15:01:07 +0200
editline (1.16.0) unstable; urgency=medium
* New upstream release, v1.60.0
+ Event loop support
+ New GNU Readline compat functions and callbacks
+ Minor compat fixes for movement and deletion
* Bump .so/ABI version => libeditline1
* New maintainer, upstream author
-- Joachim Nilsson <troglobit@gmail.com> Sun, 16 Sep 2018 09:45:53 +0200
editline (1.15.3-1) unstable; urgency=medium
* New upstream bug fix release, v1.15.3
-- Joachim Nilsson <troglobit@gmail.com> Thu, 07 Sep 2017 01:24:19 +0200
editline (1.15.2-1) unstable; urgency=medium
* New upstream bug fix release, v1.15.2
-- Joachim Nilsson <troglobit@gmail.com> Wed, 06 Jun 2016 20:04:35 +0200
editline (1.15.1-1) unstable; urgency=medium
* New upstream bug fix release, v1.15.1
-- Joachim Nilsson <troglobit@gmail.com> Wed, 16 Nov 2015 21:17:17 +0200
editline (1.15.0-1) unstable; urgency=medium
* New upstream release, v1.15.0
-- Joachim Nilsson <troglobit@gmail.com> Wed, 10 Sep 2015 13:26:03 +0200
editline (1.14.2-1) unstable; urgency=low
* Minor bugfix release:
+ Fix `el_no_echo` bug causing secrets to leak when disabling no-echo
+ Handle `EINTR` in syscalls better
-- Joachim Nilsson <troglobit@gmail.com> Sun, 14 Sep 2014 04:27:25 +0200
editline (1.14.1-1) unstable; urgency=low
* New release.
+ Minor fixes to key binding.
+ Check signals and custom keys before acting on them in readline().
+ Update maintainer email address.
-- Joachim Nilsson <troglobit@gmail.com> Mon, 8 Jul 2013 17:04:00 +0100
editline (1.14.0-1) unstable; urgency=low
* Update to new configure based build.
-- Joachim Nilsson <joachim.nilsson@vmlinux.org> Wed, 11 Aug 2010 13:28:00 +0100
editline (1.12-6) unstable; urgency=low
* Switch package format to 3.0 (quilt).
* 200_fix-truncation-at-64-char.diff: fix invalid 64-char truncation in
batch mode, courtesy of Mark O'Donohue. Thanks to Damyan Ivanov for
forwarding the patch from Ubuntu (Closes: #508640).
-- Sam Hocevar <sho@debian.org> Sun, 03 Jan 2010 15:45:34 +0100
editline (1.12-5) unstable; urgency=low
* New maintainer (Closes: #229962).
* debian/changelog:
+ Removed emacs helper variables.
* debian/control:
+ Set policy to 3.6.1.0.
+ Set debhelper build dependency to (>= 4.0).
+ Use the default dh_shlibs information, since the API is rock stable
(Closes: #131139).
+ Removed the libc6-dev dependency in the -dev package.
+ Rephrased the short and long descriptions.
* debian/copyright:
+ Replaced "Author(s)" with "Author".
* debian/rules:
+ Removed obsolete call to dh_suidregister.
+ Use debian/compat instead of DH_COMPAT.
* include_editline.h:
+ Added a minimalist /usr/include/editline.h (Closes: #129544).
* Makefile:
+ Call libtool with the proper --mode flags.
-- Sam Hocevar (Debian packages) <sam+deb@zoy.org> Sat, 31 Jan 2004 22:32:35 +0100
editline (1.12-4) unstable; urgency=low
* Add a Build-Depends for debhelper and libtool. Thought those
were baseline. closes: #117780
-- Jim Studt <jim@federated.com> Thu, 15 Nov 2001 19:00:00 -0600
editline (1.12-3) unstable; urgency=low
* Make man pages not be in the shared library package.
-- Jim Studt <jim@federated.com> Sat, 13 Jan 2001 00:03:53 -0600
editline (1.12-2) unstable; urgency=low
* Patch to not declare read() and write(), it fails on alphas.
-- Jim Studt <jim@federated.com> Tue, 12 Sep 2000 16:39:34 -0500
editline (1.12-1) unstable; urgency=low
* Initial Release.
-- Jim Studt <jim@federated.com> Fri, 5 May 2000 13:25:51 -0500

1
vendor/editline/debian/compat vendored Normal file
View file

@ -0,0 +1 @@
9

31
vendor/editline/debian/control vendored Normal file
View file

@ -0,0 +1,31 @@
Source: editline
Section: devel
Priority: optional
Build-Depends: debhelper (>= 5.0), libtool
Maintainer: Joachim Nilsson <troglobit@gmail.com>
Standards-Version: 3.8.3
Package: libeditline-dev
Architecture: any
Section: libdevel
Depends: libeditline1 (= ${binary:Version}), ${misc:Depends}
Description: development files for libeditline
This is a line-editing library. It can be linked into almost any program
to provide command-line editing and recall. It is call-compatible with a
subset of the FSF readline library, but it is a fraction of the size (and
offers fewer features).
.
This package contains the developer files: static libraries, headers,
manpages.
Package: libeditline1
Architecture: any
Section: libs
Depends: ${misc:Depends}
Description: line editing library similar to readline
This is a line-editing library. It can be linked into almost any program
to provide command-line editing and recall. It is call-compatible with a
subset of the FSF readline library, but it is a fraction of the size (and
offers fewer features).
.
This package contains the runtime library only.

27
vendor/editline/debian/copyright vendored Normal file
View file

@ -0,0 +1,27 @@
This package was debianized by Jim Studt <jim@federated.com> on
Fri, 5 May 2000 13:25:51 -0500.
It was received from Rich Salz rsalz@shore.net
Upstream Author: Rich Salz rsalz@shore.net
Copyright:
Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
This software is not subject to any license of the American Telephone
and Telegraph Company or of the Regents of the University of California.
Permission is granted to anyone to use this software for any purpose on
any computer system, and to alter it and redistribute it freely, subject
to the following restrictions:
1. The authors are not responsible for the consequences of use of this
software, no matter how awful, even if they arise from flaws in it.
2. The origin of this software must not be misrepresented, either by
explicit claim or by omission. Since few users ever read sources,
credits must appear in the documentation.
3. Altered versions must be plainly marked as such, and must not be
misrepresented as being the original software. Since few users
ever read sources, credits must appear in the documentation.
4. This notice may not be removed or altered.

2
vendor/editline/debian/dirs vendored Normal file
View file

@ -0,0 +1,2 @@
usr/lib
usr/include

1
vendor/editline/debian/docs vendored Normal file
View file

@ -0,0 +1 @@
README.md

View file

@ -0,0 +1,4 @@
usr/include/*.h
usr/lib/*/libeditline*.*a
usr/lib/*/pkgconfig/*
usr/share/man/man3/*

View file

@ -0,0 +1 @@
usr/lib/*/libeditline*.so*

8
vendor/editline/debian/rules vendored Executable file
View file

@ -0,0 +1,8 @@
#!/usr/bin/make -f
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
%:
dh $@ --with autoreconf

1
vendor/editline/debian/source/format vendored Normal file
View file

@ -0,0 +1 @@
3.0 (native)

106
vendor/editline/docs/HACKING.md vendored Normal file
View file

@ -0,0 +1,106 @@
Maintenance and Release Checklist
=================================
Maintenance
-----------
* Encourage contributors to write tests, in particular for new features
* Run tests regularly, use Travis-CI to do this automatically
* Leverage GitHub issues for milestone planning
* Reference issues from GitHub pull requests to alert issue subscribers
* Bump library ABI version just before release!
Release Checklist
-----------------
* Update ChangeLog, follow http://keepachangelog.com/ loosely
- Inform users in a plain language of changes and bug fixes
- Do *not* copy-paste GIT commit logs!
- Order entries according to importance, most relevant first
* Run unit tests: `make check`
* Make at least one `-rcN` release and test it in an actual real project
* **REMEMBER:** bump ABI version according to below rules
* Tag
* Push last commit(s) *and* tags to GitHub
* Make release
make distclean
./autogen.sh
./configure
make release
* Create new release in GitHub releases page
* Copy and paste ChangeLog entry, check any stale links!
* Upload release tarball and MD5 files
Library Versioning
------------------
Editline relies on GNU Libtool for building the library. For a user of
the library it is important to maintain a clear ABI versioning scheme.
This is not the same as the Editline version, but rather the library
"compatibility level".
The Editline ABI version is specified in `src/Makefile.am` and looks
like this:
libeditline_la_LDFLAGS = -version-info 0:0:0
\ \ `-- age
\ `--- revision
`---- current
It must be updated according to the [GNU Libtool recommendations][1]:
1. Start with version information of `0:0:0` for each libtool library.
2. Update the version information only immediately before a public
release of your software. More frequent updates are unnecessary, and
only guarantee that the current interface number gets larger faster.
3. If the library *source code has changed at all* since the last update,
then increment revision (`c:r:a` becomes `c:r+1:a`).
4. If any *interfaces have been added, removed, or changed* since the
last update, increment current, and set revision to 0.
5. If any *interfaces have been added* since the last public release,
then increment age.
6. If any *interfaces have been removed or changed* since the last
public release, then set age to 0.
The libtool ABI versioning logic is very confusing but works if you just
disable your brain and follow the rules, one by one.
**Example #1:** a new function has been added, none of the existing ones
have changed. The initial version is 1:0:0, we follow the rules above to
the letter: increase revision, increase current and set revision to zero,
and finally increase age. This, rather confusingly, gives us 2:0:1 which
libtool then translates to `libeditline.so.1.1.0`.
**Example #2:** some existing functions are changed, they now return an
`int` instead of `void`. The initial version is 0:0:0, and we follow the
rules again: increment revision, increment current and set revision to
zero, set age to zero. This gives us 1:0:0, which is then translated to
`libeditline.so.1.0.0`.
### Note
Usually, non-developers have no interest in running development versions
(releases are frequent enough), and developers are expected to know how
to juggle versions. In such an ideal world, it is good enough to bump
the library version just prior to a release, point 2.
However, if releases are few and far between, distributors may start to
use snapshots. When a distributor uses a snapshot, the distributor has
to handle the library version manually. Things can get ugly when the
distributor has released an intermediate version with a bumped library
version, and when the official release is bumped to that version, the
distributor will then have to bump the library version for the official
release, and it can be confusing if someone reports bugs on versions
that you didn't even know existed.
The problem with bumping the version with every change is that if your
interface is not finished, the version number might run away, and it
looks pretty bad if a library is at version 262. It kind of tells the
user that the library interface is volatile, which is not good for
business.
[1]: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html

68
vendor/editline/docs/README vendored Executable file
View file

@ -0,0 +1,68 @@
Original Minix README
=====================
Below is the original Minix editline README file. It has been
split into a modified README and LICENSE file.
-- Joachim Nilsson, June 7th 2008
-----------------------------------------------------------------
$Revision: 5 $
This is a line-editing library. It can be linked into almost any
program to provide command-line editing and recall.
It is call-compatible with the FSF readline library, but it is a
fraction of the size (and offers fewer features). It does not use
standard I/O. It is distributed under a "C News-like" copyright.
Configuration is done in the Makefile. Type "make testit" to get
a small slow shell for testing.
An earlier version was distributed with Byron's rc. Principal
changes over that version include:
Faster.
Is eight-bit clean (thanks to brendan()cs!widener!edu)
Written in K&R C, but ANSI compliant (gcc all warnings)
Propagates EOF properly; rc trip test now passes
Doesn't need or use or provide memmove.
More robust
Calling sequence changed to be compatible with readline.
Test program, new manpage, better configuration
More system-independant; includes Unix and OS-9 support.
This contains some changes since the posting to comp.sources.misc:
Bugfix for completion on absolute pathnames.
Better handling of M-n versus showing raw 8bit chars.
Better signal handling.
Now supports termios/termio/sgttyb ioctl's.
Add M-m command to toggle how 8bit data is displayed.
There is one known bug:
History-searching redraws the line wrong if the text
retrieved is shorter then the prompt.
Enjoy,
Rich $alz
<rsalz()osf!org>
Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
This software is not subject to any license of the American Telephone
and Telegraph Company or of the Regents of the University of California.
Permission is granted to anyone to use this software for any purpose on
any computer system, and to alter it and redistribute it freely, subject
to the following restrictions:
1. The authors are not responsible for the consequences of use of this
software, no matter how awful, even if they arise from flaws in it.
2. The origin of this software must not be misrepresented, either by
explicit claim or by omission. Since few users ever read sources,
credits must appear in the documentation.
3. Altered versions must be plainly marked as such, and must not be
misrepresented as being the original software. Since few users
ever read sources, credits must appear in the documentation.
4. This notice may not be removed or altered.
--
$PchId: README,v 1.3 1996/02/22 21:18:51 philip Exp $

41
vendor/editline/docs/TODO.md vendored Normal file
View file

@ -0,0 +1,41 @@
TODO
====
Issues in need of work. Mostly compatibility with GNU readline,
BSD [libedit][], and usability improvements.
Remember, the general idea is to keep this library small with no
external dependencies, except for a generic C library.
Check what's needed to run the fileman example
----------------------------------------------
The BSD libedit library has imported the GNU readline "fileman" example
into its tree to demonstrate the abilities of that library. This would
also be quite useful for this library!
The first task is to investigate the depependencies and form TODO list
items detailing what is missing and, if possible, proposals how to
implement including any optional configure flags.
Other minor TODO's
------------------
- Instead of supporting multiline input, try the Emacs approach, line
scrolling.
- Add support for `rl_bind_key()`, currently only en editline specific
`el_bind_key()` exists.
- Make `char *rl_prompt;` globally visible.
- Add support for `rl_set_prompt()`
- Add support for `--enable-utf8` to configure script
- Use `strcmp(nl_langinfo(CODESET), "UTF-8")` to look for utf8 capable
terminal
- Implement simple UTF-8 parser according to
http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
[gnu]: http://www.delorie.com/gnu/docs/readline/rlman_41.html#IDX288
[libuEv]: https://github.com/troglobit/libuev/
[libedit]: http://www.thrysoee.dk/editline/

5
vendor/editline/examples/.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
*.o
cli
testit
excallback
fileman

5
vendor/editline/examples/Makefile.am vendored Normal file
View file

@ -0,0 +1,5 @@
noinst_PROGRAMS = testit cli excallback fileman
LDADD = $(top_builddir)/src/libeditline.la
AM_CPPFLAGS = -DEDITLINE_LIBRARY
AM_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/include
AM_LDFLAGS = -static

168
vendor/editline/examples/cli.c vendored Normal file
View file

@ -0,0 +1,168 @@
/* Custom CLI command completion.
*
* Copyright (c) 1992, 1993 Simmule Turner and Rich Salz. All rights reserved.
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or of the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
* 1. The authors are not responsible for the consequences of use of this
* software, no matter how awful, even if they arise from flaws in it.
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Since few users ever read sources,
* credits must appear in the documentation.
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software. Since few users
* ever read sources, credits must appear in the documentation.
* 4. This notice may not be removed or altered.
*/
#include "editline.h"
#include <string.h>
#define HISTORY "/tmp/.cli-history"
static char *list[] = {
"foo ", "bar ", "bsd ", "cli ", "ls ", "cd ", "malloc ", "tee ", NULL
};
/* Attempt to complete the pathname, returning an allocated copy.
* Fill in *unique if we completed it, or set it to 0 if ambiguous. */
static char *my_rl_complete(char *token, int *match)
{
int i;
int index = -1;
int matchlen = 0;
int count = 0;
for (i = 0; list[i]; i++) {
int partlen = strlen (token); /* Part of token */
if (!strncmp (list[i], token, partlen)) {
index = i;
matchlen = partlen;
count ++;
}
}
if (count == 1) {
*match = 1;
return strdup (list[index] + matchlen);
}
return NULL;
}
/* Return all possible completions. */
static int my_rl_list_possib(char *token, char ***av)
{
int i, num, total = 0;
char **copy;
for (num = 0; list[num]; num++)
;
copy = (char **) malloc (num * sizeof(char *));
for (i = 0; i < num; i++) {
if (!strncmp (list[i], token, strlen (token))) {
copy[total] = strdup (list[i]);
total ++;
}
}
*av = copy;
return total;
}
el_status_t list_possible(void)
{
char **av;
char *word;
int ac;
word = el_find_word();
ac = rl_list_possib(word, &av);
if (word)
free(word);
if (ac) {
el_print_columns(ac, av);
while (--ac >= 0)
free(av[ac]);
free(av);
return CSmove;
}
return el_ring_bell();
}
el_status_t do_suspend(void)
{
puts("Abort!");
return CSstay;
}
static void breakit(int signo)
{
puts("Got SIGINT");
}
int main(void)
{
char *line;
char *prompt = "cli> ";
char *passwd = "Enter password: ";
signal(SIGINT, breakit);
/* Setup callbacks */
rl_set_complete_func(&my_rl_complete);
rl_set_list_possib_func(&my_rl_list_possib);
el_bind_key('?', list_possible);
el_bind_key(CTL('Z'), do_suspend);
read_history(HISTORY);
while ((line = readline(prompt))) {
int next = 0;
/* Use el_no_echo when reading passwords and similar */
if (!strncmp(line, "unlock", 6)) {
el_no_echo = 1;
while ((line = readline(passwd))) {
if (strncmp(line, "secret", 6)) {
printf("\nWrong password, please try again, it's secret.\n");
free(line);
continue;
}
el_no_echo = 0;
printf("\nAchievement unlocked!\n");
free(line);
next = 1;
break;
}
}
if (next)
continue;
if (*line != '\0')
printf("\t\t\t|%s|\n", line);
free(line);
}
write_history(HISTORY);
return 0;
}
/**
* Local Variables:
* c-file-style: "k&r"
* c-basic-offset: 4
* End:
*/

195
vendor/editline/examples/excallback.c vendored Normal file
View file

@ -0,0 +1,195 @@
/*
From: Jeff Solomon <jsolomon@stanford.edu>
Date: Fri, 9 Apr 1999 10:13:27 -0700 (PDT)
To: chet@po.cwru.edu
Subject: new readline example
Message-ID: <14094.12094.527305.199695@mrclean.Stanford.EDU>
Chet,
I've been using readline 4.0. Specifically, I've been using the perl
version Term::ReadLine::Gnu. It works great.
Anyway, I've been playing around the alternate interface and I wanted
to contribute a little C program, callback.c, to you that you could
use as an example of the alternate interface in the /examples
directory of the readline distribution.
My example shows how, using the alternate interface, you can
interactively change the prompt (which is very nice imo). Also, I
point out that you must roll your own terminal setting when using the
alternate interface because readline depreps (using your parlance) the
terminal while in the user callback. I try to demostrate what I mean
with an example. I've included the program below.
To compile, I just put the program in the examples directory and made
the appropriate changes to the EXECUTABLES and OBJECTS line and added
an additional target 'callback'.
I compiled on my Sun Solaris2.6 box using Sun's cc.
Let me know what you think.
Jeff
*/
#if defined (HAVE_CONFIG_H)
#include <config.h>
#endif
#include <stdio.h>
#include <sys/types.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <termios.h> /* xxx - should make this more general */
#ifdef EDITLINE_LIBRARY
# include "editline.h"
#else
# include <readline/readline.h>
#endif
/* This little examples demonstrates the alternate interface to using readline.
* In the alternate interface, the user maintains control over program flow and
* only calls readline when STDIN is readable. Using the alternate interface,
* you can do anything else while still using readline (like talking to a
* network or another program) without blocking.
*
* Specifically, this program highlights two importants features of the
* alternate interface. The first is the ability to interactively change the
* prompt, which can't be done using the regular interface since rl_prompt is
* read-only.
*
* The second feature really highlights a subtle point when using the alternate
* interface. That is, readline will not alter the terminal when inside your
* callback handler. So let's so, your callback executes a user command that
* takes a non-trivial amount of time to complete (seconds). While your
* executing the command, the user continues to type keystrokes and expects them
* to be re-echoed on the new prompt when it returns. Unfortunately, the default
* terminal configuration doesn't do this. After the prompt returns, the user
* must hit one additional keystroke and then will see all of his previous
* keystrokes. To illustrate this, compile and run this program. Type "sleep" at
* the prompt and then type "bar" before the prompt returns (you have 3
* seconds). Notice how "bar" is re-echoed on the prompt after the prompt
* returns? This is what you expect to happen. Now comment out the 4 lines below
* the line that says COMMENT LINE BELOW. Recompile and rerun the program and do
* the same thing. When the prompt returns, you should not see "bar". Now type
* "f", see how "barf" magically appears? This behavior is un-expected and not
* desired.
*/
void process_line(char *line);
int change_prompt(void);
char *get_prompt(void);
int prompt = 1;
char prompt_buf[40], line_buf[256];
tcflag_t old_lflag;
cc_t old_vtime;
struct termios term;
int
main()
{
fd_set fds;
/* Adjust the terminal slightly before the handler is installed. Disable
* canonical mode processing and set the input character time flag to be
* non-blocking.
*/
if( tcgetattr(STDIN_FILENO, &term) < 0 ) {
perror("tcgetattr");
exit(1);
}
old_lflag = term.c_lflag;
old_vtime = term.c_cc[VTIME];
term.c_lflag &= ~ICANON;
term.c_cc[VTIME] = 1;
/* COMMENT LINE BELOW - see above */
if( tcsetattr(STDIN_FILENO, TCSANOW, &term) < 0 ) {
perror("tcsetattr");
exit(1);
}
// rl_add_defun("change-prompt", change_prompt, CTRL('t'));
rl_callback_handler_install(get_prompt(), process_line);
while(1) {
FD_ZERO(&fds);
FD_SET(fileno(stdin), &fds);
if( select(FD_SETSIZE, &fds, NULL, NULL, NULL) < 0) {
perror("select");
exit(1);
}
if( FD_ISSET(fileno(stdin), &fds) ) {
rl_callback_read_char();
}
}
return 0;
}
void
process_line(char *line)
{
if( line == NULL ) {
fprintf(stderr, "\n");
/* reset the old terminal setting before exiting */
term.c_lflag = old_lflag;
term.c_cc[VTIME] = old_vtime;
if( tcsetattr(STDIN_FILENO, TCSANOW, &term) < 0 ) {
perror("tcsetattr");
exit(1);
}
exit(0);
}
if( strcmp(line, "sleep") == 0 ) {
sleep(3);
} else {
fprintf(stderr, "|%s|\n", line);
}
free (line);
}
int
change_prompt(void)
{
/* toggle the prompt variable */
prompt = !prompt;
/* save away the current contents of the line */
strncpy(line_buf, rl_line_buffer, sizeof(line_buf));
line_buf[sizeof(line_buf) - 1] = 0;
/* install a new handler which will change the prompt and erase the current line */
rl_callback_handler_install(get_prompt(), process_line);
/* insert the old text on the new line */
rl_insert_text(line_buf);
/* redraw the current line - this is an undocumented function. It invokes the
* redraw-current-line command.
*/
return rl_refresh_line(0, 0);
}
char *
get_prompt(void)
{
/* The prompts can even be different lengths! */
sprintf(prompt_buf, "%s",
prompt ? "Hit ctrl-t to toggle prompt> " : "Pretty cool huh?> ");
return prompt_buf;
}

431
vendor/editline/examples/fileman.c vendored Normal file
View file

@ -0,0 +1,431 @@
/* fileman.c -- A tiny application which demonstrates how to use the
GNU Readline library. This application interactively allows users
to manipulate files and their modes.
NOTE: this was taken from the GNU Readline documentation and ported
to libedit. A command to output the history list was added.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <locale.h>
#include <time.h>
#include "editline.h"
void too_dangerous(char *caller);
void initialize_readline();
int execute_line(char *line);
int valid_argument(char *caller, char *arg);
/* The names of functions that actually do the manipulation. */
int com_list(char *);
int com_view(char *);
int com_history(char *);
int com_rename(char *);
int com_stat(char *);
int com_pwd(char *);
int com_delete(char *);
int com_help(char *);
int com_cd(char *);
int com_quit(char *);
struct cmd {
char *name; /* User printable name of the function. */
int (*func)(char *); /* Function to call to do the job. */
char *doc; /* Documentation for this function. */
};
struct cmd commands[] = {
{ "cd", com_cd, "Change to directory DIR"},
{ "delete", com_delete, "Delete FILE"},
{ "help", com_help, "Display this text"},
{ "?", com_help, "Synonym for `help'"},
{ "list", com_list, "List files in DIR"},
{ "ls", com_list, "Synonym for `list'"},
{ "pwd", com_pwd, "Print the current working directory"},
{ "quit", com_quit, "Quit using Fileman"},
{ "rename", com_rename, "Rename FILE to NEWNAME"},
{ "stat", com_stat, "Print out statistics on FILE"},
{ "view", com_view, "View the contents of FILE"},
{ "history", com_history, "List editline history"},
{ NULL, NULL, NULL },
};
/* Forward declarations. */
char *stripwhite();
struct cmd *find_command();
/* When non-zero, this means the user is done using this program. */
int done;
int main(int argc, char **argv)
{
char *line, *s;
setlocale(LC_CTYPE, "");
initialize_readline(); /* Bind our completer. */
/* Loop reading and executing lines until the user quits. */
for (; done == 0;) {
line = readline("FileMan: ");
if (!line)
break;
/* Remove leading and trailing whitespace from the line.
Then, if there is anything left, add it to the history list
and execute it. */
s = stripwhite(line);
#if 0
if (*s) {
char *expansion;
int result;
result = history_expand(s, &expansion);
if (result < 0 || result == 2) {
fprintf(stderr, "%s\n", expansion);
} else {
add_history(expansion);
execute_line(expansion);
}
free(expansion);
}
#else
execute_line(s);
#endif
free(line);
}
return 0;
}
/* Execute a command line. */
int execute_line(char *line)
{
int i;
struct cmd *command;
char *word;
/* Isolate the command word. */
i = 0;
while (line[i] && isspace(line[i]))
i++;
word = line + i;
while (line[i] && !isspace(line[i]))
i++;
if (line[i])
line[i++] = '\0';
command = find_command(word);
if (!command) {
fprintf(stderr, "%s: No such command for FileMan.\n", word);
return -1;
}
/* Get argument to command, if any. */
while (isspace(line[i]))
i++;
word = line + i;
/* Call the function. */
return command->func(word);
}
/* Look up NAME as the name of a command, and return a pointer to that
command. Return a NULL pointer if NAME isn't a command name. */
struct cmd *find_command(char *name)
{
int i;
for (i = 0; commands[i].name; i++)
if (strcmp(name, commands[i].name) == 0)
return &commands[i];
return NULL;
}
/*
* Strip whitespace from the start and end of STRING. Return a pointer
* into STRING.
*/
char *stripwhite(char *string)
{
char *s, *t;
for (s = string; isspace(*s); s++) ;
if (*s == 0)
return s;
t = s + strlen(s) - 1;
while (t > s && isspace(*t))
t--;
*++t = '\0';
return s;
}
/* **************************************************************** */
/* */
/* Interface to Readline Completion */
/* */
/* **************************************************************** */
char *command_generator(const char *, int);
char **fileman_completion(const char *, int, int);
/*
* Tell the GNU Readline library how to complete. We want to try to
* complete on command names if this is the first word in the line, or
* on filenames if not.
*/
void initialize_readline(void)
{
/* Allow conditional parsing of the ~/.inputrc file. */
rl_readline_name = "FileMan";
/* Tell the completer that we want a crack first. */
rl_attempted_completion_function = fileman_completion;
}
/*
* Attempt to complete on the contents of TEXT. START and END
* bound the region of rl_line_buffer that contains the word to
* complete. TEXT is the word to complete. We can use the entire
* contents of rl_line_buffer in case we want to do some simple
* parsing. Returnthe array of matches, or NULL if there aren't any.
*/
char **fileman_completion(const char *text, int start, int end)
{
char **matches = NULL;
/* If this word is at the start of the line, then it is a command
to complete. Otherwise it is the name of a file in the current
directory. */
if (start == 0)
matches = rl_completion_matches(text, command_generator);
return matches;
}
/* Generator function for command completion. STATE lets us
know whether to start from scratch; without any state
(i.e. STATE == 0), then we start at the top of the list. */
char *command_generator(const char *text, int state)
{
static int list_index, len;
char *name;
/* If this is a new word to complete, initialize now. This
includes saving the length of TEXT for efficiency, and
initializing the index variable to 0. */
if (!state) {
list_index = 0;
len = strlen(text);
}
/* Return the next name which partially matches from the
command list. */
while ((name = commands[list_index].name)) {
list_index++;
if (strncmp(name, text, len) == 0)
return strdup(name);
}
/* If no names matched, then return NULL. */
return NULL;
}
/* **************************************************************** */
/* */
/* FileMan Commands */
/* */
/* **************************************************************** */
/* String to pass to system (). This is for the LIST, VIEW and RENAME
commands. */
static char syscom[1024];
/* List the file(s) named in arg. */
int com_list(char *arg)
{
if (!arg)
arg = "";
sprintf(syscom, "ls -FClg %s", arg);
return system(syscom);
}
int com_view(char *arg)
{
if (!valid_argument("view", arg))
return 1;
sprintf(syscom, "more %s", arg);
return system(syscom);
}
int com_history(char *arg)
{
const char *he;
/* rewind history */
while (el_prev_hist()) ;
for (he = el_next_hist(); he != NULL; he = el_next_hist())
printf("%s\n", he);
return 0;
}
int com_rename(char *arg)
{
too_dangerous("rename");
return 1;
}
int com_stat(char *arg)
{
struct stat finfo;
if (!valid_argument("stat", arg))
return 1;
if (stat(arg, &finfo) == -1) {
perror(arg);
return 1;
}
printf("Statistics for `%s':\n", arg);
printf("%s has %ld link%s, and is %lld byte%s in length.\n", arg,
(long)finfo.st_nlink,
(finfo.st_nlink == 1) ? "" : "s",
(long long)finfo.st_size, (finfo.st_size == 1) ? "" : "s");
printf("Inode Last Change at: %s", ctime(&finfo.st_ctime));
printf(" Last access at: %s", ctime(&finfo.st_atime));
printf(" Last modified at: %s", ctime(&finfo.st_mtime));
return 0;
}
int com_delete(char *arg)
{
too_dangerous("delete");
return 1;
}
/* Print out help for ARG, or for all of the commands if ARG is
not present. */
int com_help(char *arg)
{
int i;
int printed = 0;
for (i = 0; commands[i].name; i++) {
if (!*arg || (strcmp(arg, commands[i].name) == 0)) {
printf("%s\t\t%s.\n", commands[i].name,
commands[i].doc);
printed++;
}
}
if (!printed) {
printf("No commands match `%s'. Possibilties are:\n", arg);
for (i = 0; commands[i].name; i++) {
/* Print in six columns. */
if (printed == 6) {
printed = 0;
printf("\n");
}
printf("%s\t", commands[i].name);
printed++;
}
if (printed)
printf("\n");
}
return 0;
}
/* Change to the directory ARG. */
int com_cd(char *arg)
{
if (chdir(arg) == -1) {
perror(arg);
return 1;
}
com_pwd("");
return 0;
}
/* Print out the current working directory. */
int com_pwd(char *ignore)
{
char dir[1024], *s;
s = getcwd(dir, sizeof(dir) - 1);
if (!s) {
printf("Error getting pwd: %s\n", dir);
return 1;
}
printf("Current directory is %s\n", dir);
return 0;
}
/* The user wishes to quit using this program. Just set DONE
non-zero. */
int com_quit(char *arg)
{
done = 1;
return 0;
}
/* Function which tells you that you can't do this. */
void too_dangerous(char *caller)
{
fprintf(stderr, "%s: Too dangerous for me to distribute.\n", caller);
fprintf(stderr, "Write it yourself.\n");
}
/* Return non-zero if ARG is a valid argument for CALLER,
else print an error message and return zero. */
int valid_argument(char *caller, char *arg)
{
if (!arg || !*arg) {
fprintf(stderr, "%s: Argument required.\n", caller);
return 0;
}
return 1;
}
/**
* Local Variables:
* c-file-style: "k&r"
* c-basic-offset: 4
* End:
*/

78
vendor/editline/examples/testit.c vendored Normal file
View file

@ -0,0 +1,78 @@
/* A "micro-shell" to test editline library.
* If given any arguments, commands aren't executed.
*
* Copyright (c) 1992, 1993 Simmule Turner and Rich Salz. All rights reserved.
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or of the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
* 1. The authors are not responsible for the consequences of use of this
* software, no matter how awful, even if they arise from flaws in it.
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Since few users ever read sources,
* credits must appear in the documentation.
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software. Since few users
* ever read sources, credits must appear in the documentation.
* 4. This notice may not be removed or altered.
*/
#include <config.h>
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "editline.h"
#ifndef HAVE_PERROR
extern int errno;
void perror(char *s)
{
fprintf(stderr, "%s: error %d\n", s, errno);
}
#endif /* !HAVE_PERROR */
int main(int argc, char *argv[] __attribute__ ((unused)))
{
int doit;
char *prompt, *p;
read_history(".testit_history");
doit = argc == 1;
if ((prompt = getenv("TESTPROMPT")) == NULL)
prompt = "testit> ";
while ((p = readline(prompt)) != NULL) {
printf("\t\t\t|%s|\n", p);
if (doit) {
if (strncmp(p, "cd ", 3) == 0) {
if (chdir(&p[3]) < 0)
perror(&p[3]);
} else if (system(p) != 0) {
perror(p);
}
}
free(p);
}
write_history(".testit_history");
rl_uninitialize();
return 0;
}
/**
* Local Variables:
* c-file-style: "k&r"
* c-basic-offset: 4
* End:
*/

2
vendor/editline/include/Makefile.am vendored Normal file
View file

@ -0,0 +1,2 @@
library_includedir = $(includedir)
library_include_HEADERS = editline.h

132
vendor/editline/include/editline.h vendored Normal file
View file

@ -0,0 +1,132 @@
/*
* Copyright (c) 1992, 1993 Simmule Turner and Rich Salz
* All rights reserved.
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or of the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
* 1. The authors are not responsible for the consequences of use of this
* software, no matter how awful, even if they arise from flaws in it.
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Since few users ever read sources,
* credits must appear in the documentation.
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software. Since few users
* ever read sources, credits must appear in the documentation.
* 4. This notice may not be removed or altered.
*/
#ifndef EDITLINE_H_
#define EDITLINE_H_
/* Handy macros when binding keys. */
#define CTL(x) ((x) & 0x1F)
#define ISCTL(x) ((x) && (x) < ' ')
#define UNCTL(x) ((x) + 64)
#define META(x) ((x) | 0x80)
#define ISMETA(x) ((x) & 0x80)
#define UNMETA(x) ((x) & 0x7F)
#ifdef __cplusplus
extern "C" {
#endif
/* Command status codes. */
typedef enum {
CSdone = 0, /* OK */
CSeof, /* Error, or EOF */
CSmove,
CSdispatch,
CSstay,
CSsignal
} el_status_t;
/* Editline specific types, despite rl_ prefix. From Heimdal project. */
typedef int rl_list_possib_func_t(char*, char***);
typedef el_status_t el_keymap_func_t(void);
typedef int rl_hook_func_t(void);
typedef int rl_getc_func_t(void);
typedef void rl_voidfunc_t(void);
typedef void rl_vintfunc_t(int);
typedef void rl_vcpfunc_t(char *);
/* FSF Readline compat tupes */
typedef char *rl_complete_func_t (char *, int*);
typedef char *rl_compentry_func_t (const char *, int);
typedef char **rl_completion_func_t (const char *, int, int);
/* Display 8-bit chars "as-is" or as `M-x'? Toggle with M-m. (Default:0 - "as-is") */
extern int rl_meta_chars;
/* Editline specific functions. */
extern char * el_find_word(void);
extern void el_print_columns(int ac, char **av);
extern el_status_t el_ring_bell(void);
extern el_status_t el_del_char(void);
extern el_status_t el_bind_key(int key, el_keymap_func_t function);
extern el_status_t el_bind_key_in_metamap(int key, el_keymap_func_t function);
extern const char *el_next_hist(void);
extern const char *el_prev_hist(void);
extern char *rl_complete(char *token, int *match);
extern int rl_list_possib(char *token, char ***av);
extern char **rl_completion_matches(const char *token, rl_compentry_func_t *generator);
extern char *rl_filename_completion_function(const char *text, int state);
/* For compatibility with FSF readline. */
extern int rl_point;
extern int rl_mark;
extern int rl_end;
extern int rl_inhibit_complete;
extern char *rl_line_buffer;
extern const char *rl_readline_name;
extern FILE *rl_instream; /* The stdio stream from which input is read. Defaults to stdin if NULL - Not supported yet! */
extern FILE *rl_outstream; /* The stdio stream to which output is flushed. Defaults to stdout if NULL - Not supported yet! */
extern int el_no_echo; /* E.g under emacs, don't echo except prompt */
extern int el_no_hist; /* Disable auto-save of and access to history -- e.g. for password prompts or wizards */
extern int el_hist_size; /* size of history scrollback buffer, default: 15 */
extern void rl_initialize (void);
extern void rl_reset_terminal (const char *terminal_name);
extern void rl_uninitialize (void);
extern void rl_save_prompt (void);
extern void rl_restore_prompt (void);
extern void rl_set_prompt (const char *prompt);
extern void rl_clear_message (void);
extern void rl_forced_update_display(void);
extern void rl_prep_terminal (int meta_flag);
extern void rl_deprep_terminal (void);
extern int rl_getc(void);
extern int rl_insert_text (const char *text);
extern int rl_refresh_line (int ignore1, int ignore2);
extern char *readline (const char *prompt);
extern void add_history (const char *line);
extern int read_history (const char *filename);
extern int write_history (const char *filename);
extern rl_getc_func_t *rl_set_getc_func(rl_getc_func_t *func);
extern rl_completion_func_t *rl_attempted_completion_function;
extern rl_complete_func_t *rl_set_complete_func (rl_complete_func_t *func);
extern rl_list_possib_func_t *rl_set_list_possib_func (rl_list_possib_func_t *func);
/* Alternate interface to plain readline(), for event loops */
extern void rl_callback_handler_install (const char *prompt, rl_vcpfunc_t *lhandler);
extern void rl_callback_read_char (void);
extern void rl_callback_handler_remove (void);
#ifdef __cplusplus
}
#endif
#endif /* EDITLINE_H_ */

12
vendor/editline/libeditline.pc.in vendored Normal file
View file

@ -0,0 +1,12 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: @PACKAGE@
Description: A small line editing library without termcap/curses
Version: @VERSION@
Requires:
Libs: -L${libdir} -leditline
Cflags: -I${includedir}

1
vendor/editline/m4/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*.m4

3
vendor/editline/man/Makefile.am vendored Normal file
View file

@ -0,0 +1,3 @@
AUTOMAKE_OPTIONS = foreign
dist_man_MANS = editline.3

274
vendor/editline/man/editline.3 vendored Normal file
View file

@ -0,0 +1,274 @@
.Dd April 27, 2019
.Dt EDITLINE 3
.Os
.Sh NAME
.Nm editline
.Nd command-line editing library with history
.Sh LIBRARY
.Lb libeditline
.Sh SYNOPSIS
.In editline.h
.Fn "char *readline" "const char *prompt"
.Fn "void add_history" "const char *line"
.Fn "int read_history" "const char *filename"
.Fn "int write_history" "const char *filename"
.Sh DESCRIPTION
.Nm
is a library that provides n line-editing interface with history. It
is intended to be functionally equivalent with the
.Nm readline
library provided by the Free Software Foundation, but much smaller. The
bulk of this manual page describes the basic user interface. More APIs,
both native and for
.Nm readline
compatibility ,
are also available. See the
.Cm editline.h
header file for details.
.Pp
The
.Fn readline
function displays the given
.Fa prompt
on stdout, waits for user input on stdin and then returns a line of text
with the trailing newline removed. The data is returned in a buffer
allocated with
.Xr malloc 3 ,
so the space should be released with
.Xr free 3
when the calling program is done with it.
.Pp
Each line returned is automatically saved in the internal history list,
unless it happens to be equal to the previous line. This is
configurable if you are building editline from source, i.e. if you would
rather like to call
.Fn add_history
manually.
.Pp
The
.Fn read_history
and
.Fn write_history
functions can be used to load and store the history of your application.
.Em Note:
these APIs do not do any tilde or environment variable expansion of the
given filename.
.Ss User Interface
A program that uses this library provides a simple emacs-like editing
interface to its users. A line may be edited before it is sent to the
calling program by typing either control characters or escape sequences.
A control character, shown as a caret followed by a letter, is typed by
holding down the control key while the letter is typed. For example,
.Cm ^A
is a control-A. An escape sequence is entered by typing the escape key
followed by one or more characters. The escape key is abbreviated as
.Cm ESC .
Note that unlike control keys, case matters in escape sequences;
.Cm ESC F
is not the same as
.Cm ESC f .
.Pp
An editing command may be typed anywhere on the line, not just at the
beginning. In addition, a return may also be typed anywhere on the
line, not just at the end.
.Pp
Most editing commands may be given a repeat count,
.Ar n ,
where
.Ar n
is a number. To enter a repeat count, type the escape key, the number,
and then the command to execute. For example,
.Cm ESC 4 ^f
moves forward four characters. If a command may be given a repeat count
then the text
.Cm [n]
is given at the end of its description.
.Pp
The following control characters are accepted:
.Pp
.Bl -tag -width "ESC DEL " -compact
.It ^A
Move to the beginning of the line
.It ^B
Move left (backwards) [n]
.It ^D
Delete character [n]
.It ^E
Move to end of line
.It ^F
Move right (forwards) [n]
.It ^G
Ring the bell
.It ^H
Delete character before cursor (backspace key) [n]
.It ^I
Complete filename (tab key); see below
.It ^J
Done with line (return key)
.It ^K
Kill to end of line (or column [n])
.It ^L
Redisplay line
.It ^M
Done with line (alternate return key)
.It ^N
Get next line from history [n]
.It ^P
Get previous line from history [n]
.It ^R
Search backward (forward if [n]) through history for text; prefixing the
string with a caret (^) forces it to match only at the beginning of a
history line
.It ^T
Transpose characters
.It ^V
Insert next character, even if it is an edit command
.It ^W
Wipe to the mark
.It ^X^X
Exchange current location and mark
.It ^Y
Yank back last killed text
.It ^[
Start an escape sequence (escape key)
.It ^]c
Move forward to next character
.Cm c
.It ^?
Delete character before cursor (delete key) [n]
.El
.Pp
The following escape sequences are provided:
.Pp
.Bl -tag -width "ESC DEL " -compact
.It ESC ^H
Delete previous word (backspace key) [n]
.It ESC DEL
Delete previous word (delete key) [n]
.It ESC SP
Set the mark (space key); see ^X^X and ^Y above
.It ESC\ .
Get the last (or [n]'th) word from previous line
.It ESC\ ?
Show possible completions; see below
.It ESC <
Move to start of history
.It ESC >
Move to end of history
.It ESC b
Move backward a word [n]
.It ESC d
Delete word under cursor [n]
.It ESC f
Move forward a word [n]
.It ESC l
Make word lowercase [n]
.It ESC m
Toggle if 8bit chars display normally or with an
.Ar M-
prefix
.It ESC u
Make word uppercase [n]
.It ESC y
Yank back last killed text
.It ESC v
Show library version
.It ESC w
Make area up to mark yankable
.It ESC nn
Set repeat count to the number nn
.It ESC C
Read from environment variable
.Ar $C ,
where
.Ar C
is an uppercase letter
.El
.Pp
The
.Nm
library has a small macro facility. If you type the escape key followed
by an uppercase letter,
.Ar C ,
then the contents of the environment variable
.Ar $C
are read in as if you had typed them at the keyboard. For example, if
the variable
.Ar $L
contains the following:
.Pp
.Dl ^A^Kecho '^V^[[H^V^[[2J'^M
.Pp
Then typing
.Cm ESC L
will move to the beginning of the line, kill the entire line, enter the
echo command needed to clear the terminal (if your terminal is like a
VT-100), and send the line back to the shell.
.Pp
The
.Nm
library also does filename completion. Suppose the root directory has
the following files in it:
.Pp
.Dl bin vmunix
.Dl core vmunix.old
.Pp
If you type
.Cm rm /v
and then the tab key,
.Nm
will then finish off as much of the name as possible by adding
.Ar munix .
Because the name is not unique, it will then beep. If you type the
escape key and a question mark, it will display the two choices. If you
then type a period and a tab, the library will finish off the filename
for you:
.Pp
.Bd -ragged -offset indent
rm /v[TAB]
.Em munix
\&.[TAB]
.Em old
.Ed
.Pp
The tab key is shown by [TAB] and the automatically-entered text
is shown in italics, or underline.
.Sh USAGE
To include
.Nm
in your program, call it as you do any other function and link your
program with
.Ar -leditline .
.Ss Example
The following brief example lets you enter a line and edit it, then displays it.
.Pp
.Bd -literal -offset indent
#include <stdio.h>
#include <stdlib.h>
#include <editline.h>
int main(void)
{
char *p;
while ((p = readline("CLI> "))) {
puts(p);
free(p);
}
return 0;
}
.El
.Sh AUTHORS
The original editline library was posted to comp.sources.unix newsgroup
by created by Simmule R. Turner and Rich Salz in 1992. It now exists in
several forks: Debian, Minix, Heimdal, Festival speech tools, Mozilla,
Google Gadgets for Linux, and many other places. The original manual
page was made by David W. Sanderson.
.Pp
This version was originally based on the Minix 2 sources, but has since
evolved to include patches from all relevant forks. It is currently
maintained by Joachim Nilsson at GitHub,
.Aq http://github.com/troglobit/editline
.Sh BUGS
Does not handle multiple lines or unicode characters well.

2
vendor/editline/src/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
libeditline.a
libeditline.la

6
vendor/editline/src/Makefile.am vendored Normal file
View file

@ -0,0 +1,6 @@
lib_LTLIBRARIES = libeditline.la
libeditline_la_SOURCES = editline.c editline.h complete.c sysunix.c unix.h
libeditline_la_CFLAGS = -std=gnu99
libeditline_la_CFLAGS += -W -Wall -Wextra -Wundef -Wunused -Wstrict-prototypes
libeditline_la_CFLAGS += -Werror-implicit-function-declaration -Wshadow -Wcast-qual
libeditline_la_LDFLAGS = $(AM_LDFLAGS) -version-info 1:0:0

442
vendor/editline/src/complete.c vendored Normal file
View file

@ -0,0 +1,442 @@
/* History and file completion functions for editline library.
*
* Copyright (c) 1992, 1993 Simmule Turner and Rich Salz
* All rights reserved.
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or of the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
* 1. The authors are not responsible for the consequences of use of this
* software, no matter how awful, even if they arise from flaws in it.
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Since few users ever read sources,
* credits must appear in the documentation.
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software. Since few users
* ever read sources, credits must appear in the documentation.
* 4. This notice may not be removed or altered.
*/
#include <ctype.h>
#include "editline.h"
#define MAX_TOTAL_MATCHES (256 << sizeof(char *))
int rl_attempted_completion_over = 0;
rl_completion_func_t *rl_attempted_completion_function = NULL;
rl_compentry_func_t *rl_completion_entry_function = NULL;
/* Wrap strcmp() for qsort() -- weird construct to pass -Wcast-qual */
static int compare(const void *p1, const void *p2)
{
char *const *v1 = (char *const *)p1;
char *const *v2 = (char *const *)p2;
return strcmp(*v1, *v2);
}
/* Fill in *avp with an array of names that match file, up to its length.
* Ignore . and .. . */
static int FindMatches(char *dir, char *file, char ***avp)
{
char **av;
char **word;
char *p;
DIR *dp;
DIRENTRY *ep;
size_t ac;
size_t len;
size_t choices;
size_t total;
if ((dp = opendir(dir)) == NULL)
return 0;
av = NULL;
ac = 0;
len = strlen(file);
choices = 0;
total = 0;
while ((ep = readdir(dp)) != NULL) {
p = ep->d_name;
if (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0')))
continue;
if (len && strncmp(p, file, len) != 0)
continue;
choices++;
if ((total += strlen(p)) > MAX_TOTAL_MATCHES) {
/* This is a bit too much. */
while (ac > 0) free(av[--ac]);
continue;
}
if ((ac % MEM_INC) == 0) {
word = malloc(sizeof(char *) * (ac + MEM_INC));
if (!word) {
total = 0;
break;
}
if (ac) {
memcpy(word, av, ac * sizeof(char *));
free(av);
}
*avp = av = word;
}
if ((av[ac] = strdup(p)) == NULL) {
if (ac == 0)
free(av);
total = 0;
break;
}
ac++;
}
/* Clean up and return. */
closedir(dp);
if (total > MAX_TOTAL_MATCHES) {
char many[sizeof(total) * 3];
p = many + sizeof(many);
*--p = '\0';
while (choices > 0) {
*--p = '0' + choices % 10;
choices /= 10;
}
while (p > many + sizeof(many) - 8)
*--p = ' ';
if ((p = strdup(p)) != NULL)
av[ac++] = p;
if ((p = strdup("choices")) != NULL)
av[ac++] = p;
} else {
if (ac)
qsort(av, ac, sizeof(char *), compare);
}
return ac;
}
/* Split a pathname into allocated directory and trailing filename parts. */
static int SplitPath(const char *path, char **dirpart, char **filepart)
{
static char DOT[] = ".";
char *dpart;
char *fpart;
if ((fpart = strrchr(path, '/')) == NULL) {
if ((dpart = strdup(DOT)) == NULL)
return -1;
if ((fpart = strdup(path)) == NULL) {
free(dpart);
return -1;
}
} else {
if ((dpart = strdup(path)) == NULL)
return -1;
dpart[fpart - path + 1] = '\0';
if ((fpart = strdup(fpart + 1)) == NULL) {
free(dpart);
return -1;
}
}
*dirpart = dpart;
*filepart = fpart;
return 0;
}
static rl_complete_func_t *el_complete_func = NULL;
/* For compatibility with the Heimdal project. */
rl_complete_func_t *rl_set_complete_func(rl_complete_func_t *func)
{
rl_complete_func_t *old = el_complete_func;
el_complete_func = func;
return old;
}
/* Attempt to complete the pathname, returning an allocated copy.
* Fill in *match if we completed it, or set it to 0 if ambiguous. */
char *el_filename_complete(char *pathname, int *match)
{
char **av;
char *dir;
char *file;
char *path;
char *p;
size_t ac;
size_t end;
size_t i;
size_t j;
size_t len;
if (SplitPath((const char *)pathname, &dir, &file) < 0)
return NULL;
if ((ac = FindMatches(dir, file, &av)) == 0) {
free(dir);
free(file);
return NULL;
}
p = NULL;
len = strlen(file);
if (ac == 1) {
/* Exactly one match -- finish it off. */
*match = 1;
j = strlen(av[0]) - len + 2;
p = malloc(sizeof(char) * (j + 1));
if (p) {
memcpy(p, av[0] + len, j);
len = strlen(dir) + strlen(av[0]) + 2;
path = malloc(sizeof(char) * len);
if (path) {
snprintf(path, len, "%s/%s", dir, av[0]);
rl_add_slash(path, p);
free(path);
}
}
} else {
*match = 0;
if (len) {
/* Find largest matching substring. */
for (i = len, end = strlen(av[0]); i < end; i++) {
for (j = 1; j < ac; j++) {
if (av[0][i] != av[j][i])
goto breakout;
}
}
breakout:
if (i > len) {
j = i - len + 1;
p = malloc(sizeof(char) * j);
if (p) {
memcpy(p, av[0] + len, j);
p[j - 1] = '\0';
}
}
}
}
/* Clean up and return. */
free(dir);
free(file);
for (i = 0; i < ac; i++)
free(av[i]);
free(av);
return p;
}
char *rl_filename_completion_function(const char *text, int state)
{
char *dir;
char *file;
static char **av;
static size_t i, ac;
if (!state) {
if (SplitPath(text, &dir, &file) < 0)
return NULL;
ac = FindMatches(dir, file, &av);
free(dir);
free(file);
if (!ac)
return NULL;
i = 0;
}
if (i < ac)
return av[i++];
do {
free(av[--i]);
} while (i > 0);
return NULL;
}
/* Similar to el_find_word(), but used by GNU Readline API */
static char *rl_find_token(size_t *len)
{
char *ptr;
int pos;
for (pos = rl_point; pos < rl_end; pos++) {
if (isspace(rl_line_buffer[pos])) {
if (pos > 0)
pos--;
break;
}
}
ptr = &rl_line_buffer[pos];
while (pos >= 0 && !isspace(rl_line_buffer[pos])) {
if (pos == 0)
break;
pos--;
}
if (ptr != &rl_line_buffer[pos]) {
*len = (size_t)(ptr - &rl_line_buffer[pos]);
return &rl_line_buffer[pos];
}
return NULL;
}
/*
* "uses an application-supplied generator function to generate the list
* of possible matches, and then returns the array of these matches. The
* caller should place the address of its generator function in
* rl_completion_entry_function"
*/
char **rl_completion_matches(const char *token, rl_compentry_func_t *generator)
{
int state = 0, num = 0;
char **array, *entry;
if (!generator) {
generator = rl_completion_entry_function;
if (!generator)
generator = rl_filename_completion_function;
}
if (!generator)
return NULL;
array = malloc(512 * sizeof(char *));
if (!array)
return NULL;
while (num < 511 && (entry = generator(token, state))) {
state = 1;
array[num++] = entry;
}
array[num] = NULL;
if (!num) {
free(array);
return NULL;
}
return array;
}
static char *complete(char *token, int *match)
{
size_t len = 0;
char *word, **words = NULL;
int start, end;
word = rl_find_token(&len);
if (!word)
goto fallback;
start = word - rl_line_buffer;
end = start + len;
word = strndup(word, len);
if (!word)
goto fallback;
rl_attempted_completion_over = 0;
words = rl_attempted_completion_function(word, start, end);
if (!rl_attempted_completion_over && !words)
words = rl_completion_matches(word, NULL);
if (words) {
int i = 0;
free(word);
word = NULL;
if (words[0])
word = strdup(words[0] + len);
while (words[i])
free(words[i++]);
free(words);
if (word)
return word;
}
fallback:
return el_filename_complete(token, match);
}
/*
* First check for editline specific custom completion function, then
* for any GNU Readline compat, then fallback to filename completion.
*/
char *rl_complete(char *token, int *match)
{
if (el_complete_func)
return el_complete_func(token, match);
if (rl_attempted_completion_function)
return complete(token, match);
return el_filename_complete(token, match);
}
static rl_list_possib_func_t *el_list_possib_func = NULL;
/* For compatibility with the Heimdal project. */
rl_list_possib_func_t *rl_set_list_possib_func(rl_list_possib_func_t *func)
{
rl_list_possib_func_t *old = el_list_possib_func;
el_list_possib_func = func;
return old;
}
/* Default possible completions. */
int el_filename_list_possib(char *pathname, char ***av)
{
char *dir;
char *file;
int ac;
if (SplitPath(pathname, &dir, &file) < 0)
return 0;
ac = FindMatches(dir, file, av);
free(dir);
free(file);
return ac;
}
/* Return all possible completions. */
int rl_list_possib(char *token, char ***av)
{
if (el_list_possib_func)
return el_list_possib_func(token, av);
return el_filename_list_possib(token, av);
}
/**
* Local Variables:
* c-file-style: "k&r"
* c-basic-offset: 4
* End:
*/

1969
vendor/editline/src/editline.c vendored Normal file

File diff suppressed because it is too large Load diff

101
vendor/editline/src/editline.h vendored Normal file
View file

@ -0,0 +1,101 @@
/* Internal header file for editline library.
*
* Copyright (c) 1992, 1993 Simmule Turner and Rich Salz
* All rights reserved.
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or of the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
* 1. The authors are not responsible for the consequences of use of this
* software, no matter how awful, even if they arise from flaws in it.
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Since few users ever read sources,
* credits must appear in the documentation.
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software. Since few users
* ever read sources, credits must appear in the documentation.
* 4. This notice may not be removed or altered.
*/
#ifndef EDITLINE_PRIVATE_H_
#define EDITLINE_PRIVATE_H_
#include <config.h>
#include <stdio.h>
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#ifdef SYS_UNIX
#include "unix.h"
#endif
#ifdef SYS_OS9
#include "os9.h"
#endif
/* The following two are for TIOCGWINSZ */
#ifdef HAVE_TERMIOS_H
# include <termios.h>
#endif
#ifdef GWINSZ_IN_SYS_IOCTL
# include <sys/ioctl.h>
#endif
#define MEM_INC 64
#define SCREEN_INC 256
/* From The Practice of Programming, by Kernighan and Pike */
#ifndef NELEMS
#define NELEMS(array) (sizeof(array) / sizeof(array[0]))
#endif
/*
** Variables and routines internal to this package.
*/
extern int rl_eof;
extern int rl_erase;
extern int rl_intr;
extern int rl_kill;
extern int rl_quit;
#ifdef CONFIG_SIGSTOP
extern int rl_susp;
#endif
void rl_ttyset(int Reset);
void rl_add_slash(char *path, char *p);
char *rl_complete(char *token, int *match);
int rl_list_possib(char *token, char ***av);
#ifndef HAVE_STDLIB_H
extern char *getenv(const char *name);
extern char *malloc(size_t size);
extern char *realloc(void *ptr, size_t size);
extern char *memcpy(void *dest, const void *src, size_t n);
extern char *strcat(char *dest, const char *src);
extern char *strchr(const char *s, int c);
extern char *strrchr(const char *s, int c);
extern char *strcpy(char *dest, const char *src);
extern char *strdup(const char *s);
extern int strcmp(const char *s1, const char *s2);
extern int strlen(const char *s);
extern int strncmp(const char *s1, const char *s2, size_t n);
#endif/* !HAVE_STDLIB_H */
#ifndef HAVE_STRDUP
extern char *strdup(const char *s);
#endif
#include "../include/editline.h"
#endif /* EDITLINE_PRIVATE_H_ */

26
vendor/editline/src/os9.h vendored Normal file
View file

@ -0,0 +1,26 @@
/* Editline system header file for OS-9 (on 68k).
*
* Copyright (c) 1992, 1993 Simmule Turner and Rich Salz
* All rights reserved.
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or of the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
* 1. The authors are not responsible for the consequences of use of this
* software, no matter how awful, even if they arise from flaws in it.
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Since few users ever read sources,
* credits must appear in the documentation.
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software. Since few users
* ever read sources, credits must appear in the documentation.
* 4. This notice may not be removed or altered.
*/
#define CRLF "\r\l"
#include <dir.h>
typedef struct direct DIRENTRY;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1 @@
libeditline.so.1.0.0

Binary file not shown.

64
vendor/editline/src/sysos9.c vendored Normal file
View file

@ -0,0 +1,64 @@
/* OS-9 (on 68k) system-dependant routines for editline library.
*
* Copyright (c) 1992, 1993 Simmule Turner and Rich Salz
* All rights reserved.
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or of the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
* 1. The authors are not responsible for the consequences of use of this
* software, no matter how awful, even if they arise from flaws in it.
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Since few users ever read sources,
* credits must appear in the documentation.
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software. Since few users
* ever read sources, credits must appear in the documentation.
* 4. This notice may not be removed or altered.
*/
#include "editline.h"
#include <sgstat.h>
#include <modes.h>
void rl_ttyset(int Reset)
{
static struct sgbuf old;
struct sgbuf new;
if (Reset == 0) {
_gs_opt(0, &old);
_gs_opt(0, &new);
new.sg_backsp = 0; new.sg_delete = 0; new.sg_echo = 0;
new.sg_alf = 0; new.sg_nulls = 0; new.sg_pause = 0;
new.sg_page = 0; new.sg_bspch = 0; new.sg_dlnch = 0;
new.sg_eorch = 0; new.sg_eofch = 0; new.sg_rlnch = 0;
new.sg_dulnch = 0; new.sg_psch = 0; new.sg_kbich = 0;
new.sg_kbach = 0; new.sg_bsech = 0; new.sg_bellch = 0;
new.sg_xon = 0; new.sg_xoff = 0; new.sg_tabcr = 0;
new.sg_tabsiz = 0;
_ss_opt(0, &new);
rl_erase = old.sg_bspch;
rl_kill = old.sg_dlnch;
rl_eof = old.sg_eofch;
rl_intr = old.sg_kbich;
rl_quit = -1;
}
else {
_ss_opt(0, &old);
}
}
void rl_add_slash(char *path, char *p)
{
strcat(p, access(path, S_IREAD | S_IFDIR) ? " " : "/");
}
/**
* Local Variables:
* c-file-style: "k&r"
* c-basic-offset: 4
* End:
*/

251
vendor/editline/src/sysunix.c vendored Normal file
View file

@ -0,0 +1,251 @@
/* Unix system-dependant routines for editline library.
*
* Copyright (c) 1992, 1993 Simmule Turner and Rich Salz
* All rights reserved.
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or of the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
* 1. The authors are not responsible for the consequences of use of this
* software, no matter how awful, even if they arise from flaws in it.
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Since few users ever read sources,
* credits must appear in the documentation.
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software. Since few users
* ever read sources, credits must appear in the documentation.
* 4. This notice may not be removed or altered.
*/
#include <errno.h>
#include "editline.h"
#ifndef HAVE_TCGETATTR
/* Wrapper for ioctl syscalls to restart on signal */
static int ioctl_wrap(int fd, int req, void *arg)
{
int result, retries = 3;
while (-1 == (result = ioctl(fd, req, arg)) && retries > 0) {
retries--;
if (EINTR == errno)
continue;
break;
}
return result;
}
#endif
/* Prefer termios over the others since it is likely the most portable. */
#if defined(HAVE_TCGETATTR)
#include <termios.h>
/* Wrapper for tcgetattr */
static int getattr(int fd, struct termios *arg)
{
int result, retries = 3;
while (-1 == (result = tcgetattr(fd, arg)) && retries > 0) {
retries--;
if (EINTR == errno)
continue;
break;
}
return result;
}
/* Wrapper for tcgetattr */
static int setattr(int fd, int opt, const struct termios *arg)
{
int result, retries = 3;
while (-1 == (result = tcsetattr(fd, opt, arg)) && retries > 0) {
retries--;
if (EINTR == errno)
continue;
break;
}
return result;
}
void rl_ttyset(int Reset)
{
static struct termios old;
struct termios new;
if (!Reset) {
if (-1 == getattr(0, &old))
perror("Failed tcgetattr()");
rl_erase = old.c_cc[VERASE];
rl_kill = old.c_cc[VKILL];
rl_eof = old.c_cc[VEOF];
rl_intr = old.c_cc[VINTR];
rl_quit = old.c_cc[VQUIT];
#ifdef CONFIG_SIGSTOP
rl_susp = old.c_cc[VSUSP];
#endif
new = old;
new.c_lflag &= ~(ECHO | ICANON | ISIG);
new.c_iflag &= ~INPCK;
if (rl_meta_chars)
new.c_iflag |= ISTRIP;
else
new.c_iflag &= ~ISTRIP;
new.c_cc[VMIN] = 1;
new.c_cc[VTIME] = 0;
if (-1 == setattr(0, TCSADRAIN, &new))
perror("Failed tcsetattr(TCSADRAIN)");
} else {
if (-1 == setattr(0, TCSADRAIN, &old))
perror("Failed tcsetattr(TCSADRAIN)");
}
}
#elif defined(HAVE_TERMIO_H)
#include <termio.h>
void rl_ttyset(int Reset)
{
static struct termio old;
struct termio new;
if (!Reset) {
if (-1 == ioctl_wrap(0, TCGETA, &old))
perror("Failed ioctl(TCGETA)");
rl_erase = old.c_cc[VERASE];
rl_kill = old.c_cc[VKILL];
rl_eof = old.c_cc[VEOF];
rl_intr = old.c_cc[VINTR];
rl_quit = old.c_cc[VQUIT];
#ifdef CONFIG_SIGSTOP
rl_susp = old.c_cc[VSUSP];
#endif
new = old;
new.c_lflag &= ~(ECHO | ICANON | ISIG);
new.c_iflag &= ~INPCK;
if (rl_meta_chars)
new.c_iflag |= ISTRIP;
else
new.c_iflag &= ~ISTRIP;
new.c_cc[VMIN] = 1;
new.c_cc[VTIME] = 0;
if (-1 == ioctl_wrap(0, TCSETAW, &new))
perror("Failed ioctl(TCSETAW)");
} else {
if (-1 == ioctl_wrap(0, TCSETAW, &old))
perror("Failed ioctl(TCSETAW)");
}
}
#elif defined(HAVE_SGTTY_H)
#include <sgtty.h>
void rl_ttyset(int Reset)
{
static struct sgttyb old_sgttyb;
static struct tchars old_tchars;
struct sgttyb new_sgttyb;
struct tchars new_tchars;
#ifdef CONFIG_SIGSTOP
struct ltchars old_ltchars;
#endif
if (!Reset) {
if (-1 == ioctl_wrap(0, TIOCGETP, &old_sgttyb))
perror("Failed TIOCGETP");
rl_erase = old_sgttyb.sg_erase;
rl_kill = old_sgttyb.sg_kill;
if (-1 == ioctl_wrap(0, TIOCGETC, &old_tchars))
perror("Failed TIOCGETC");
rl_eof = old_tchars.t_eofc;
rl_intr = old_tchars.t_intrc;
rl_quit = old_tchars.t_quitc;
#ifdef CONFIG_SIGSTOP
if (-1 == ioctl_wrap(0, TIOCGLTC, &old_ltchars))
perror("Failed TIOCGLTC");
rl_susp = old_ltchars.t_suspc;
#endif
new_sgttyb = old_sgttyb;
new_sgttyb.sg_flags &= ~ECHO;
new_sgttyb.sg_flags |= RAW;
if (rl_meta_chars)
new_sgttyb.sg_flags &= ~PASS8;
else
new_sgttyb.sg_flags |= PASS8;
if (-1 == ioctl_wrap(0, TIOCSETP, &new_sgttyb))
perror("Failed TIOCSETP");
new_tchars = old_tchars;
new_tchars.t_intrc = -1;
new_tchars.t_quitc = -1;
if (-1 == ioctl_wrap(0, TIOCSETC, &new_tchars))
perror("Failed TIOCSETC");
} else {
if (-1 == ioctl_wrap(0, TIOCSETP, &old_sgttyb))
perror("Failed TIOCSETP");
if (-1 == ioctl_wrap(0, TIOCSETC, &old_tchars))
perror("Failed TIOCSETC");
}
}
#else /* Neither HAVE_SGTTY_H, HAVE_TERMIO_H or HAVE_TCGETATTR */
#error Unsupported platform, missing tcgetattr(), termio.h and sgtty.h
#endif /* Neither HAVE_SGTTY_H, HAVE_TERMIO_H or HAVE_TCGETATTR */
#ifndef HAVE_STRDUP
/* Return an allocated copy of a string. */
char *strdup(const char *s)
{
size_t len;
char *ptr;
if (!s)
return NULL;
len = strlen(s) + 1;
ptr = malloc(len);
if (ptr)
return memcpy(ptr, s, len);
return NULL;
}
#endif
void rl_add_slash(char *path, char *p)
{
struct stat Sb;
if (stat(path, &Sb) >= 0)
strcat(p, S_ISDIR(Sb.st_mode) ? "/" : " ");
}
/**
* Local Variables:
* c-file-style: "k&r"
* c-basic-offset: 4
* End:
*/

36
vendor/editline/src/unix.h vendored Normal file
View file

@ -0,0 +1,36 @@
/* Editline system header file for Unix.
*
* Copyright (c) 1992, 1993 Simmule Turner and Rich Salz
* All rights reserved.
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or of the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
* 1. The authors are not responsible for the consequences of use of this
* software, no matter how awful, even if they arise from flaws in it.
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Since few users ever read sources,
* credits must appear in the documentation.
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software. Since few users
* ever read sources, credits must appear in the documentation.
* 4. This notice may not be removed or altered.
*/
#ifndef EDITLINE_UNIX_H_
#define EDITLINE_UNIX_H_
#define CRLF "\r\n"
#define FORWARD STATIC
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
typedef struct dirent DIRENTRY;
#endif /* EDITLINE_UNIX_H_ */

View file

@ -0,0 +1 @@
cmd='/home/pbattu/freelance/gitlab/peerplays/libraries/fc/vendor/editline/configure;--prefix=/home/pbattu/freelance/gitlab/peerplays/libraries/fc/vendor/editline'

View file

@ -0,0 +1 @@
cmd='@cmd@'

View file

@ -1,4 +1,7 @@
HEAD HEAD
- Bug: Change default listen backlog from 0 to socket_base::max_connections.
#549. Thank you derwassi and zwelab for reporting and na1pir for providing
access to hardware to debug the issue.
0.7.0 - 2016-02-22 0.7.0 - 2016-02-22
- MINOR BREAKING SOCKET POLICY CHANGE: Asio transport socket policy method - MINOR BREAKING SOCKET POLICY CHANGE: Asio transport socket policy method

View file

@ -30,6 +30,8 @@
#include "connection_tu2.hpp" #include "connection_tu2.hpp"
#include <algorithm>
// Include special debugging transport // Include special debugging transport
//#include <websocketpp/config/minimal_client.hpp> //#include <websocketpp/config/minimal_client.hpp>
#include <websocketpp/transport/debug/endpoint.hpp> #include <websocketpp/transport/debug/endpoint.hpp>
@ -172,6 +174,20 @@ void http_func(server* s, websocketpp::connection_hdl hdl) {
BOOST_CHECK_EQUAL(con->get_response_msg(), status_code::get_string(status_code::ok)); BOOST_CHECK_EQUAL(con->get_response_msg(), status_code::get_string(status_code::ok));
} }
void http_func_with_move(server* s, websocketpp::connection_hdl hdl) {
using namespace websocketpp::http;
server::connection_ptr con = s->get_con_from_hdl(hdl);
std::string res = con->get_resource();
con->set_body( std::move(res) );
con->set_status(status_code::ok);
BOOST_CHECK_EQUAL(con->get_response_code(), status_code::ok);
BOOST_CHECK_EQUAL(con->get_response_msg(), status_code::get_string(status_code::ok));
}
void defer_http_func(server* s, bool * deferred, websocketpp::connection_hdl hdl) { void defer_http_func(server* s, bool * deferred, websocketpp::connection_hdl hdl) {
*deferred = true; *deferred = true;
@ -237,6 +253,18 @@ BOOST_AUTO_TEST_CASE( http_request ) {
BOOST_CHECK_EQUAL(run_server_test(s,input), output); BOOST_CHECK_EQUAL(run_server_test(s,input), output);
} }
BOOST_AUTO_TEST_CASE( http_request_with_move ) {
std::string input = "GET /foo/bar HTTP/1.1\r\nHost: www.example.com\r\nOrigin: http://www.example.com\r\n\r\n";
std::string output = "HTTP/1.1 200 OK\r\nContent-Length: 8\r\nServer: ";
output+=websocketpp::user_agent;
output+="\r\n\r\n/foo/bar";
server s;
s.set_http_handler(bind(&http_func_with_move,&s,::_1));
BOOST_CHECK_EQUAL(run_server_test(s,input), output);
}
BOOST_AUTO_TEST_CASE( deferred_http_request ) { BOOST_AUTO_TEST_CASE( deferred_http_request ) {
std::string input = "GET /foo/bar HTTP/1.1\r\nHost: www.example.com\r\nOrigin: http://www.example.com\r\n\r\n"; std::string input = "GET /foo/bar HTTP/1.1\r\nHost: www.example.com\r\nOrigin: http://www.example.com\r\n\r\n";
std::string output = "HTTP/1.1 200 OK\r\nContent-Length: 8\r\nServer: "; std::string output = "HTTP/1.1 200 OK\r\nContent-Length: 8\r\nServer: ";

View file

@ -1041,6 +1041,7 @@ public:
* @see websocketpp::http::response::set_body * @see websocketpp::http::response::set_body
*/ */
void set_body(std::string const & value); void set_body(std::string const & value);
void set_body( std::string&& value );
/// Append a header /// Append a header
/** /**

View file

@ -32,6 +32,7 @@
#include <websocketpp/common/cpp11.hpp> #include <websocketpp/common/cpp11.hpp>
#include <websocketpp/common/memory.hpp> #include <websocketpp/common/memory.hpp>
#include <websocketpp/common/platforms.hpp> #include <websocketpp/common/platforms.hpp>
#include <websocketpp/common/stdint.hpp>
#include <websocketpp/common/system_error.hpp> #include <websocketpp/common/system_error.hpp>
#include <websocketpp/error.hpp> #include <websocketpp/error.hpp>
@ -46,7 +47,7 @@
namespace websocketpp { namespace websocketpp {
namespace extensions { namespace extensions {
/// Implementation of the draft permessage-deflate WebSocket extension /// Implementation of RFC 7692, the permessage-deflate WebSocket extension
/** /**
* ### permessage-deflate interface * ### permessage-deflate interface
* *
@ -174,18 +175,30 @@ namespace websocketpp {
namespace extensions { namespace extensions {
namespace permessage_deflate { namespace permessage_deflate {
/// Default value for server_max_window_bits as defined by draft 17 /// Default value for server_max_window_bits as defined by RFC 7692
static uint8_t const default_server_max_window_bits = 15; static uint8_t const default_server_max_window_bits = 15;
/// Minimum value for server_max_window_bits as defined by draft 17 /// Minimum value for server_max_window_bits as defined by RFC 7692
/**
* NOTE: A value of 8 is not actually supported by zlib, the deflate
* library that WebSocket++ uses. To preserve backwards compatibility
* with RFC 7692 and previous versions of the library a value of 8
* is accepted by the library but will always be negotiated as 9.
*/
static uint8_t const min_server_max_window_bits = 8; static uint8_t const min_server_max_window_bits = 8;
/// Maximum value for server_max_window_bits as defined by draft 17 /// Maximum value for server_max_window_bits as defined by RFC 7692
static uint8_t const max_server_max_window_bits = 15; static uint8_t const max_server_max_window_bits = 15;
/// Default value for client_max_window_bits as defined by draft 17 /// Default value for client_max_window_bits as defined by RFC 7692
static uint8_t const default_client_max_window_bits = 15; static uint8_t const default_client_max_window_bits = 15;
/// Minimum value for client_max_window_bits as defined by draft 17 /// Minimum value for client_max_window_bits as defined by RFC 7692
/**
* NOTE: A value of 8 is not actually supported by zlib, the deflate
* library that WebSocket++ uses. To preserve backwards compatibility
* with RFC 7692 and previous versions of the library a value of 8
* is accepted by the library but will always be negotiated as 9.
*/
static uint8_t const min_client_max_window_bits = 8; static uint8_t const min_client_max_window_bits = 8;
/// Maximum value for client_max_window_bits as defined by draft 17 /// Maximum value for client_max_window_bits as defined by RFC 7692
static uint8_t const max_client_max_window_bits = 15; static uint8_t const max_client_max_window_bits = 15;
namespace mode { namespace mode {
@ -213,7 +226,7 @@ public:
, m_server_max_window_bits_mode(mode::accept) , m_server_max_window_bits_mode(mode::accept)
, m_client_max_window_bits_mode(mode::accept) , m_client_max_window_bits_mode(mode::accept)
, m_initialized(false) , m_initialized(false)
, m_compress_buffer_size(16384) , m_compress_buffer_size(8192)
{ {
m_dstate.zalloc = Z_NULL; m_dstate.zalloc = Z_NULL;
m_dstate.zfree = Z_NULL; m_dstate.zfree = Z_NULL;
@ -292,6 +305,7 @@ public:
} }
m_compress_buffer.reset(new unsigned char[m_compress_buffer_size]); m_compress_buffer.reset(new unsigned char[m_compress_buffer_size]);
m_decompress_buffer.reset(new unsigned char[m_compress_buffer_size]);
if ((m_server_no_context_takeover && is_server) || if ((m_server_no_context_takeover && is_server) ||
(m_client_no_context_takeover && !is_server)) (m_client_no_context_takeover && !is_server))
{ {
@ -372,7 +386,7 @@ public:
/** /**
* The bits setting is the base 2 logarithm of the maximum window size that * The bits setting is the base 2 logarithm of the maximum window size that
* the server must use to compress outgoing messages. The permitted range * the server must use to compress outgoing messages. The permitted range
* is 8 to 15 inclusive. 8 represents a 256 byte window and 15 a 32KiB * is 9 to 15 inclusive. 9 represents a 512 byte window and 15 a 32KiB
* window. The default setting is 15. * window. The default setting is 15.
* *
* Mode Options: * Mode Options:
@ -386,6 +400,14 @@ public:
* adjusted by the server. A server may unilaterally set this value without * adjusted by the server. A server may unilaterally set this value without
* client support. * client support.
* *
* NOTE: The permessage-deflate spec specifies that a value of 8 is allowed.
* Prior to version 0.8.0 a value of 8 was also allowed by this library.
* zlib, the deflate compression library that WebSocket++ uses has always
* silently adjusted a value of 8 to 9. In recent versions of zlib (1.2.9
* and greater) a value of 8 is now explicitly rejected. WebSocket++ 0.8.0
* continues to perform the 8->9 conversion for backwards compatibility
* purposes but this should be considered deprecated functionality.
*
* @param bits The size to request for the outgoing window size * @param bits The size to request for the outgoing window size
* @param mode The mode to use for negotiating this parameter * @param mode The mode to use for negotiating this parameter
* @return A status code * @return A status code
@ -394,6 +416,12 @@ public:
if (bits < min_server_max_window_bits || bits > max_server_max_window_bits) { if (bits < min_server_max_window_bits || bits > max_server_max_window_bits) {
return error::make_error_code(error::invalid_max_window_bits); return error::make_error_code(error::invalid_max_window_bits);
} }
// See note in doc comment above about what is happening here
if (bits == 8) {
bits = 9;
}
m_server_max_window_bits = bits; m_server_max_window_bits = bits;
m_server_max_window_bits_mode = mode; m_server_max_window_bits_mode = mode;
@ -403,8 +431,8 @@ public:
/// Limit client LZ77 sliding window size /// Limit client LZ77 sliding window size
/** /**
* The bits setting is the base 2 logarithm of the window size that the * The bits setting is the base 2 logarithm of the window size that the
* client must use to compress outgoing messages. The permitted range is 8 * client must use to compress outgoing messages. The permitted range is 9
* to 15 inclusive. 8 represents a 256 byte window and 15 a 32KiB window. * to 15 inclusive. 9 represents a 512 byte window and 15 a 32KiB window.
* The default setting is 15. * The default setting is 15.
* *
* Mode Options: * Mode Options:
@ -417,6 +445,14 @@ public:
* outgoing window size unilaterally. A server may only limit the client's * outgoing window size unilaterally. A server may only limit the client's
* window size if the remote client supports that feature. * window size if the remote client supports that feature.
* *
* NOTE: The permessage-deflate spec specifies that a value of 8 is allowed.
* Prior to version 0.8.0 a value of 8 was also allowed by this library.
* zlib, the deflate compression library that WebSocket++ uses has always
* silently adjusted a value of 8 to 9. In recent versions of zlib (1.2.9
* and greater) a value of 8 is now explicitly rejected. WebSocket++ 0.8.0
* continues to perform the 8->9 conversion for backwards compatibility
* purposes but this should be considered deprecated functionality.
*
* @param bits The size to request for the outgoing window size * @param bits The size to request for the outgoing window size
* @param mode The mode to use for negotiating this parameter * @param mode The mode to use for negotiating this parameter
* @return A status code * @return A status code
@ -425,6 +461,12 @@ public:
if (bits < min_client_max_window_bits || bits > max_client_max_window_bits) { if (bits < min_client_max_window_bits || bits > max_client_max_window_bits) {
return error::make_error_code(error::invalid_max_window_bits); return error::make_error_code(error::invalid_max_window_bits);
} }
// See note in doc comment above about what is happening here
if (bits == 8) {
bits = 9;
}
m_client_max_window_bits = bits; m_client_max_window_bits = bits;
m_client_max_window_bits_mode = mode; m_client_max_window_bits_mode = mode;
@ -555,7 +597,7 @@ public:
do { do {
m_istate.avail_out = m_compress_buffer_size; m_istate.avail_out = m_compress_buffer_size;
m_istate.next_out = m_compress_buffer.get(); m_istate.next_out = m_decompress_buffer.get();
ret = inflate(&m_istate, Z_SYNC_FLUSH); ret = inflate(&m_istate, Z_SYNC_FLUSH);
@ -564,7 +606,7 @@ public:
} }
out.append( out.append(
reinterpret_cast<char *>(m_compress_buffer.get()), reinterpret_cast<char *>(m_decompress_buffer.get()),
m_compress_buffer_size - m_istate.avail_out m_compress_buffer_size - m_istate.avail_out
); );
} while (m_istate.avail_out == 0); } while (m_istate.avail_out == 0);
@ -642,11 +684,17 @@ private:
* client requested that we use. * client requested that we use.
* *
* options: * options:
* - decline (refuse to use the attribute) * - decline (ignore value, offer our default instead)
* - accept (use whatever the client says) * - accept (use the value requested by the client)
* - largest (use largest possible value) * - largest (use largest value acceptable to both)
* - smallest (use smallest possible value) * - smallest (use smallest possible value)
* *
* NOTE: As a value of 8 is no longer explicitly supported by zlib but might
* be requested for negotiation by an older client/server, if the result of
* the negotiation would be to send a value of 8, a value of 9 is offered
* instead. This ensures that WebSocket++ will only ever negotiate connections
* with compression settings explicitly supported by zlib.
*
* @param [in] value The value of the attribute from the offer * @param [in] value The value of the attribute from the offer
* @param [out] ec A reference to the error code to return errors via * @param [out] ec A reference to the error code to return errors via
*/ */
@ -678,6 +726,11 @@ private:
ec = make_error_code(error::invalid_mode); ec = make_error_code(error::invalid_mode);
m_server_max_window_bits = default_server_max_window_bits; m_server_max_window_bits = default_server_max_window_bits;
} }
// See note in doc comment
if (m_server_max_window_bits == 8) {
m_server_max_window_bits = 9;
}
} }
/// Negotiate client_max_window_bits attribute /// Negotiate client_max_window_bits attribute
@ -687,11 +740,17 @@ private:
* negotiation mode. * negotiation mode.
* *
* options: * options:
* - decline (refuse to use the attribute) * - decline (ignore value, offer our default instead)
* - accept (use whatever the client says) * - accept (use the value requested by the client)
* - largest (use largest possible value) * - largest (use largest value acceptable to both)
* - smallest (use smallest possible value) * - smallest (use smallest possible value)
* *
* NOTE: As a value of 8 is no longer explicitly supported by zlib but might
* be requested for negotiation by an older client/server, if the result of
* the negotiation would be to send a value of 8, a value of 9 is offered
* instead. This ensures that WebSocket++ will only ever negotiate connections
* with compression settings explicitly supported by zlib.
*
* @param [in] value The value of the attribute from the offer * @param [in] value The value of the attribute from the offer
* @param [out] ec A reference to the error code to return errors via * @param [out] ec A reference to the error code to return errors via
*/ */
@ -727,6 +786,11 @@ private:
ec = make_error_code(error::invalid_mode); ec = make_error_code(error::invalid_mode);
m_client_max_window_bits = default_client_max_window_bits; m_client_max_window_bits = default_client_max_window_bits;
} }
// See note in doc comment
if (m_client_max_window_bits == 8) {
m_client_max_window_bits = 9;
}
} }
bool m_enabled; bool m_enabled;
@ -741,6 +805,7 @@ private:
int m_flush; int m_flush;
size_t m_compress_buffer_size; size_t m_compress_buffer_size;
lib::unique_ptr_uchar_array m_compress_buffer; lib::unique_ptr_uchar_array m_compress_buffer;
lib::unique_ptr_uchar_array m_decompress_buffer;
z_stream m_dstate; z_stream m_dstate;
z_stream m_istate; z_stream m_istate;
}; };
@ -750,3 +815,4 @@ private:
} // namespace websocketpp } // namespace websocketpp
#endif // WEBSOCKETPP_PROCESSOR_EXTENSION_PERMESSAGEDEFLATE_HPP #endif // WEBSOCKETPP_PROCESSOR_EXTENSION_PERMESSAGEDEFLATE_HPP

View file

@ -575,6 +575,17 @@ void connection<config>::set_body(std::string const & value) {
m_response.set_body(value); m_response.set_body(value);
} }
template <typename config>
void connection<config>::set_body( std::string&& value )
{
if (m_internal_state != istate::PROCESS_HTTP_REQUEST) {
throw exception("Call to set_status from invalid state",
error::make_error_code(error::invalid_state));
}
m_response.set_body(std::move(value));
}
// TODO: EXCEPTION_FREE // TODO: EXCEPTION_FREE
template <typename config> template <typename config>
void connection<config>::append_header(std::string const & key, void connection<config>::append_header(std::string const & key,

View file

@ -311,10 +311,10 @@ public:
* needed. * needed.
*/ */
timer_ptr set_timer(long duration, timer_handler callback) { timer_ptr set_timer(long duration, timer_handler callback) {
timer_ptr new_timer = lib::make_shared<lib::asio::steady_timer>( timer_ptr new_timer(
lib::ref(*m_io_service), new lib::asio::steady_timer(
lib::asio::milliseconds(duration) *m_io_service,
); lib::asio::milliseconds(duration)));
if (config::enable_multithreading) { if (config::enable_multithreading) {
new_timer->async_wait(m_strand->wrap(lib::bind( new_timer->async_wait(m_strand->wrap(lib::bind(
@ -461,8 +461,7 @@ protected:
m_io_service = io_service; m_io_service = io_service;
if (config::enable_multithreading) { if (config::enable_multithreading) {
m_strand = lib::make_shared<lib::asio::io_service::strand>( m_strand.reset(new lib::asio::io_service::strand(*io_service));
lib::ref(*io_service));
} }
lib::error_code ec = socket_con_type::init_asio(io_service, m_strand, lib::error_code ec = socket_con_type::init_asio(io_service, m_strand,

View file

@ -35,6 +35,7 @@
#include <websocketpp/uri.hpp> #include <websocketpp/uri.hpp>
#include <websocketpp/logger/levels.hpp> #include <websocketpp/logger/levels.hpp>
#include <websocketpp/common/asio.hpp>
#include <websocketpp/common/functional.hpp> #include <websocketpp/common/functional.hpp>
#include <sstream> #include <sstream>
@ -191,8 +192,7 @@ public:
m_io_service = ptr; m_io_service = ptr;
m_external_io_service = true; m_external_io_service = true;
m_acceptor = lib::make_shared<lib::asio::ip::tcp::acceptor>( m_acceptor.reset(new lib::asio::ip::tcp::acceptor(*m_io_service));
lib::ref(*m_io_service));
m_state = READY; m_state = READY;
ec = lib::error_code(); ec = lib::error_code();
@ -314,8 +314,10 @@ public:
* *
* New values affect future calls to listen only. * New values affect future calls to listen only.
* *
* A value of zero will use the operating system default. This is the * The default value is specified as *::asio::socket_base::max_connections
* default value. * which uses the operating system defined maximum queue length. Your OS
* may restrict or silently lower this value. A value of zero may cause
* all connections to be rejected.
* *
* @since 0.3.0 * @since 0.3.0
* *
@ -660,9 +662,7 @@ public:
* @since 0.3.0 * @since 0.3.0
*/ */
void start_perpetual() { void start_perpetual() {
m_work = lib::make_shared<lib::asio::io_service::work>( m_work.reset(new lib::asio::io_service::work(*m_io_service));
lib::ref(*m_io_service)
);
} }
/// Clears the endpoint's perpetual flag, allowing it to exit when empty /// Clears the endpoint's perpetual flag, allowing it to exit when empty
@ -826,8 +826,7 @@ protected:
// Create a resolver // Create a resolver
if (!m_resolver) { if (!m_resolver) {
m_resolver = lib::make_shared<lib::asio::ip::tcp::resolver>( m_resolver.reset(new lib::asio::ip::tcp::resolver(*m_io_service));
lib::ref(*m_io_service));
} }
tcon->set_uri(u); tcon->set_uri(u);

View file

@ -168,8 +168,7 @@ protected:
return socket::make_error_code(socket::error::invalid_state); return socket::make_error_code(socket::error::invalid_state);
} }
m_socket = lib::make_shared<lib::asio::ip::tcp::socket>( m_socket.reset(new lib::asio::ip::tcp::socket(*service));
lib::ref(*service));
m_state = READY; m_state = READY;

View file

@ -193,8 +193,7 @@ protected:
if (!m_context) { if (!m_context) {
return socket::make_error_code(socket::error::invalid_tls_context); return socket::make_error_code(socket::error::invalid_tls_context);
} }
m_socket = lib::make_shared<socket_type>( m_socket.reset(new socket_type(*service, *m_context));
_WEBSOCKETPP_REF(*service),lib::ref(*m_context));
m_io_service = service; m_io_service = service;
m_strand = strand; m_strand = strand;