From: g0dil Date: Wed, 7 Jan 2009 13:13:14 +0000 (+0000) Subject: Utils/Termlib: Implement LineEditor X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=54b5df35c9877b91730f4e79da29f1a470b81754;p=senf.git Utils/Termlib: Implement LineEditor Utils/Termlib: Implement more terminfo error handling git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1043 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Utils/Termlib/Editor.cc b/Utils/Termlib/Editor.cc index c523907..0023322 100644 --- a/Utils/Termlib/Editor.cc +++ b/Utils/Termlib/Editor.cc @@ -74,7 +74,7 @@ prefix_ void senf::term::BaseEditor::toColumn(unsigned c) column_ = c; } else { - char const * cub1 (tifo_.getString(Terminfo::properties::CursorRight)); + char const * cub1 (tifo_.getString(Terminfo::properties::CursorLeft)); while (c < column_) { write(cub1); --column_; @@ -83,34 +83,49 @@ prefix_ void senf::term::BaseEditor::toColumn(unsigned c) } } -prefix_ void senf::term::BaseEditor::insertChar(char ch) +prefix_ void senf::term::BaseEditor::put(char ch) { - if (column_+1 >= width()) + if (column_ >= width()-1) return; - if (tifo_.hasProperty(Terminfo::properties::InsertCharacter)) - write(tifo_.getString(Terminfo::properties::InsertCharacter)); - else - write(tifo_.formatString(Terminfo::properties::ParmIch, 1)); write(ch); ++ column_; } -prefix_ void senf::term::BaseEditor::overwriteChar(char ch) +prefix_ void senf::term::BaseEditor::put(std::string const & text) { - write(ch); - ++ column_; + if (text.size() > width()-column_-1) { + write(text.substr(0,width()-column_-1)); + column_ = width() - 1; + } + else { + write(text); + column_ += text.size(); + } +} + +prefix_ void senf::term::BaseEditor::clearLine() +{ + write("\r"); + write(tifo_.getString(Terminfo::properties::ClrEol)); + column_ = 0; +} + +prefix_ void senf::term::BaseEditor::setBold() +{ + if (tifo_.hasProperty(Terminfo::properties::EnterBoldMode) && + tifo_.hasProperty(Terminfo::properties::ExitAttributeMode)) + write(tifo_.getString(Terminfo::properties::EnterBoldMode)); } -prefix_ void senf::term::BaseEditor::deleteChar() +prefix_ void senf::term::BaseEditor::setNormal() { - if (tifo_.hasProperty(Terminfo::properties::DeleteCharacter)) - write(tifo_.getString(Terminfo::properties::DeleteCharacter)); - else - write(tifo_.formatString(Terminfo::properties::ParmDch, 1)); + if (tifo_.hasProperty(Terminfo::properties::EnterBoldMode) && + tifo_.hasProperty(Terminfo::properties::ExitAttributeMode)) + write(tifo_.getString(Terminfo::properties::ExitAttributeMode)); } prefix_ unsigned senf::term::BaseEditor::currentColumn() - const + const { return column_; } @@ -119,6 +134,13 @@ prefix_ void senf::term::BaseEditor::cb_init() { tifo_.load(terminal_->terminalType()); keyParser_.load(tifo_); + + typedef Terminfo::properties p; + if (! (tifo_.hasProperty(p::ClrEol) && + (tifo_.hasProperty(p::ParmRightCursor) || tifo_.hasProperty(p::CursorRight)) && + (tifo_.hasProperty(p::ParmLeftCursor) || tifo_.hasProperty(p::CursorLeft)))) + throw Terminfo::InvalidTerminfoException(); + if (tifo_.hasProperty(Terminfo::properties::KeypadXmit)) write(tifo_.getString(Terminfo::properties::KeypadXmit)); } @@ -174,6 +196,266 @@ prefix_ void senf::term::BaseEditor::write(std::string const & s) write(*i); } +/////////////////////////////////////////////////////////////////////////// + +prefix_ senf::term::LineEditor::LineEditor(AbstractTerminal & terminal, AcceptCallback cb) + : BaseEditor(terminal), enabled_ (true), prompt_ ("$"), promptWidth_ (1u), editWidth_ (0u), + text_ (""), point_ (0u), displayPos_ (0u), lastKey_ (0u), callback_ (cb) +{ + defineKey(KeyParser::Return, &bindings::accept); + defineKey(KeyParser::Right, &bindings::forwardChar); + defineKey(KeyParser::Left, &bindings::backwardChar); + defineKey(KeyParser::Backspace, &bindings::backwardDeleteChar); + defineKey(KeyParser::Delete, &bindings::deleteChar); + defineKey(KeyParser::Home, &bindings::beginningOfLine); + defineKey(KeyParser::End, &bindings::endOfLine); + defineKey(KeyParser::Ctrl('K'), &bindings::deleteToEndOfLine); + defineKey(KeyParser::Ctrl('A'), &bindings::beginningOfLine); + defineKey(KeyParser::Ctrl('E'), &bindings::endOfLine); + defineKey(KeyParser::Ctrl('D'), &bindings::deleteChar); + defineKey(KeyParser::Ctrl('C'), &bindings::restartEdit); +} + +prefix_ void senf::term::LineEditor::prompt(std::string const & text) +{ + prompt_ = text; + promptWidth_ = prompt_.size(); + editWidth_ = width() - promptWidth_ - 3; + if (enabled_) + redisplay(); +} + +prefix_ void senf::term::LineEditor::set(std::string const & text, unsigned pos) +{ + text_ = text; + point_ = pos; + if (point_ > text.size()) + point_ = text.size(); + displayPos_ = 0u; + if (point_ > editWidth_) + displayPos_ = point_ - editWidth_; + redisplay(); +} + +prefix_ void senf::term::LineEditor::show() +{ + if (enabled_) + return; + enabled_ = true; + redisplay(); +} + +prefix_ void senf::term::LineEditor::hide() +{ + if (! enabled_) + return; + clearLine(); + enabled_ = false; +} + +prefix_ void senf::term::LineEditor::accept() +{ + if (enabled_) + newline(); + hide(); + callback_(text_); + clear(); +} + +prefix_ void senf::term::LineEditor::clear() +{ + set(""); +} + +prefix_ void senf::term::LineEditor::redisplay() +{ + redisplayNeeded_ = true; +} + +prefix_ void senf::term::LineEditor::forceRedisplay() +{ + if (! enabled_) + return; + clearLine(); + setBold(); + put(prompt_); + put( displayPos_ > 0 ? '<' : ' ' ); + if (text_.size() > displayPos_ + editWidth_) { + toColumn(editWidth_ + promptWidth_ + 1); + put('>'); + toColumn(promptWidth_ + 1); + } + setNormal(); + put(text_.substr(displayPos_, editWidth_)); + toColumn(point_ - displayPos_ + promptWidth_ + 1); + redisplayNeeded_ = false; +} + +prefix_ void senf::term::LineEditor::gotoChar(unsigned n) +{ + point_ = n; + if (point_ > text_.size()) + point_ = text_.size(); + if (point_ < displayPos_) + displayPos_ = point_; + if (point_ > displayPos_+editWidth_) + displayPos_ = point_-editWidth_; + redisplay(); +} + +prefix_ void senf::term::LineEditor::scrollTo(unsigned n) +{ + displayPos_ = n; + if (displayPos_ > text_.size()) + displayPos_ = text_.size(); + if (point_ < displayPos_) + point_ = displayPos_; + if (point_ > displayPos_+editWidth_) + point_ = displayPos_+editWidth_; + redisplay(); +} + +prefix_ void senf::term::LineEditor::deleteChar(unsigned n) +{ + if (point_ >= text_.size()) + return; + text_.erase(point_, n); + redisplay(); +} + +prefix_ void senf::term::LineEditor::insert(char ch) +{ + text_.insert(point_, std::string(1, ch)); + gotoChar(point_+1); + redisplay(); +} + +prefix_ void senf::term::LineEditor::insert(std::string const & text) +{ + text_.insert(point_, text); + gotoChar(point_+text.size()); + redisplay(); +} + +prefix_ std::string const & senf::term::LineEditor::text() +{ + return text_; +} + +prefix_ unsigned senf::term::LineEditor::point() +{ + return point_; +} + +prefix_ unsigned senf::term::LineEditor::displayPos() +{ + return displayPos_; +} + +prefix_ senf::term::LineEditor::keycode_t senf::term::LineEditor::lastKey() +{ + return lastKey_; +} + +prefix_ void senf::term::LineEditor::defineKey(keycode_t key, KeyBinding binding) +{ + bindings_[key] = binding; +} + +prefix_ void senf::term::LineEditor::unsetKey(keycode_t key) +{ + bindings_.erase(key); +} + +prefix_ void senf::term::LineEditor::cb_init() +{ + BaseEditor::cb_init(); + editWidth_ = width() - promptWidth_ - 3; + forceRedisplay(); +} + +prefix_ void senf::term::LineEditor::cb_windowSizeChanged() +{ + BaseEditor::cb_windowSizeChanged(); + editWidth_ = width() - promptWidth_ - 3; + gotoChar(point_); + forceRedisplay(); +} + +prefix_ void senf::term::LineEditor::v_keyReceived(keycode_t key) +{ + lastKey_ = key; + KeyMap::iterator i (bindings_.find(key)); + if (i != bindings_.end()) + i->second(*this); + else if (key >= ' ' && key < 256) + insert(char(key)); + if (redisplayNeeded_) + forceRedisplay(); +} + +/////////////////////////////////////////////////////////////////////////// + +prefix_ void senf::term::bindings::selfInsertCommand(LineEditor & editor) +{ + LineEditor::keycode_t key (editor.lastKey()); + if (key >= ' ' && key < 256) + editor.insert(key); +} + +prefix_ void senf::term::bindings::forwardChar(LineEditor & editor) +{ + editor.gotoChar(editor.point()+1); +} + +prefix_ void senf::term::bindings::backwardChar(LineEditor & editor) +{ + unsigned p (editor.point()); + if (p>0) + editor.gotoChar(p-1); +} + +prefix_ void senf::term::bindings::accept(LineEditor & editor) +{ + editor.accept(); +} + +prefix_ void senf::term::bindings::backwardDeleteChar(LineEditor & editor) +{ + unsigned p (editor.point()); + if (p>0) { + editor.gotoChar(p-1); + editor.deleteChar(); + } +} + +prefix_ void senf::term::bindings::deleteChar(LineEditor & editor) +{ + editor.deleteChar(); +} + +prefix_ void senf::term::bindings::beginningOfLine(LineEditor & editor) +{ + editor.gotoChar(0u); +} + +prefix_ void senf::term::bindings::endOfLine(LineEditor & editor) +{ + editor.gotoChar(editor.text().size()); +} + +prefix_ void senf::term::bindings::deleteToEndOfLine(LineEditor & editor) +{ + editor.deleteChar(editor.text().size()-editor.point()); +} + +prefix_ void senf::term::bindings::restartEdit(LineEditor & editor) +{ + editor.newline(); + editor.clear(); + editor.redisplay(); +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ //#include "Editor.mpp" diff --git a/Utils/Termlib/Editor.hh b/Utils/Termlib/Editor.hh index 6253423..de94ae1 100644 --- a/Utils/Termlib/Editor.hh +++ b/Utils/Termlib/Editor.hh @@ -27,6 +27,7 @@ #define HH_SENF_Utils_Termlib_Editor_ 1 // Custom includes +#include #include #include #include "AbstractTerminal.hh" @@ -50,23 +51,27 @@ namespace term { void newline(); ///< Move to beginning of a new, empty line void toColumn(unsigned c); ///< Move cursor to column \p c - void insertChar(char ch); ///< Insert \p ch at current column, shifting text right - void overwriteChar(char ch); ///< Write \p ch at current column - void deleteChar(); ///< Delete a character a current column + void put(char ch); ///< Write \p ch at current column + void put(std::string const & text); + void clearLine(); ///< Clear current line and move cursor to first column + void setBold(); ///< Set bold char display + void setNormal(); ///< Set normal char display unsigned currentColumn() const; ///< Return number of current column + unsigned width(); + + protected: + virtual void cb_init(); + virtual void cb_windowSizeChanged(); private: virtual void v_keyReceived(keycode_t key) = 0; - virtual void cb_init(); virtual void cb_charReceived(char c); - virtual void cb_windowSizeChanged(); void keySequenceTimeout(); void processKeys(); - unsigned width(); void write(char ch); void write(std::string const & s); @@ -79,6 +84,87 @@ namespace term { unsigned column_; }; + class LineEditor + : public BaseEditor + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef boost::function KeyBinding; + typedef boost::function AcceptCallback; + + /////////////////////////////////////////////////////////////////////////// + + LineEditor(AbstractTerminal & terminal, AcceptCallback cb); + + /////////////////////////////////////////////////////////////////////////// + + void prompt(std::string const & text); + void set(std::string const & text, unsigned pos = 0u); + + // Overall edit control + void show(); + void hide(); + void accept(); + void clear(); + void redisplay(); + void forceRedisplay(); + + // Cursor and display movement + void gotoChar(unsigned n); + void scrollTo(unsigned n); + + // Text manipulation + void deleteChar(unsigned n=1); + void insert(char ch); + void insert(std::string const & text); + + // Get information + std::string const & text(); + unsigned point(); + unsigned displayPos(); + keycode_t lastKey(); + + // Key bindings + void defineKey(keycode_t key, KeyBinding binding); + void unsetKey(keycode_t key); + + private: + virtual void cb_init(); + virtual void cb_windowSizeChanged(); + virtual void v_keyReceived(keycode_t key); + + typedef std::map KeyMap; + + bool enabled_; + bool redisplayNeeded_; + std::string prompt_; + unsigned promptWidth_; + unsigned editWidth_; + std::string text_; + unsigned point_; + unsigned displayPos_; + keycode_t lastKey_; + AcceptCallback callback_; + KeyMap bindings_; + }; + +namespace bindings { + + void selfInsertCommand (LineEditor & editor); + void forwardChar (LineEditor & editor); + void backwardChar (LineEditor & editor); + void accept (LineEditor & editor); + void backwardDeleteChar (LineEditor & editor); + void deleteChar (LineEditor & editor); + void beginningOfLine (LineEditor & editor); + void endOfLine (LineEditor & editor); + void deleteToEndOfLine (LineEditor & editor); + void restartEdit (LineEditor & editor); + +} + }} ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/Utils/Termlib/Terminfo.cc b/Utils/Termlib/Terminfo.cc index 7ad201f..232a188 100644 --- a/Utils/Termlib/Terminfo.cc +++ b/Utils/Termlib/Terminfo.cc @@ -140,9 +140,9 @@ prefix_ senf::term::Terminfo::Terminfo(std::string const & term) prefix_ void senf::term::Terminfo::load(std::string const & term) { std::string filename (findTerminfo(term)); + if (filename.empty()) throw InvalidTerminfoException(); std::ifstream is (filename.c_str()); - if (!is) - throw InvalidTerminfoException(); + if (!is) throw InvalidTerminfoException(); load(is); } @@ -359,28 +359,25 @@ prefix_ std::string senf::term::Terminfo::formatString(properties::String p, prefix_ std::string senf::term::Terminfo::findTerminfo(std::string const & name) { + if (name.empty()) return ""; boost::filesystem::path subdir (name.substr(0,1)); subdir /= name; - boost::filesystem::path tientry, tipath; + boost::filesystem::path tientry; { char const * tivar (::getenv("TERMINFO")); if (tivar) { - tipath = tivar; - tientry = tipath / subdir; + tientry = boost::filesystem::path(tivar) / subdir; if (boost::filesystem::exists(tientry)) return tientry.native_file_string(); } } - tipath = "/etc/terminfo"; - tientry = tipath / subdir; + tientry = boost::filesystem::path("/etc/terminfo") / subdir; if (boost::filesystem::exists(tientry)) return tientry.native_file_string(); - tipath = "/lib/terminfo"; - tientry = tipath / subdir; + tientry = boost::filesystem::path("/lib/terminfo") / subdir; if (boost::filesystem::exists(tientry)) return tientry.native_file_string(); - tipath = "/usr/share/terminfo"; - tientry = tipath / subdir; + tientry = boost::filesystem::path("/usr/share/terminfo") / subdir; if (boost::filesystem::exists(tientry)) return tientry.native_file_string(); return ""; @@ -405,11 +402,13 @@ prefix_ void senf::term::Terminfo::load(std::istream & is) { TerminfoHeader h; is.read(static_cast(static_cast(&h)), sizeof(h)); - if (h.magic != TerminfoMagic) - throw InvalidTerminfoException(); + if (!is || h.magic != TerminfoMagic) throw InvalidTerminfoException(); name_.resize(h.namesSz); is.read(&(name_[0]), name_.size()); + if (!is) throw InvalidTerminfoException(); + if (name_.size() & 1) + is.ignore(1u); { std::string::size_type n (name_.find('\0')); if (n != std::string::npos) @@ -420,6 +419,7 @@ prefix_ void senf::term::Terminfo::load(std::istream & is) for (BoolVec::iterator i (booleans_.begin()); i != booleans_.end(); ++i) { char v; is.read(&v, sizeof(v)); + if (!is) throw InvalidTerminfoException(); *i = v; } if (booleans_.size() & 1) @@ -429,6 +429,7 @@ prefix_ void senf::term::Terminfo::load(std::istream & is) for (NumberVec::iterator i (numbers_.begin()); i != numbers_.end(); ++i) { number_t v; is.read(static_cast(static_cast(&v)), sizeof(v)); + if (!is) throw InvalidTerminfoException(); *i = v; } @@ -438,17 +439,21 @@ prefix_ void senf::term::Terminfo::load(std::istream & is) for (OffsetVec::iterator i (offsets.begin()); i != offsets.end(); ++i) { number_t v; is.read(static_cast(static_cast(&v)), sizeof(v)); + if (!is) throw InvalidTerminfoException(); *i = v; } stringPool_.resize(h.stringPoolSz); is.read(&(stringPool_[0]), stringPool_.size()); + if (!is) throw InvalidTerminfoException(); strings_.resize(offsets.size()); StringVec::iterator j (strings_.begin()); for (OffsetVec::iterator i (offsets.begin()); i != offsets.end(); ++i, ++j) - if (*i != NoValue) + if (*i != NoValue && *i >= 0 && *i < stringPool_.size()) *j = &(stringPool_[0]) + *i; + else + *j = 0; } /////////////////////////////////////////////////////////////////////////// diff --git a/Utils/Termlib/Terminfo.hh b/Utils/Termlib/Terminfo.hh index f001df8..616f374 100644 --- a/Utils/Termlib/Terminfo.hh +++ b/Utils/Termlib/Terminfo.hh @@ -198,26 +198,28 @@ namespace term { // Types enum KeyCode { - Space = ' ', Tab = '\t', First = 0xE000, Esc = First, Backspace, Backtab, Begin, CATab, - CTab, Cancel, Center, Clear, ClearToEOL, ClearToEOS, Close, Command, Copy, Create, - Delete, DeleteLine, Down, DownLeft, DownRight, End, Enter, Exit, F0, F1, F2, F3, F4, F5, - F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, - F24, F25, F26, F27, F28, F29, F30, F31, F32, F33, F34, F35, F36, F37, F38, F39, F40, - F41, F42, F43, F44, F45, F46, F47, F48, F49, F50, F51, F52, F53, F54, F55, F56, F57, - F58, F59, F60, F61, F62, F63, Find, Help, Home, Insert, InsertLine, Left, Mark, Message, - Mouse, Move, Next, Open, Options, PageDown, PageUp, Previous, Print, Redo, Reference, - Refresh, Replace, Restart, Resume, Right, Save, Select, ShiftBegin, ShiftCancel, - ShiftCommand, ShiftCopy, ShiftCreate, ShiftDelete, ShiftDeleteLine, ShiftEnd, - ShiftClearToEOL, ShiftExit, ShiftFind, ShiftHelp, ShiftHome, ShiftInsert, ShiftLeft, - ShiftMessage, ShiftMove, ShiftNext, ShiftOptions, ShiftPrevious, ShiftPrint, ShiftRedo, - ShiftReplace, ShiftResume, ShiftRight, ShiftSave, ShiftSuspend, ShiftTab, ShiftUndo, - Suspend, Undo, Up, UpLeft, UpRight, Incomplete = 0xE0FF }; + Space = ' ', Tab = '\t', Return = '\r', First = 0xE000, Esc = First, Backspace, Backtab, + Begin, CATab, CTab, Cancel, Center, Clear, ClearToEOL, ClearToEOS, Close, Command, Copy, + Create, Delete, DeleteLine, Down, DownLeft, DownRight, End, Enter, Exit, F0, F1, F2, F3, + F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, + F23, F24, F25, F26, F27, F28, F29, F30, F31, F32, F33, F34, F35, F36, F37, F38, F39, + F40, F41, F42, F43, F44, F45, F46, F47, F48, F49, F50, F51, F52, F53, F54, F55, F56, + F57, F58, F59, F60, F61, F62, F63, Find, Help, Home, Insert, InsertLine, Left, Mark, + Message, Mouse, Move, Next, Open, Options, PageDown, PageUp, Previous, Print, Redo, + Reference, Refresh, Replace, Restart, Resume, Right, Save, Select, ShiftBegin, + ShiftCancel, ShiftCommand, ShiftCopy, ShiftCreate, ShiftDelete, ShiftDeleteLine, + ShiftEnd, ShiftClearToEOL, ShiftExit, ShiftFind, ShiftHelp, ShiftHome, ShiftInsert, + ShiftLeft, ShiftMessage, ShiftMove, ShiftNext, ShiftOptions, ShiftPrevious, ShiftPrint, + ShiftRedo, ShiftReplace, ShiftResume, ShiftRight, ShiftSave, ShiftSuspend, ShiftTab, + ShiftUndo, Suspend, Undo, Up, UpLeft, UpRight, Incomplete = 0xE0FF }; static char const * const KeyNames[]; typedef wchar_t keycode_t; typedef std::string::size_type size_type; + static keycode_t Ctrl(char ch) { return ch-'@'; } + /////////////////////////////////////////////////////////////////////////// KeyParser(); diff --git a/Utils/Termlib/telnetServer.cc b/Utils/Termlib/telnetServer.cc index a02711f..4f9ccf2 100644 --- a/Utils/Termlib/telnetServer.cc +++ b/Utils/Termlib/telnetServer.cc @@ -28,6 +28,7 @@ // Custom includes #include +#include "../../Utils/membind.hh" #include "../../Scheduler/Scheduler.hh" #include "../Logger.hh" #include "../../Socket/Protocols/INet.hh" @@ -39,65 +40,32 @@ ///////////////////////////////cc.p//////////////////////////////////////// namespace { - - class MyEditor - : public senf::term::BaseEditor - { - public: - MyEditor(senf::term::AbstractTerminal & terminal) - : BaseEditor(terminal) {} - - private: - virtual void v_keyReceived(keycode_t key) - { - SENF_LOG(("Key " << senf::term::KeyParser::describe(key))); - if (key >= ' ' && key < 256) - insertChar(key); - else - switch (key) { - case '\r': - newline(); - break; - case senf::term::KeyParser::Left: - { - unsigned c (currentColumn()); - if (c > 0) - toColumn(c-1); - break; - } - case senf::term::KeyParser::Backspace: - { - unsigned c (currentColumn()); - if (c > 0) { - toColumn(c-1); - deleteChar(); - } - break; - } - case senf::term::KeyParser::Delete: - deleteChar(); - break; - } - } - - }; - + class MyTelnet : public senf::term::TelnetTerminal { public: explicit MyTelnet(Handle handle) - : senf::term::BaseTelnetProtocol(handle), - editor_(*this) {} - + : senf::term::BaseTelnetProtocol (handle), + editor_ (*this, senf::membind(&MyTelnet::executeLine, this)) + { + editor_.prompt("myTelnet$"); + } + virtual void v_eof() { SENF_LOG(("EOF")); delete this; } + virtual void executeLine(std::string const & text) + { + SENF_LOG(("Execute line: " << text)); + editor_.show(); + } + private: - MyEditor editor_; + senf::term::LineEditor editor_; }; typedef senf::TCPv4ServerSocketHandle ServerHandle; @@ -111,7 +79,15 @@ namespace { } ClientHandle client (handle.accept()); SENF_LOG(("new client ...")); - new MyTelnet (client); + try { + new MyTelnet (client); + } + catch (std::exception & ex) { + SENF_LOG(("Client open failed: " << ex.what())); + } + catch (...) { + SENF_LOG(("Client open failed: unknown exception")); + } } }