• Support
  • Articles
  • Resources
  • Products

Tera Term Source Code Overview

This article was written by Tera Term Project team in Februry 2008. The original is in Japanese language and is available from ttssh2.osdn.jp. Yutaka Hirata and Boris Maisuradze translated the article to English in December 2015.

Copyright © of below article belongs to Tera Term Project. Reproduction of this article, or any part of this article whithout prior written permission of copyright owners is not allowed.

 Index

  1. Foreword
  2. Required Skill Sets
  3. Tera Term Package Content
  4. Third Party Libraries
  5. Plug-in Support
  6. Reading and Writing Configuration File
  7. Secure Programming
  8. Compatibility with Obsolete Windows Versions
  9. Debugging Methods
  10. Multithreading
  11. DDE Communication
  12. SSH Design and Implementation in TTSSH
  13. Macro Language Design and Implementation
  14. Caret Control
  15. Serial Port
  16. Binary Transfer Protocols

1. Foreword

This article describes the source code of Tera Term version 4.58 released in February 2008. The general architecture of Tera Term did not change since then, so this description can be considered as up-to-date.


2. Required Skill Sets

Most programs included in Tera Term package are written in programming language C. Part of the code is written in C++ and uses Microsoft Foundation Classes (MFC). Knowledge of Win32 API is also required because the source code contains lots of calls to Windows platform specific functions from Win32 API.

Microsoft Visual Studio 2005 Standard Edition or later is required to build the source code. Unfortunately, Express Edition cannot be used as it does not support MFC. Other compilers like C++ Builder, Turbo C++ Explorer and gcc cannot be used either.

Tera Term project team recently successfully compiled Tera Term source code using free Visual Studio Community 2015 Edition Update 3.

The main source of information about programming for Windows is MSDN Library provided by Microsoft. Tera Term developers often use MSDN Library as a reference.

The core of Tera Term is written on C++. This should not cause a problem for those who only knows C language because the syntax of both languages is very close. Microsoft Visual C++ (VC++) supports the original ANSI C standard (C89) and does not support newer standard C99. VC++ has its own implementation of C99-like functions. The names of these functions start with underscore (_), which makes it easy to identify them. For example, _snprintf() in VC++ is different from snprintf() in ANSI C (C99).

CygTerm is written in C language and should be compiled using gcc compiler included in Cygwin package.


3. Tera Term Package Content

Tera Term installation package contains several binary files (.exe and .dll) and their relationship is shown on the drawing below. Executable files have extension ".exe". Dynamically linked libraries (DLL) that are called only when needed, have extension ".dll". All binary files are 32-bit programs (x86) and Tera Term developers currently do not test them in 64-bit OS environments like x86-64, or IA-64.

Tera Term Package Content

When a user launches Tera Term from desktop shortcut or from Start Menu, "ttermpro.exe" file is executed. Then "ttermpro.exe" calls five DLL files. Tera Term was not designed as all-in-one application intentionally to reduce memory consumption. In the initial design of the program is was assumed that when a number of Tera Term instances start they will share the same DLL files, i.e. only one instance of each DDL file will be loaded into the system memory.

Launching a macro script starts "ttpmacro.exe" program. Macro scripts can be executed by themselves because the Tera Term contains 2 separate programs: "ttermpro.exe" and "ttpmacro.exe". These two programs need to communicate with each other and they use Dynamic Data Exchange (DDE) as their communication mechanism. DDE is considered legacy in current Windows operating systems. If Microsoft decides to stop supporting DDE mechanism in future Windows releases, macro script execution will be impossible.

Plug-in DLL-s, like TTSSH, TTProxy and TTXKanjiMenu, are dynamically loaded by LoadLibrary() API call at Tera Term startup. DLL filename should follow the pattern "TTX*.DLL" defined in TTXInit()#ttplug.c function.

"keycode.exe", "ttpmenu.exe", "LogMeTT.exe" and "TTLEdit.exe" are separate applications that are not in direct communication with Tera Term.


4. Third Party Libraries

It is inefficient to build advanced software from scratch, that's why Tera Term actively uses open source libraries. This, however, requires from developers to be careful and avoid license violations, especially GPL.

Several Tera Term modules are linked to open source libraries as shown on the drawing below. The macro program is linked to regular expression library "Oniguruma", which allows to handle regular expressions in "waitregex" and "sprintf" macro commands. Tera Term also calls this library to display Oniguruma version information in "About Tera Term" dialog box.

Tera Term libraries

"TTSSH" module uses OpenSSL library to perform cryptography related operations. One may think that OpenSSL library contains only Secure Socket Layer (SSL) protocol related functions used for secure web access, however that is wrong assumption. OpenSSL library also supports basic cipher algorithms, which are utilized by "TTSSH" module. Since Secure Layer related functions of the library are not used, it is very unlikely that "TTSSH" module will be compromised if a security hole is found in OpenSSL library.

