77 *
88 * \author Cory R. Thornsberry
99 *
10- * \date May 13th , 2015
10+ * \date Oct. 2nd , 2015
1111 *
12- * \version 1.1.06
12+ * \version 1.2.02
1313*/
1414
1515#include < iostream>
1616#include < fstream>
1717#include < unistd.h>
1818#include < vector>
19+ #include < ctime>
1920
2021#ifdef USE_NCURSES
2122
3031
3132#ifdef USE_NCURSES
3233
34+ bool SIGNAL_SEGFAULT = false ;
3335bool SIGNAL_INTERRUPT = false ;
36+ bool SIGNAL_TERMSTOP = false ;
3437bool SIGNAL_RESIZE = false ;
3538
3639#endif
@@ -273,26 +276,48 @@ void CommandString::Pop(unsigned int index_){
273276// Terminal
274277// /////////////////////////////////////////////////////////////////////////////
275278
279+ void sig_segv_handler (int ignore_){
280+ SIGNAL_SEGFAULT = true ;
281+ }
282+
276283void sig_int_handler (int ignore_){
277284 SIGNAL_INTERRUPT = true ;
278285}
279286
287+ void sig_tstp_handler (int ignore_){
288+ SIGNAL_TERMSTOP = true ;
289+ }
290+
280291void signalResize (int ignore_) {
281292 SIGNAL_RESIZE = true ;
282293}
283294
284295
285296// Setup the interrupt signal intercept
286297void setup_signal_handlers (){
298+ // Handle segmentation faults press (SIGSEGV)
299+ if (signal (SIGSEGV, SIG_IGN) != SIG_IGN){
300+ if (signal (SIGSEGV, sig_segv_handler) == SIG_ERR){
301+ throw std::runtime_error (" Error setting up SIGSEGV signal handler!" );
302+ }
303+ }
304+
305+ // Handle ctrl-c press (SIGINT)
287306 if (signal (SIGINT, SIG_IGN) != SIG_IGN){
288307 if (signal (SIGINT, sig_int_handler) == SIG_ERR){
289- throw std::runtime_error (" Error setting up signal handler!" );
308+ throw std::runtime_error (" Error setting up SIGINT signal handler!" );
309+ }
310+ }
311+
312+ // Handle ctrl-z press (SIGTSTP)
313+ if (signal (SIGTSTP, SIG_IGN) != SIG_IGN){
314+ if (signal (SIGTSTP, sig_tstp_handler) == SIG_ERR){
315+ throw std::runtime_error (" Error setting up SIGTSTP signal handler!" );
290316 }
291317 }
292318
293319 // Handle resize signal
294320 signal (SIGWINCH, signalResize);
295-
296321}
297322void Terminal::resize_ () {
298323 // end session and then refresh to get new window sizes.
@@ -524,6 +549,7 @@ bool Terminal::save_commands_(){
524549Terminal::Terminal () :
525550 status_window(NULL ),
526551 _statusWindowSize(0 ),
552+ commandTimeout_(0 ),
527553 _scrollbackBufferSize(SCROLLBACK_SIZE),
528554 _scrollPosition(0 )
529555{
@@ -721,6 +747,17 @@ void Terminal::EnableTabComplete(bool enable) {
721747 enableTabComplete = enable;
722748}
723749
750+ /* *By enabling the timeout the GetCommand() routine returns after a set
751+ * timesout period has passed. The current typed text is stored for the next
752+ * GetCommand call.
753+ *
754+ * \param[in] timeout The amount of time to wait before timeout in seconds
755+ * defaults to 0.5 s.
756+ */
757+ void Terminal::EnableTimeout (float timeout/* =0.5*/ ) {
758+ commandTimeout_ = timeout;
759+ }
760+
724761/* *Take the list of matching tab complete values and output resulting tab completion.
725762 * If the list is empty nothing happens, if a unique value is given the command is completed. If there are multiple
726763 * matches the common part of the matches is determined and printed to the input. If there is no common part of the
@@ -780,6 +817,9 @@ void Terminal::TabComplete(std::vector<std::string> matches) {
780817
781818std::string Terminal::GetCommand (){
782819 std::string output = " " ;
820+ time_t commandRequestTime;
821+ time_t currentTime;
822+ time (&commandRequestTime);
783823
784824 // Update status message
785825 if (status_window) {
@@ -788,40 +828,58 @@ std::string Terminal::GetCommand(){
788828 }
789829
790830 while (true ){
831+ if (SIGNAL_SEGFAULT){ // segmentation fault (SIGSEGV)
832+ Close ();
833+ return " _SIGSEGV_" ;
834+ }
791835 if (SIGNAL_INTERRUPT){ // ctrl-c (SIGINT)
792836 SIGNAL_INTERRUPT = false ;
793837 output = " CTRL_C" ;
794838 text_length = 0 ;
795839 break ;
796840 }
841+ else if (SIGNAL_TERMSTOP){ // ctrl-z (SIGTSTP)
842+ SIGNAL_TERMSTOP = false ;
843+ output = " CTRL_Z" ;
844+ text_length = 0 ;
845+ break ;
846+ }
797847
798848 flush (); // If there is anything in the stream, dump it to the screen
849+
850+ // Time out if there is no command within the set interval (default 0.5 s).
851+ if (commandTimeout_ > 0 ) {
852+ time (¤tTime);
853+ // If the timeout has passed we simply return the empty output string.
854+ if (currentTime > commandRequestTime + commandTimeout_) {
855+ break ;
856+ }
857+ }
799858
800859 int keypress = wgetch (input_window);
801860
802861 // Check for internal commands
803- if (keypress == 10 ){ // Enter key (10)
862+ if (keypress == ERR){ } // No key was pressed in the interval
863+ else if (keypress == 10 ){ // Enter key (10)
804864 std::string temp_cmd = cmd.Get ();
805- if (temp_cmd != " " ){
806- // Reset the position in the history.
807- commands.Reset ();
808- if (temp_cmd != commands.PeekPrev ()){ // Only save this command if it is different than the previous command
809- commands.Push (temp_cmd);
810- }
811- output = temp_cmd;
812- std::cout << prompt.c_str () << output << " \n " ;
813- flush ();
814- text_length = 0 ;
815- _scrollPosition = 0 ;
816- clear_ ();
817- tabCount = 0 ;
818- return output;
865+ // Reset the position in the history.
866+ commands.Reset ();
867+ if (temp_cmd != " " && temp_cmd != commands.PeekPrev ()){ // Only save this command if it is different than the previous command
868+ commands.Push (temp_cmd);
819869 }
870+ output = temp_cmd;
871+ std::cout << prompt << output << " \n " ;
872+ flush ();
873+ text_length = 0 ;
874+ _scrollPosition = 0 ;
875+ clear_ ();
876+ tabCount = 0 ;
877+ break ;
820878 }
821879 else if (keypress == ' \t ' && enableTabComplete) {
822880 tabCount++;
823881 output = cmd.Get ().substr (0 ,cursX - offset) + " \t " ;
824- return output ;
882+ break ;
825883 }
826884 else if (keypress == 4 ){ // ctrl-d (EOT)
827885 output = " CTRL_D" ;
@@ -893,7 +951,6 @@ std::string Terminal::GetCommand(){
893951 else if (keypress == KEY_RESIZE) {
894952 // Do nothing with the resize key
895953 }
896- else if (keypress == ERR){ } // No key was pressed in the interval
897954 else {
898955 in_char_ ((char )keypress);
899956 cmd.Put ((char )keypress, cursX - offset - 1 );
0 commit comments