mirror of
https://github.com/kingToolbox/WindTerm.git
synced 2026-08-30 11:27:52 +08:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8336c1d1e | ||
|
|
b8d2cb7d18 | ||
|
|
3dc9041343 | ||
|
|
52b53014f9 | ||
|
|
ba078c0c7c | ||
|
|
10304684e3 | ||
|
|
13101e098b | ||
|
|
24c96a6aa6 | ||
|
|
ee11e00722 | ||
|
|
aa779b4b09 | ||
|
|
6c57450c56 | ||
|
|
05ffe7e8d4 | ||
|
|
f1a49022a9 | ||
|
|
d76580bea2 | ||
|
|
be6e770876 | ||
|
|
44cc3bb57c | ||
|
|
99c095a22c | ||
|
|
3bc1a009d5 | ||
|
|
07b34806ac | ||
|
|
7a61ac2155 | ||
|
|
8cc7dcb147 | ||
|
|
b02dc28a9e | ||
|
|
7920e91b74 |
205
README.md
205
README.md
@@ -1,9 +1,9 @@
|
|||||||
# WindTerm
|
# WindTerm
|
||||||
A professional SSH/Telnet/Serial/Shell/Sftp client for DevOps.
|
A Quicker and better SSH/Telnet/Serial/Shell/Sftp client for DevOps.
|
||||||
|
|
||||||
_Hello WindTerm :rose:, hello world!_
|
_Hello WindTerm :rose:, hello world!_
|
||||||
|
|
||||||
**We're just beginning! If you want a high performance text editor, you can try [WindEdit](https://www.github.com/kingToolbox/DIGEdit/).**
|
**We're just beginning! If you want a high performance text editor, you can try [WindEdit](https://www.github.com/kingToolbox/WindEdit/).**
|
||||||
|
|
||||||
# License
|
# License
|
||||||
**Completely FREE for commercial and non-commercial use without limitations.**
|
**Completely FREE for commercial and non-commercial use without limitations.**
|
||||||
@@ -15,9 +15,7 @@ See [Intro Videos](https://kingtoolbox.github.io)
|
|||||||
|
|
||||||
# Download
|
# Download
|
||||||
|
|
||||||
**Linux binary** and **Windows binary**: https://github.com/kingToolbox/WindTerm/releases
|
**Linux binary**, **MacOS binary** and **Windows binary**: https://github.com/kingToolbox/WindTerm/releases
|
||||||
|
|
||||||
(The binary of Macos will be committed later)
|
|
||||||
|
|
||||||
# Source Code
|
# Source Code
|
||||||
|
|
||||||
@@ -49,20 +47,37 @@ DigeWhite Theme:
|
|||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
|
||||||
### SSH, Telnet, Tcp, Shell, Serial
|
### SSH, Telnet, Tcp, Shell, Serial, Tmux
|
||||||
- SSH v2, Telnet, Raw Tcp, Serial, Shell protocols implemented. [Intro Video](https://kingtoolbox.github.io/2020/01/22/new-session/)
|
- SSH v2, Telnet, Raw Tcp, Serial, Shell protocols implemented. [Intro Video](https://kingtoolbox.github.io/2020/01/22/new-session/)
|
||||||
- Supports SSH auto execution when session authenticated.
|
- Supports SSH auto execution when session authenticated.
|
||||||
- Supports SSH agent forwarding. [Intro Video](https://kingtoolbox.github.io/2020/08/22/ssh_agent_forwarding/)
|
- Supports SSH ControlMaster.
|
||||||
|
- Supports SSH ProxyCommand or ProxyJump. [Intro Video](https://kingtoolbox.github.io/2021/03/11/proxycommand/)
|
||||||
|
- Supports SSH agent. [Intro Video](https://kingtoolbox.github.io/2020/08/22/ssh_agent/)
|
||||||
|
- Supports SSH agent forwarding.
|
||||||
- Supports SSH auto login with password, public-key, keyboard-interactive, gssapi-with-mic. [Intro Video](https://kingtoolbox.github.io/2020/01/23/auto-login/)
|
- Supports SSH auto login with password, public-key, keyboard-interactive, gssapi-with-mic. [Intro Video](https://kingtoolbox.github.io/2020/01/23/auto-login/)
|
||||||
- Supports X11 forwarding. [Intro Video](https://kingtoolbox.github.io/2020/07/21/x11_forwarding/)
|
- Supports X11 forwarding. [Intro Video](https://kingtoolbox.github.io/2020/07/21/x11_forwarding/)
|
||||||
- Supports direct/local port forwarding, reverse/remote port forwarding and dynamic port forwarding. [Intro Video](https://kingtoolbox.github.io/2020/07/21/port_forwarding/)
|
- Supports direct/local port forwarding, reverse/remote port forwarding and dynamic port forwarding. [Intro Video](https://kingtoolbox.github.io/2020/07/21/port_forwarding/)
|
||||||
|
- Supports XModem, YModem and ZModem. [Intro Video](https://kingtoolbox.github.io/tags/modem/)
|
||||||
- Integrated sftp, scp client, supports download, upload, remove, rename, make new file/directory and so on. [Intro Video](https://kingtoolbox.github.io/tags/transfer/)
|
- Integrated sftp, scp client, supports download, upload, remove, rename, make new file/directory and so on. [Intro Video](https://kingtoolbox.github.io/tags/transfer/)
|
||||||
- Integrated local file manager, supports move to, copy to, copy from, remove, rename, make new file/directory and so on.
|
- Integrated local file manager, supports move to, copy to, copy from, remove, rename, make new file/directory and so on.
|
||||||
- Supports Cmd, PowerShell and Cmd, PowerShell as administrator.
|
- Supports Windows Cmd, PowerShell and Cmd, PowerShell as administrator.
|
||||||
|
- Supports Linux bash, zsh, powershell core and so on.
|
||||||
|
- Supports MacOS bash, zsh, powershell core and so on.
|
||||||
|
- **Supports `tmux integration`**. [Intro Video](https://kingtoolbox.github.io/2025/01/05/tmux-integration/)
|
||||||
### GUI
|
### GUI
|
||||||
- Session dialog and session tree.
|
- **Supports Windows, MacOS and Linux.**
|
||||||
|
- **Supports Multilingual User Interface.**
|
||||||
|
- Supports Unicode 13.
|
||||||
|
- Session dialog and session tree. [Intro Video](https://kingtoolbox.github.io/2020/01/22/manage-sessions/)
|
||||||
|
- **Auto Completion.** [Intro Video](https://kingtoolbox.github.io/tags/auto-completion/)
|
||||||
|
- **Free Type Mode.** [Intro Video](https://kingtoolbox.github.io/2022/04/12/free_type_mode/)
|
||||||
|
- **Focus Mode.** [Intro Video](https://kingtoolbox.github.io/2021/06/28/ui_focus_mode/)
|
||||||
|
- **Sync Input.** [Intro Video](https://kingtoolbox.github.io/2021/05/27/sync-input/)
|
||||||
|
- **Enhanced protection of the session username and password.** [Intro Video](https://kingtoolbox.github.io/2021/03/11/protection-username-password/)
|
||||||
- **Command palette.** [Intro Video](https://kingtoolbox.github.io/tags/command-palette/)
|
- **Command palette.** [Intro Video](https://kingtoolbox.github.io/tags/command-palette/)
|
||||||
- **Command sender.** [Intro Video](https://kingtoolbox.github.io/tags/sender/)
|
- **Command sender.** [Intro Video](https://kingtoolbox.github.io/tags/sender/)
|
||||||
|
- **Explorer Pane.** [Intro Video](https://kingtoolbox.github.io/2021/05/27/explorer/)
|
||||||
|
- **Shell Pane.**
|
||||||
- **Quick Bar.** [Intro Video](https://kingtoolbox.github.io/2020/08/22/quickbar/)
|
- **Quick Bar.** [Intro Video](https://kingtoolbox.github.io/2020/08/22/quickbar/)
|
||||||
- **Paste Dialog.** [Intro Video](https://kingtoolbox.github.io/2020/08/22/paste_dialog/)
|
- **Paste Dialog.** [Intro Video](https://kingtoolbox.github.io/2020/08/22/paste_dialog/)
|
||||||
- **Local and remote modes with vim keybindings. (Using Shift+Enter key to switch between remote and local mode**) [Intro Video](https://kingtoolbox.github.io/2020/06/21/keyboard-modes/)
|
- **Local and remote modes with vim keybindings. (Using Shift+Enter key to switch between remote and local mode**) [Intro Video](https://kingtoolbox.github.io/2020/06/21/keyboard-modes/)
|
||||||
@@ -73,10 +88,13 @@ DigeWhite Theme:
|
|||||||
- Supports highlighting the opening and closing delimiter, such as (), [], {} and the customed delimiters. [Intro Video](https://kingtoolbox.github.io/2020/06/28/pair/)
|
- Supports highlighting the opening and closing delimiter, such as (), [], {} and the customed delimiters. [Intro Video](https://kingtoolbox.github.io/2020/06/28/pair/)
|
||||||
- Supports changing the UI theme. [Intro Video](https://kingtoolbox.github.io/2020/09/18/theme/)
|
- Supports changing the UI theme. [Intro Video](https://kingtoolbox.github.io/2020/09/18/theme/)
|
||||||
- Supports setting the tab color. [Intro Video](https://kingtoolbox.github.io/2020/09/18/tabbar-change-tabcolor/)
|
- Supports setting the tab color. [Intro Video](https://kingtoolbox.github.io/2020/09/18/tabbar-change-tabcolor/)
|
||||||
|
- Supports searching over the opened tabs. [Intro Video](https://kingtoolbox.github.io/2021/03/11/tabbar-search-tab/)
|
||||||
- Supports closing tabs to the right.
|
- Supports closing tabs to the right.
|
||||||
- Supports setting the windows transparency. [Intro video](https://kingtoolbox.github.io/2020/11/13/windows-opacity/)
|
- Supports setting the windows transparency. [Intro video](https://kingtoolbox.github.io/2020/11/13/windows-opacity/)
|
||||||
- Supports select-to-copy and middle-click-to-paste.
|
- Supports select-to-copy, right-click-to-paste or middle-click-to-paste.
|
||||||
- Supports searching text online with Google, Bing, Github, Stackoverflow, Wikipedia and DuckDuckGo. [Intro video](https://kingtoolbox.github.io/2020/11/13/search-online/)
|
- Supports searching text online with Google, Bing, Github, Stackoverflow, Wikipedia and DuckDuckGo. [Intro video](https://kingtoolbox.github.io/2020/11/13/search-online/)
|
||||||
|
- Supports hiding mouse cursor while typing.
|
||||||
|
- **Supports locking screen.** [Intro video](https://kingtoolbox.github.io/2021/04/23/lock-screen/)
|
||||||
### Term
|
### Term
|
||||||
- Supports vt100, vt220, vt340, vt420, vt520, xterm, xterm-256-colors.
|
- Supports vt100, vt220, vt340, vt420, vt520, xterm, xterm-256-colors.
|
||||||
- Supports unicode, emojis, true-color, mouse protocol, etc.
|
- Supports unicode, emojis, true-color, mouse protocol, etc.
|
||||||
@@ -84,11 +102,14 @@ DigeWhite Theme:
|
|||||||
- Protocols and terms can be customed.
|
- Protocols and terms can be customed.
|
||||||
- All vttest tests have passed except Tektronix 4014.
|
- All vttest tests have passed except Tektronix 4014.
|
||||||
### Session
|
### Session
|
||||||
- **Supports HTTP and SOCKS5 proxy.** [Intro Video](https://kingtoolbox.github.io/2020/10/17/proxy/)
|
- **Supports HTTP and SOCKS5 proxy.** [Intro Video](https://kingtoolbox.github.io/2021/03/11/proxy-http-socks5/)
|
||||||
|
- **Supports Jump Server proxy.** [Intro Video](https://kingtoolbox.github.io/2021/03/11/proxy-jump-server/)
|
||||||
- Supports manual and automated session logging. [Intro Video](https://kingtoolbox.github.io/tags/logging/)
|
- Supports manual and automated session logging. [Intro Video](https://kingtoolbox.github.io/tags/logging/)
|
||||||
- Rename and duplicate session. [Intro Video](https://kingtoolbox.github.io/tags/tabbar/)
|
- Rename and duplicate session. [Intro Video](https://kingtoolbox.github.io/tags/tabbar/)
|
||||||
- Restore last sessions and layouts when restart. [Intro Video](https://kingtoolbox.github.io/2020/01/22/restore-sessions/)
|
- Restore last sessions and layouts when restart. [Intro Video](https://kingtoolbox.github.io/2020/01/22/restore-sessions/)
|
||||||
|
- Supports opening a specific session or set of sessions on startup.
|
||||||
### Performance
|
### Performance
|
||||||
|
- Dynamic memory compression, typically `20%` to `90%` of the working memory load can be reduced.
|
||||||
- High performance, low memory, low latency. [Intro Video](https://kingtoolbox.github.io/2020/01/23/windterm-putty-performance/)
|
- High performance, low memory, low latency. [Intro Video](https://kingtoolbox.github.io/2020/01/23/windterm-putty-performance/)
|
||||||
|
|
||||||
# Sftp Performance
|
# Sftp Performance
|
||||||
@@ -110,7 +131,7 @@ The version of clients:
|
|||||||
|
|
||||||
**All test data is for reference only.**
|
**All test data is for reference only.**
|
||||||
|
|
||||||
- 5GB huge file (5,154,830 KB), generated by random data
|
### 5GB huge file (5,154,830 KB), generated by random data
|
||||||
|
|
||||||
| | Download Time | Download Rate | Upload Time | Upload Rate |
|
| | Download Time | Download Rate | Upload Time | Upload Rate |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
@@ -120,7 +141,7 @@ The version of clients:
|
|||||||
| FileZilla | 32s | 161.1 MB/s | 30s | 171.8 MB/s |
|
| FileZilla | 32s | 161.1 MB/s | 30s | 171.8 MB/s |
|
||||||
| WinSCP | 81s | 63.7 MB/s | 91s | 56.7 MB/s |
|
| WinSCP | 81s | 63.7 MB/s | 91s | 56.7 MB/s |
|
||||||
|
|
||||||
- 4400 files, 16 folders (107,042 KB), unzipped from [vim-7.4.1049.zip](https://github.com/vim/vim/archive/v7.4.1049.zip)
|
### 4400 files, 16 folders (107,042 KB), unzipped from [vim-7.4.1049.zip](https://github.com/vim/vim/archive/v7.4.1049.zip)
|
||||||
|
|
||||||
| | Download Time | Download Rate | Upload Time | Upload Rate |
|
| | Download Time | Download Rate | Upload Time | Upload Rate |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
@@ -161,7 +182,9 @@ The version of terminals:
|
|||||||
|
|
||||||
**All test data is for reference only.**
|
**All test data is for reference only.**
|
||||||
|
|
||||||
- 97.6MB random text (102,401,504 bytes, 1,329,878 lines, generated and tested by [random_test.sh](https://github.com/kingToolbox/WindTerm/blob/master/benchmark/urandom_test.sh))
|
## Test Command: "cat ./benchmark_randomdata"
|
||||||
|
|
||||||
|
The benchmark_randomdata contains 97.6MB random text (102,401,504 bytes, 1,329,878 lines, generated and tested by [random_test.sh](https://github.com/kingToolbox/WindTerm/blob/master/benchmark/urandom_test.sh))
|
||||||
|
|
||||||
In all cases, three runs were made to warm system caches. The reported numbers are the median of five runs.
|
In all cases, three runs were made to warm system caches. The reported numbers are the median of five runs.
|
||||||
|
|
||||||
@@ -193,9 +216,9 @@ In all cases, three runs were made to warm system caches. The reported numbers a
|
|||||||
| kitty | unlimited | 17.2 | 2655 |
|
| kitty | unlimited | 17.2 | 2655 |
|
||||||
| Alacritty | 100,000 | 41.3 | - |
|
| Alacritty | 100,000 | 41.3 | - |
|
||||||
|
|
||||||
- time seq 1 n
|
## Test command: "time seq 1 n" (n = [1000000, 2000000, 5000000, 10000000], scrollback lines: unlimited)
|
||||||
|
|
||||||
1. n = 1,000,000, scrollback = 1,000,000 Lines
|
### n = 1,000,000
|
||||||
|
|
||||||
| | Time(sec) | Memory Usage(MB) |
|
| | Time(sec) | Memory Usage(MB) |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
@@ -208,7 +231,7 @@ In all cases, three runs were made to warm system caches. The reported numbers a
|
|||||||
| Alacritty | **1.162** | Not measured, use 100,000 scrollback lines setting |
|
| Alacritty | **1.162** | Not measured, use 100,000 scrollback lines setting |
|
||||||
| Windows Terminal + ssh.exe | 23.246 | Not measured, use 65,535 scrollback lines setting |
|
| Windows Terminal + ssh.exe | 23.246 | Not measured, use 65,535 scrollback lines setting |
|
||||||
|
|
||||||
2. n = 2,000,000, scrollback = 2,000,000 Lines
|
### n = 2,000,000
|
||||||
|
|
||||||
| | Time(sec) | Memory Usage(MB) |
|
| | Time(sec) | Memory Usage(MB) |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
@@ -221,33 +244,33 @@ In all cases, three runs were made to warm system caches. The reported numbers a
|
|||||||
| Alacritty | 2.322 | Not measured, use 100,000 scrollback lines setting |
|
| Alacritty | 2.322 | Not measured, use 100,000 scrollback lines setting |
|
||||||
| Windows Terminal + ssh.exe | 50.381 | Not measured, use 65,535 scrollback lines setting |
|
| Windows Terminal + ssh.exe | 50.381 | Not measured, use 65,535 scrollback lines setting |
|
||||||
|
|
||||||
3. n = 5,000,000 scrollback = 5,000,000 Lines
|
### n = 5,000,000
|
||||||
|
|
||||||
| | Time(sec) | Memory Usage(MB) |
|
| | Time(sec) | Memory Usage(MB) |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| WindTerm | **5.520** | **68.2** |
|
| WindTerm | **5.520** | **68.2** |
|
||||||
| rxvt | 27.533 | 3166.2 |
|
| rxvt | 27.533 | 3166.2 |
|
||||||
| putty | 45.911 | 2757.1 |
|
| putty | 45.911 | 2757.1 |
|
||||||
| xterm | - | Out of memmory |
|
| xterm | - | Out of memory |
|
||||||
| iterm2 | 10.805 | 1048.3 |
|
| iterm2 | 10.805 | 1048.3 |
|
||||||
| Kitty | - | Out of memory |
|
| Kitty | - | Out of memory |
|
||||||
| Alacritty | 5.799 | Not measured, use 100,000 scrollback lines setting |
|
| Alacritty | 5.799 | Not measured, use 100,000 scrollback lines setting |
|
||||||
| Windows Terminal + ssh.exe | 130.371 | Not measured, use 65,535 scrollback lines setting |
|
| Windows Terminal + ssh.exe | 130.371 | Not measured, use 65,535 scrollback lines setting |
|
||||||
|
|
||||||
4. n = 10,000,000 scrollback = 10,000,000 Lines
|
### n = 10,000,000
|
||||||
|
|
||||||
| | Time(sec) | Memory Usage(MB) |
|
| | Time(sec) | Memory Usage(MB) |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| WindTerm | **10.674** | **133.3** |
|
| WindTerm | **10.674** | **133.3** |
|
||||||
| rxvt | - | Out of memory |
|
| rxvt | - | Out of memory |
|
||||||
| putty | - | Out of memory |
|
| putty | - | Out of memory |
|
||||||
| xterm | - | Out of memmory |
|
| xterm | - | Out of memory |
|
||||||
| iterm2 | 20.468 | 2231.3 |
|
| iterm2 | 20.468 | 2231.3 |
|
||||||
| Kitty | - | Out of memory |
|
| Kitty | - | Out of memory |
|
||||||
| Alacritty | 11.598 | Not measured, use 100,000 scrollback lines setting |
|
| Alacritty | 11.598 | Not measured, use 100,000 scrollback lines setting |
|
||||||
| Windows Terminal + ssh.exe | 264.739 | Not measured, use 65,535 scrollback lines setting |
|
| Windows Terminal + ssh.exe | 264.739 | Not measured, use 65,535 scrollback lines setting |
|
||||||
|
|
||||||
5. n = 10,000,000 scrollback = 30 Lines
|
### n = 10,000,000 scrollback = 30 Lines
|
||||||
|
|
||||||
| | Time(sec) | Memory Usage(MB) |
|
| | Time(sec) | Memory Usage(MB) |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
@@ -260,6 +283,55 @@ In all cases, three runs were made to warm system caches. The reported numbers a
|
|||||||
| Alacritty | 11.798 | Not measured, use zero scrollback lines setting |
|
| Alacritty | 11.798 | Not measured, use zero scrollback lines setting |
|
||||||
| Windows Terminal + ssh.exe | 261.096 | Not measured, use zero scrollback lines setting |
|
| Windows Terminal + ssh.exe | 261.096 | Not measured, use zero scrollback lines setting |
|
||||||
|
|
||||||
|
# Linux Terminal Performance
|
||||||
|
|
||||||
|
The hardware used for generating the data in these benchmarks was
|
||||||
|
|
||||||
|
Debian 10 Vm - 4cpu and 4GB memory.
|
||||||
|
|
||||||
|
For WindTerm: No color scheme used in windterm. Color scheme will result in approximately 2% loss and more memory usage.
|
||||||
|
|
||||||
|
For other terminals: No memory usage measured because most of them write the history to disk or only support a limited number of lines in memory..
|
||||||
|
|
||||||
|
The version of terminals:
|
||||||
|
|
||||||
|
| Application | Version | Release Date |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Windterm | v1.9 | 2020-12-22 |
|
||||||
|
| Gnome | v3.30.2 | 2018-10-22 |
|
||||||
|
| Mate Terminal | v1.20.2 | 2019-02-11 |
|
||||||
|
| Konsole | v18.04.0 | 2019-04-12 |
|
||||||
|
| Xfce4 Terminal | v0.8.7.4 | 2018-5-15 |
|
||||||
|
| QTerminal | v0.14.1 | 2019-01-26 |
|
||||||
|
|
||||||
|
**All test data is for reference only.**
|
||||||
|
|
||||||
|
## Test Command: "cat ./benchmark_randomdata"
|
||||||
|
|
||||||
|
The benchmark_randomdata contains 97.6MB random text (102,401,504 bytes, 1,329,878 lines, generated and tested by [random_test.sh](https://github.com/kingToolbox/WindTerm/blob/master/benchmark/urandom_test.sh))
|
||||||
|
|
||||||
|
In all cases, three runs were made to warm system caches. The reported numbers are the median of five runs.
|
||||||
|
|
||||||
|
| | Cost Time |
|
||||||
|
| --- | --- |
|
||||||
|
| WindTerm | **1.976s** |
|
||||||
|
| Gnome Terminal | 9.781s |
|
||||||
|
| Mate Terminal | 9.841s |
|
||||||
|
| Konsole | 25.050s |
|
||||||
|
| xfce4 Terminal | 10.520s |
|
||||||
|
| QTerminal | 20.763s |
|
||||||
|
|
||||||
|
## Test command: "time seq 1 n" (n = [1000000, 2000000, 5000000, 10000000], scrollback lines: unlimited)
|
||||||
|
|
||||||
|
| n | 1,000,000 | 2,000,000 | 5,000,000 | 10,000,000 | 10,000,000<br>(scrollback lines: 100) |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| WindTerm | 0.846s (18.6MB) | **1.574s** (26.6MB) | **4.046s** (56.4MB) | **8.232s** (102.2MB) | **7.748s** (3.4MB) |
|
||||||
|
| Gnome Terminal | 0.920s | 2.152s | 5.271s | 11.111s | 13.109s |
|
||||||
|
| Mate Terminal | **0.822s** | 1.698s | 5.943s | 10.920s | 12.290s |
|
||||||
|
| Konsole | 1.612s | 3.199s | 8.157s | 16.029s | 15.650s |
|
||||||
|
| xfce4 Terminal | 0.870s | 2.160s | 5.866s | 12.089s | 13.304s |
|
||||||
|
| QTerminal | 9.272s | 18.391s | 45.999s | 104.277s | 17.208s |
|
||||||
|
|
||||||
# Latency
|
# Latency
|
||||||
|
|
||||||
Considering the network influence on the latency, the following data is from [WindEdit](https://github.com/kingToolbox/digedit).
|
Considering the network influence on the latency, the following data is from [WindEdit](https://github.com/kingToolbox/digedit).
|
||||||
@@ -273,69 +345,33 @@ DIGEdit is the text component of WindTerm.
|
|||||||
|
|
||||||
# Shortcuts
|
# Shortcuts
|
||||||
|
|
||||||
| Shortcut | Action |
|
[Shortcut Keys List](https://kingtoolbox.github.io/tags/keyboard/)
|
||||||
| --- | --- |
|
|
||||||
| Alt+C | Copy |
|
|
||||||
| Alt+D | Show command palette |
|
|
||||||
| Alt+F | Find |
|
|
||||||
| Alt+F3 | Find next |
|
|
||||||
| Alt+Shift+F3 | Find previous |
|
|
||||||
| Alt+F4 | Exit |
|
|
||||||
| Alt+M, Alt+F | Toggle full screen |
|
|
||||||
| Alt+M, Alt+H | Toggle hex view |
|
|
||||||
| Alt+N | New session |
|
|
||||||
| Alt+O | Open session |
|
|
||||||
| Alt+S | Save text |
|
|
||||||
| Alt+T, Alt+B | Toggle margin blank |
|
|
||||||
| Alt+T, Alt+F | Toggle margin fold |
|
|
||||||
| Alt+T, Alt+N | Toggle margin number |
|
|
||||||
| Alt+T, Alt+S | Toggle margin symbol |
|
|
||||||
| Alt+V | Paste |
|
|
||||||
| Alt+W, Alt+D | Close active dock |
|
|
||||||
| Alt+W, Alt+G | Close active group |
|
|
||||||
| Alt+W, Alt+H | Split horizontally |
|
|
||||||
| Alt+W, Alt+L | Show outline pane |
|
|
||||||
| Alt+W, Alt+V | Split vertically |
|
|
||||||
| Alt+X | Copy and paste |
|
|
||||||
| Alt+- | Zoom in |
|
|
||||||
| Alt++ | Zoom out |
|
|
||||||
| Alt+\[ | Activate next view |
|
|
||||||
| Alt+] | Activate previous view |
|
|
||||||
| Ctrl+. | Jump to next fold |
|
|
||||||
| Ctrl+, | Jump to previous fold |
|
|
||||||
| Ctrl+Shift+A | Select all text |
|
|
||||||
| Ctrl+Shift+T | Reopen closed session |
|
|
||||||
| Ctrl+Shift+W | Close current session |
|
|
||||||
| Ctrl+Shift+- | Select current fold text |
|
|
||||||
| Shift+Del | Copy |
|
|
||||||
| Shift+End | Jump to document end |
|
|
||||||
| Shift+Home | Jump to document home |
|
|
||||||
| Shift+Ins | Paste |
|
|
||||||
| Shift+PgDown | Jump to next page |
|
|
||||||
| Shift+PgUp | Jump to previous page |
|
|
||||||
|
|
||||||
# Roadmap
|
# Roadmap
|
||||||
|
|
||||||
**Release cycle:**
|
**Release cycle:**
|
||||||
|
|
||||||
2-4 weeks.
|
2-3 months.
|
||||||
|
|
||||||
**Next release (Late November,for reference only):**
|
**Prerelease cycle:**
|
||||||
- **Linux Version**
|
|
||||||
- **Linux Shells**
|
4~6 weeks
|
||||||
- Xmodem, Ymodem, Zmodem(sz, rz)
|
|
||||||
|
# Roadmap of v2.7 (February 2025, for reference only)
|
||||||
|
- **Resolve issues as much as possible**
|
||||||
|
- SSH Agent Forwaring
|
||||||
|
- Tmux integration
|
||||||
|
- Command Snippet [Description](https://github.com/kingToolbox/WindTerm/issues/239#issuecomment-951934488) (Postponed to a later version )
|
||||||
|
- SSH GSSAPI Authentication (Postponed to a later version )
|
||||||
|
- Search in sessions (Postponed to a later version )
|
||||||
|
|
||||||
|
Download: [WindTerm 2.7.0 Prerelease 3](https://github.com/kingToolbox/WindTerm/releases/tag/2.7-prerelease-3) (2025-2-10)
|
||||||
|
|
||||||
|
**Roadmap of version 2.x:**
|
||||||
- External tools
|
- External tools
|
||||||
|
|
||||||
**Todo list:**
|
|
||||||
- Protocols:
|
- Protocols:
|
||||||
- Rlogin
|
|
||||||
- Mosh
|
- Mosh
|
||||||
- SSH
|
- Rlogin
|
||||||
- ProxyCommand
|
|
||||||
- UI:
|
|
||||||
- Config dialog
|
|
||||||
- Terminal:
|
|
||||||
- MacOs bash
|
|
||||||
- Session:
|
- Session:
|
||||||
- Auto Complete
|
- Auto Complete
|
||||||
- Chat mode
|
- Chat mode
|
||||||
@@ -344,3 +380,20 @@ DIGEdit is the text component of WindTerm.
|
|||||||
- ftp, ftps
|
- ftp, ftps
|
||||||
- Script, macro and plugin stystem
|
- Script, macro and plugin stystem
|
||||||
- More ...
|
- More ...
|
||||||
|
|
||||||
|
**Release Schedule:**
|
||||||
|
Version | Level | Target | Status | Timeline
|
||||||
|
------------ | ------------- | -------------- | ---------- | -----------
|
||||||
|
v0.x | Basic | Basic framework and basic features, but complete a high-performance text editor ([WindEdit](https://github.com/kingToolbox/WindEdit)) as the base, and be able to use them normally. | Finished | Long long ago ~ Sprint of 2020
|
||||||
|
v1.x | Manual | Perfect features and can be used by most developers in their daily work | Finished | Spring of 2020 ~ Winter of 2020
|
||||||
|
**v2.x** | **Semi automatic** | **Through triggers, macros, events, notifications and so on, developers can be assisted to complete some operations.** | **Developing** | **Spring of 2021 ~ Summer of 2022**
|
||||||
|
v3.x | Fully automatic | Through plugins, scripts, machine learning and so on, automatically operating with achieving non-attended | Planning | Summer of 2022 ~ Winter of 2023
|
||||||
|
|
||||||
|
# Acknowledgement
|
||||||
|
| | Contribution |
|
||||||
|
| ---------- | ------------- |
|
||||||
|
| [EvoWebFrance](https://github.com/EvoWebFrance) | French translation |
|
||||||
|
| [kvnklk](https://github.com/kvnklk) | German translation |
|
||||||
|
| [Lemonawa](https://github.com/Lemonawa) | Simplified Chinese translation |
|
||||||
|
| [LuxNegra](https://github.com/LuxNegra) | French translation |
|
||||||
|
| [MosamXu](https://github.com/MosamXu) | Simplified Chinese translation |
|
||||||
|
|||||||
BIN
images/WindTerm_icon_1024x1024.png
Normal file
BIN
images/WindTerm_icon_1024x1024.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
328
src/Pty/UnixPty.cpp
Normal file
328
src/Pty/UnixPty.cpp
Normal file
@@ -0,0 +1,328 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020, WindTerm.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#include "UnixPty.h"
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <utmpx.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
constexpr int BUFFER_SIZE = 0x800; // 2048 bytes
|
||||||
|
|
||||||
|
ShellProcess::ShellProcess()
|
||||||
|
: QProcess()
|
||||||
|
, m_handleMaster(-1)
|
||||||
|
, m_handleSlave(-1)
|
||||||
|
{
|
||||||
|
setProcessChannelMode(QProcess::MergedChannels);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShellProcess::setupChildProcess() {
|
||||||
|
dup2(m_handleSlave, STDIN_FILENO);
|
||||||
|
dup2(m_handleSlave, STDOUT_FILENO);
|
||||||
|
dup2(m_handleSlave, STDERR_FILENO);
|
||||||
|
|
||||||
|
pid_t sid = setsid();
|
||||||
|
ioctl(m_handleSlave, TIOCSCTTY, 0);
|
||||||
|
tcsetpgrp(m_handleSlave, sid);
|
||||||
|
|
||||||
|
struct utmpx utmpxInfo;
|
||||||
|
memset(&utmpxInfo, 0, sizeof(utmpxInfo));
|
||||||
|
|
||||||
|
strncpy(utmpxInfo.ut_user, qgetenv("USER"), sizeof(utmpxInfo.ut_user));
|
||||||
|
|
||||||
|
QString device(m_handleSlaveName);
|
||||||
|
if (device.startsWith("/dev/")) {
|
||||||
|
device = device.mid(5);
|
||||||
|
}
|
||||||
|
const char *d = device.toLatin1().constData();
|
||||||
|
strncpy(utmpxInfo.ut_line, d, sizeof(utmpxInfo.ut_line));
|
||||||
|
strncpy(utmpxInfo.ut_id, d + strlen(d) - sizeof(utmpxInfo.ut_id), sizeof(utmpxInfo.ut_id));
|
||||||
|
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, 0);
|
||||||
|
utmpxInfo.ut_tv.tv_sec = tv.tv_sec;
|
||||||
|
utmpxInfo.ut_tv.tv_usec = tv.tv_usec;
|
||||||
|
|
||||||
|
utmpxInfo.ut_type = USER_PROCESS;
|
||||||
|
utmpxInfo.ut_pid = getpid();
|
||||||
|
|
||||||
|
utmpxname(_PATH_UTMPX);
|
||||||
|
setutxent();
|
||||||
|
pututxline(&utmpxInfo);
|
||||||
|
endutxent();
|
||||||
|
|
||||||
|
#if !defined(Q_OS_UNIX)
|
||||||
|
updwtmpx(_PATH_UTMPX, &loginInfo);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
UnixPty::UnixPty(QObject *parent /*= nullptr*/)
|
||||||
|
: Pty(parent)
|
||||||
|
, m_pid(0)
|
||||||
|
, m_readMasterNotify(nullptr)
|
||||||
|
{
|
||||||
|
m_buffer = static_cast<char *>(malloc(BUFFER_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
UnixPty::~UnixPty() {
|
||||||
|
stop();
|
||||||
|
|
||||||
|
free(m_buffer);
|
||||||
|
m_buffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnixPty::createProcess(QString command, const QString &arguments,
|
||||||
|
const QString &workingDirectory, const QProcessEnvironment &environment,
|
||||||
|
int rows, int columns) {
|
||||||
|
if (m_shellProcess.state() == QProcess::Running) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileInfo fileInfo(command);
|
||||||
|
if (fileInfo.isRelative() || fileInfo.exists() == false) {
|
||||||
|
setErrorString(tr("UnixPty: shell file path must be absolute"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
do {
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
m_shellProcess.m_handleMaster = ::posix_openpt(O_RDWR | O_NOCTTY);
|
||||||
|
if (m_shellProcess.m_handleMaster < 0) {
|
||||||
|
setError("Unable to open master");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shellProcess.m_handleSlaveName = ptsname(m_shellProcess.m_handleMaster);
|
||||||
|
if (m_shellProcess.m_handleSlaveName.isEmpty()) {
|
||||||
|
setError("Unable to get slave name");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = grantpt(m_shellProcess.m_handleMaster);
|
||||||
|
if (result != 0) {
|
||||||
|
setError("Unable to change perms for slave");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = unlockpt(m_shellProcess.m_handleMaster);
|
||||||
|
if (result != 0) {
|
||||||
|
setError("Unable to unlock slave");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shellProcess.m_handleSlave = ::open(m_shellProcess.m_handleSlaveName.toLatin1().data(), O_RDWR | O_NOCTTY);
|
||||||
|
if (m_shellProcess.m_handleSlave < 0) {
|
||||||
|
setError("Unable to open slave");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int flags = fcntl(m_shellProcess.m_handleMaster, F_GETFL, 0);
|
||||||
|
result = fcntl(m_shellProcess.m_handleMaster, F_SETFL, flags | O_NONBLOCK);
|
||||||
|
if (result == -1) {
|
||||||
|
setError("Unable to set non-blocking mode for master");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = fcntl(m_shellProcess.m_handleMaster, F_SETFD, FD_CLOEXEC);
|
||||||
|
if (result == -1) {
|
||||||
|
setError("Unable to set flags for master");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = fcntl(m_shellProcess.m_handleSlave, F_SETFD, FD_CLOEXEC);
|
||||||
|
if (result == -1) {
|
||||||
|
setError("Unable to set flags for slave");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ::termios ttmode;
|
||||||
|
if (terminalAttributes(&ttmode) == false) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ttmode.c_iflag |= IXON;
|
||||||
|
ttmode.c_iflag |= IUTF8;
|
||||||
|
ttmode.c_lflag |= ECHO;
|
||||||
|
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
ttmode.c_cc[VDSUSP] = 25;
|
||||||
|
ttmode.c_cc[VSTATUS] = 20;
|
||||||
|
#endif
|
||||||
|
if (setTerminalAttributes(&ttmode) == false) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_readMasterNotify = new QSocketNotifier(m_shellProcess.m_handleMaster, QSocketNotifier::Read, &m_shellProcess);
|
||||||
|
m_readMasterNotify->setEnabled(true);
|
||||||
|
m_readMasterNotify->moveToThread(m_shellProcess.thread());
|
||||||
|
|
||||||
|
QObject::connect(m_readMasterNotify, &QSocketNotifier::activated, [this](int socket) {
|
||||||
|
Q_UNUSED(socket)
|
||||||
|
int readSize = 0;
|
||||||
|
QByteArray readData;
|
||||||
|
|
||||||
|
do {
|
||||||
|
readSize = ::read(m_shellProcess.m_handleMaster, m_buffer, BUFFER_SIZE);
|
||||||
|
|
||||||
|
if (readSize == -1) {
|
||||||
|
if (errno == EAGAIN) {
|
||||||
|
QThread::yieldCurrentThread();
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
readData.append(QByteArray::fromRawData(m_buffer, readSize));
|
||||||
|
} while (readSize == BUFFER_SIZE || (readSize == -1 && errno == EAGAIN)); //last data block always < readSize
|
||||||
|
|
||||||
|
if (readData.isEmpty() == false) {
|
||||||
|
m_shellReadBuffer.append(readData);
|
||||||
|
emit readyRead();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
m_shellProcess.setWorkingDirectory(workingDirectory);
|
||||||
|
m_shellProcess.setProcessEnvironment(environment);
|
||||||
|
m_shellProcess.setReadChannel(QProcess::StandardOutput);
|
||||||
|
m_shellProcess.start(command, arguments.isEmpty() ? QStringList() : QStringList(arguments));
|
||||||
|
m_shellProcess.waitForStarted();
|
||||||
|
|
||||||
|
m_pid = m_shellProcess.processId();
|
||||||
|
success = resizeWindow(rows, columns);
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
if (success == false) {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
Q_ASSERT(success == true);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnixPty::resizeWindow(int rows, int columns) {
|
||||||
|
if (rows != m_rows || columns != m_columns) {
|
||||||
|
bool success = false;
|
||||||
|
struct winsize winSize;
|
||||||
|
|
||||||
|
memset(&winSize, 0, sizeof(winSize));
|
||||||
|
winSize.ws_row = static_cast<quint16>(rows);
|
||||||
|
winSize.ws_col = static_cast<quint16>(columns);
|
||||||
|
|
||||||
|
if (ioctl(m_shellProcess.m_handleMaster, TIOCSWINSZ, &winSize) == 0
|
||||||
|
&& ioctl(m_shellProcess.m_handleSlave, TIOCSWINSZ, &winSize) == 0) {
|
||||||
|
m_rows = rows;
|
||||||
|
m_columns = columns;
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnixPty::setError(const char *error) {
|
||||||
|
Pty::setErrorString(QString("%1: %2 -> %3").arg(tr("UnixPty"), tr(error), strerror(errno)));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnixPty::setTerminalAttributes(struct ::termios *ttmode) {
|
||||||
|
Q_ASSERT(m_shellProcess.m_handleMaster >= 0);
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
|
if (m_shellProcess.m_handleMaster >=0) {
|
||||||
|
result = tcsetattr(m_shellProcess.m_handleMaster, TCSANOW, ttmode);
|
||||||
|
|
||||||
|
if (result != 0) {
|
||||||
|
setError("Unable to set terminal attributes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnixPty::stop() {
|
||||||
|
m_shellProcess.m_handleSlaveName = QString();
|
||||||
|
|
||||||
|
if (m_shellProcess.m_handleSlave >= 0) {
|
||||||
|
::close(m_shellProcess.m_handleSlave);
|
||||||
|
m_shellProcess.m_handleSlave = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_shellProcess.m_handleMaster >= 0) {
|
||||||
|
::close(m_shellProcess.m_handleMaster);
|
||||||
|
m_shellProcess.m_handleMaster = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_shellProcess.state() == QProcess::Running) {
|
||||||
|
m_readMasterNotify->disconnect();
|
||||||
|
m_readMasterNotify->deleteLater();
|
||||||
|
|
||||||
|
m_shellProcess.terminate();
|
||||||
|
m_shellProcess.waitForFinished(1000);
|
||||||
|
|
||||||
|
if (m_shellProcess.state() == QProcess::Running) {
|
||||||
|
QProcess::startDetached(QString("kill -9 %1").arg(m_pid));
|
||||||
|
m_shellProcess.kill();
|
||||||
|
m_shellProcess.waitForFinished(1000);
|
||||||
|
}
|
||||||
|
Q_ASSERT(m_shellProcess.state() == QProcess::NotRunning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnixPty::terminalAttributes(struct ::termios *ttmode) {
|
||||||
|
Q_ASSERT(m_shellProcess.m_handleMaster >= 0);
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
|
if (m_shellProcess.m_handleMaster >= 0) {
|
||||||
|
result = tcgetattr(m_shellProcess.m_handleMaster, ttmode);
|
||||||
|
|
||||||
|
if (result != 0) {
|
||||||
|
setError("Unable to get terminal attributes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray UnixPty::readAll() {
|
||||||
|
QByteArray shellReadBuffer = m_shellReadBuffer;
|
||||||
|
|
||||||
|
m_shellReadBuffer.clear();
|
||||||
|
return shellReadBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 UnixPty::write(const QByteArray &text) {
|
||||||
|
int writeSize = ::write(m_shellProcess.m_handleMaster, text.constData(), text.size());
|
||||||
|
Q_ASSERT(writeSize == text.size());
|
||||||
|
|
||||||
|
if (writeSize == -1) {
|
||||||
|
setError("Unable to write output");
|
||||||
|
}
|
||||||
|
return writeSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnixPty::isAvailable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnixPty::moveToThread(QThread *targetThread) {
|
||||||
|
m_shellProcess.moveToThread(targetThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // Q_OS_UNIX
|
||||||
83
src/Pty/UnixPty.h
Normal file
83
src/Pty/UnixPty.h
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020, WindTerm.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#ifndef UNIXPTY_H
|
||||||
|
#define UNIXPTY_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
|
||||||
|
#include "Pty.h"
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QSocketNotifier>
|
||||||
|
|
||||||
|
#include <termios.h>
|
||||||
|
|
||||||
|
class ShellProcess
|
||||||
|
: public QProcess
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ShellProcess();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupChildProcess() final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_handleMaster;
|
||||||
|
int m_handleSlave;
|
||||||
|
QString m_handleSlaveName;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class UnixPty;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UnixPty
|
||||||
|
: public Pty
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UnixPty(QObject *parent = nullptr);
|
||||||
|
virtual ~UnixPty();
|
||||||
|
|
||||||
|
bool createProcess(QString command, const QString &arguments,
|
||||||
|
const QString &workingDirectory, const QProcessEnvironment &environment,
|
||||||
|
int rows, int columns) final;
|
||||||
|
static bool isAvailable();
|
||||||
|
bool resizeWindow(int rows, int columns) final;
|
||||||
|
QByteArray readAll() final;
|
||||||
|
qint64 write(const QByteArray &text) final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void moveToThread(QThread *targetThread);
|
||||||
|
void setError(const char *error);
|
||||||
|
bool setTerminalAttributes(struct ::termios *ttmode);
|
||||||
|
void stop();
|
||||||
|
bool terminalAttributes(struct ::termios *ttmode);
|
||||||
|
|
||||||
|
private:
|
||||||
|
qint64 m_pid;
|
||||||
|
ShellProcess m_shellProcess;
|
||||||
|
QSocketNotifier *m_readMasterNotify;
|
||||||
|
|
||||||
|
char *m_buffer;
|
||||||
|
QByteArray m_shellReadBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // Q_OS_UNIX
|
||||||
|
#endif // UNIXPTY_H
|
||||||
@@ -30,6 +30,10 @@ A quick circular buffer template class.
|
|||||||
|
|
||||||
A very safe encryption class using the PBKDF2-algorithm as defined in RFC 8018. WindTerm uses this class together with the user's master password to protect user data, including passwords, private keys and so on.
|
A very safe encryption class using the PBKDF2-algorithm as defined in RFC 8018. WindTerm uses this class together with the user's master password to protect user data, including passwords, private keys and so on.
|
||||||
|
|
||||||
|
## Utility/MemoryPointer.h
|
||||||
|
|
||||||
|
A smart memory pointer.
|
||||||
|
|
||||||
## Utility/ScopeGuard.h
|
## Utility/ScopeGuard.h
|
||||||
|
|
||||||
A class of which the sole purpose is to run the function f in its destructor. This is useful for guaranteeing your cleanup code is executed.
|
A class of which the sole purpose is to run the function f in its destructor. This is useful for guaranteeing your cleanup code is executed.
|
||||||
|
|||||||
140
src/Utility/MemoryPointer.h
Normal file
140
src/Utility/MemoryPointer.h
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
#ifndef MEMORYPOINTER_H
|
||||||
|
#define MEMORYPOINTER_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct MemoryPointer {
|
||||||
|
typedef decltype(nullptr) nullptr_t;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MemoryPointer()
|
||||||
|
: uMemory({ 0 })
|
||||||
|
{}
|
||||||
|
|
||||||
|
MemoryPointer(const MemoryPointer &other) = delete;
|
||||||
|
MemoryPointer &MemoryPointer::operator=(const MemoryPointer &other) = delete;
|
||||||
|
|
||||||
|
MemoryPointer &MemoryPointer::operator=(nullptr_t) noexcept {
|
||||||
|
free();
|
||||||
|
|
||||||
|
uMemory = { 0 };
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryPointer(MemoryPointer &&other) noexcept {
|
||||||
|
uMemory = other.uMemory;
|
||||||
|
other.uMemory = { 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryPointer& MemoryPointer::operator=(MemoryPointer &&other) noexcept {
|
||||||
|
if (this != &other) {
|
||||||
|
free();
|
||||||
|
|
||||||
|
uMemory = other.uMemory;
|
||||||
|
other.uMemory = { 0 };
|
||||||
|
}
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~MemoryPointer() {
|
||||||
|
free();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline T *data() const {
|
||||||
|
return static_cast<T *>(uMemory.pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline T *operator->() const {
|
||||||
|
return data();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline T &operator*() const {
|
||||||
|
return *data();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline operator T*() const {
|
||||||
|
return data();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline operator bool() const noexcept {
|
||||||
|
return data() != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isNull() const {
|
||||||
|
return uMemory.pointer == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void free() {
|
||||||
|
if (uMemory.alloced) {
|
||||||
|
::free(reinterpret_cast<void *>(uMemory.pointer));
|
||||||
|
uMemory = { 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
union MemoryUnion {
|
||||||
|
quint64 value;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
quint64 alloced : 1;
|
||||||
|
quint64 pointer : 48;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
MemoryUnion uMemory;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline bool operator==(const T *o, const MemoryPointer<T> &p) {
|
||||||
|
return o == p.operator->();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline bool operator==(const MemoryPointer<T> &p, const T *o) {
|
||||||
|
return p.operator->() == o;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline bool operator==(T *o, const MemoryPointer<T> &p) {
|
||||||
|
return o == p.operator->();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline bool operator==(const MemoryPointer<T> &p, T *o) {
|
||||||
|
return p.operator->() == o;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline bool operator==(const MemoryPointer<T> &lhs, const MemoryPointer<T> &rhs) {
|
||||||
|
return lhs.operator->() == rhs.operator->();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline bool operator!=(const T *o, const MemoryPointer<T> &p) {
|
||||||
|
return o != p.operator->();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline bool operator!= (const MemoryPointer<T> &p, const T *o) {
|
||||||
|
return p.operator->() != o;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline bool operator!=(T *o, const MemoryPointer<T> &p) {
|
||||||
|
return o != p.operator->();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline bool operator!= (const MemoryPointer<T> &p, T *o) {
|
||||||
|
return p.operator->() != o;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline bool operator!= (const MemoryPointer<T> &lhs, const MemoryPointer<T> &rhs) {
|
||||||
|
return lhs.operator->() != rhs.operator->();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MEMORYPOINTER_H
|
||||||
@@ -2922,6 +2922,12 @@ int ssh_channel_read_timeout(ssh_channel channel,
|
|||||||
timeout_ms,
|
timeout_ms,
|
||||||
ssh_channel_read_termination,
|
ssh_channel_read_termination,
|
||||||
&ctx);
|
&ctx);
|
||||||
|
|
||||||
|
if (rc == SSH_AGAIN && ssh_is_blocking(session)) {
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Handle packets timeout.");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
if (rc == SSH_ERROR){
|
if (rc == SSH_ERROR){
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user