Zlib library is used to compress SSH packets. Packet compression is effective on low speed networks like for example with dial-up connections, however in high speed networks it may slow down communication. That's why packet compression function is disabled by default.

"PuTTY" is another free terminal emulator that became a de-facto standard worldwide. PuTTY package contains SSH authentication agent called "Pageant". TTSSH uses part of PuTTY source code to support Pageant based authentication method.

Note that these libraries are called statically (not via dynamic link). When compiling the source code with these libraries use "/MT" option. Tera Term doesn't use dynamic calls to the libraries because not all user environments can support such calls, which may cause Tera Term to crash.


5. Plug-in Support

Tera Term supports external plug-in functionality. Plug-ins should be written and compiled as dynamically linked libraries (DLL files). This allows developers to add new features to Tera Term without modifying its source code. Presence of a plug-in (.dll file) in Tera Term installation directory is enough for it to work.
TTSSH is typical example of Tera Term plug-in module. TTXSamples\ttxtest\ttxtest.c file contains a sample plug-in code. It is recommended to develop plug-ins based on this sample. "TTX KanjiMenu" source code (TTXKanjiMenu\ directory) is another example of practical and simple plug-in module.

Plug-in modules are loaded at Tera Term (ttermpro.exe) startup by TTXInit()#ttplug.c function. All DLL files matching "TTX*.DLL" naming pattern will be loaded. When multiple DLL modules are found, export function of each DLL module is loaded by Tera Term core in the order defined by "loadOrder" member of TTXExports structure as follows:

Module Order
TTProxy 0
TTSSH 2500
TTX Kanji Menu 5000

The lower is order number value - the higher is corresponding module's priority, i.e. the module with the lowest order number will be contacted by Tera Term core the first. For example, TTXModifyMenu() is called in the following order:

    TTXModifyMenu()#ttplug.c -> TTProxy@TTXModifyMenu() -> TTSSH@TTXModifyMenu() -> TTX Kanji Menu@TTXModifyMenu()

Export function of a plug-in should be defined as TTXExports structure, which is sent to Tera Term core by TTXBind() function. For example, TTXExports structure of TTX Kanji Menu plug-in looks like shown below. All unused functions are replaced with NULL pointers.

  1. static TTXExports Exports = {
  2. /* This must contain the size of the structure. See below for its usage. */
  3. sizeof(TTXExports),
  4.  
  5. /* This is the load order number of this DLL. */
  6. ORDER,
  7.  
  8. /* Now we just list the functions that we've implemented. */
  9. TTXInit,
  10. NULL, /* TTXGetUIHooks */
  11. NULL, /* TTXGetSetupHooks */
  12. NULL, /* TTXOpenTCP */
  13. NULL, /* TTXCloseTCP */
  14. NULL, /* TTXSetWinSize */
  15. TTXModifyMenu,
  16. TTXModifyPopupMenu,
  17. TTXProcessCommand,
  18. NULL, /* TTXEnd */
  19. NULL /* TTXSetCommandLine */
  20. };

The export function of the plug-in module should be designed in such a way that it does not interfere with other plug-ins. Also, when the plug-in module is called by Tera Term core, the module needs to check whether the request was sent to it, or to another module.

The table below contains the complete list of plug-in export functions.

Function Description
TTXBind This function is called the first. The function sends export function structure to Tera Term core.
TTXInit This function is called right after TTXBind(). The function receives global variables (ts and cv) from Tera Term core and initialized plug-in module.
TTXGetUIHooks This function can hook a dialog handle. The function is used to change the dialog interface of Tera Term. The hook targets are: &SetupTerminal, &SetupWin, &SetupKeyboard, &SetupSerialPort, &SetupTCPIP, &GetHostName, &ChangeDirectory, &AboutDialog, &ChooseFontDlg, &SetupGeneral, &WindowWindow
TTXGetSetupHooks This function can hook to setup routine. The hooked function should call the original function. When several plug-in modules exist, each function is called in accordance with order number. The hook targets are: &ReadIniFile, &WriteIniFile, &ReadKeyboardCnf, &CopyHostList, &AddHostToList, &ParseParam
TTXOpenTCP This function is called only for TCP connections; it should not be used for Serial connections. The function can hook to the socket interfaces: &Pclosesocket, &Pconnect, &Phtonl, &Phtons, &Pinet_addr, &Pioctlsocket, &Precv, &Pselect, &Psend, &Psetsockopt, &Psocket, &PWSAAsyncSelect, &PWSAAsyncGetHostByName, &PWSACancelAsyncRequest, &PWSAGetLastError
TTXCloseTCP This function is called only for TCP connections; it should not be used for Serial connections. If there is a hook to one of the following socket interfaces, the function must restore the original interface prior to exit: &Pclosesocket, &Pconnect, &Phtonl, &Phtons, &Pinet_addr, &Pioctlsocket, &Precv, &Pselect, &Psend, &Psetsockopt, &Psocket, &PWSAAsyncSelect, &PWSAAsyncGetHostByName, &PWSACancelAsyncRequest, &PWSAGetLastError
TTXSetWinSize This function is called when the terminal screen is resized.
TTXModifyMenu This function is called when Tera Term menu is initialized. The function allows to insert new menu item into original Tera Term menu.
TTXModifyPopupMenu This function is called when Tera Term pop-up menu is initialized. The function can add new pop-up menu item to the original pop-up menu.
TTXProcessCommand This function is called when Tera Term menu is executed. The function can process the plug-in module menu.
TTXEnd This function is called when Tera Term exits.
TTXSetCommandLine This function is called when the command line parameter is processed during set up of new connection and also while duplicating existing connection. The original parameter of plug-in module is processed.

