diff --git a/ChangeLog b/ChangeLog index 14c0d05f..d4564873 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2018-09-16 Markus Gans + * Implement a ttytype test for the FTermDetection unit test + 2018-09-14 Markus Gans * Added unit test for FTermDetection with a terminal simulation for common terminals diff --git a/include/final/ftermdetection.h b/include/final/ftermdetection.h index 99b382dc..72733a5d 100644 --- a/include/final/ftermdetection.h +++ b/include/final/ftermdetection.h @@ -152,6 +152,7 @@ class FTermDetection static void setTmuxTerm (bool); static void setTerminalDetection (bool); static void setTermFileName (char[]); + static void setTtyTypeFileName (char[]); // Methods static void detect(); @@ -166,7 +167,7 @@ class FTermDetection private: // Methods static void getSystemTermType(); - static void getTTYtype(); + static bool getTTYtype(); #if F_HAVE_GETTTYNAM static bool getTTYSFileEntry(); #endif @@ -187,6 +188,7 @@ class FTermDetection static char* secDA_Analysis_1 (char[]); static char* secDA_Analysis_24 (char[]); static char* secDA_Analysis_32 (char[]); + static char* secDA_Analysis_67 (char[]); static char* secDA_Analysis_77 (char[]); static char* secDA_Analysis_82 (char[]); static char* secDA_Analysis_83 (char[]); @@ -196,6 +198,7 @@ class FTermDetection // Data Members static char termtype[256]; static char termfilename[256]; + static char ttytypename[256]; static bool decscusr_support; static bool terminal_detection; static bool color256; diff --git a/src/ffiledialog.cpp b/src/ffiledialog.cpp index 80b8b007..c4f9d0d9 100644 --- a/src/ffiledialog.cpp +++ b/src/ffiledialog.cpp @@ -508,10 +508,12 @@ inline bool FFileDialog::pattern_match ( const char* const pattern { search[0] = '.'; search[1] = '\0'; - std::strncat(search, pattern, sizeof(search) - std::strlen(search) - 1); + std::strncat(search, pattern, sizeof(search) - std::strlen(search)); } else - std::strncpy(search, pattern, sizeof(search) - 1); + std::strncpy(search, pattern, sizeof(search)); + + search[sizeof(search) - 1] = '\0'; if ( fnmatch (search, fname, FNM_PERIOD) == 0 ) return true; @@ -699,10 +701,12 @@ void FFileDialog::followSymLink (const char* const dir, dir_entry& entry) char symLink[MAXPATHLEN] = { }; struct stat sb; - std::strncpy (symLink, dir, sizeof(symLink) - 1); + std::strncpy (symLink, dir, sizeof(symLink)); + symLink[sizeof(symLink) - 1] = '\0'; std::strncat ( symLink , entry.name - , sizeof(symLink) - std::strlen(symLink) - 1); + , sizeof(symLink) - std::strlen(symLink)); + symLink[sizeof(symLink) - 1] = '\0'; if ( realpath(symLink, resolved_path) == 0 ) return; // Cannot follow the symlink diff --git a/src/foptiattr.cpp b/src/foptiattr.cpp index 060f2313..50c8a73d 100644 --- a/src/foptiattr.cpp +++ b/src/foptiattr.cpp @@ -1694,7 +1694,8 @@ inline bool FOptiAttr::append_sequence (char seq[]) { if ( seq ) { - std::strncat (attr_ptr, seq, sizeof(attr_buf) - std::strlen(attr_ptr) - 1 ); + std::strncat (attr_ptr, seq, sizeof(attr_buf) - std::strlen(attr_ptr)); + attr_buf[sizeof(attr_buf) - 1] = '\0'; return true; } else diff --git a/src/foptimove.cpp b/src/foptimove.cpp index eecbc9fe..a9c87fa6 100644 --- a/src/foptimove.cpp +++ b/src/foptimove.cpp @@ -744,9 +744,12 @@ inline int FOptiMove::verticalMove (char move[], int from_y, int to_y) if ( F_row_address.cap ) { if ( move ) + { std::strncpy ( move , tparm(F_row_address.cap, to_y, 0, 0, 0, 0, 0, 0, 0, 0) - , BUF_SIZE - 1 ); + , BUF_SIZE ); + move[BUF_SIZE - 1] = '\0'; + } vtime = F_row_address.duration; } @@ -768,9 +771,12 @@ inline void FOptiMove::downMove ( char move[], int& vtime if ( F_parm_down_cursor.cap && F_parm_down_cursor.duration < vtime ) { if ( move ) + { std::strncpy ( move , tparm(F_parm_down_cursor.cap, num, 0, 0, 0, 0, 0, 0, 0, 0) - , BUF_SIZE - 1 ); + , BUF_SIZE ); + move[BUF_SIZE - 1] = '\0'; + } vtime = F_parm_down_cursor.duration; } @@ -793,9 +799,12 @@ inline void FOptiMove::upMove ( char move[], int& vtime if ( F_parm_up_cursor.cap && F_parm_up_cursor.duration < vtime ) { if ( move ) + { std::strncpy ( move , tparm(F_parm_up_cursor.cap, num, 0, 0, 0, 0, 0, 0, 0, 0) - , BUF_SIZE - 1 ); + , BUF_SIZE ); + move[BUF_SIZE - 1] = '\0'; + } vtime = F_parm_up_cursor.duration; } @@ -819,7 +828,8 @@ inline int FOptiMove::horizontalMove (char hmove[], int from_x, int to_x) // Move to fixed column position1 std::strncat ( hmove , tparm(F_column_address.cap, to_x, 0, 0, 0, 0, 0, 0, 0, 0) - , BUF_SIZE - std::strlen(hmove) - 1 ); + , BUF_SIZE - std::strlen(hmove) ); + hmove[BUF_SIZE - 1] = '\0'; htime = F_column_address.duration; } @@ -841,7 +851,8 @@ inline void FOptiMove::rightMove ( char hmove[], int& htime { std::strncpy ( hmove , tparm(F_parm_right_cursor.cap, num, 0, 0, 0, 0, 0, 0, 0, 0) - , BUF_SIZE - 1 ); + , BUF_SIZE ); + hmove[BUF_SIZE - 1] = '\0'; htime = F_parm_right_cursor.duration; } @@ -895,7 +906,8 @@ inline void FOptiMove::leftMove ( char hmove[], int& htime { std::strncpy ( hmove , tparm(F_parm_left_cursor.cap, num, 0, 0, 0, 0, 0, 0, 0, 0) - , BUF_SIZE - 1 ); + , BUF_SIZE ); + hmove[BUF_SIZE - 1] = '\0'; htime = F_parm_left_cursor.duration; } @@ -959,7 +971,8 @@ inline bool FOptiMove::isMethod0Faster ( int& move_time if ( move_xy ) { char* move_ptr = move_buf; - std::strncpy (move_ptr, move_xy, BUF_SIZE - 1); + std::strncpy (move_ptr, move_xy, BUF_SIZE); + move_ptr[BUF_SIZE - 1] = '\0'; move_time = F_cursor_address.duration; return true; } @@ -1108,22 +1121,25 @@ void FOptiMove::moveByMethod ( int method case 2: if ( F_carriage_return.cap ) { - std::strncpy (move_ptr, F_carriage_return.cap, BUF_SIZE - 1); + std::strncpy (move_ptr, F_carriage_return.cap, BUF_SIZE); move_ptr += F_carriage_return.length; relativeMove (move_ptr, 0, yold, xnew, ynew); + move_buf[BUF_SIZE - 1] ='\0'; } break; case 3: - std::strncpy (move_ptr, F_cursor_home.cap, BUF_SIZE - 1); + std::strncpy (move_ptr, F_cursor_home.cap, BUF_SIZE); move_ptr += F_cursor_home.length; relativeMove (move_ptr, 0, 0, xnew, ynew); + move_buf[BUF_SIZE - 1] ='\0'; break; case 4: - std::strncpy (move_ptr, F_cursor_to_ll.cap, BUF_SIZE - 1); + std::strncpy (move_ptr, F_cursor_to_ll.cap, BUF_SIZE); move_ptr += F_cursor_to_ll.length; relativeMove (move_ptr, 0, screen_height - 1, xnew, ynew); + move_buf[BUF_SIZE - 1] ='\0'; break; case 5: @@ -1132,13 +1148,14 @@ void FOptiMove::moveByMethod ( int method if ( xold >= 0 ) std::strncat ( move_ptr , F_carriage_return.cap - , BUF_SIZE - std::strlen(move_ptr) - 1 ); + , BUF_SIZE - std::strlen(move_ptr) ); std::strncat ( move_ptr , F_cursor_left.cap - , BUF_SIZE - std::strlen(move_ptr) - 1 ); + , BUF_SIZE - std::strlen(move_ptr) ); move_ptr += std::strlen(move_buf); relativeMove (move_ptr, screen_width - 1, yold - 1, xnew, ynew); + move_buf[BUF_SIZE - 1] ='\0'; break; default: diff --git a/src/fstring.cpp b/src/fstring.cpp index ab8263a9..08f49acf 100644 --- a/src/fstring.cpp +++ b/src/fstring.cpp @@ -2668,6 +2668,7 @@ inline void FString::_assign (const wchar_t s[]) } std::wcsncpy (string, s, bufsize); + string[bufsize - 1] = L'\0'; length = new_length; } @@ -2695,6 +2696,7 @@ inline void FString::_insert (uInt pos, uInt len, const wchar_t s[]) } std::wcsncpy (string, s, bufsize); + string[bufsize - 1] = L'\0'; return; } else diff --git a/src/fswitch.cpp b/src/fswitch.cpp index a611a25d..cb83c748 100644 --- a/src/fswitch.cpp +++ b/src/fswitch.cpp @@ -147,7 +147,7 @@ void FSwitch::drawChecked() { if ( isMonochron() ) { - std::wcsncpy ( on, L" ", 6); + std::wcsncpy (on, L" ", 6); setBold(true); } else if ( getMaxColor() < 16 ) @@ -203,7 +203,7 @@ void FSwitch::drawUnchecked() { if ( isMonochron() ) { - std::wcsncpy ( off, L"", 6); + std::wcsncpy (off, L"", 6); setBold(true); } else if ( getMaxColor() < 16 ) diff --git a/src/fterm.cpp b/src/fterm.cpp index a45d4d75..6fef158f 100644 --- a/src/fterm.cpp +++ b/src/fterm.cpp @@ -450,9 +450,9 @@ char* FTerm::enableCursor() char*& ve = TCAP(fc::t_cursor_normal); if ( ve ) - std::strncpy (enable_str, ve, SIZE - 1); + std::strncpy (enable_str, ve, SIZE); else if ( vs ) - std::strncpy (enable_str, vs, SIZE - 1); + std::strncpy (enable_str, vs, SIZE); #if defined(__linux__) if ( isLinuxTerm() ) @@ -460,10 +460,12 @@ char* FTerm::enableCursor() // Restore the last used Linux console cursor style char* cstyle; cstyle = linux->restoreCursorStyle(); - std::strncat (enable_str, cstyle, SIZE - std::strlen(enable_str) - 1); + std::strncat (enable_str, cstyle, SIZE - std::strlen(enable_str)); } #endif + enable_str[SIZE - 1] = '\0'; + #if defined(__FreeBSD__) || defined(__DragonFly__) if ( isFreeBSDTerm() ) { diff --git a/src/ftermcapquirks.cpp b/src/ftermcapquirks.cpp index 77006d3a..3c36eecc 100644 --- a/src/ftermcapquirks.cpp +++ b/src/ftermcapquirks.cpp @@ -46,7 +46,8 @@ FTermcapQuirks::~FTermcapQuirks() // destructor //---------------------------------------------------------------------- void FTermcapQuirks::setTerminalType (const char tt[]) { - std::strncpy (termtype, tt, sizeof(termtype) - 1); + std::strncpy (termtype, tt, sizeof(termtype)); + termtype[sizeof(termtype) - 1] = '\0'; } //---------------------------------------------------------------------- diff --git a/src/ftermdetection.cpp b/src/ftermdetection.cpp index bfa98af2..45f5d59e 100644 --- a/src/ftermdetection.cpp +++ b/src/ftermdetection.cpp @@ -30,6 +30,7 @@ FTermDetection::colorEnv FTermDetection::color_env; FTermDetection::secondaryDA FTermDetection::secondary_da; char FTermDetection::termtype[256] = { }; char FTermDetection::termfilename[256] = { }; +char FTermDetection::ttytypename[256] = { }; bool FTermDetection::decscusr_support; bool FTermDetection::terminal_detection; bool FTermDetection::color256; @@ -66,6 +67,10 @@ FTermDetection::FTermDetection() // Initialize the structs color_env.setDefault(); secondary_da.setDefault(); + + // Set default ttytype file + std::strncpy (ttytypename, C_STR("/etc/ttytype"), sizeof(ttytypename)); + ttytypename[sizeof(ttytypename) - 1] = '\0'; } //---------------------------------------------------------------------- @@ -86,7 +91,18 @@ void FTermDetection::setTermFileName (char term_filename[]) if ( ! term_filename ) return; - std::strncpy (termfilename, term_filename, sizeof(termfilename) - 1); + std::strncpy (termfilename, term_filename, sizeof(termfilename)); + termfilename[sizeof(termfilename) - 1] = '\0'; +} + +//---------------------------------------------------------------------- +void FTermDetection::setTtyTypeFileName (char ttytype_filename[]) +{ + if ( ! ttytype_filename ) + return; + + std::strncpy (ttytypename, ttytype_filename, sizeof(ttytypename)); + ttytypename[sizeof(ttytypename) - 1] = '\0'; } //---------------------------------------------------------------------- @@ -113,12 +129,14 @@ void FTermDetection::getSystemTermType() if ( term_env ) { // Save name in termtype - std::strncpy (termtype, term_env, sizeof(termtype) - 1); + std::strncpy (termtype, term_env, sizeof(termtype)); + termtype[sizeof(termtype) - 1] = '\0'; return; } else if ( *termfilename ) // 1st fallback: use the teminal file name { - getTTYtype(); // Look into /etc/ttytype + if ( getTTYtype() ) // Look into /etc/ttytype + return; #if F_HAVE_GETTTYNAM if ( getTTYSFileEntry() ) // Look into /etc/ttys @@ -131,7 +149,7 @@ void FTermDetection::getSystemTermType() } //---------------------------------------------------------------------- -void FTermDetection::getTTYtype() +bool FTermDetection::getTTYtype() { // Analyse /etc/ttytype and get the term name // ------------------------------------------ @@ -152,7 +170,7 @@ void FTermDetection::getTTYtype() std::FILE *fp; - if ( (fp = std::fopen("/etc/ttytype", "r")) != 0 ) + if ( (fp = std::fopen(ttytypename, "r")) != 0 ) { char* p; char str[BUFSIZ]; @@ -180,14 +198,17 @@ void FTermDetection::getTTYtype() if ( type != 0 && name != 0 && ! std::strcmp(name, term_basename) ) { // Save name in termtype - std::strncpy (termtype, type, sizeof(termtype) - 1); + std::strncpy (termtype, type, sizeof(termtype)); + termtype[sizeof(termtype) - 1] = '\0'; std::fclose(fp); - return; + return true; } } std::fclose(fp); } + + return false; } #if F_HAVE_GETTTYNAM @@ -214,7 +235,8 @@ bool FTermDetection::getTTYSFileEntry() if ( type != 0 ) { // Save name in termtype - std::strncpy (termtype, type, sizeof(termtype) - 1); + std::strncpy (termtype, type, sizeof(termtype)); + termtype[sizeof(termtype) - 1] = '\0'; endttyent(); return true; } @@ -326,7 +348,8 @@ void FTermDetection::detectTerminal() if ( new_termtype ) { setenv(C_STR("TERM"), new_termtype, 1); - std::strncpy (termtype, new_termtype, sizeof(termtype) - 1); + std::strncpy (termtype, new_termtype, sizeof(termtype)); + termtype[sizeof(termtype) - 1] = '\0'; } } @@ -723,6 +746,7 @@ char* FTermDetection::secDA_Analysis (char current_termtype[]) case 64: // DEC VT520 case 65: // DEC VT525 case 67: // Cygwin + new_termtype = secDA_Analysis_67(current_termtype); break; case 77: // mintty @@ -840,6 +864,18 @@ inline char* FTermDetection::secDA_Analysis_32 (char[]) return new_termtype; } +//---------------------------------------------------------------------- +inline char* FTermDetection::secDA_Analysis_67 (char[]) +{ + // Terminal ID 67 - cygwin + + char* new_termtype; + terminal_type.cygwin = true; + new_termtype = C_STR("cygwin"); + std::fflush(stdout); + return new_termtype; +} + //---------------------------------------------------------------------- inline char* FTermDetection::secDA_Analysis_77 (char[]) { diff --git a/src/test/ftermdetection-test.cpp b/src/test/ftermdetection-test.cpp index 9639e140..0ba14348 100644 --- a/src/test/ftermdetection-test.cpp +++ b/src/test/ftermdetection-test.cpp @@ -32,6 +32,8 @@ #include #include +#define CPPUNIT_ASSERT_CSTRING(expected, actual) \ + check_c_string (expected, actual, CPPUNIT_SOURCELINE()) static char* colorname[] = { @@ -294,6 +296,20 @@ static char* colorname[] = 0 }; +//---------------------------------------------------------------------- +void check_c_string ( const char* s1 + , const char* s2 + , CppUnit::SourceLine sourceLine ) +{ + if ( s1 == 0 && s2 == 0 ) // Strings are equal + return; + + if ( s1 && s2 && std::strcmp (s1, s2) == 0 ) // Strings are equal + return; + + ::CppUnit::Asserter::fail ("Strings are not equal", sourceLine); +} + //---------------------------------------------------------------------- // class FTermDetectionTest @@ -353,6 +369,7 @@ class FTermDetectionTest : public CPPUNIT_NS::TestFixture void sunTest(); void screenTest(); void tmuxTest(); + void ttytypeTest(); private: char* getAnswerback (console); @@ -396,6 +413,7 @@ class FTermDetectionTest : public CPPUNIT_NS::TestFixture CPPUNIT_TEST (sunTest); CPPUNIT_TEST (screenTest); CPPUNIT_TEST (tmuxTest); + CPPUNIT_TEST (ttytypeTest); // End of test suite definition CPPUNIT_TEST_SUITE_END(); @@ -464,6 +482,7 @@ void FTermDetectionTest::ansiTest() if ( isChildProcess(pid) ) { setenv ("TERM", "ansi", 1); + unsetenv("TERMCAP"); unsetenv("COLORTERM"); unsetenv("VTE_VERSION"); unsetenv("XTERM_VERSION"); @@ -495,6 +514,14 @@ void FTermDetectionTest::ansiTest() CPPUNIT_ASSERT ( ! detect.canDisplay256Colors() ); CPPUNIT_ASSERT ( ! detect.hasTerminalDetection() ); CPPUNIT_ASSERT ( ! detect.hasSetCursorStyleSupport() ); + CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("ansi") ); + + // Test fallback to vt100 without TERM environment variable + unsetenv("TERM"); + detect.setAnsiTerminal(false); + detect.detect(); + CPPUNIT_ASSERT ( ! detect.isAnsiTerminal() ); + CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("vt100") ); debugOutput(); closeStandardStreams(); @@ -506,7 +533,7 @@ void FTermDetectionTest::ansiTest() terminalSimulation (ansi); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } @@ -523,6 +550,7 @@ void FTermDetectionTest::xtermTest() { setenv ("TERM", "xterm", 1); setenv ("XTERM_VERSION", "XTerm(312)", 1); + unsetenv("TERMCAP"); unsetenv("COLORTERM"); unsetenv("VTE_VERSION"); unsetenv("ROXTERM_ID"); @@ -564,7 +592,7 @@ void FTermDetectionTest::xtermTest() terminalSimulation (xterm); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } @@ -581,6 +609,7 @@ void FTermDetectionTest::rxvtTest() { setenv ("TERM", "rxvt-cygwin-native", 1); setenv ("COLORTERM", "rxvt-xpm", 1); + unsetenv("TERMCAP"); unsetenv("VTE_VERSION"); unsetenv("XTERM_VERSION"); unsetenv("ROXTERM_ID"); @@ -622,7 +651,7 @@ void FTermDetectionTest::rxvtTest() terminalSimulation (rxvt); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } @@ -639,6 +668,7 @@ void FTermDetectionTest::urxvtTest() { setenv ("TERM", "rxvt-unicode-256color", 1); setenv ("COLORTERM", "rxvt-xpm", 1); + unsetenv("TERMCAP"); unsetenv("VTE_VERSION"); unsetenv("XTERM_VERSION"); unsetenv("ROXTERM_ID"); @@ -680,7 +710,7 @@ void FTermDetectionTest::urxvtTest() terminalSimulation (urxvt); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } @@ -697,6 +727,7 @@ void FTermDetectionTest::mltermTest() { setenv ("TERM", "mlterm", 1); setenv ("MLTERM", "3.8.4", 1); + unsetenv("TERMCAP"); unsetenv("COLORTERM"); unsetenv("VTE_VERSION"); unsetenv("XTERM_VERSION"); @@ -739,7 +770,7 @@ void FTermDetectionTest::mltermTest() terminalSimulation (mlterm); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } @@ -755,6 +786,7 @@ void FTermDetectionTest::puttyTest() if ( isChildProcess(pid) ) { setenv ("TERM", "xterm", 1); + unsetenv("TERMCAP"); unsetenv("COLORTERM"); unsetenv("VTE_VERSION"); unsetenv("XTERM_VERSION"); @@ -798,7 +830,7 @@ void FTermDetectionTest::puttyTest() terminalSimulation (putty); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } @@ -817,6 +849,7 @@ void FTermDetectionTest::kdeKonsoleTest() setenv ("COLORTERM", "truecolor", 1); setenv ("KONSOLE_DBUS_SERVICE", "DCOPRef(konsole-11768,konsole)", 1); setenv ("KONSOLE_DCOP", ":1.77", 1); + unsetenv("TERMCAP"); unsetenv("VTE_VERSION"); unsetenv("XTERM_VERSION"); unsetenv("ROXTERM_ID"); @@ -856,7 +889,7 @@ void FTermDetectionTest::kdeKonsoleTest() terminalSimulation (kde_konsole); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } @@ -874,6 +907,7 @@ void FTermDetectionTest::gnomeTerminalTest() setenv ("TERM", "xterm-256color", 1); setenv ("COLORTERM", "truecolor", 1); setenv ("VTE_VERSION", "5202", 1); + unsetenv("TERMCAP"); unsetenv("XTERM_VERSION"); unsetenv("ROXTERM_ID"); unsetenv("KONSOLE_DBUS_SESSION"); @@ -915,7 +949,7 @@ void FTermDetectionTest::gnomeTerminalTest() terminalSimulation (gnome_terminal); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } @@ -931,6 +965,7 @@ void FTermDetectionTest::ktermTest() if ( isChildProcess(pid) ) { setenv ("TERM", "kterm", 1); + unsetenv("TERMCAP"); unsetenv("COLORTERM"); unsetenv("VTE_VERSION"); unsetenv("XTERM_VERSION"); @@ -964,6 +999,13 @@ void FTermDetectionTest::ktermTest() CPPUNIT_ASSERT ( ! detect.hasTerminalDetection() ); CPPUNIT_ASSERT ( ! detect.hasSetCursorStyleSupport() ); + // Test fallback to vt100 without TERM environment variable + unsetenv("TERM"); + detect.setKtermTerminal(false); + detect.detect(); + CPPUNIT_ASSERT ( ! detect.isKtermTerminal() ); + CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("vt100") ); + debugOutput(); closeStandardStreams(); exit(EXIT_SUCCESS); @@ -974,7 +1016,7 @@ void FTermDetectionTest::ktermTest() terminalSimulation (kterm); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } @@ -990,6 +1032,7 @@ void FTermDetectionTest::teraTermTest() if ( isChildProcess(pid) ) { setenv ("TERM", "xterm", 1); + unsetenv("TERMCAP"); unsetenv("COLORTERM"); unsetenv("VTE_VERSION"); unsetenv("XTERM_VERSION"); @@ -1033,7 +1076,7 @@ void FTermDetectionTest::teraTermTest() terminalSimulation (tera_term); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } @@ -1049,6 +1092,7 @@ void FTermDetectionTest::cygwinTest() if ( isChildProcess(pid) ) { setenv ("TERM", "cygwin", 1); + unsetenv("TERMCAP"); unsetenv("COLORTERM"); unsetenv("VTE_VERSION"); unsetenv("XTERM_VERSION"); @@ -1092,7 +1136,7 @@ void FTermDetectionTest::cygwinTest() terminalSimulation (cygwin); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } @@ -1108,6 +1152,7 @@ void FTermDetectionTest::minttyTest() if ( isChildProcess(pid) ) { setenv ("TERM", "xterm-256color", 1); + unsetenv("TERMCAP"); unsetenv("COLORTERM"); unsetenv("VTE_VERSION"); unsetenv("XTERM_VERSION"); @@ -1151,7 +1196,7 @@ void FTermDetectionTest::minttyTest() terminalSimulation (mintty); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } @@ -1167,6 +1212,7 @@ void FTermDetectionTest::linuxTest() if ( isChildProcess(pid) ) { setenv ("TERM", "linux", 1); + unsetenv("TERMCAP"); unsetenv("COLORTERM"); unsetenv("VTE_VERSION"); unsetenv("XTERM_VERSION"); @@ -1200,6 +1246,13 @@ void FTermDetectionTest::linuxTest() CPPUNIT_ASSERT ( detect.hasTerminalDetection() ); CPPUNIT_ASSERT ( ! detect.hasSetCursorStyleSupport() ); + // Test fallback to vt100 without TERM environment variable + unsetenv("TERM"); + detect.setLinuxTerm(false); + detect.detect(); + CPPUNIT_ASSERT ( ! detect.isLinuxTerm() ); + CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("vt100") ); + debugOutput(); closeStandardStreams(); exit(EXIT_SUCCESS); @@ -1210,7 +1263,7 @@ void FTermDetectionTest::linuxTest() terminalSimulation (linux_con); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } @@ -1226,6 +1279,7 @@ void FTermDetectionTest::freebsdTest() if ( isChildProcess(pid) ) { setenv ("TERM", "xterm", 1); + unsetenv("TERMCAP"); unsetenv("COLORTERM"); unsetenv("VTE_VERSION"); unsetenv("XTERM_VERSION"); @@ -1260,6 +1314,15 @@ void FTermDetectionTest::freebsdTest() CPPUNIT_ASSERT ( detect.hasTerminalDetection() ); CPPUNIT_ASSERT ( ! detect.hasSetCursorStyleSupport() ); + // Test fallback to vt100 without TERM environment variable + unsetenv("TERM"); + detect.setXTerminal (false); + detect.setFreeBSDTerm(false); + detect.detect(); + CPPUNIT_ASSERT ( ! detect.isXTerminal() ); + CPPUNIT_ASSERT ( ! detect.isFreeBSDTerm() ); + CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("vt100") ); + debugOutput(); closeStandardStreams(); exit(EXIT_SUCCESS); @@ -1270,7 +1333,7 @@ void FTermDetectionTest::freebsdTest() terminalSimulation (freebsd_con); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } @@ -1286,6 +1349,7 @@ void FTermDetectionTest::netbsdTest() if ( isChildProcess(pid) ) { setenv ("TERM", "wsvt25", 1); + unsetenv("TERMCAP"); unsetenv("COLORTERM"); unsetenv("VTE_VERSION"); unsetenv("XTERM_VERSION"); @@ -1320,6 +1384,13 @@ void FTermDetectionTest::netbsdTest() CPPUNIT_ASSERT ( detect.hasTerminalDetection() ); CPPUNIT_ASSERT ( ! detect.hasSetCursorStyleSupport() ); + // Test fallback to vt100 without TERM environment variable + unsetenv("TERM"); + detect.setNetBSDTerm(false); + detect.detect(); + CPPUNIT_ASSERT ( ! detect.isFreeBSDTerm() ); + CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("vt100") ); + debugOutput(); closeStandardStreams(); exit(EXIT_SUCCESS); @@ -1330,7 +1401,7 @@ void FTermDetectionTest::netbsdTest() terminalSimulation (netbsd_con); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } @@ -1346,6 +1417,7 @@ void FTermDetectionTest::openbsdTest() if ( isChildProcess(pid) ) { setenv ("TERM", "vt220", 1); + unsetenv("TERMCAP"); unsetenv("COLORTERM"); unsetenv("VTE_VERSION"); unsetenv("XTERM_VERSION"); @@ -1380,6 +1452,13 @@ void FTermDetectionTest::openbsdTest() CPPUNIT_ASSERT ( detect.hasTerminalDetection() ); CPPUNIT_ASSERT ( ! detect.hasSetCursorStyleSupport() ); + // Test fallback to vt100 without TERM environment variable + unsetenv("TERM"); + detect.setOpenBSDTerm(false); + detect.detect(); + CPPUNIT_ASSERT ( ! detect.isOpenBSDTerm() ); + CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("vt100") ); + debugOutput(); closeStandardStreams(); exit(EXIT_SUCCESS); @@ -1390,7 +1469,7 @@ void FTermDetectionTest::openbsdTest() terminalSimulation (openbsd_con); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } @@ -1405,6 +1484,7 @@ void FTermDetectionTest::sunTest() if ( isChildProcess(pid) ) { setenv ("TERM", "sun-color", 1); + unsetenv("TERMCAP"); unsetenv("COLORTERM"); unsetenv("VTE_VERSION"); unsetenv("XTERM_VERSION"); @@ -1438,6 +1518,13 @@ void FTermDetectionTest::sunTest() CPPUNIT_ASSERT ( ! detect.hasTerminalDetection() ); CPPUNIT_ASSERT ( ! detect.hasSetCursorStyleSupport() ); + // Test fallback to vt100 without TERM environment variable + unsetenv("TERM"); + detect.setSunTerminal(false); + detect.detect(); + CPPUNIT_ASSERT ( ! detect.isSunTerminal() ); + CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("vt100") ); + debugOutput(); closeStandardStreams(); exit(EXIT_SUCCESS); @@ -1448,7 +1535,7 @@ void FTermDetectionTest::sunTest() terminalSimulation (sun_con); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } @@ -1508,7 +1595,7 @@ void FTermDetectionTest::screenTest() terminalSimulation (screen); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } @@ -1526,6 +1613,7 @@ void FTermDetectionTest::tmuxTest() setenv ("TERM", "screen", 1); setenv ("TMUX", "/tmp/tmux-1000/default,7844,0", 1); setenv ("TMUX_PANE", "%0", 1); + unsetenv("TERMCAP"); unsetenv("COLORTERM"); unsetenv("VTE_VERSION"); unsetenv("XTERM_VERSION"); @@ -1568,10 +1656,99 @@ void FTermDetectionTest::tmuxTest() terminalSimulation (tmux); if ( waitpid(pid, 0, 0) != pid ) - ::fprintf (stderr, "waitpid error"); + std::cerr << "waitpid error" << std::endl; } } +//---------------------------------------------------------------------- +void FTermDetectionTest::ttytypeTest() +{ + struct stat sb = { }; + + if ( stat("new-root-dir", &sb) == -1 ) + if ( mkdir("new-root-dir", 0755) == -1 ) + return; + + if ( stat("new-root-dir/etc", &sb) == -1 ) + if ( mkdir("new-root-dir/etc", 0755) == -1 ) + return; + + // Write a own /etc/ttytype file + std::ofstream ttytype ("new-root-dir/etc/ttytype"); + + if ( ! ttytype.is_open() ) + { + rmdir("new-root-dir/etc"); + rmdir("new-root-dir"); + return; + } + + ttytype << "linux" << "\t" << "tty1" << std::endl; + ttytype << "linux" << "\t" << "tty2" << std::endl; + ttytype << "linux" << "\t" << "tty3" << std::endl; + ttytype << "linux" << "\t" << "tty4" << std::endl; + ttytype << "linux" << "\t" << "tty5" << std::endl; + ttytype << "linux" << "\t" << "tty6" << std::endl; + ttytype << "vt100" << "\t" << "ttyp0" << std::endl; + ttytype << "vt100" << "\t" << "ttyp1" << std::endl; + ttytype << "vt100" << "\t" << "ttyp2" << std::endl; + ttytype << "vt100" << "\t" << "ttyp3" << std::endl; + ttytype << "vt100" << "\t" << "ttyp4" << std::endl; + ttytype << "vt100" << "\t" << "ttyp5" << std::endl; + ttytype << "vt100" << "\t" << "ttyp6" << std::endl; + ttytype.close(); + + FTermDetection detect; + detect.setTerminalDetection(true); + detect.setTtyTypeFileName(C_STR("new-root-dir/etc/ttytype")); + + pid_t pid = forkProcess(); + + if ( isChildProcess(pid) ) + { + unsetenv("TERM"); + unsetenv("TERMCAP"); + unsetenv("COLORTERM"); + unsetenv("VTE_VERSION"); + unsetenv("XTERM_VERSION"); + unsetenv("ROXTERM_ID"); + unsetenv("KONSOLE_DBUS_SESSION"); + unsetenv("KONSOLE_DCOP"); + unsetenv("TMUX"); + + // Test /dev/tty3 with linux + detect.setTermFileName(C_STR("/dev/tty3")); + detect.detect(); + CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("linux") ); + + // Test /dev/ttyp0 with vt100 + detect.setTermFileName(C_STR("/dev/ttyp0")); + detect.detect(); + CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("vt100") ); + + // Test non-existent /dev/tty8 with fallback to vt100 + detect.setTermFileName(C_STR("/dev/tty8")); + detect.detect(); + CPPUNIT_ASSERT_CSTRING ( detect.getTermType(), C_STR("vt100") ); + + debugOutput(); + closeStandardStreams(); + exit(EXIT_SUCCESS); + } + else // Parent + { + // Start the terminal simulation + terminalSimulation (ansi); + + if ( waitpid(pid, 0, 0) != pid ) + std::cerr << "waitpid error" << std::endl; + } + + unlink("new-root-dir/etc/ttytype"); + rmdir("new-root-dir/etc"); + rmdir("new-root-dir"); +} + // private methods of FOptiMoveTest //---------------------------------------------------------------------- @@ -1770,9 +1947,9 @@ void FTermDetectionTest::debugOutput() setenv ("GO_RIGHT", "\\033[79D\\033[40C", 1); FString line (69, '-'); - ::printf ("\n%s\n", line.c_str()); - ::printf ("Probe Escape sequence Reply\n"); - ::printf ("%s\n", line.c_str()); + std::cout << std::endl << line << std::endl; + std::cout << "Probe Escape sequence Reply"; + std::cout << std::endl << line << std::endl; // Command line char* child_av[] = @@ -1900,7 +2077,10 @@ pid_t FTermDetectionTest::forkProcess() #ifdef TIOCSCTTY // Set controlling tty if ( ioctl(fd_slave, TIOCSCTTY, 0) == -1 ) + { + *shared_state = true; return -1; + } #endif // Get current terminal settings @@ -1909,6 +2089,20 @@ pid_t FTermDetectionTest::forkProcess() // Set raw mode on the slave side of the PTY cfmakeraw (&term_settings); tcsetattr (fd_slave, TCSANOW, &term_settings); + +#ifdef TIOCSWINSZ + // Set slave tty window size + struct winsize size; + size.ws_row = 25; + size.ws_col = 80; + + if ( ioctl(fd_slave, TIOCSWINSZ, &size) == -1) + { + *shared_state = true; + return -1; + } +#endif + closeStandardStreams(); fd_stdin = dup(fd_slave); // PTY becomes stdin (0)