6. Reading and Writing Configuration File

Modern Windows applications use system Registry to store their settings. Tera Term, however, stores its configuration in .ini file because that was the common practice back in the days when Tera Term was created.

Collector, LogMeTT, TTLEdit and CygTerm programs included in Tera Term package store their configurations in system Registry.

Unlike other applications, Tera Term Menu stores its configuration in Registry, but if current directory contains "ttpmenu.ini" file, it will try to read configuration from this file even if the file is empty (0 bytes in size). Note that the tool does not migrate settings from Registry to .ini file, so you may need to re-create them if you decide to use .ini file.

When new entry is added to TERATERM.INI file it can be read with ReadIniFile()#ttset.c

  1. ts->ConfirmChangePaste =
  2. GetOnOff(Section, "ConfirmChangePaste", FName, TRUE);

Use WriteIniFile()#ttset.c to write into .ini file.

  1. WriteOnOff(Section, "ConfirmChangePaste", FName,
  2. ts->ConfirmChangePaste);

To read or write string entries use GetPrivateProfileString() and WritePrivateProfileString() Win32 API functions. For integer values use GetPrivateProfileInt() and WriteInt() from Win32 API.


7. Secure Programming

String Operations

Prior to Windows Vista default user account in Microsoft Windows had Administrator privileges. When an application run by administrator contains a bug causing buffer overflow error, a third-party can illegally obtain Administrator level privileges. Traditionally string operations were causing majority of buffer overflow errors in C language. To address this Microsoft developed enhanced, more secure string operation functions and made them available in Visual Studio 2005.

In order to increase Tera Term security every string operation related function was replaced in the source code with it's secure equivalent. Few examples of such replacements are shown in the table below.

Old New
sprintf(), _snprintf() _snprintf_s()
strcat(), strncat() strncat_s()
strcpy(), strncpy() strncpy_s()

Since these functions do not work well when default locale changes, Tera Term uses _snprintf_s_l() and similar functions instead.

Each of these functions have suffix "_s" (secure) in their names, which makes it easy to recognize them. Obviously, these functions are not compatible with ANSI C specification.

It should be noted that in these functions "count" argument (the maximum number of characters to store) is enforced by "_TRUNCATE" macro. If the buffer overflow can occurs, the string will be truncated to avoid this to happen.

An example of strncpy_s() function use is shown below. The second argument (numberOfElements) specifies the buffer size including terminating null (\0). Since the write buffer size is only three bytes, five bytes of data specified in the third argument (strSource) are truncates down to two bytes and null is added to the end. After executing these commands buf[] will contain the string "he\0".

  1. char buf[3];
  2. strncpy_s(buf, sizeof(buf), "hello", _TRUNCATE);

Below is an example of using strncat_s() function. The first argument (strDest) of strncat_s() function must have terminating null to concatenate strings. The second argument (numberOfElements) is specified with the buffer size that includes terminating null. In this example, when the first strncat_s() function is executed, five bytes (four chars + null) will be stored in str[]. When the second strncat_s() is executed, only two chars will be copied into the buffer, because there are only two free bytes remaining. After executing below code the buffer will contain "TeraTe\0" (4 chars + 2 chars + null).

  1. char str[7];
  2. str[0] = '\0';
  3. strncat_s(str, sizeof(str), "Tera", _TRUNCATE);
  4. strncat_s(str, sizeof(str), "Term", _TRUNCATE);

The final example demonstartes the use of _snprintf_s() function. Don't confuse this function with _snprintf() that doesn't add terminating null to the buffer. After execution of the code shown below buf[] will contain "ab\0".

  1. char buf[3];
  2. _snprintf_s(buf, sizeof(buf), _TRUNCATE, "abcdef");

Copyright © 2008-2015 Tera Term Project