From 89fff90de738025d338fa5d06b6ff3b589c33c9c Mon Sep 17 00:00:00 2001
From: klemens
Date: Sat, 15 Apr 2017 10:06:22 +0200
Subject: [PATCH 001/166] Spelling fixes (just in comments).
As found by a bot ( http://www.misfix.org,
https://github.com/ka7/misspell_fixer ).
---
doc/config.but | 2 +-
minibidi.c | 4 ++--
mkfiles.pl | 2 +-
pageant.c | 2 +-
settings.c | 2 +-
terminal.c | 2 +-
windows/window.c | 4 ++--
7 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/doc/config.but b/doc/config.but
index eb96fc17e..269dbdc1b 100644
--- a/doc/config.but
+++ b/doc/config.but
@@ -2507,7 +2507,7 @@ used:
Disabling data-based rekeys entirely is a bad idea. The \i{integrity},
and to a lesser extent, \i{confidentiality} of the SSH-2 protocol depend
-in part on rekeys occuring before a 32-bit packet sequence number
+in part on rekeys occurring before a 32-bit packet sequence number
wraps around. Unlike time-based rekeys, data-based rekeys won't occur
when the SSH connection is idle, so they shouldn't cause the same
problems. The SSH-1 protocol, incidentally, has even weaker integrity
diff --git a/minibidi.c b/minibidi.c
index 6c0621162..8d78594d2 100644
--- a/minibidi.c
+++ b/minibidi.c
@@ -3,7 +3,7 @@
* ------------
* Description:
* ------------
- * This is an implemention of Unicode's Bidirectional Algorithm
+ * This is an implementation of Unicode's Bidirectional Algorithm
* (known as UAX #9).
*
* http://www.unicode.org/reports/tr9/
@@ -89,7 +89,7 @@ enum {
/* Shaping Types */
enum {
- SL, /* Left-Joining, doesnt exist in U+0600 - U+06FF */
+ SL, /* Left-Joining, doesn't exist in U+0600 - U+06FF */
SR, /* Right-Joining, ie has Isolated, Final */
SD, /* Dual-Joining, ie has Isolated, Final, Initial, Medial */
SU, /* Non-Joining */
diff --git a/mkfiles.pl b/mkfiles.pl
index ae15ac488..a19cec5d0 100755
--- a/mkfiles.pl
+++ b/mkfiles.pl
@@ -1966,7 +1966,7 @@ sub manpages {
"# ** DO NOT EDIT **\r\n".
"\r\n".
# No difference between DEBUG and RELEASE here as in 'vcproj', because
- # Dev-C++ does not support mutiple compilation profiles in one single project.
+ # Dev-C++ does not support multiple compilation profiles in one single project.
# (At least I can say this for Dev-C++ 5 Beta)
"[Project]\r\n".
"FileName=$windows_project.dev\r\n".
diff --git a/pageant.c b/pageant.c
index 2d9a74023..366717251 100644
--- a/pageant.c
+++ b/pageant.c
@@ -1469,7 +1469,7 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase,
}
/*
- * If we get here, we've succesfully loaded the key into
+ * If we get here, we've successfully loaded the key into
* rkey/skey, but not yet added it to the agent.
*/
diff --git a/settings.c b/settings.c
index f810d3f97..00c01c546 100644
--- a/settings.c
+++ b/settings.c
@@ -892,7 +892,7 @@ void load_open_settings(void *sesskey, Conf *conf)
{
/* SSH-2 only by default */
int sshprot = gppi_raw(sesskey, "SshProt", 3);
- /* Old sessions may contain the values correponding to the fallbacks
+ /* Old sessions may contain the values corresponding to the fallbacks
* we used to allow; migrate them */
if (sshprot == 1) sshprot = 0; /* => "SSH-1 only" */
else if (sshprot == 2) sshprot = 3; /* => "SSH-2 only" */
diff --git a/terminal.c b/terminal.c
index c79944cda..f47fe1bdb 100644
--- a/terminal.c
+++ b/terminal.c
@@ -2437,7 +2437,7 @@ static void erase_lots(Terminal *term,
/* After an erase of lines from the top of the screen, we shouldn't
* bring the lines back again if the terminal enlarges (since the user or
- * application has explictly thrown them away). */
+ * application has explicitly thrown them away). */
if (erasing_lines_from_top && !(term->alt_which))
term->tempsblines = 0;
}
diff --git a/windows/window.c b/windows/window.c
index 004eb4f82..38c0e3cd7 100644
--- a/windows/window.c
+++ b/windows/window.c
@@ -1700,7 +1700,7 @@ void request_resize(void *frontend, int w, int h)
{
int width, height;
- /* If the window is maximized supress resizing attempts */
+ /* If the window is maximized suppress resizing attempts */
if (IsZoomed(hwnd)) {
if (conf_get_int(conf, CONF_resize_action) == RESIZE_TERM)
return;
@@ -4777,7 +4777,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
return p - output;
}
- /* If we're definitly not building up an ALT-54321 then clear it */
+ /* If we're definitely not building up an ALT-54321 then clear it */
if (!left_alt)
keys_unicode[0] = 0;
/* If we will be using alt_sum fix the 256s */
From b189df947d2625499cf508fd1fae7e18b03b9247 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sat, 15 Apr 2017 18:13:47 +0100
Subject: [PATCH 002/166] Condition out some API type-checks in the MinGW
build.
A couple of the functions for which I was already turning off the type
check for old Visual Studio turn out to also need it turning off for
MinGW.
---
windows/winhsock.c | 7 ++++---
windows/winnet.c | 6 +++---
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/windows/winhsock.c b/windows/winhsock.c
index e5f0fa4fd..c8cb46f68 100644
--- a/windows/winhsock.c
+++ b/windows/winhsock.c
@@ -282,9 +282,10 @@ static char *sk_handle_peer_info(Socket s)
if (!kernel32_module) {
kernel32_module = load_system32_dll("kernel32.dll");
-#if defined _MSC_VER && _MSC_VER < 1900
- /* For older Visual Studio, this function isn't available in
- * the header files to type-check */
+#if (defined _MSC_VER && _MSC_VER < 1900) || defined __MINGW32__
+ /* For older Visual Studio, and MinGW too (at least as of
+ * Ubuntu 16.04), this function isn't available in the header
+ * files to type-check */
GET_WINDOWS_FUNCTION_NO_TYPECHECK(
kernel32_module, GetNamedPipeClientProcessId);
#else
diff --git a/windows/winnet.c b/windows/winnet.c
index 7ceca4863..fc26c3e55 100644
--- a/windows/winnet.c
+++ b/windows/winnet.c
@@ -314,9 +314,9 @@ void sk_init(void)
GET_WINDOWS_FUNCTION(winsock_module, getservbyname);
GET_WINDOWS_FUNCTION(winsock_module, inet_addr);
GET_WINDOWS_FUNCTION(winsock_module, inet_ntoa);
-#if defined _MSC_VER && _MSC_VER < 1900
- /* Older Visual Studio doesn't know about this function at all, so
- * can't type-check it */
+#if (defined _MSC_VER && _MSC_VER < 1900) || defined __MINGW32__
+ /* Older Visual Studio, and MinGW as of Ubuntu 16.04, don't know
+ * about this function at all, so can't type-check it */
GET_WINDOWS_FUNCTION_NO_TYPECHECK(winsock_module, inet_ntop);
#else
GET_WINDOWS_FUNCTION(winsock_module, inet_ntop);
From 73039b7831aa863fabba1e6ff06471643303ae09 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Mon, 13 Mar 2017 21:24:06 +0000
Subject: [PATCH 003/166] Load winmm.dll (for PlaySound()) at run time.
It's not on the default list of important system 'known DLLs' stored
at HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs (see
https://isc.sans.edu/forums/diary/DLL+hijacking+vulnerabilities/9445/ )
which apparently makes it exempt from Windows's standard DLL hijacking
defence, i.e. if an executable links against it in the normal way then
that executable will be vulnerable to DLL hijacking from a file called
winmm.dll in the same directory as it.
The solution is to load it dynamically _after_ we've locked down our
DLL search path, which fortunately PuTTY's code base is well used to
doing already for other DLLs.
---
Recipe | 2 +-
windows/window.c | 8 +++++---
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/Recipe b/Recipe
index 54e006366..e2cce9ae8 100644
--- a/Recipe
+++ b/Recipe
@@ -274,7 +274,7 @@ CHARSET = sbcsdat slookup sbcs utf8 toucs fromucs xenc mimeenc macenc localenc
# Standard libraries.
LIBS = advapi32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib
- + shell32.lib winmm.lib imm32.lib winspool.lib ole32.lib
+ + shell32.lib imm32.lib winspool.lib ole32.lib
# Network backend sets. This also brings in the relevant attachment
# to proxy.c depending on whether we're crypto-avoidant or not.
diff --git a/windows/window.c b/windows/window.c
index 38c0e3cd7..cb42addf7 100644
--- a/windows/window.c
+++ b/windows/window.c
@@ -3949,12 +3949,14 @@ int char_width(Context ctx, int uc) {
DECL_WINDOWS_FUNCTION(static, BOOL, FlashWindowEx, (PFLASHWINFO));
DECL_WINDOWS_FUNCTION(static, BOOL, ToUnicodeEx,
(UINT, UINT, const BYTE *, LPWSTR, int, UINT, HKL));
+DECL_WINDOWS_FUNCTION(static, BOOL, PlaySound, (LPCTSTR, HMODULE, DWORD));
static void init_winfuncs(void)
{
HMODULE user32_module = load_system32_dll("user32.dll");
+ HMODULE winmm_module = load_system32_dll("winmm.dll");
GET_WINDOWS_FUNCTION(user32_module, FlashWindowEx);
- GET_WINDOWS_FUNCTION(user32_module, ToUnicodeEx);
+ GET_WINDOWS_FUNCTION_PP(winmm_module, PlaySound);
}
/*
@@ -5540,8 +5542,8 @@ void do_beep(void *frontend, int mode)
lastbeep = GetTickCount();
} else if (mode == BELL_WAVEFILE) {
Filename *bell_wavefile = conf_get_filename(conf, CONF_bell_wavefile);
- if (!PlaySound(bell_wavefile->path, NULL,
- SND_ASYNC | SND_FILENAME)) {
+ if (!p_PlaySound || !p_PlaySound(bell_wavefile->path, NULL,
+ SND_ASYNC | SND_FILENAME)) {
char buf[sizeof(bell_wavefile->path) + 80];
char otherbuf[100];
sprintf(buf, "Unable to play sound file\n%s\n"
From 793ac872757667a87df4636b5b3eed61302dd837 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Mon, 13 Mar 2017 21:28:36 +0000
Subject: [PATCH 004/166] Load the Windows printing subsystem at run time.
The printing functions are split between winspool.drv and spoolss.dll
in a really weird way (who would have guessed that OpenPrinter and
ClosePrinter don't live in the same dynamic library?!), but _neither_
of those counts as a system 'known DLL', so linking against either one
of these at load time is again a potential DLL hijacking vector.
---
Recipe | 2 +-
windows/winprint.c | 65 ++++++++++++++++++++++++++++++++++++----------
2 files changed, 52 insertions(+), 15 deletions(-)
diff --git a/Recipe b/Recipe
index e2cce9ae8..0fb7bbb76 100644
--- a/Recipe
+++ b/Recipe
@@ -274,7 +274,7 @@ CHARSET = sbcsdat slookup sbcs utf8 toucs fromucs xenc mimeenc macenc localenc
# Standard libraries.
LIBS = advapi32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib
- + shell32.lib imm32.lib winspool.lib ole32.lib
+ + shell32.lib imm32.lib ole32.lib
# Network backend sets. This also brings in the relevant attachment
# to proxy.c depending on whether we're crypto-avoidant or not.
diff --git a/windows/winprint.c b/windows/winprint.c
index c190e5fb0..115872739 100644
--- a/windows/winprint.c
+++ b/windows/winprint.c
@@ -18,11 +18,46 @@ struct printer_job_tag {
HANDLE hprinter;
};
+DECL_WINDOWS_FUNCTION(static, BOOL, EnumPrinters,
+ (DWORD, LPTSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD));
+DECL_WINDOWS_FUNCTION(static, BOOL, OpenPrinter,
+ (LPTSTR, LPHANDLE, LPPRINTER_DEFAULTS));
+DECL_WINDOWS_FUNCTION(static, BOOL, ClosePrinter, (HANDLE));
+DECL_WINDOWS_FUNCTION(static, BOOL, StartDocPrinter, (HANDLE, DWORD, LPBYTE));
+DECL_WINDOWS_FUNCTION(static, BOOL, EndDocPrinter, (HANDLE));
+DECL_WINDOWS_FUNCTION(static, BOOL, StartPagePrinter, (HANDLE));
+DECL_WINDOWS_FUNCTION(static, BOOL, EndPagePrinter, (HANDLE));
+DECL_WINDOWS_FUNCTION(static, BOOL, WritePrinter,
+ (HANDLE, LPVOID, DWORD, LPDWORD));
+
+static void init_winfuncs(void)
+{
+ static int initialised = FALSE;
+ char buf[4096];
+ if (initialised)
+ return;
+ {
+ HMODULE winspool_module = load_system32_dll("winspool.drv");
+ HMODULE spoolss_module = load_system32_dll("spoolss.dll");
+ GET_WINDOWS_FUNCTION_PP(winspool_module, EnumPrinters);
+ GET_WINDOWS_FUNCTION_PP(winspool_module, OpenPrinter);
+ GET_WINDOWS_FUNCTION_PP(spoolss_module, ClosePrinter);
+ GET_WINDOWS_FUNCTION_PP(winspool_module, StartDocPrinter);
+ GET_WINDOWS_FUNCTION_PP(spoolss_module, EndDocPrinter);
+ GET_WINDOWS_FUNCTION_PP(spoolss_module, StartPagePrinter);
+ GET_WINDOWS_FUNCTION_PP(spoolss_module, EndPagePrinter);
+ GET_WINDOWS_FUNCTION_PP(spoolss_module, WritePrinter);
+ }
+ initialised = TRUE;
+}
+
static int printer_add_enum(int param, DWORD level, char **buffer,
int offset, int *nprinters_ptr)
{
DWORD needed = 0, nprinters = 0;
+ init_winfuncs();
+
*buffer = sresize(*buffer, offset+512, char);
/*
@@ -30,16 +65,16 @@ static int printer_add_enum(int param, DWORD level, char **buffer,
* we'll need for the output. Discard the return value since it
* will almost certainly be a failure due to lack of space.
*/
- EnumPrinters(param, NULL, level, (LPBYTE)((*buffer)+offset), 512,
- &needed, &nprinters);
+ p_EnumPrinters(param, NULL, level, (LPBYTE)((*buffer)+offset), 512,
+ &needed, &nprinters);
if (needed < 512)
needed = 512;
*buffer = sresize(*buffer, offset+needed, char);
- if (EnumPrinters(param, NULL, level, (LPBYTE)((*buffer)+offset),
- needed, &needed, &nprinters) == 0)
+ if (p_EnumPrinters(param, NULL, level, (LPBYTE)((*buffer)+offset),
+ needed, &needed, &nprinters) == 0)
return FALSE;
*nprinters_ptr += nprinters;
@@ -131,19 +166,21 @@ printer_job *printer_start_job(char *printer)
DOC_INFO_1 docinfo;
int jobstarted = 0, pagestarted = 0;
+ init_winfuncs();
+
ret->hprinter = NULL;
- if (!OpenPrinter(printer, &ret->hprinter, NULL))
+ if (!p_OpenPrinter(printer, &ret->hprinter, NULL))
goto error;
docinfo.pDocName = "PuTTY remote printer output";
docinfo.pOutputFile = NULL;
docinfo.pDatatype = "RAW";
- if (!StartDocPrinter(ret->hprinter, 1, (LPBYTE)&docinfo))
+ if (!p_StartDocPrinter(ret->hprinter, 1, (LPBYTE)&docinfo))
goto error;
jobstarted = 1;
- if (!StartPagePrinter(ret->hprinter))
+ if (!p_StartPagePrinter(ret->hprinter))
goto error;
pagestarted = 1;
@@ -151,11 +188,11 @@ printer_job *printer_start_job(char *printer)
error:
if (pagestarted)
- EndPagePrinter(ret->hprinter);
+ p_EndPagePrinter(ret->hprinter);
if (jobstarted)
- EndDocPrinter(ret->hprinter);
+ p_EndDocPrinter(ret->hprinter);
if (ret->hprinter)
- ClosePrinter(ret->hprinter);
+ p_ClosePrinter(ret->hprinter);
sfree(ret);
return NULL;
}
@@ -167,7 +204,7 @@ void printer_job_data(printer_job *pj, void *data, int len)
if (!pj)
return;
- WritePrinter(pj->hprinter, data, len, &written);
+ p_WritePrinter(pj->hprinter, data, len, &written);
}
void printer_finish_job(printer_job *pj)
@@ -175,8 +212,8 @@ void printer_finish_job(printer_job *pj)
if (!pj)
return;
- EndPagePrinter(pj->hprinter);
- EndDocPrinter(pj->hprinter);
- ClosePrinter(pj->hprinter);
+ p_EndPagePrinter(pj->hprinter);
+ p_EndDocPrinter(pj->hprinter);
+ p_ClosePrinter(pj->hprinter);
sfree(pj);
}
From f77ee39e8cae2eaaea3a8fdd1eaffaf484cada08 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Mon, 13 Mar 2017 21:42:44 +0000
Subject: [PATCH 005/166] Load comctl32.dll (for drag lists) at run time.
This too is not in the list of known DLLs on Windows 10. I don't know
of any actual viable hijacking attack based on it, which according to
my reading of MSDN (specifically, a rather vague hint in
https://msdn.microsoft.com/library/ff919712) _may_ be because we
mention the common controls assembly in our application manifest; but
better safe than sorry.
Now the entire list of remaining DLLs that PuTTY links against at load
time is a subset of the Win10 known DLLs list, so that _should_ mean
that everything we load before we've deployed our own defence
(SetDefaultDllDirectories) is defended against for us by Windows
itself.
---
Recipe | 2 +-
windows/winctrls.c | 33 ++++++++++++++++++++++++---------
windows/window.c | 2 +-
windows/winpgen.c | 2 +-
windows/winstuff.h | 1 +
5 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/Recipe b/Recipe
index 0fb7bbb76..f54581223 100644
--- a/Recipe
+++ b/Recipe
@@ -273,7 +273,7 @@ IMPORT = import sshbcrypt sshblowf
CHARSET = sbcsdat slookup sbcs utf8 toucs fromucs xenc mimeenc macenc localenc
# Standard libraries.
-LIBS = advapi32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib
+LIBS = advapi32.lib user32.lib gdi32.lib comdlg32.lib
+ shell32.lib imm32.lib ole32.lib
# Network backend sets. This also brings in the relevant attachment
diff --git a/windows/winctrls.c b/windows/winctrls.c
index a03967e6f..737018e45 100644
--- a/windows/winctrls.c
+++ b/windows/winctrls.c
@@ -38,6 +38,21 @@
#define PUSHBTNHEIGHT 14
#define PROGBARHEIGHT 14
+DECL_WINDOWS_FUNCTION(static, void, InitCommonControls, (void));
+DECL_WINDOWS_FUNCTION(static, BOOL, MakeDragList, (HWND));
+DECL_WINDOWS_FUNCTION(static, int, LBItemFromPt, (HWND, POINT, BOOL));
+DECL_WINDOWS_FUNCTION(static, int, DrawInsert, (HWND, HWND, int));
+
+void init_common_controls(void)
+{
+ HMODULE comctl32_module = load_system32_dll("comctl32.dll");
+ GET_WINDOWS_FUNCTION(comctl32_module, InitCommonControls);
+ GET_WINDOWS_FUNCTION(comctl32_module, MakeDragList);
+ GET_WINDOWS_FUNCTION(comctl32_module, LBItemFromPt);
+ GET_WINDOWS_FUNCTION(comctl32_module, DrawInsert);
+ p_InitCommonControls();
+}
+
void ctlposinit(struct ctlpos *cp, HWND hwnd,
int leftborder, int rightborder, int topborder)
{
@@ -921,7 +936,7 @@ void prefslist(struct prefslist *hdl, struct ctlpos *cp, int lines,
WS_VSCROLL | LBS_HASSTRINGS | LBS_USETABSTOPS,
WS_EX_CLIENTEDGE,
"", listid);
- MakeDragList(ctl);
+ p_MakeDragList(ctl);
}
break;
@@ -996,17 +1011,17 @@ int pl_itemfrompt(HWND hwnd, POINT cursor, BOOL scroll)
* current item if the upper edge is closer than
* the lower edge, or _below_ it if vice versa.
*/
- ret = LBItemFromPt(hwnd, cursor, scroll);
+ ret = p_LBItemFromPt(hwnd, cursor, scroll);
if (ret == -1)
return ret;
- ret = LBItemFromPt(hwnd, cursor, FALSE);
+ ret = p_LBItemFromPt(hwnd, cursor, FALSE);
updist = downdist = 0;
for (i = 1; i < 4096 && (!updist || !downdist); i++) {
uppoint = downpoint = cursor;
uppoint.y -= i;
downpoint.y += i;
- upitem = LBItemFromPt(hwnd, uppoint, FALSE);
- downitem = LBItemFromPt(hwnd, downpoint, FALSE);
+ upitem = p_LBItemFromPt(hwnd, uppoint, FALSE);
+ downitem = p_LBItemFromPt(hwnd, downpoint, FALSE);
if (!updist && upitem != ret)
updist = i;
if (!downdist && downitem != ret)
@@ -1047,13 +1062,13 @@ int handle_prefslist(struct prefslist *hdl,
SendDlgItemMessage(hwnd, hdl->listid,
LB_ADDSTRING, 0, (LPARAM) "");
- hdl->srcitem = LBItemFromPt(dlm->hWnd, dlm->ptCursor, TRUE);
+ hdl->srcitem = p_LBItemFromPt(dlm->hWnd, dlm->ptCursor, TRUE);
hdl->dragging = 0;
/* XXX hack Q183115 */
SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE);
ret |= 1; break;
case DL_CANCELDRAG:
- DrawInsert(hwnd, dlm->hWnd, -1); /* Clear arrow */
+ p_DrawInsert(hwnd, dlm->hWnd, -1); /* Clear arrow */
SendDlgItemMessage(hwnd, hdl->listid,
LB_DELETESTRING, hdl->dummyitem, 0);
hdl->dragging = 0;
@@ -1062,7 +1077,7 @@ int handle_prefslist(struct prefslist *hdl,
hdl->dragging = 1;
dest = pl_itemfrompt(dlm->hWnd, dlm->ptCursor, TRUE);
if (dest > hdl->dummyitem) dest = hdl->dummyitem;
- DrawInsert (hwnd, dlm->hWnd, dest);
+ p_DrawInsert (hwnd, dlm->hWnd, dest);
if (dest >= 0)
SetWindowLongPtr(hwnd, DWLP_MSGRESULT, DL_MOVECURSOR);
else
@@ -1072,7 +1087,7 @@ int handle_prefslist(struct prefslist *hdl,
if (hdl->dragging) {
dest = pl_itemfrompt(dlm->hWnd, dlm->ptCursor, TRUE);
if (dest > hdl->dummyitem) dest = hdl->dummyitem;
- DrawInsert (hwnd, dlm->hWnd, -1);
+ p_DrawInsert (hwnd, dlm->hWnd, -1);
}
SendDlgItemMessage(hwnd, hdl->listid,
LB_DELETESTRING, hdl->dummyitem, 0);
diff --git a/windows/window.c b/windows/window.c
index cb42addf7..e01a3c32d 100644
--- a/windows/window.c
+++ b/windows/window.c
@@ -359,7 +359,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
sk_init();
- InitCommonControls();
+ init_common_controls();
/* Set Explicit App User Model Id so that jump lists don't cause
PuTTY to hang on to removable media. */
diff --git a/windows/winpgen.c b/windows/winpgen.c
index c4f4de45b..2507d37ea 100644
--- a/windows/winpgen.c
+++ b/windows/winpgen.c
@@ -1529,7 +1529,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
dll_hijacking_protection();
- InitCommonControls();
+ init_common_controls();
hinst = inst;
hwnd = NULL;
diff --git a/windows/winstuff.h b/windows/winstuff.h
index 007889e4a..f8c4243f9 100644
--- a/windows/winstuff.h
+++ b/windows/winstuff.h
@@ -329,6 +329,7 @@ struct ctlpos {
int boxystart, boxid;
char *boxtext;
};
+void init_common_controls(void); /* also does some DLL-loading */
/*
* Exports from winutils.c.
From b1829b81b5c0d12dcc91f6b50b0b4d83c3df6a8e Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Mon, 24 Apr 2017 14:45:52 +0100
Subject: [PATCH 006/166] Update version number for 0.69 release.
---
Buildscr | 2 +-
LATEST.VER | 2 +-
doc/plink.but | 2 +-
doc/pscp.but | 2 +-
windows/putty.iss | 8 ++++----
5 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/Buildscr b/Buildscr
index 7ca4eb7f5..086800ac6 100644
--- a/Buildscr
+++ b/Buildscr
@@ -35,7 +35,7 @@ module putty
ifeq "$(RELEASE)" "" set Ndate $(!builddate)
ifneq "$(Ndate)" "" in . do echo $(Ndate) | perl -pe 's/(....)(..)(..)/$$1-$$2-$$3/' > date
ifneq "$(Ndate)" "" read Date date
-set Epoch 16214 # update this at every release
+set Epoch 16280 # update this at every release
ifneq "$(Ndate)" "" in . do echo $(Ndate) | perl -ne 'use Time::Local; /(....)(..)(..)/ and print timegm(0,0,0,$$3,$$2-1,$$1) / 86400 - $(Epoch)' > days
ifneq "$(Ndate)" "" read Days days
diff --git a/LATEST.VER b/LATEST.VER
index db1ed30c7..b04c64745 100644
--- a/LATEST.VER
+++ b/LATEST.VER
@@ -1 +1 @@
-0.68
+0.69
diff --git a/doc/plink.but b/doc/plink.but
index 351e13ea7..153982e07 100644
--- a/doc/plink.but
+++ b/doc/plink.but
@@ -41,7 +41,7 @@ use Plink:
\c Z:\sysosd>plink
\c Plink: command-line connection utility
-\c Release 0.68
+\c Release 0.69
\c Usage: plink [options] [user@]host [command]
\c ("host" can also be a PuTTY saved session name)
\c Options:
diff --git a/doc/pscp.but b/doc/pscp.but
index 27643a468..30a47f83b 100644
--- a/doc/pscp.but
+++ b/doc/pscp.but
@@ -39,7 +39,7 @@ use PSCP:
\c Z:\owendadmin>pscp
\c PuTTY Secure Copy client
-\c Release 0.68
+\c Release 0.69
\c Usage: pscp [options] [user@]host:source target
\c pscp [options] source [source...] [user@]host:target
\c pscp [options] -ls [user@]host:filespec
diff --git a/windows/putty.iss b/windows/putty.iss
index dda68f63b..b3deb76c2 100644
--- a/windows/putty.iss
+++ b/windows/putty.iss
@@ -14,10 +14,10 @@
[Setup]
AppName=PuTTY
-AppVerName=PuTTY version 0.68
-VersionInfoTextVersion=Release 0.68
-AppVersion=0.68
-VersionInfoVersion=0.68.0.0
+AppVerName=PuTTY version 0.69
+VersionInfoTextVersion=Release 0.69
+AppVersion=0.69
+VersionInfoVersion=0.69.0.0
AppPublisher=Simon Tatham
AppPublisherURL=http://www.chiark.greenend.org.uk/~sgtatham/putty/
AppReadmeFile={app}\README.txt
From d6d10932ac1f9333b06ee8027dcfad231f17ed04 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sat, 29 Apr 2017 10:23:31 +0100
Subject: [PATCH 007/166] Release checklist update: no @releases array!
The rewritten bugs2html.py in the wishlist repository no longer needs
me to manually maintain a mapping between releases and version control
- and the one thing I forgot was to remove the reminder in the release
checklist telling me to keep that mapping up to date :-)
---
CHECKLST.txt | 1 -
1 file changed, 1 deletion(-)
diff --git a/CHECKLST.txt b/CHECKLST.txt
index 0499d7802..8d55ac412 100644
--- a/CHECKLST.txt
+++ b/CHECKLST.txt
@@ -96,7 +96,6 @@ for it:
branch (so that the wishlist mechanism can't automatically mark
them as fixed in the new release), add appropriate Fixed-in
headers for those.
- * Add an entry to the @releases array in control/bugs2html.
- Make a release-candidate build from the release tag, and put the
build.out and build.log dfiles somewhere safe. Normally I store
From 5a576e0c891ddc745ea1f67bcca10f1386ff1849 Mon Sep 17 00:00:00 2001
From: Jacob Nevins
Date: Sat, 29 Apr 2017 12:07:37 +0100
Subject: [PATCH 008/166] Reinstate use of ToUnicodeEx().
This was accidentally disabled by 73039b783, causing a regression in
ability to type characters outside of the current Windows code page.
---
windows/window.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/windows/window.c b/windows/window.c
index e01a3c32d..89ddb8636 100644
--- a/windows/window.c
+++ b/windows/window.c
@@ -3956,6 +3956,7 @@ static void init_winfuncs(void)
HMODULE user32_module = load_system32_dll("user32.dll");
HMODULE winmm_module = load_system32_dll("winmm.dll");
GET_WINDOWS_FUNCTION(user32_module, FlashWindowEx);
+ GET_WINDOWS_FUNCTION(user32_module, ToUnicodeEx);
GET_WINDOWS_FUNCTION_PP(winmm_module, PlaySound);
}
From ed600ab23f87fd1785d100937e992e244ba82ed5 Mon Sep 17 00:00:00 2001
From: Jacob Nevins
Date: Sat, 29 Apr 2017 14:24:17 +0100
Subject: [PATCH 009/166] Fix double negative in TTY mode docs.
---
doc/config.but | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/doc/config.but b/doc/config.but
index 269dbdc1b..a7d45689f 100644
--- a/doc/config.but
+++ b/doc/config.but
@@ -2959,7 +2959,7 @@ modes from the local terminal, if any.
}
-\b If \q{Nothing} is selected, no value for the mode will not be
+\b If \q{Nothing} is selected, no value for the mode will be
specified to the server under any circumstances.
\b If a value is specified, it will be sent to the server under all
From fb023da0fdcbfca104b39c2315a79186d7254c99 Mon Sep 17 00:00:00 2001
From: Jacob Nevins
Date: Sun, 30 Apr 2017 10:42:02 +0100
Subject: [PATCH 010/166] Be less vague in the description of IUTF8.
---
doc/config.but | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/doc/config.but b/doc/config.but
index a7d45689f..bb18b794b 100644
--- a/doc/config.but
+++ b/doc/config.but
@@ -3006,18 +3006,19 @@ PuTTY in a variety of ways, such as \cw{true}/\cw{false},
\cw{no} is different from not sending the mode at all.)
\b The boolean mode \I{IUTF8 terminal mode}\cw{IUTF8} signals to the
-server whether the terminal character set is \i{UTF-8} or not.
-If this is set incorrectly, keys like backspace may do the wrong thing
-in some circumstances. However, setting this is not usually
-sufficient to cause servers to expect the terminal to be in UTF-8 mode;
-POSIX servers will generally require the locale to be set (by some
-server-dependent means), although many default to UTF-8. Also,
-since this mode was added to the SSH protocol much later than the
-others, \#{circa 2016} many servers (particularly older servers) do
-not honour this mode sent over SSH; indeed, a few poorly-written
-servers object to its mere presence, so you may find you need to set
-it to not be sent at all. When set to \q{Auto}, this follows the local
-configured character set (see \k{config-charset}).
+server whether the terminal character set is \i{UTF-8} or not, for
+purposes such as basic line editing; if this is set incorrectly,
+the backspace key may erase the wrong amount of text, for instance.
+However, simply setting this is not usually sufficient for the server
+to use UTF-8; POSIX servers will generally also require the locale to
+be set (by some server-dependent means), although many newer
+installations default to UTF-8. Also, since this mode was added to the
+SSH protocol much later than the others, \#{circa 2016} many servers
+(particularly older servers) do not honour this mode sent over SSH;
+indeed, a few poorly-written servers object to its mere presence, so
+you may find you need to set it to not be sent at all. When set to
+\q{Auto}, this follows the local configured character set (see
+\k{config-charset}).
\b Terminal speeds are configured elsewhere; see \k{config-termspeed}.
From 230f7d56284a703c65c4fecf7e6f23b791043f81 Mon Sep 17 00:00:00 2001
From: Zero King
Date: Sun, 30 Apr 2017 11:01:13 +0100
Subject: [PATCH 011/166] Fix thinko introduced in 8833634f4.
This prevented compilation with Gtk 2.
---
unix/gtkwin.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/unix/gtkwin.c b/unix/gtkwin.c
index 69e335094..bca6daa43 100644
--- a/unix/gtkwin.c
+++ b/unix/gtkwin.c
@@ -2188,11 +2188,11 @@ void set_gtk_widget_background(GtkWidget *widget, const GdkColor *col)
free(data);
free(col_css);
#else
- if (gtk_widget_get_window(win)) {
+ if (gtk_widget_get_window(widget)) {
/* For GTK1, which doesn't have a 'const' on
* gdk_window_set_background's second parameter type. */
GdkColor col_mutable = *col;
- gdk_window_set_background(gtk_widget_get_window(win), &col_mutable);
+ gdk_window_set_background(gtk_widget_get_window(widget), &col_mutable);
}
#endif
}
From b566c5f125efb9933303a61303ab17e2af0a859b Mon Sep 17 00:00:00 2001
From: Jacob Nevins
Date: Sun, 30 Apr 2017 11:39:07 +0100
Subject: [PATCH 012/166] Add a cast to fix a warning.
This fixes compilation with Gtk 2 with -Werror. Problem introduced by
64221972c.
---
unix/gtkwin.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/unix/gtkwin.c b/unix/gtkwin.c
index bca6daa43..67cfcac38 100644
--- a/unix/gtkwin.c
+++ b/unix/gtkwin.c
@@ -1935,7 +1935,7 @@ gboolean scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer data)
event_button->x_root = event->x_root;
event_button->y_root = event->y_root;
ret = button_internal(inst, event_button);
- gdk_event_free(event_button);
+ gdk_event_free((GdkEvent *)event_button);
return ret;
#endif
}
From ad694a494158d44ff3dce86d20f4f2afb1dc142e Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Mon, 1 May 2017 06:53:06 +0100
Subject: [PATCH 013/166] mkfiles.pl: fix regex syntax error.
Thanks to Brian K. White for spotting this straight-up syntax error of
a missing ), in the regex handling the special case of &splitlines
when it findss a word in its input string too long to fit in the
specified output line width. Apparently in all my own uses of
&splitline I'd never exercised that special-case code path before.
---
mkfiles.pl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mkfiles.pl b/mkfiles.pl
index a19cec5d0..8a63c65dc 100755
--- a/mkfiles.pl
+++ b/mkfiles.pl
@@ -364,7 +364,7 @@ sub splitline {
$len = (defined $width ? $width : 76);
$splitchar = (defined $splitchar ? $splitchar : '\\');
while (length $line > $len) {
- $line =~ /^(.{0,$len})\s(.*)$/ or $line =~ /^(.{$len,}?\s(.*)$/;
+ $line =~ /^(.{0,$len})\s(.*)$/ or $line =~ /^(.{$len,})?\s(.*)$/;
$result .= $1;
$result .= " ${splitchar}\n\t\t" if $2 ne '';
$line = $2;
From 6ea9d36ae94736493216591fb18d20efe79b5216 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sun, 7 May 2017 16:29:01 +0100
Subject: [PATCH 014/166] Switch chiark URLs to https.
---
Buildscr | 4 ++--
README | 4 ++--
contrib/cygtermd/README | 2 +-
doc/blurb.but | 2 +-
doc/faq.but | 18 +++++++++---------
doc/feedback.but | 18 +++++++++---------
doc/man-pl.but | 2 +-
doc/man-pscp.but | 2 +-
doc/man-psft.but | 2 +-
doc/man-ptel.but | 2 +-
doc/man-putt.but | 2 +-
doc/pgpkeys.but | 20 ++++++++++----------
doc/udp.but | 2 +-
ssh.c | 2 +-
windows/README-msi.txt | 2 +-
windows/README.txt | 2 +-
windows/putty.iss | 2 +-
windows/website.url | Bin 103 -> 104 bytes
windows/windlg.c | 2 +-
windows/winpgen.c | 2 +-
windows/winpgnt.c | 2 +-
21 files changed, 47 insertions(+), 47 deletions(-)
diff --git a/Buildscr b/Buildscr
index 086800ac6..afcc2766e 100644
--- a/Buildscr
+++ b/Buildscr
@@ -172,7 +172,7 @@ delegate windows
# provide a 'more info' URL, and an optional -n option to provide a
# program name, and that it can take multiple .exe filename
# arguments and sign them all in place.
- ifneq "$(winsigncode)" "" in putty/windows do $(winsigncode) -i http://www.chiark.greenend.org.uk/~sgtatham/putty/ build*/*.exe
+ ifneq "$(winsigncode)" "" in putty/windows do $(winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/putty/ build*/*.exe
# Ignore exit code from hhc, in favour of seeing whether the .chm
# file was created. (Yuck; but hhc appears to return non-zero
@@ -187,7 +187,7 @@ delegate windows
in putty/windows with innosetup do/win iscc putty.iss
# Sign the installers.
- ifneq "$(winsigncode)" "" in putty/windows do $(winsigncode) -i http://www.chiark.greenend.org.uk/~sgtatham/putty/ -n "PuTTY Installer" installer32.msi installer64.msi Output/installer.exe
+ ifneq "$(winsigncode)" "" in putty/windows do $(winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/putty/ -n "PuTTY Installer" installer32.msi installer64.msi Output/installer.exe
# Finished Windows builds.
return putty/windows/buildold/*.exe
diff --git a/README b/README
index ef931dd14..4d73a995d 100644
--- a/README
+++ b/README
@@ -127,11 +127,11 @@ Documentation (in various formats including Windows Help and Unix
`man' pages) is built from the Halibut (`.but') files in the `doc'
subdirectory using `doc/Makefile'. If you aren't using one of our
source snapshots, you'll need to do this yourself. Halibut can be
-found at .
+found at .
The PuTTY home web site is
- http://www.chiark.greenend.org.uk/~sgtatham/putty/
+ https://www.chiark.greenend.org.uk/~sgtatham/putty/
If you want to send bug reports or feature requests, please read the
Feedback section of the web site before doing so. Sending one-line
diff --git a/contrib/cygtermd/README b/contrib/cygtermd/README
index ebfdfdd77..a722fe10a 100644
--- a/contrib/cygtermd/README
+++ b/contrib/cygtermd/README
@@ -8,4 +8,4 @@ install it in Cygwin's /bin, and configure PuTTY to use it as a local
proxy process. For detailed instructions, see the PuTTY Wishlist page
at
-http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/cygwin-terminal-window.html
+https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/cygwin-terminal-window.html
diff --git a/doc/blurb.but b/doc/blurb.but
index 227300f46..64e8ab74c 100644
--- a/doc/blurb.but
+++ b/doc/blurb.but
@@ -7,7 +7,7 @@
\cfg{xhtml-leaf-contains-contents}{true}
\cfg{xhtml-body-end}{
If you want to provide feedback on this manual
or on the PuTTY tools themselves, see the
-Feedback
+Feedback
page.
}
\cfg{html-template-fragment}{%k}{%b}
diff --git a/doc/faq.but b/doc/faq.but
index 42f965b27..80cf9d639 100644
--- a/doc/faq.but
+++ b/doc/faq.but
@@ -27,18 +27,18 @@ else.
\I{supported features}In general, if you want to know if PuTTY supports
a particular feature, you should look for it on the
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/}{PuTTY web site}.
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/}{PuTTY web site}.
In particular:
\b try the
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/changes.html}{changes
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/changes.html}{changes
page}, and see if you can find the feature on there. If a feature is
listed there, it's been implemented. If it's listed as a change made
\e{since} the latest version, it should be available in the
development snapshots, in which case testing will be very welcome.
\b try the
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/}{Wishlist
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/}{Wishlist
page}, and see if you can find the feature there. If it's on there,
and not in the \q{Recently fixed} section, it probably \e{hasn't} been
implemented.
@@ -54,7 +54,7 @@ version 0.52.
\cw{ssh.com} SSH-2 private key files?
PuTTY doesn't support this natively (see
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/key-formats-natively.html}{the wishlist entry}
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/key-formats-natively.html}{the wishlist entry}
for reasons why not), but as of 0.53
PuTTYgen can convert both OpenSSH and \cw{ssh.com} private key
files into PuTTY's format.
@@ -236,7 +236,7 @@ port, or any other port of PuTTY, they were mistaken. We don't.
There are some third-party ports to various platforms, mentioned
on the
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/links.html}{Links page of our website}.
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/links.html}{Links page of our website}.
\S{faq-unix}{Question} \I{Unix version}Is there a port to Unix?
@@ -323,7 +323,7 @@ for, it might be a long time before any of us get round to learning
a new system and doing the port for that.
However, some of the work has been done by other people; see the
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/links.html}{Links page of our website}
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/links.html}{Links page of our website}
for various third-party ports.
\S{faq-iphone}{Question} Will there be a port to the iPhone?
@@ -351,7 +351,7 @@ Most of the code cleanup work would be a good thing to happen in
general, so if anyone feels like helping, we wouldn't say no.
See also
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/dll-frontend.html}{the wishlist entry}.
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/dll-frontend.html}{the wishlist entry}.
\S{faq-vb}{Question} Is the SSH or Telnet code available as a Visual
Basic component?
@@ -891,7 +891,7 @@ us \q{I wanted the F1 key to send \c{^[[11~}, but instead it's
sending \c{^[OP}, can this be done?}, or something similar.
You should still read the
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/feedback.html}{Feedback
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/feedback.html}{Feedback
page} on the PuTTY website (also provided as \k{feedback} in the
manual), and follow the guidelines contained in that.
@@ -1060,7 +1060,7 @@ still. We do not recommend it.)
This is caused by a bug in certain versions of \i{Windows XP} which
is triggered by PuTTY 0.58. This was fixed in 0.59. The
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/xp-wont-run}{\q{xp-wont-run}}
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/xp-wont-run}{\q{xp-wont-run}}
entry in PuTTY's wishlist has more details.
\S{faq-system32}{Question} When I put 32-bit PuTTY in
diff --git a/doc/feedback.but b/doc/feedback.but
index e0854fc54..b8428e415 100644
--- a/doc/feedback.but
+++ b/doc/feedback.but
@@ -112,7 +112,7 @@ If you think you have found a bug in PuTTY, your first steps should
be:
\b Check the
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/}{Wishlist
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/}{Wishlist
page} on the PuTTY website, and see if we already know about the
problem. If we do, it is almost certainly not necessary to mail us
about it, unless you think you have extra information that might be
@@ -121,12 +121,12 @@ specific extra information about a particular bug, the Wishlist page
will say so.)
\b Check the
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/changes.html}{Change
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/changes.html}{Change
Log} on the PuTTY website, and see if we have already fixed the bug
in the \i{development snapshots}.
\b Check the
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/faq.html}{FAQ}
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/faq.html}{FAQ}
on the PuTTY website (also provided as \k{faq} in the manual), and
see if it answers your question. The FAQ lists the most common
things which people think are bugs, but which aren't bugs.
@@ -188,7 +188,7 @@ you haven't supplied us with full information about the actual bug,
then we won't be able to find a better solution.
\b
-\W{http://www.chiark.greenend.org.uk/~sgtatham/bugs.html}\cw{http://www.chiark.greenend.org.uk/~sgtatham/bugs.html}
+\W{https://www.chiark.greenend.org.uk/~sgtatham/bugs.html}\cw{https://www.chiark.greenend.org.uk/~sgtatham/bugs.html}
is an article on how to report bugs effectively in general. If your
bug report is \e{particularly} unclear, we may ask you to go away,
read this article, and then report the bug again.
@@ -224,14 +224,14 @@ If you want to request a new feature in PuTTY, the very first things
you should do are:
\b Check the
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/}{Wishlist
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/}{Wishlist
page} on the PuTTY website, and see if your feature is already on
the list. If it is, it probably won't achieve very much to repeat
the request. (But see \k{feedback-feature-priority} if you want to
persuade us to give your particular feature higher priority.)
\b Check the Wishlist and
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/changes.html}{Change
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/changes.html}{Change
Log} on the PuTTY website, and see if we have already added your
feature in the development snapshots. If it isn't clear, download
the latest development snapshot and see if the feature is present.
@@ -350,7 +350,7 @@ Of course, if the web site has some other error (Connection Refused,
If you want to report a problem with our web site, check that you're
looking at our \e{real} web site and not a mirror. The real web site
is at
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/}\c{http://www.chiark.greenend.org.uk/~sgtatham/putty/};
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/}\c{https://www.chiark.greenend.org.uk/~sgtatham/putty/};
if that's not where you're reading this, then don't report the
problem to us until you've checked that it's really a problem with
the main site. If it's only a problem with the mirror, you should
@@ -399,7 +399,7 @@ setting up a mirror. You already have permission.
If the mirror is in a country where we don't already have plenty of
mirrors, we may be willing to add it to the list on our
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/mirrors.html}{mirrors
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/mirrors.html}{mirrors
page}. Read the guidelines on that page, make sure your mirror
works, and email us the information listed at the bottom of the
page.
@@ -414,7 +414,7 @@ to be a cheap way to gain search rankings.
If you have technical questions about the process of mirroring, then
you might want to mail us before setting up the mirror (see also the
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/mirrors.html#guidelines}{guidelines on the Mirrors page});
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/mirrors.html#guidelines}{guidelines on the Mirrors page});
but if you just want to ask for permission, you don't need to. You
already have permission.
diff --git a/doc/man-pl.but b/doc/man-pl.but
index a46e6a196..9f4118719 100644
--- a/doc/man-pl.but
+++ b/doc/man-pl.but
@@ -260,7 +260,7 @@ exists, nonzero otherwise.
For more information on plink, it's probably best to go and look at
the manual on the PuTTY web page:
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/}\cw{http://www.chiark.greenend.org.uk/~sgtatham/putty/}
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/}\cw{https://www.chiark.greenend.org.uk/~sgtatham/putty/}
\S{plink-manpage-bugs} BUGS
diff --git a/doc/man-pscp.but b/doc/man-pscp.but
index 05e5a23cb..6c703e138 100644
--- a/doc/man-pscp.but
+++ b/doc/man-pscp.but
@@ -174,7 +174,7 @@ encrypted packet data.
For more information on \cw{pscp} it's probably best to go and look at
the manual on the PuTTY web page:
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/}\cw{http://www.chiark.greenend.org.uk/~sgtatham/putty/}
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/}\cw{https://www.chiark.greenend.org.uk/~sgtatham/putty/}
\S{pscp-manpage-bugs} BUGS
diff --git a/doc/man-psft.but b/doc/man-psft.but
index 80d86ecf6..51f30d3a0 100644
--- a/doc/man-psft.but
+++ b/doc/man-psft.but
@@ -159,7 +159,7 @@ at the \cw{psftp>} prompt.
For more information on \cw{psftp} it's probably best to go and look at
the manual on the PuTTY web page:
-\cw{http://www.chiark.greenend.org.uk/~sgtatham/putty/}
+\cw{https://www.chiark.greenend.org.uk/~sgtatham/putty/}
\S{psftp-manpage-bugs} BUGS
diff --git a/doc/man-ptel.but b/doc/man-ptel.but
index a3b794059..73b85ecce 100644
--- a/doc/man-ptel.but
+++ b/doc/man-ptel.but
@@ -208,7 +208,7 @@ your home directory.
For more information on PuTTY and PuTTYtel, it's probably best to go
and look at the manual on the web page:
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/}\cw{http://www.chiark.greenend.org.uk/~sgtatham/putty/}
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/}\cw{https://www.chiark.greenend.org.uk/~sgtatham/putty/}
\S{puttytel-manpage-bugs} BUGS
diff --git a/doc/man-putt.but b/doc/man-putt.but
index df7b9e1fe..cb7cca470 100644
--- a/doc/man-putt.but
+++ b/doc/man-putt.but
@@ -321,7 +321,7 @@ your home directory.
For more information on PuTTY, it's probably best to go and look at
the manual on the web page:
-\W{http://www.chiark.greenend.org.uk/~sgtatham/putty/}\cw{http://www.chiark.greenend.org.uk/~sgtatham/putty/}
+\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/}\cw{https://www.chiark.greenend.org.uk/~sgtatham/putty/}
\S{putty-manpage-bugs} BUGS
diff --git a/doc/pgpkeys.but b/doc/pgpkeys.but
index 9ec900665..71143af22 100644
--- a/doc/pgpkeys.but
+++ b/doc/pgpkeys.but
@@ -53,19 +53,19 @@ The current issue of those keys are available for download from the
PuTTY website, and are also available on PGP keyservers using the key
IDs listed below.
-\dt \W{http://www.chiark.greenend.org.uk/~sgtatham/putty/keys/master-2015.asc}{\s{Master Key}}
+\dt \W{https://www.chiark.greenend.org.uk/~sgtatham/putty/keys/master-2015.asc}{\s{Master Key}}
\dd RSA, 4096-bit. Key ID: \cw{4096R/04676F7C} (long version:
\cw{4096R/AB585DC604676F7C}). Fingerprint:
\cw{440D\_E3B5\_B7A1\_CA85\_B3CC\_\_1718\_AB58\_5DC6\_0467\_6F7C}
-\dt \W{http://www.chiark.greenend.org.uk/~sgtatham/putty/keys/release-2015.asc}{\s{Release Key}}
+\dt \W{https://www.chiark.greenend.org.uk/~sgtatham/putty/keys/release-2015.asc}{\s{Release Key}}
\dd RSA, 2048-bit. Key ID: \cw{2048R/B43434E4} (long version:
\cw{2048R/9DFE2648B43434E4}). Fingerprint:
\cw{0054\_DDAA\_8ADA\_15D2\_768A\_\_6DE7\_9DFE\_2648\_B434\_34E4}
-\dt \W{http://www.chiark.greenend.org.uk/~sgtatham/putty/keys/contact-2016.asc}{\s{Secure Contact Key}}
+\dt \W{https://www.chiark.greenend.org.uk/~sgtatham/putty/keys/contact-2016.asc}{\s{Secure Contact Key}}
\dd RSA, 2048-bit. Main key ID: \cw{2048R/8A0AF00B} (long version:
\cw{2048R/C4FCAAD08A0AF00B}). Encryption subkey ID:
@@ -73,7 +73,7 @@ IDs listed below.
Fingerprint:
\cw{8A26\_250E\_763F\_E359\_75F3\_\_118F\_C4FC\_AAD0\_8A0A\_F00B}
-\dt \W{http://www.chiark.greenend.org.uk/~sgtatham/putty/keys/snapshot-2015.asc}{\s{Snapshot Key}}
+\dt \W{https://www.chiark.greenend.org.uk/~sgtatham/putty/keys/snapshot-2015.asc}{\s{Snapshot Key}}
\dd RSA, 2048-bit. Key ID: \cw{2048R/D15F7E8A} (long version:
\cw{2048R/EEF20295D15F7E8A}). Fingerprint:
@@ -179,37 +179,37 @@ Releases prior to the rollover are signed with the old Release Keys.
For completeness, those old keys are given here:
-\dt \W{http://www.chiark.greenend.org.uk/~sgtatham/putty/keys/master-rsa.asc}{\s{Master Key} (original RSA)}
+\dt \W{https://www.chiark.greenend.org.uk/~sgtatham/putty/keys/master-rsa.asc}{\s{Master Key} (original RSA)}
\dd RSA, 1024-bit. Key ID: \cw{1024R/1E34AC41} (long version:
\cw{1024R/9D5877BF1E34AC41}). Fingerprint:
\cw{8F\_15\_97\_DA\_25\_30\_AB\_0D\_\_88\_D1\_92\_54\_11\_CF\_0C\_4C}
-\dt \W{http://www.chiark.greenend.org.uk/~sgtatham/putty/keys/master-dsa.asc}{\s{Master Key} (original DSA)}
+\dt \W{https://www.chiark.greenend.org.uk/~sgtatham/putty/keys/master-dsa.asc}{\s{Master Key} (original DSA)}
\dd DSA, 1024-bit. Key ID: \cw{1024D/6A93B34E} (long version:
\cw{1024D/4F5E6DF56A93B34E}). Fingerprint:
\cw{313C\_3E76\_4B74\_C2C5\_F2AE\_\_83A8\_4F5E\_6DF5\_6A93\_B34E}
-\dt \W{http://www.chiark.greenend.org.uk/~sgtatham/putty/keys/release-rsa.asc}{\s{Release Key} (original RSA)}
+\dt \W{https://www.chiark.greenend.org.uk/~sgtatham/putty/keys/release-rsa.asc}{\s{Release Key} (original RSA)}
\dd RSA, 1024-bit. Key ID: \cw{1024R/B41CAE29} (long version:
\cw{1024R/EF39CCC0B41CAE29}). Fingerprint:
\cw{AE\_65\_D3\_F7\_85\_D3\_18\_E0\_\_3B\_0C\_9B\_02\_FF\_3A\_81\_FE}
-\dt \W{http://www.chiark.greenend.org.uk/~sgtatham/putty/keys/release-dsa.asc}{\s{Release Key} (original DSA)}
+\dt \W{https://www.chiark.greenend.org.uk/~sgtatham/putty/keys/release-dsa.asc}{\s{Release Key} (original DSA)}
\dd DSA, 1024-bit. Key ID: \cw{1024D/08B0A90B} (long version:
\cw{1024D/FECD6F3F08B0A90B}). Fingerprint:
\cw{00B1\_1009\_38E6\_9800\_6518\_\_F0AB\_FECD\_6F3F\_08B0\_A90B}
-\dt \W{http://www.chiark.greenend.org.uk/~sgtatham/putty/keys/snapshot-rsa.asc}{\s{Snapshot Key} (original RSA)}
+\dt \W{https://www.chiark.greenend.org.uk/~sgtatham/putty/keys/snapshot-rsa.asc}{\s{Snapshot Key} (original RSA)}
\dd RSA, 1024-bit. Key ID: \cw{1024R/32B903A9} (long version:
\cw{1024R/FAAED21532B903A9}). Fingerprint:
\cw{86\_8B\_1F\_79\_9C\_F4\_7F\_BD\_\_8B\_1B\_D7\_8E\_C6\_4E\_4C\_03}
-\dt \W{http://www.chiark.greenend.org.uk/~sgtatham/putty/keys/snapshot-dsa.asc}{\s{Snapshot Key} (original DSA)}
+\dt \W{https://www.chiark.greenend.org.uk/~sgtatham/putty/keys/snapshot-dsa.asc}{\s{Snapshot Key} (original DSA)}
\dd DSA, 1024-bit. Key ID: \cw{1024D/7D3E4A00} (long version:
\cw{1024D/165E56F77D3E4A00}). Fingerprint:
diff --git a/doc/udp.but b/doc/udp.but
index c50464ee1..9ca8ed3f8 100644
--- a/doc/udp.but
+++ b/doc/udp.but
@@ -331,7 +331,7 @@ local state structures \c{s} or \c{st} in each function, or the
backend-wide structure \c{ssh}.
See
-\W{http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html}\c{http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html}
+\W{https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html}\c{https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html}
for a more in-depth discussion of what these macros are for and how
they work.
diff --git a/ssh.c b/ssh.c
index 693f52d8d..994e93aeb 100644
--- a/ssh.c
+++ b/ssh.c
@@ -303,7 +303,7 @@ enum {
* macros look impenetrable to you, you might find it helpful to
* read
*
- * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
+ * https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
*
* which explains the theory behind these macros.
*
diff --git a/windows/README-msi.txt b/windows/README-msi.txt
index a6c2707d5..14aac092d 100644
--- a/windows/README-msi.txt
+++ b/windows/README-msi.txt
@@ -35,7 +35,7 @@ What do I do if it doesn't work?
The PuTTY home web site is
- http://www.chiark.greenend.org.uk/~sgtatham/putty/
+ https://www.chiark.greenend.org.uk/~sgtatham/putty/
Here you will find our list of known bugs and pending feature
requests. If your problem is not listed in there, or in the FAQ, or
diff --git a/windows/README.txt b/windows/README.txt
index fa153c624..d929df903 100644
--- a/windows/README.txt
+++ b/windows/README.txt
@@ -29,7 +29,7 @@ What do I do if it doesn't work?
The PuTTY home web site is
- http://www.chiark.greenend.org.uk/~sgtatham/putty/
+ https://www.chiark.greenend.org.uk/~sgtatham/putty/
Here you will find our list of known bugs and pending feature
requests. If your problem is not listed in there, or in the FAQ, or
diff --git a/windows/putty.iss b/windows/putty.iss
index b3deb76c2..3fadcb922 100644
--- a/windows/putty.iss
+++ b/windows/putty.iss
@@ -19,7 +19,7 @@ VersionInfoTextVersion=Release 0.69
AppVersion=0.69
VersionInfoVersion=0.69.0.0
AppPublisher=Simon Tatham
-AppPublisherURL=http://www.chiark.greenend.org.uk/~sgtatham/putty/
+AppPublisherURL=https://www.chiark.greenend.org.uk/~sgtatham/putty/
AppReadmeFile={app}\README.txt
DefaultDirName={pf}\PuTTY
DefaultGroupName=PuTTY
diff --git a/windows/website.url b/windows/website.url
index 4b50369cec07713e189e28b5e0724a8dee278eba..4f6d47d1f7136fed66f8bd3d36f26e7315f5496a 100644
GIT binary patch
delta 9
QcmYe#m>|tqJW<*Q01toy=Kufz
delta 7
Ocmc~upCCO^#s>fjyaIFp
diff --git a/windows/windlg.c b/windows/windlg.c
index e29f12914..8bd02d855 100644
--- a/windows/windlg.c
+++ b/windows/windlg.c
@@ -227,7 +227,7 @@ static INT_PTR CALLBACK AboutProc(HWND hwnd, UINT msg,
case IDA_WEB:
/* Load web browser */
ShellExecute(hwnd, "open",
- "http://www.chiark.greenend.org.uk/~sgtatham/putty/",
+ "https://www.chiark.greenend.org.uk/~sgtatham/putty/",
0, 0, SW_SHOWDEFAULT);
return 0;
}
diff --git a/windows/winpgen.c b/windows/winpgen.c
index 2507d37ea..7903c1cf2 100644
--- a/windows/winpgen.c
+++ b/windows/winpgen.c
@@ -322,7 +322,7 @@ static INT_PTR CALLBACK AboutProc(HWND hwnd, UINT msg,
case 102:
/* Load web browser */
ShellExecute(hwnd, "open",
- "http://www.chiark.greenend.org.uk/~sgtatham/putty/",
+ "https://www.chiark.greenend.org.uk/~sgtatham/putty/",
0, 0, SW_SHOWDEFAULT);
return 0;
}
diff --git a/windows/winpgnt.c b/windows/winpgnt.c
index 70f3d2ca5..ebb6c6ace 100644
--- a/windows/winpgnt.c
+++ b/windows/winpgnt.c
@@ -178,7 +178,7 @@ static INT_PTR CALLBACK AboutProc(HWND hwnd, UINT msg,
case 102:
/* Load web browser */
ShellExecute(hwnd, "open",
- "http://www.chiark.greenend.org.uk/~sgtatham/putty/",
+ "https://www.chiark.greenend.org.uk/~sgtatham/putty/",
0, 0, SW_SHOWDEFAULT);
return 0;
}
From ce050c5b72d17559ef79f07b2013b35e2dd22467 Mon Sep 17 00:00:00 2001
From: Ben Harris
Date: Mon, 8 May 2017 21:33:03 +0100
Subject: [PATCH 015/166] Fix a luking mention of Win32 in README.
---
README | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README b/README
index 4d73a995d..50314ca63 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-This is the README for the source archive of PuTTY, a free Win32
+This is the README for the source archive of PuTTY, a free Windows
and Unix Telnet and SSH client.
If you want to rebuild PuTTY from source, we provide a variety of
From 93931b0a568c8f39801ffcb0c67cc001dac4f9b3 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sat, 13 May 2017 17:10:36 +0100
Subject: [PATCH 016/166] Switch to using Halibut's new direct .CHM generation.
This allows me to remove HTML Help Workshop completely from my build
dependencies, and good riddance!
---
Buildscr | 9 +--------
doc/Makefile | 10 ++++------
doc/blurb.but | 6 ++++++
doc/chm.but | 22 ----------------------
4 files changed, 11 insertions(+), 36 deletions(-)
delete mode 100644 doc/chm.but
diff --git a/Buildscr b/Buildscr
index afcc2766e..de7f41b57 100644
--- a/Buildscr
+++ b/Buildscr
@@ -139,8 +139,7 @@ ifneq "$(MAKEARGS)" "" set Makeargs $(Makeargs) $(MAKEARGS)
in putty do ./mksrcarc.sh
in putty do ./mkunxarc.sh '$(Autoconfver)' '$(Uxarcsuffix)' $(Docmakever)
in putty do perl mkfiles.pl
-in putty/doc do make $(Docmakever) putty.hlp
-in putty/doc do make $(Docmakever) chm
+in putty/doc do make $(Docmakever) putty.hlp putty.chm
# Munge the installer script locally so that it reports the version
# we're really building.
@@ -174,11 +173,6 @@ delegate windows
# arguments and sign them all in place.
ifneq "$(winsigncode)" "" in putty/windows do $(winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/putty/ build*/*.exe
- # Ignore exit code from hhc, in favour of seeing whether the .chm
- # file was created. (Yuck; but hhc appears to return non-zero
- # exit codes on whim.)
- in putty/doc with htmlhelp do/win hhc putty.hhp & type putty.chm >nul
-
# Build a WiX MSI installer, for each of build32 and build64.
in putty/windows with wix do/win candle -arch x86 -dWin64=no -dBuilddir=build32\ -dWinver="$(Winver)" -dPuttytextver="$(Puttytextver)" installer.wxs && light -ext WixUIExtension -ext WixUtilExtension -sval installer.wixobj -o installer32.msi
in putty/windows with wix do/win candle -arch x64 -dWin64=yes -dBuilddir=build64\ -dWinver="$(Winver)" -dPuttytextver="$(Puttytextver)" installer.wxs && light -ext WixUIExtension -ext WixUtilExtension -sval installer.wixobj -o installer64.msi
@@ -196,7 +190,6 @@ delegate windows
return putty/windows/build32/*.map
return putty/windows/build64/*.exe
return putty/windows/build64/*.map
- return putty/doc/putty.chm
return putty/windows/installer32.msi
return putty/windows/installer64.msi
return putty/windows/Output/installer.exe
diff --git a/doc/Makefile b/doc/Makefile
index e7bf287e0..cb079fb5d 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -44,19 +44,17 @@ INPUTS = $(patsubst %,%.but,$(CHAPTERS))
HALIBUT = halibut
index.html: $(INPUTS)
- $(HALIBUT) --text --html --winhelp $(INPUTS)
+ $(HALIBUT) --text --html --winhelp --chm $(INPUTS)
-# During formal builds it's useful to be able to build this one alone.
+# During formal builds it's useful to be able to build these ones alone.
putty.hlp: $(INPUTS)
$(HALIBUT) --winhelp $(INPUTS)
+putty.chm: $(INPUTS)
+ $(HALIBUT) --chm $(INPUTS)
putty.info: $(INPUTS)
$(HALIBUT) --info $(INPUTS)
-chm: putty.hhp
-putty.hhp: $(INPUTS) chm.but
- $(HALIBUT) --html $(INPUTS) chm.but
-
MKMAN = $(HALIBUT) --man=$@ mancfg.but $<
MANPAGES = putty.1 puttygen.1 plink.1 pscp.1 psftp.1 puttytel.1 pterm.1 \
pageant.1
diff --git a/doc/blurb.but b/doc/blurb.but
index 64e8ab74c..e5e03a600 100644
--- a/doc/blurb.but
+++ b/doc/blurb.but
@@ -14,10 +14,16 @@ page.
}
\cfg{info-max-file-size}{0}
+\cfg{chm-contents-filename}{index.html}
+\cfg{chm-template-filename}{%k.html}
+\cfg{chm-head-end}{}
+\cfg{chm-extra-file}{chm.css}
+
\cfg{xhtml-contents-filename}{index.html}
\cfg{text-filename}{puttydoc.txt}
\cfg{winhelp-filename}{putty.hlp}
\cfg{info-filename}{putty.info}
+\cfg{chm-filename}{putty.chm}
PuTTY is a free (MIT-licensed) Windows Telnet and SSH client. This
manual documents PuTTY, and its companion utilities PSCP, PSFTP,
diff --git a/doc/chm.but b/doc/chm.but
deleted file mode 100644
index 44d1dca3f..000000000
--- a/doc/chm.but
+++ /dev/null
@@ -1,22 +0,0 @@
-\# File containing the magic HTML configuration directives to create
-\# an MS HTML Help project. We put this on the end of the PuTTY
-\# docs build command line to build the HHP and friends.
-
-\cfg{html-leaf-level}{infinite}
-\cfg{html-leaf-contains-contents}{false}
-\cfg{html-suppress-navlinks}{true}
-\cfg{html-suppress-address}{true}
-
-\cfg{html-contents-filename}{index.html}
-\cfg{html-template-filename}{%k.html}
-\cfg{html-template-fragment}{%k}
-
-\cfg{html-mshtmlhelp-chm}{putty.chm}
-\cfg{html-mshtmlhelp-project}{putty.hhp}
-\cfg{html-mshtmlhelp-contents}{putty.hhc}
-\cfg{html-mshtmlhelp-index}{putty.hhk}
-
-\cfg{html-body-end}{}
-
-\cfg{html-head-end}{}
-
From 95f81227a29a79eeafb6395db159c376cafd6bc2 Mon Sep 17 00:00:00 2001
From: Ben Harris
Date: Mon, 30 May 2016 20:40:29 +0100
Subject: [PATCH 017/166] uxplink: remove the "connopen" variable.
It had the constant value 1 everywhere that it was read.
---
unix/uxplink.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/unix/uxplink.c b/unix/uxplink.c
index 2d4259b91..e891d66a8 100644
--- a/unix/uxplink.c
+++ b/unix/uxplink.c
@@ -616,7 +616,6 @@ int main(int argc, char **argv)
int *fdlist;
int fd;
int i, fdcount, fdsize, fdstate;
- int connopen;
int exitcode;
int errors;
int use_subsystem = 0;
@@ -1027,7 +1026,6 @@ int main(int argc, char **argv)
ldisc_create(conf, NULL, back, backhandle, NULL);
sfree(realhost);
}
- connopen = 1;
/*
* Set up the initial console mode. We don't care if this call
@@ -1054,7 +1052,7 @@ int main(int argc, char **argv)
FD_SET_MAX(signalpipe[0], maxfd, rset);
- if (connopen && !sending &&
+ if (!sending &&
back->connected(backhandle) &&
back->sendok(backhandle) &&
back->sendbuffer(backhandle) < MAX_STDIN_BACKLOG) {
@@ -1165,7 +1163,7 @@ int main(int argc, char **argv)
char buf[4096];
int ret;
- if (connopen && back->connected(backhandle)) {
+ if (back->connected(backhandle)) {
ret = read(STDIN_FILENO, buf, sizeof(buf));
if (ret < 0) {
perror("stdin: read");
@@ -1192,7 +1190,7 @@ int main(int argc, char **argv)
run_toplevel_callbacks();
- if ((!connopen || !back->connected(backhandle)) &&
+ if (!back->connected(backhandle) &&
bufchain_size(&stdout_data) == 0 &&
bufchain_size(&stderr_data) == 0)
break; /* we closed the connection */
From 30cdaa7ca8bfa03d90e170c2260d71a5819996b2 Mon Sep 17 00:00:00 2001
From: Ben Harris
Date: Mon, 30 May 2016 22:37:32 +0100
Subject: [PATCH 018/166] unix: make select_result() return void.
Nothing was using its return value anyway.
---
unix/unix.h | 2 +-
unix/uxsel.c | 6 ++----
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/unix/unix.h b/unix/unix.h
index 7ab2ca24f..68f749acc 100644
--- a/unix/unix.h
+++ b/unix/unix.h
@@ -183,7 +183,7 @@ void uxsel_init(void);
typedef int (*uxsel_callback_fn)(int fd, int event);
void uxsel_set(int fd, int rwx, uxsel_callback_fn callback);
void uxsel_del(int fd);
-int select_result(int fd, int event);
+void select_result(int fd, int event);
int first_fd(int *state, int *rwx);
int next_fd(int *state, int *rwx);
/* The following are expected to be provided _to_ uxsel.c by the frontend */
diff --git a/unix/uxsel.c b/unix/uxsel.c
index ef25cdb57..52f346a48 100644
--- a/unix/uxsel.c
+++ b/unix/uxsel.c
@@ -111,7 +111,7 @@ int first_fd(int *state, int *rwx)
return next_fd(state, rwx);
}
-int select_result(int fd, int event)
+void select_result(int fd, int event)
{
struct fd *fdstruct = find234(fds, &fd, uxsel_fd_findcmp);
/*
@@ -120,7 +120,5 @@ int select_result(int fd, int event)
* fd I've stopped being interested in. Sigh.
*/
if (fdstruct)
- return fdstruct->callback(fd, event);
- else
- return 1;
+ fdstruct->callback(fd, event);
}
From d56496c31c85767b805f261f01fc87cc8a468dec Mon Sep 17 00:00:00 2001
From: Ben Harris
Date: Mon, 30 May 2016 22:52:30 +0100
Subject: [PATCH 019/166] unix: make uxsel callback functions return void.
Nothing used their return values anyway. At least, not after the
previous commit.
---
unix/unix.h | 2 +-
unix/uxagentc.c | 7 +++----
unix/uxnet.c | 24 +++++++++++-------------
unix/uxproxy.c | 15 ++++++---------
unix/uxpty.c | 13 ++++---------
unix/uxser.c | 12 +++++-------
6 files changed, 30 insertions(+), 43 deletions(-)
diff --git a/unix/unix.h b/unix/unix.h
index 68f749acc..f21d23ffa 100644
--- a/unix/unix.h
+++ b/unix/unix.h
@@ -180,7 +180,7 @@ void postmsg(struct termios *);
/* The interface used by uxsel.c */
typedef struct uxsel_id uxsel_id;
void uxsel_init(void);
-typedef int (*uxsel_callback_fn)(int fd, int event);
+typedef void (*uxsel_callback_fn)(int fd, int event);
void uxsel_set(int fd, int rwx, uxsel_callback_fn callback);
void uxsel_del(int fd);
void select_result(int fd, int event);
diff --git a/unix/uxagentc.c b/unix/uxagentc.c
index ffc5879cf..51f9a1ebe 100644
--- a/unix/uxagentc.c
+++ b/unix/uxagentc.c
@@ -98,7 +98,7 @@ void agent_cancel_query(agent_pending_query *conn)
sfree(conn);
}
-static int agent_select_result(int fd, int event)
+static void agent_select_result(int fd, int event)
{
agent_pending_query *conn;
@@ -107,11 +107,11 @@ static int agent_select_result(int fd, int event)
conn = find234(agent_pending_queries, &fd, agent_connfind);
if (!conn) {
uxsel_del(fd);
- return 1;
+ return;
}
if (!agent_try_read(conn))
- return 0; /* more data to come */
+ return; /* more data to come */
/*
* We have now completed the agent query. Do the callback, and
@@ -120,7 +120,6 @@ static int agent_select_result(int fd, int event)
*/
conn->callback(conn->callback_ctx, conn->retbuf, conn->retlen);
agent_cancel_query(conn);
- return 0;
}
agent_pending_query *agent_query(
diff --git a/unix/uxnet.c b/unix/uxnet.c
index 79f4fbcee..ddcd92280 100644
--- a/unix/uxnet.c
+++ b/unix/uxnet.c
@@ -1266,7 +1266,7 @@ static void sk_tcp_write_eof(Socket sock)
uxsel_tell(s);
}
-static int net_select_result(int fd, int event)
+static void net_select_result(int fd, int event)
{
int ret;
char buf[20480]; /* nice big buffer for plenty of speed */
@@ -1276,7 +1276,7 @@ static int net_select_result(int fd, int event)
/* Find the Socket structure */
s = find234(sktree, &fd, cmpforsearch);
if (!s)
- return 1; /* boggle */
+ return; /* boggle */
noise_ultralight(event);
@@ -1292,9 +1292,9 @@ static int net_select_result(int fd, int event)
ret = recv(s->s, buf, sizeof(buf), MSG_OOB);
noise_ultralight(ret);
if (ret <= 0) {
- return plug_closing(s->plug,
- ret == 0 ? "Internal networking trouble" :
- strerror(errno), errno, 0);
+ plug_closing(s->plug,
+ ret == 0 ? "Internal networking trouble" :
+ strerror(errno), errno, 0);
} else {
/*
* Receiving actual data on a socket means we can
@@ -1305,7 +1305,7 @@ static int net_select_result(int fd, int event)
sk_addr_free(s->addr);
s->addr = NULL;
}
- return plug_receive(s->plug, 2, buf, ret);
+ plug_receive(s->plug, 2, buf, ret);
}
break;
}
@@ -1377,11 +1377,11 @@ static int net_select_result(int fd, int event)
}
}
if (ret < 0) {
- return plug_closing(s->plug, strerror(errno), errno, 0);
+ plug_closing(s->plug, strerror(errno), errno, 0);
} else if (0 == ret) {
s->incomingeof = TRUE; /* stop trying to read now */
uxsel_tell(s);
- return plug_closing(s->plug, NULL, 0, 0);
+ plug_closing(s->plug, NULL, 0, 0);
} else {
/*
* Receiving actual data on a socket means we can
@@ -1392,7 +1392,7 @@ static int net_select_result(int fd, int event)
sk_addr_free(s->addr);
s->addr = NULL;
}
- return plug_receive(s->plug, atmark ? 0 : 1, buf, ret);
+ plug_receive(s->plug, atmark ? 0 : 1, buf, ret);
}
break;
case 2: /* writable */
@@ -1430,9 +1430,9 @@ static int net_select_result(int fd, int event)
err = try_connect(s);
}
if (err)
- return plug_closing(s->plug, strerror(err), err, 0);
+ plug_closing(s->plug, strerror(err), err, 0);
if (!s->connected)
- return 0; /* another async attempt in progress */
+ return; /* another async attempt in progress */
}
}
@@ -1456,8 +1456,6 @@ static int net_select_result(int fd, int event)
}
break;
}
-
- return 1;
}
/*
diff --git a/unix/uxproxy.c b/unix/uxproxy.c
index 3df4cebe4..d3a82fa4e 100644
--- a/unix/uxproxy.c
+++ b/unix/uxproxy.c
@@ -33,7 +33,7 @@ struct Socket_localproxy_tag {
enum { EOF_NO, EOF_PENDING, EOF_SENT } outgoingeof;
};
-static int localproxy_select_result(int fd, int event);
+static void localproxy_select_result(int fd, int event);
/*
* Trees to look up the pipe fds in.
@@ -229,7 +229,7 @@ static const char * sk_localproxy_socket_error (Socket s)
return ps->error;
}
-static int localproxy_select_result(int fd, int event)
+static void localproxy_select_result(int fd, int event)
{
Local_Proxy_Socket s;
char buf[20480];
@@ -238,7 +238,7 @@ static int localproxy_select_result(int fd, int event)
if (!(s = find234(localproxy_by_fromfd, &fd, localproxy_fromfd_find)) &&
!(s = find234(localproxy_by_fromfd, &fd, localproxy_errfd_find)) &&
!(s = find234(localproxy_by_tofd, &fd, localproxy_tofd_find)) )
- return 1; /* boggle */
+ return; /* boggle */
if (event == 1) {
if (fd == s->cmd_err) {
@@ -249,21 +249,18 @@ static int localproxy_select_result(int fd, int event)
assert(fd == s->from_cmd);
ret = read(fd, buf, sizeof(buf));
if (ret < 0) {
- return plug_closing(s->plug, strerror(errno), errno, 0);
+ plug_closing(s->plug, strerror(errno), errno, 0);
} else if (ret == 0) {
- return plug_closing(s->plug, NULL, 0, 0);
+ plug_closing(s->plug, NULL, 0, 0);
} else {
- return plug_receive(s->plug, 0, buf, ret);
+ plug_receive(s->plug, 0, buf, ret);
}
}
} else if (event == 2) {
assert(fd == s->to_cmd);
if (localproxy_try_send(s))
plug_sent(s->plug, bufchain_size(&s->pending_output_data));
- return 1;
}
-
- return 1;
}
Socket platform_new_connection(SockAddr addr, const char *hostname,
diff --git a/unix/uxpty.c b/unix/uxpty.c
index 39f96f126..618fe9bd7 100644
--- a/unix/uxpty.c
+++ b/unix/uxpty.c
@@ -572,7 +572,7 @@ void pty_pre_init(void)
}
-int pty_real_select_result(Pty pty, int event, int status)
+void pty_real_select_result(Pty pty, int event, int status)
{
char buf[4096];
int ret;
@@ -672,13 +672,10 @@ int pty_real_select_result(Pty pty, int event, int status)
notify_remote_exit(pty->frontend);
}
-
- return !finished;
}
-int pty_select_result(int fd, int event)
+void pty_select_result(int fd, int event)
{
- int ret = TRUE;
Pty pty;
if (fd == pty_signal_pipe[0]) {
@@ -696,16 +693,14 @@ int pty_select_result(int fd, int event)
pty = find234(ptys_by_pid, &pid, pty_find_by_pid);
if (pty)
- ret = ret && pty_real_select_result(pty, -1, status);
+ pty_real_select_result(pty, -1, status);
} while (pid > 0);
} else {
pty = find234(ptys_by_fd, &fd, pty_find_by_fd);
if (pty)
- ret = ret && pty_real_select_result(pty, event, 0);
+ pty_real_select_result(pty, event, 0);
}
-
- return ret;
}
static void pty_uxsel_setup(Pty pty)
diff --git a/unix/uxser.c b/unix/uxser.c
index 41beaf0e7..e77f797a3 100644
--- a/unix/uxser.c
+++ b/unix/uxser.c
@@ -56,7 +56,7 @@ static int serial_find_by_fd(void *av, void *bv)
static tree234 *serial_by_fd = NULL;
-static int serial_select_result(int fd, int event);
+static void serial_select_result(int fd, int event);
static void serial_uxsel_setup(Serial serial);
static void serial_try_write(Serial serial);
@@ -366,7 +366,7 @@ static void serial_reconfig(void *handle, Conf *conf)
serial_configure(serial, conf);
}
-static int serial_select_result(int fd, int event)
+static void serial_select_result(int fd, int event)
{
Serial serial;
char buf[4096];
@@ -376,7 +376,7 @@ static int serial_select_result(int fd, int event)
serial = find234(serial_by_fd, &fd, serial_find_by_fd);
if (!serial)
- return 1; /* spurious event; keep going */
+ return; /* spurious event; keep going */
if (event == 1) {
ret = read(serial->fd, buf, sizeof(buf));
@@ -391,11 +391,11 @@ static int serial_select_result(int fd, int event)
} else if (ret < 0) {
#ifdef EAGAIN
if (errno == EAGAIN)
- return 1; /* spurious */
+ return; /* spurious */
#endif
#ifdef EWOULDBLOCK
if (errno == EWOULDBLOCK)
- return 1; /* spurious */
+ return; /* spurious */
#endif
perror("read serial port");
exit(1);
@@ -417,8 +417,6 @@ static int serial_select_result(int fd, int event)
notify_remote_exit(serial->frontend);
}
-
- return !finished;
}
static void serial_uxsel_setup(Serial serial)
From f65c31667e0dee8d416df41dac66198a80c3314b Mon Sep 17 00:00:00 2001
From: Ben Harris
Date: Mon, 30 May 2016 20:47:04 +0100
Subject: [PATCH 020/166] winplink: remove "connopen" variable.
It's redundant with back->connected(): only the SSH backend has a
receive function that can ever return 0, and whenever ssh_receive
returns 0 it has called ssh_do_close, which will cause future calls
to ssh_connected also to return 0. Similarly, all backend closing
functions ensure that future calls to their connected function will
return 0.
---
windows/winplink.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/windows/winplink.c b/windows/winplink.c
index 474707777..a1a8dda0d 100644
--- a/windows/winplink.c
+++ b/windows/winplink.c
@@ -87,7 +87,6 @@ void cmdline_error(const char *p, ...)
HANDLE inhandle, outhandle, errhandle;
struct handle *stdin_handle, *stdout_handle, *stderr_handle;
DWORD orig_console_mode;
-int connopen;
WSAEVENT netevent;
@@ -267,7 +266,7 @@ int stdin_gotdata(struct handle *h, void *data, int len)
cleanup_exit(0);
}
noise_ultralight(len);
- if (connopen && back->connected(backhandle)) {
+ if (back->connected(backhandle)) {
if (len > 0) {
return back->send(backhandle, data, len);
} else {
@@ -294,7 +293,7 @@ void stdouterr_sent(struct handle *h, int new_backlog)
(h == stdout_handle ? "output" : "error"), buf);
cleanup_exit(0);
}
- if (connopen && back->connected(backhandle)) {
+ if (back->connected(backhandle)) {
back->unthrottle(backhandle, (handle_backlog(stdout_handle) +
handle_backlog(stderr_handle)));
}
@@ -662,7 +661,6 @@ int main(int argc, char **argv)
back->provide_logctx(backhandle, logctx);
sfree(realhost);
}
- connopen = 1;
inhandle = GetStdHandle(STD_INPUT_HANDLE);
outhandle = GetStdHandle(STD_OUTPUT_HANDLE);
@@ -782,7 +780,7 @@ int main(int argc, char **argv)
LPARAM lp;
int err = things.iErrorCode[eventtypes[e].bit];
lp = WSAMAKESELECTREPLY(eventtypes[e].mask, err);
- connopen &= select_result(wp, lp);
+ select_result(wp, lp);
}
}
}
@@ -810,7 +808,7 @@ int main(int argc, char **argv)
if (sending)
handle_unthrottle(stdin_handle, back->sendbuffer(backhandle));
- if ((!connopen || !back->connected(backhandle)) &&
+ if (!back->connected(backhandle) &&
handle_backlog(stdout_handle) + handle_backlog(stderr_handle) == 0)
break; /* we closed the connection */
}
From 70e2e140f054f5cd894d0fd7f2c31a23cd7f7377 Mon Sep 17 00:00:00 2001
From: Ben Harris
Date: Thu, 2 Jun 2016 22:37:36 +0100
Subject: [PATCH 021/166] windows: Remove spurious redeclarations of
select_result().
---
windows/winplink.c | 1 -
windows/winsftp.c | 2 --
2 files changed, 3 deletions(-)
diff --git a/windows/winplink.c b/windows/winplink.c
index a1a8dda0d..ea4175012 100644
--- a/windows/winplink.c
+++ b/windows/winplink.c
@@ -727,7 +727,6 @@ int main(int argc, char **argv)
WSANETWORKEVENTS things;
SOCKET socket;
extern SOCKET first_socket(int *), next_socket(int *);
- extern int select_result(WPARAM, LPARAM);
int i, socketstate;
/*
diff --git a/windows/winsftp.c b/windows/winsftp.c
index e25d7e064..4558e5a9b 100644
--- a/windows/winsftp.c
+++ b/windows/winsftp.c
@@ -498,7 +498,6 @@ char *do_select(SOCKET skt, int startup)
}
return NULL;
}
-extern int select_result(WPARAM, LPARAM);
int do_eventsel_loop(HANDLE other_event)
{
@@ -547,7 +546,6 @@ int do_eventsel_loop(HANDLE other_event)
WSANETWORKEVENTS things;
SOCKET socket;
extern SOCKET first_socket(int *), next_socket(int *);
- extern int select_result(WPARAM, LPARAM);
int i, socketstate;
/*
From a2fb1d96ef4660f94c2bed6cad1749c10013d351 Mon Sep 17 00:00:00 2001
From: Ben Harris
Date: Thu, 2 Jun 2016 22:38:36 +0100
Subject: [PATCH 022/166] windows: Make select_result() return void.
Nothing now uses its return value anyway.
---
windows/winnet.c | 33 +++++++++++++--------------------
windows/winstuff.h | 2 +-
2 files changed, 14 insertions(+), 21 deletions(-)
diff --git a/windows/winnet.c b/windows/winnet.c
index fc26c3e55..0ec64a55e 100644
--- a/windows/winnet.c
+++ b/windows/winnet.c
@@ -1625,9 +1625,9 @@ static void sk_tcp_write_eof(Socket sock)
try_send(s);
}
-int select_result(WPARAM wParam, LPARAM lParam)
+void select_result(WPARAM wParam, LPARAM lParam)
{
- int ret, open;
+ int ret;
DWORD err;
char buf[20480]; /* nice big buffer for plenty of speed */
Actual_Socket s;
@@ -1636,11 +1636,11 @@ int select_result(WPARAM wParam, LPARAM lParam)
/* wParam is the socket itself */
if (wParam == 0)
- return 1; /* boggle */
+ return; /* boggle */
s = find234(sktree, (void *) wParam, cmpforsearch);
if (!s)
- return 1; /* boggle */
+ return; /* boggle */
if ((err = WSAGETSELECTERROR(lParam)) != 0) {
/*
@@ -1657,9 +1657,8 @@ int select_result(WPARAM wParam, LPARAM lParam)
}
}
if (err != 0)
- return plug_closing(s->plug, winsock_error_string(err), err, 0);
- else
- return 1;
+ plug_closing(s->plug, winsock_error_string(err), err, 0);
+ return;
}
noise_ultralight(lParam);
@@ -1712,12 +1711,11 @@ int select_result(WPARAM wParam, LPARAM lParam)
}
}
if (ret < 0) {
- return plug_closing(s->plug, winsock_error_string(err), err,
- 0);
+ plug_closing(s->plug, winsock_error_string(err), err, 0);
} else if (0 == ret) {
- return plug_closing(s->plug, NULL, 0, 0);
+ plug_closing(s->plug, NULL, 0, 0);
} else {
- return plug_receive(s->plug, atmark ? 0 : 1, buf, ret);
+ plug_receive(s->plug, atmark ? 0 : 1, buf, ret);
}
break;
case FD_OOB:
@@ -1737,7 +1735,7 @@ int select_result(WPARAM wParam, LPARAM lParam)
logevent(NULL, str);
fatalbox("%s", str);
} else {
- return plug_receive(s->plug, 2, buf, ret);
+ plug_receive(s->plug, 2, buf, ret);
}
break;
case FD_WRITE:
@@ -1753,23 +1751,20 @@ int select_result(WPARAM wParam, LPARAM lParam)
break;
case FD_CLOSE:
/* Signal a close on the socket. First read any outstanding data. */
- open = 1;
do {
ret = p_recv(s->s, buf, sizeof(buf), 0);
if (ret < 0) {
err = p_WSAGetLastError();
if (err == WSAEWOULDBLOCK)
break;
- return plug_closing(s->plug, winsock_error_string(err),
- err, 0);
+ plug_closing(s->plug, winsock_error_string(err), err, 0);
} else {
if (ret)
- open &= plug_receive(s->plug, 0, buf, ret);
+ plug_receive(s->plug, 0, buf, ret);
else
- open &= plug_closing(s->plug, NULL, 0, 0);
+ plug_closing(s->plug, NULL, 0, 0);
}
} while (ret > 0);
- return open;
case FD_ACCEPT:
{
#ifdef NO_IPV6
@@ -1807,8 +1802,6 @@ int select_result(WPARAM wParam, LPARAM lParam)
}
}
}
-
- return 1;
}
/*
diff --git a/windows/winstuff.h b/windows/winstuff.h
index f8c4243f9..dfa032f48 100644
--- a/windows/winstuff.h
+++ b/windows/winstuff.h
@@ -284,7 +284,7 @@ GLOBAL void *logctx;
/*
* Exports from winnet.c.
*/
-extern int select_result(WPARAM, LPARAM);
+extern void select_result(WPARAM, LPARAM);
/*
* winnet.c dynamically loads WinSock 2 or WinSock 1 depending on
From 0d9c7d82e8506d9b6da557cfaf8a08bc3bfeb299 Mon Sep 17 00:00:00 2001
From: Ben Harris
Date: Sat, 4 Jun 2016 15:42:06 +0100
Subject: [PATCH 023/166] Don't treat plug_closing() and plug_receive() as
returning backlog.
plug_receive() and plug_closing() return 0 or 1 depending on whether
they think the main connection has closed. It is not appropriate, as
handle_gotdata and handle_socket_unfreeze did, to treat them as
returning a backlog. In fact, plugs are unusual in PuTTY in not
reporting a backlog, but just calling into the socket to freeze and
unfreeze it as required.
---
windows/winhsock.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/windows/winhsock.c b/windows/winhsock.c
index c8cb46f68..799fd28d5 100644
--- a/windows/winhsock.c
+++ b/windows/winhsock.c
@@ -54,10 +54,11 @@ static int handle_gotdata(struct handle *h, void *data, int len)
Handle_Socket ps = (Handle_Socket) handle_get_privdata(h);
if (len < 0) {
- return plug_closing(ps->plug, "Read error from handle",
- 0, 0);
+ plug_closing(ps->plug, "Read error from handle", 0, 0);
+ return 0;
} else if (len == 0) {
- return plug_closing(ps->plug, NULL, 0, 0);
+ plug_closing(ps->plug, NULL, 0, 0);
+ return 0;
} else {
assert(ps->frozen != FROZEN && ps->frozen != THAWING);
if (ps->frozen == FREEZING) {
@@ -76,7 +77,8 @@ static int handle_gotdata(struct handle *h, void *data, int len)
*/
return INT_MAX;
} else {
- return plug_receive(ps->plug, 0, data, len);
+ plug_receive(ps->plug, 0, data, len);
+ return 0;
}
}
}
@@ -168,7 +170,7 @@ static void handle_socket_unfreeze(void *psv)
{
Handle_Socket ps = (Handle_Socket) psv;
void *data;
- int len, new_backlog;
+ int len;
/*
* If we've been put into a state other than THAWING since the
@@ -188,7 +190,7 @@ static void handle_socket_unfreeze(void *psv)
* have the effect of trying to close this socket.
*/
ps->defer_close = TRUE;
- new_backlog = plug_receive(ps->plug, 0, data, len);
+ plug_receive(ps->plug, 0, data, len);
bufchain_consume(&ps->inputdata, len);
ps->defer_close = FALSE;
if (ps->deferred_close) {
@@ -207,7 +209,7 @@ static void handle_socket_unfreeze(void *psv)
* Otherwise, we've successfully thawed!
*/
ps->frozen = UNFROZEN;
- handle_unthrottle(ps->recv_h, new_backlog);
+ handle_unthrottle(ps->recv_h, 0);
}
}
From 0d57b8a4d9c8f487c6a8806384cb2c485161d19c Mon Sep 17 00:00:00 2001
From: Ben Harris
Date: Thu, 2 Jun 2016 23:03:24 +0100
Subject: [PATCH 024/166] Make plug receive and closing functions return void
instead of int.
Nothing was paying attention to their return values any more anyway.
---
network.h | 4 ++--
pageant.c | 18 ++++++++----------
portfwd.c | 25 ++++++++++---------------
proxy.c | 41 +++++++++++++++++++++--------------------
raw.c | 8 +++-----
rlogin.c | 8 +++-----
ssh.c | 9 +++------
sshshare.c | 25 +++++++++++--------------
telnet.c | 8 +++-----
unix/uxpgnt.c | 7 +++----
x11fwd.c | 18 ++++++------------
11 files changed, 73 insertions(+), 98 deletions(-)
diff --git a/network.h b/network.h
index d58635b62..0941f721f 100644
--- a/network.h
+++ b/network.h
@@ -64,12 +64,12 @@ struct plug_function_table {
* proxy command, so the receiver should probably prefix it to
* indicate this.
*/
- int (*closing)
+ void (*closing)
(Plug p, const char *error_msg, int error_code, int calling_back);
/* error_msg is NULL iff it is not an error (ie it closed normally) */
/* calling_back != 0 iff there is a Plug function */
/* currently running (would cure the fixme in try_send()) */
- int (*receive) (Plug p, int urgent, char *data, int len);
+ void (*receive) (Plug p, int urgent, char *data, int len);
/*
* - urgent==0. `data' points to `len' bytes of perfectly
* ordinary data.
diff --git a/pageant.c b/pageant.c
index 366717251..a168e522e 100644
--- a/pageant.c
+++ b/pageant.c
@@ -964,11 +964,11 @@ int pageant_delete_ssh2_key(struct ssh2_userkey *skey)
* Coroutine macros similar to, but simplified from, those in ssh.c.
*/
#define crBegin(v) { int *crLine = &v; switch(v) { case 0:;
-#define crFinish(z) } *crLine = 0; return (z); }
+#define crFinishV } *crLine = 0; return; }
#define crGetChar(c) do \
{ \
while (len == 0) { \
- *crLine =__LINE__; return 1; case __LINE__:; \
+ *crLine =__LINE__; return; case __LINE__:; \
} \
len--; \
(c) = (unsigned char)*data++; \
@@ -987,8 +987,8 @@ struct pageant_conn_state {
int crLine; /* for coroutine in pageant_conn_receive */
};
-static int pageant_conn_closing(Plug plug, const char *error_msg,
- int error_code, int calling_back)
+static void pageant_conn_closing(Plug plug, const char *error_msg,
+ int error_code, int calling_back)
{
struct pageant_conn_state *pc = (struct pageant_conn_state *)plug;
if (error_msg)
@@ -997,7 +997,6 @@ static int pageant_conn_closing(Plug plug, const char *error_msg,
plog(pc->logctx, pc->logfn, "%p: connection closed", pc);
sk_close(pc->connsock);
sfree(pc);
- return 1;
}
static void pageant_conn_sent(Plug plug, int bufsize)
@@ -1021,7 +1020,7 @@ static void pageant_conn_log(void *logctx, const char *fmt, va_list ap)
sfree(formatted);
}
-static int pageant_conn_receive(Plug plug, int urgent, char *data, int len)
+static void pageant_conn_receive(Plug plug, int urgent, char *data, int len)
{
struct pageant_conn_state *pc = (struct pageant_conn_state *)plug;
char c;
@@ -1065,7 +1064,7 @@ static int pageant_conn_receive(Plug plug, int urgent, char *data, int len)
}
}
- crFinish(1);
+ crFinishV;
}
struct pageant_listen_state {
@@ -1077,15 +1076,14 @@ struct pageant_listen_state {
pageant_logfn_t logfn;
};
-static int pageant_listen_closing(Plug plug, const char *error_msg,
- int error_code, int calling_back)
+static void pageant_listen_closing(Plug plug, const char *error_msg,
+ int error_code, int calling_back)
{
struct pageant_listen_state *pl = (struct pageant_listen_state *)plug;
if (error_msg)
plog(pl->logctx, pl->logfn, "listening socket: error: %s", error_msg);
sk_close(pl->listensock);
pl->listensock = NULL;
- return 1;
}
static int pageant_listen_accepting(Plug plug,
diff --git a/portfwd.c b/portfwd.c
index 8a73a182d..febd8af9b 100644
--- a/portfwd.c
+++ b/portfwd.c
@@ -117,8 +117,8 @@ static void pfl_log(Plug plug, int type, SockAddr addr, int port,
/* we have to dump these since we have no interface to logging.c */
}
-static int pfd_closing(Plug plug, const char *error_msg, int error_code,
- int calling_back)
+static void pfd_closing(Plug plug, const char *error_msg, int error_code,
+ int calling_back)
{
struct PortForwarding *pf = (struct PortForwarding *) plug;
@@ -145,16 +145,13 @@ static int pfd_closing(Plug plug, const char *error_msg, int error_code,
if (pf->c)
sshfwd_write_eof(pf->c);
}
-
- return 1;
}
-static int pfl_closing(Plug plug, const char *error_msg, int error_code,
- int calling_back)
+static void pfl_closing(Plug plug, const char *error_msg, int error_code,
+ int calling_back)
{
struct PortListener *pl = (struct PortListener *) plug;
pfl_terminate(pl);
- return 1;
}
static void wrap_send_port_open(void *channel, const char *hostname, int port,
@@ -172,7 +169,7 @@ static void wrap_send_port_open(void *channel, const char *hostname, int port,
sfree(description);
}
-static int pfd_receive(Plug plug, int urgent, char *data, int len)
+static void pfd_receive(Plug plug, int urgent, char *data, int len)
{
struct PortForwarding *pf = (struct PortForwarding *) plug;
if (pf->dynamic) {
@@ -204,7 +201,7 @@ static int pfd_receive(Plug plug, int urgent, char *data, int len)
data[1] = 91; /* generic `request rejected' */
sk_write(pf->s, data, 8);
pfd_close(pf);
- return 1;
+ return;
}
if (pf->sockslen <= 8)
continue; /* haven't started user/hostname */
@@ -320,7 +317,7 @@ static int pfd_receive(Plug plug, int urgent, char *data, int len)
reply[1] = 1; /* generic failure */
sk_write(pf->s, (char *) reply, lenof(reply));
pfd_close(pf);
- return 1;
+ return;
}
/*
* Now we have a viable connect request. Switch
@@ -350,7 +347,7 @@ static int pfd_receive(Plug plug, int urgent, char *data, int len)
reply[1] = 8; /* atype not supported */
sk_write(pf->s, (char *) reply, lenof(reply));
pfd_close(pf);
- return 1;
+ return;
}
}
}
@@ -362,9 +359,8 @@ static int pfd_receive(Plug plug, int urgent, char *data, int len)
* close the connection rudely.
*/
pfd_close(pf);
- return 1;
}
- return 1;
+ return;
/*
* We come here when we're ready to make an actual
@@ -383,7 +379,7 @@ static int pfd_receive(Plug plug, int urgent, char *data, int len)
pf->c = new_sock_channel(pf->backhandle, pf);
if (pf->c == NULL) {
pfd_close(pf);
- return 1;
+ return;
} else {
/* asks to forward to the specified host/port for this */
wrap_send_port_open(pf->c, pf->hostname, pf->port, pf->s);
@@ -406,7 +402,6 @@ static int pfd_receive(Plug plug, int urgent, char *data, int len)
sk_set_frozen(pf->s, 1);
}
}
- return 1;
}
static void pfd_sent(Plug plug, int bufsize)
diff --git a/proxy.c b/proxy.c
index 52006794c..68b7e9a06 100644
--- a/proxy.c
+++ b/proxy.c
@@ -201,8 +201,8 @@ static void plug_proxy_log(Plug plug, int type, SockAddr addr, int port,
plug_log(ps->plug, type, addr, port, error_msg, error_code);
}
-static int plug_proxy_closing (Plug p, const char *error_msg,
- int error_code, int calling_back)
+static void plug_proxy_closing (Plug p, const char *error_msg,
+ int error_code, int calling_back)
{
Proxy_Plug pp = (Proxy_Plug) p;
Proxy_Socket ps = pp->proxy_socket;
@@ -211,13 +211,13 @@ static int plug_proxy_closing (Plug p, const char *error_msg,
ps->closing_error_msg = error_msg;
ps->closing_error_code = error_code;
ps->closing_calling_back = calling_back;
- return ps->negotiate(ps, PROXY_CHANGE_CLOSING);
+ ps->negotiate(ps, PROXY_CHANGE_CLOSING);
+ } else {
+ plug_closing(ps->plug, error_msg, error_code, calling_back);
}
- return plug_closing(ps->plug, error_msg,
- error_code, calling_back);
}
-static int plug_proxy_receive (Plug p, int urgent, char *data, int len)
+static void plug_proxy_receive (Plug p, int urgent, char *data, int len)
{
Proxy_Plug pp = (Proxy_Plug) p;
Proxy_Socket ps = pp->proxy_socket;
@@ -231,9 +231,10 @@ static int plug_proxy_receive (Plug p, int urgent, char *data, int len)
ps->receive_urgent = urgent;
ps->receive_data = data;
ps->receive_len = len;
- return ps->negotiate(ps, PROXY_CHANGE_RECEIVE);
+ ps->negotiate(ps, PROXY_CHANGE_RECEIVE);
+ } else {
+ plug_receive(ps->plug, urgent, data, len);
}
- return plug_receive(ps->plug, urgent, data, len);
}
static void plug_proxy_sent (Plug p, int bufsize)
@@ -644,9 +645,9 @@ int proxy_http_negotiate (Proxy_Socket p, int change)
* a socket close, then some error must have occurred. we'll
* just pass those errors up to the backend.
*/
- return plug_closing(p->plug, p->closing_error_msg,
- p->closing_error_code,
- p->closing_calling_back);
+ plug_closing(p->plug, p->closing_error_msg, p->closing_error_code,
+ p->closing_calling_back);
+ return 0; /* ignored */
}
if (change == PROXY_CHANGE_SENT) {
@@ -847,9 +848,9 @@ int proxy_socks4_negotiate (Proxy_Socket p, int change)
* a socket close, then some error must have occurred. we'll
* just pass those errors up to the backend.
*/
- return plug_closing(p->plug, p->closing_error_msg,
- p->closing_error_code,
- p->closing_calling_back);
+ plug_closing(p->plug, p->closing_error_msg, p->closing_error_code,
+ p->closing_calling_back);
+ return 0; /* ignored */
}
if (change == PROXY_CHANGE_SENT) {
@@ -987,9 +988,9 @@ int proxy_socks5_negotiate (Proxy_Socket p, int change)
* a socket close, then some error must have occurred. we'll
* just pass those errors up to the backend.
*/
- return plug_closing(p->plug, p->closing_error_msg,
- p->closing_error_code,
- p->closing_calling_back);
+ plug_closing(p->plug, p->closing_error_msg, p->closing_error_code,
+ p->closing_calling_back);
+ return 0; /* ignored */
}
if (change == PROXY_CHANGE_SENT) {
@@ -1561,9 +1562,9 @@ int proxy_telnet_negotiate (Proxy_Socket p, int change)
* a socket close, then some error must have occurred. we'll
* just pass those errors up to the backend.
*/
- return plug_closing(p->plug, p->closing_error_msg,
- p->closing_error_code,
- p->closing_calling_back);
+ plug_closing(p->plug, p->closing_error_msg, p->closing_error_code,
+ p->closing_calling_back);
+ return 0; /* ignored */
}
if (change == PROXY_CHANGE_SENT) {
diff --git a/raw.c b/raw.c
index 0c5445ad4..fbc9018d8 100644
--- a/raw.c
+++ b/raw.c
@@ -61,8 +61,8 @@ static void raw_check_close(Raw raw)
}
}
-static int raw_closing(Plug plug, const char *error_msg, int error_code,
- int calling_back)
+static void raw_closing(Plug plug, const char *error_msg, int error_code,
+ int calling_back)
{
Raw raw = (Raw) plug;
@@ -92,17 +92,15 @@ static int raw_closing(Plug plug, const char *error_msg, int error_code,
raw->sent_console_eof = TRUE;
raw_check_close(raw);
}
- return 0;
}
-static int raw_receive(Plug plug, int urgent, char *data, int len)
+static void raw_receive(Plug plug, int urgent, char *data, int len)
{
Raw raw = (Raw) plug;
c_write(raw, data, len);
/* We count 'session start', for proxy logging purposes, as being
* when data is received from the network and printed. */
raw->session_started = TRUE;
- return 1;
}
static void raw_sent(Plug plug, int bufsize)
diff --git a/rlogin.c b/rlogin.c
index eba468da2..ff2c0a8f4 100644
--- a/rlogin.c
+++ b/rlogin.c
@@ -53,8 +53,8 @@ static void rlogin_log(Plug plug, int type, SockAddr addr, int port,
rlogin->conf, !rlogin->firstbyte);
}
-static int rlogin_closing(Plug plug, const char *error_msg, int error_code,
- int calling_back)
+static void rlogin_closing(Plug plug, const char *error_msg, int error_code,
+ int calling_back)
{
Rlogin rlogin = (Rlogin) plug;
@@ -76,10 +76,9 @@ static int rlogin_closing(Plug plug, const char *error_msg, int error_code,
logevent(rlogin->frontend, error_msg);
connection_fatal(rlogin->frontend, "%s", error_msg);
} /* Otherwise, the remote side closed the connection normally. */
- return 0;
}
-static int rlogin_receive(Plug plug, int urgent, char *data, int len)
+static void rlogin_receive(Plug plug, int urgent, char *data, int len)
{
Rlogin rlogin = (Rlogin) plug;
if (urgent == 2) {
@@ -113,7 +112,6 @@ static int rlogin_receive(Plug plug, int urgent, char *data, int len)
if (len > 0)
c_write(rlogin, data, len);
}
- return 1;
}
static void rlogin_sent(Plug plug, int bufsize)
diff --git a/ssh.c b/ssh.c
index 994e93aeb..b6298b039 100644
--- a/ssh.c
+++ b/ssh.c
@@ -3560,8 +3560,8 @@ void ssh_connshare_log(Ssh ssh, int event, const char *logtext,
}
}
-static int ssh_closing(Plug plug, const char *error_msg, int error_code,
- int calling_back)
+static void ssh_closing(Plug plug, const char *error_msg, int error_code,
+ int calling_back)
{
Ssh ssh = (Ssh) plug;
int need_notify = ssh_do_close(ssh, FALSE);
@@ -3583,18 +3583,15 @@ static int ssh_closing(Plug plug, const char *error_msg, int error_code,
logevent(error_msg);
if (!ssh->close_expected || !ssh->clean_exit)
connection_fatal(ssh->frontend, "%s", error_msg);
- return 0;
}
-static int ssh_receive(Plug plug, int urgent, char *data, int len)
+static void ssh_receive(Plug plug, int urgent, char *data, int len)
{
Ssh ssh = (Ssh) plug;
ssh_gotdata(ssh, (unsigned char *)data, len);
if (ssh->state == SSH_STATE_CLOSED) {
ssh_do_close(ssh, TRUE);
- return 0;
}
- return 1;
}
static void ssh_sent(Plug plug, int bufsize)
diff --git a/sshshare.c b/sshshare.c
index 82c4bd31e..59cdad45b 100644
--- a/sshshare.c
+++ b/sshshare.c
@@ -911,8 +911,8 @@ static void share_disconnect(struct ssh_sharing_connstate *cs,
share_begin_cleanup(cs);
}
-static int share_closing(Plug plug, const char *error_msg, int error_code,
- int calling_back)
+static void share_closing(Plug plug, const char *error_msg, int error_code,
+ int calling_back)
{
struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)plug;
@@ -935,7 +935,6 @@ static int share_closing(Plug plug, const char *error_msg, int error_code,
"Socket error: %s", error_msg);
}
share_begin_cleanup(cs);
- return 1;
}
static int getstring_inner(const void *vdata, int datalen,
@@ -1775,17 +1774,17 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
* Coroutine macros similar to, but simplified from, those in ssh.c.
*/
#define crBegin(v) { int *crLine = &v; switch(v) { case 0:;
-#define crFinish(z) } *crLine = 0; return (z); }
+#define crFinishV } *crLine = 0; return; }
#define crGetChar(c) do \
{ \
while (len == 0) { \
- *crLine =__LINE__; return 1; case __LINE__:; \
+ *crLine =__LINE__; return; case __LINE__:; \
} \
len--; \
(c) = (unsigned char)*data++; \
} while (0)
-static int share_receive(Plug plug, int urgent, char *data, int len)
+static void share_receive(Plug plug, int urgent, char *data, int len)
{
struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)plug;
static const char expected_verstring_prefix[] =
@@ -1858,7 +1857,7 @@ static int share_receive(Plug plug, int urgent, char *data, int len)
}
dead:;
- crFinish(1);
+ crFinishV;
}
static void share_sent(Plug plug, int bufsize)
@@ -1875,8 +1874,8 @@ static void share_sent(Plug plug, int bufsize)
*/
}
-static int share_listen_closing(Plug plug, const char *error_msg,
- int error_code, int calling_back)
+static void share_listen_closing(Plug plug, const char *error_msg,
+ int error_code, int calling_back)
{
struct ssh_sharing_state *sharestate = (struct ssh_sharing_state *)plug;
if (error_msg)
@@ -1884,7 +1883,6 @@ static int share_listen_closing(Plug plug, const char *error_msg,
"listening socket: %s", error_msg);
sk_close(sharestate->listensock);
sharestate->listensock = NULL;
- return 1;
}
static void share_send_verstring(struct ssh_sharing_connstate *cs)
@@ -2047,10 +2045,9 @@ char *ssh_share_sockname(const char *host, int port, Conf *conf)
static void nullplug_socket_log(Plug plug, int type, SockAddr addr, int port,
const char *error_msg, int error_code) {}
-static int nullplug_closing(Plug plug, const char *error_msg, int error_code,
- int calling_back) { return 0; }
-static int nullplug_receive(Plug plug, int urgent, char *data,
- int len) { return 0; }
+static void nullplug_closing(Plug plug, const char *error_msg, int error_code,
+ int calling_back) {}
+static void nullplug_receive(Plug plug, int urgent, char *data, int len) {}
static void nullplug_sent(Plug plug, int bufsize) {}
int ssh_share_test_for_upstream(const char *host, int port, Conf *conf)
diff --git a/telnet.c b/telnet.c
index c4b041327..8d03cb7b9 100644
--- a/telnet.c
+++ b/telnet.c
@@ -658,8 +658,8 @@ static void telnet_log(Plug plug, int type, SockAddr addr, int port,
telnet->session_started);
}
-static int telnet_closing(Plug plug, const char *error_msg, int error_code,
- int calling_back)
+static void telnet_closing(Plug plug, const char *error_msg, int error_code,
+ int calling_back)
{
Telnet telnet = (Telnet) plug;
@@ -681,17 +681,15 @@ static int telnet_closing(Plug plug, const char *error_msg, int error_code,
connection_fatal(telnet->frontend, "%s", error_msg);
}
/* Otherwise, the remote side closed the connection normally. */
- return 0;
}
-static int telnet_receive(Plug plug, int urgent, char *data, int len)
+static void telnet_receive(Plug plug, int urgent, char *data, int len)
{
Telnet telnet = (Telnet) plug;
if (urgent)
telnet->in_synch = TRUE;
telnet->session_started = TRUE;
do_telnet_read(telnet, data, len);
- return 1;
}
static void telnet_sent(Plug plug, int bufsize)
diff --git a/unix/uxpgnt.c b/unix/uxpgnt.c
index 41efcbc2d..cb85b1606 100644
--- a/unix/uxpgnt.c
+++ b/unix/uxpgnt.c
@@ -183,13 +183,12 @@ void sshfwd_x11_is_local(struct ssh_channel *c) {}
*/
static void x11_log(Plug p, int type, SockAddr addr, int port,
const char *error_msg, int error_code) {}
-static int x11_receive(Plug plug, int urgent, char *data, int len) {return 0;}
+static void x11_receive(Plug plug, int urgent, char *data, int len) {}
static void x11_sent(Plug plug, int bufsize) {}
-static int x11_closing(Plug plug, const char *error_msg, int error_code,
- int calling_back)
+static void x11_closing(Plug plug, const char *error_msg, int error_code,
+ int calling_back)
{
time_to_die = TRUE;
- return 1;
}
struct X11Connection {
const struct plug_function_table *fn;
diff --git a/x11fwd.c b/x11fwd.c
index 584116aa6..9d0a58de6 100644
--- a/x11fwd.c
+++ b/x11fwd.c
@@ -58,11 +58,9 @@ static int xdmseen_cmp(void *a, void *b)
* independent network.c or something */
static void dummy_plug_log(Plug p, int type, SockAddr addr, int port,
const char *error_msg, int error_code) { }
-static int dummy_plug_closing
- (Plug p, const char *error_msg, int error_code, int calling_back)
-{ return 1; }
-static int dummy_plug_receive(Plug p, int urgent, char *data, int len)
-{ return 1; }
+static void dummy_plug_closing
+ (Plug p, const char *error_msg, int error_code, int calling_back) { }
+static void dummy_plug_receive(Plug p, int urgent, char *data, int len) { }
static void dummy_plug_sent(Plug p, int bufsize) { }
static int dummy_plug_accepting(Plug p, accept_fn_t constructor, accept_ctx_t ctx) { return 1; }
static const struct plug_function_table dummy_plug = {
@@ -616,8 +614,8 @@ static void x11_log(Plug p, int type, SockAddr addr, int port,
static void x11_send_init_error(struct X11Connection *conn,
const char *err_message);
-static int x11_closing(Plug plug, const char *error_msg, int error_code,
- int calling_back)
+static void x11_closing(Plug plug, const char *error_msg, int error_code,
+ int calling_back)
{
struct X11Connection *xconn = (struct X11Connection *) plug;
@@ -646,11 +644,9 @@ static int x11_closing(Plug plug, const char *error_msg, int error_code,
if (xconn->c)
sshfwd_write_eof(xconn->c);
}
-
- return 1;
}
-static int x11_receive(Plug plug, int urgent, char *data, int len)
+static void x11_receive(Plug plug, int urgent, char *data, int len)
{
struct X11Connection *xconn = (struct X11Connection *) plug;
@@ -659,8 +655,6 @@ static int x11_receive(Plug plug, int urgent, char *data, int len)
xconn->no_data_sent_to_x_client = FALSE;
sk_set_frozen(xconn->s, 1);
}
-
- return 1;
}
static void x11_sent(Plug plug, int bufsize)
From c7b9f846d9d4062dea9eeaca7b15c0a8caf0c73d Mon Sep 17 00:00:00 2001
From: Ben Harris
Date: Wed, 17 May 2017 23:02:14 +0100
Subject: [PATCH 025/166] windows: Fix control-flow error in select_result().
When making select_result() return void (a2fb1d9), I removed a "return"
at the end of the FD_CLOSE case, causing a fallthrough into FD_ACCEPT
with hilarious (segfaulting) consequences. Re-instate the "return".
---
windows/winnet.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/windows/winnet.c b/windows/winnet.c
index 0ec64a55e..ea950bba2 100644
--- a/windows/winnet.c
+++ b/windows/winnet.c
@@ -1765,6 +1765,7 @@ void select_result(WPARAM wParam, LPARAM lParam)
plug_closing(s->plug, NULL, 0, 0);
}
} while (ret > 0);
+ return;
case FD_ACCEPT:
{
#ifdef NO_IPV6
From 12bd5a6c722152aa27f24598785593e72b3284ea Mon Sep 17 00:00:00 2001
From: Jacob Nevins
Date: Sat, 20 May 2017 12:44:56 +0100
Subject: [PATCH 026/166] Stop Gtk2 builds exploding on scroll wheel events.
More fallout from 64221972c.
---
unix/gtkwin.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/unix/gtkwin.c b/unix/gtkwin.c
index 67cfcac38..f54289a36 100644
--- a/unix/gtkwin.c
+++ b/unix/gtkwin.c
@@ -1923,7 +1923,7 @@ gboolean scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer data)
return FALSE;
event_button = (GdkEventButton *)gdk_event_new(GDK_BUTTON_PRESS);
- event_button->window = event->window;
+ event_button->window = g_object_ref(event->window);
event_button->send_event = event->send_event;
event_button->time = event->time;
event_button->x = event->x;
@@ -1931,7 +1931,7 @@ gboolean scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer data)
event_button->axes = NULL;
event_button->state = event->state;
event_button->button = button;
- event_button->device = event->device;
+ event_button->device = g_object_ref(event->device);
event_button->x_root = event->x_root;
event_button->y_root = event->y_root;
ret = button_internal(inst, event_button);
From 22cf2823d1c5615c259eadf8a3ebb199aba6f2d6 Mon Sep 17 00:00:00 2001
From: Jacob Nevins
Date: Tue, 23 May 2017 23:13:17 +0100
Subject: [PATCH 027/166] Remove some ancient cruft from the FAQ.
- I haven't heard of OpenSSH/OpenSSL mismatches being a common problem
for a long time. Specific advice about OpenSSH 3.1/3.4 seems unlikely
to be useful these days.
- "Incorrect MAC received on packet" doesn't seem to be a common
problem these days, and if anyone encounters it, the words in the
"Errors" bit of the docs seem adequate without a FAQ entry as well.
---
doc/errors.but | 18 +++++++--------
doc/faq.but | 63 --------------------------------------------------
2 files changed, 9 insertions(+), 72 deletions(-)
diff --git a/doc/errors.but b/doc/errors.but
index fdbdd861a..8e353fb9b 100644
--- a/doc/errors.but
+++ b/doc/errors.but
@@ -122,9 +122,7 @@ ridiculous amount of memory, and will terminate with an \q{Out of
memory} error.
This can happen in SSH-2, if PuTTY and the server have not enabled
-encryption in the same way (see \k{faq-outofmem} in the FAQ). Some
-versions of \i{OpenSSH} have a known problem with this: see
-\k{faq-openssh-bad-openssl}.
+encryption in the same way (see \k{faq-outofmem} in the FAQ).
This can also happen in PSCP or PSFTP, if your \i{login scripts} on the
server generate output: the client program will be expecting an SFTP
@@ -233,8 +231,13 @@ protection (such as HTTP) will manifest in more subtle failures (such
as misdisplayed text or images in a web browser) which may not be
noticed.
-A known server problem which can cause this error is described in
-\k{faq-openssh-bad-openssl} in the FAQ.
+Occasionally this has been caused by server bugs. An example is the
+bug described at \k{config-ssh-bug-hmac2}, although you're very
+unlikely to encounter that one these days.
+
+In this context MAC stands for \ii{Message Authentication Code}. It's a
+cryptographic term, and it has nothing at all to do with Ethernet
+MAC (Media Access Control) addresses, or with the Apple computer.
\H{errors-garbled} \q{Incoming packet was garbled on decryption}
@@ -247,10 +250,7 @@ in the server, or in between.
If you get this error, one thing you could try would be to fiddle with
the setting of \q{Miscomputes SSH-2 encryption keys} (see
\k{config-ssh-bug-derivekey2}) or \q{Ignores SSH-2 maximum packet
-size} (see \k{config-ssh-bug-maxpkt2}) on the Bugs panel .
-
-Another known server problem which can cause this error is described
-in \k{faq-openssh-bad-openssl} in the FAQ.
+size} (see \k{config-ssh-bug-maxpkt2}) on the Bugs panel.
\H{errors-x11-proxy} \q{PuTTY X11 proxy: \e{various errors}}
diff --git a/doc/faq.but b/doc/faq.but
index 80cf9d639..dbc3fcc96 100644
--- a/doc/faq.but
+++ b/doc/faq.but
@@ -601,34 +601,6 @@ documentation.)
\H{faq-trouble} Troubleshooting
-\S{faq-incorrect-mac}{Question} Why do I see \q{Incorrect MAC
-received on packet}?
-
-One possible cause of this that used to be common is a bug in old
-SSH-2 servers distributed by \cw{ssh.com}. (This is not the only
-possible cause; see \k{errors-crc} in the documentation.)
-Version 2.3.0 and below of their SSH-2 server
-constructs Message Authentication Codes in the wrong way, and
-expects the client to construct them in the same wrong way. PuTTY
-constructs the MACs correctly by default, and hence these old
-servers will fail to work with it.
-
-If you are using PuTTY version 0.52 or better, this should work
-automatically: PuTTY should detect the buggy servers from their
-version number announcement, and automatically start to construct
-its MACs in the same incorrect manner as they do, so it will be able
-to work with them.
-
-If you are using PuTTY version 0.51 or below, you can enable the
-workaround by going to the SSH panel and ticking the box labelled
-\q{Imitate SSH2 MAC bug}. It's possible that you might have to do
-this with 0.52 as well, if a buggy server exists that PuTTY doesn't
-know about.
-
-In this context MAC stands for \ii{Message Authentication Code}. It's a
-cryptographic term, and it has nothing at all to do with Ethernet
-MAC (Media Access Control) addresses.
-
\S{faq-pscp-protocol}{Question} Why do I see \q{Fatal: Protocol
error: Expected control record} in PSCP?
@@ -895,41 +867,6 @@ You should still read the
page} on the PuTTY website (also provided as \k{feedback} in the
manual), and follow the guidelines contained in that.
-\S{faq-openssh-bad-openssl}{Question} Since my SSH server was upgraded
-to \i{OpenSSH} 3.1p1/3.4p1, I can no longer connect with PuTTY.
-
-There is a known problem when OpenSSH has been built against an
-incorrect version of OpenSSL; the quick workaround is to configure
-PuTTY to use SSH protocol 2 and the Blowfish cipher.
-
-For more details and OpenSSH patches, see
-\W{http://bugzilla.mindrot.org/show_bug.cgi?id=138}{bug 138} in the
-OpenSSH BTS.
-
-This is not a PuTTY-specific problem; if you try to connect with
-another client you'll likely have similar problems. (Although PuTTY's
-default cipher differs from many other clients.)
-
-\e{OpenSSH 3.1p1:} configurations known to be broken (and symptoms):
-
-\b SSH-2 with AES cipher (PuTTY says \q{Assertion failed! Expression:
-(len & 15) == 0} in \cw{sshaes.c}, or \q{Out of memory}, or crashes)
-
-\b SSH-2 with 3DES (PuTTY says \q{Incorrect MAC received on packet})
-
-\b SSH-1 with Blowfish (PuTTY says \q{Incorrect CRC received on
-packet})
-
-\b SSH-1 with 3DES
-
-\e{OpenSSH 3.4p1:} as of 3.4p1, only the problem with SSH-1 and
-Blowfish remains. Rebuild your server, apply the patch linked to from
-bug 138 above, or use another cipher (e.g., 3DES) instead.
-
-\e{Other versions:} we occasionally get reports of the same symptom
-and workarounds with older versions of OpenSSH, although it's not
-clear the underlying cause is the same.
-
\S{faq-ssh2key-ssh1conn}{Question} Why do I see \q{Couldn't load
private key from ...}? Why can PuTTYgen load my key but not PuTTY?
From e5dd1435e2f9446d7f131b4b0dd849dcec880aed Mon Sep 17 00:00:00 2001
From: Jacob Nevins
Date: Tue, 23 May 2017 23:16:36 +0100
Subject: [PATCH 028/166] Remove FAQ about Plink on Win95.
While it's still true, the link to Winsock 2 is dead, our standard
release builds don't run on Win95 any more, and it's certainly not
frequently asked.
---
doc/faq.but | 15 ---------------
doc/index.but | 3 ---
2 files changed, 18 deletions(-)
diff --git a/doc/faq.but b/doc/faq.but
index dbc3fcc96..cd3254a8b 100644
--- a/doc/faq.but
+++ b/doc/faq.but
@@ -636,21 +636,6 @@ Clicking on \q{ANSI Green} won't turn your session green; it will
only allow you to adjust the \e{shade} of green used when PuTTY is
instructed by the server to display green text.
-\S{faq-winsock2}{Question} Plink on \i{Windows 95} says it can't find
-\i\cw{WS2_32.DLL}.
-
-Plink requires the extended Windows network library, WinSock version
-2. This is installed as standard on Windows 98 and above, and on
-Windows NT, and even on later versions of Windows 95; but early
-Win95 installations don't have it.
-
-In order to use Plink on these systems, you will need to download
-the
-\W{http://www.microsoft.com/windows95/downloads/contents/wuadmintools/s_wunetworkingtools/w95sockets2/}{WinSock 2 upgrade}:
-
-\c http://www.microsoft.com/windows95/downloads/contents/
-\c wuadmintools/s_wunetworkingtools/w95sockets2/
-
\S{faq-outofmem}{Question} After trying to establish an SSH-2
connection, PuTTY says \q{\ii{Out of memory}} and dies.
diff --git a/doc/index.but b/doc/index.but
index 1e71234f7..30ebd7845 100644
--- a/doc/index.but
+++ b/doc/index.but
@@ -829,9 +829,6 @@ saved sessions from
\IM{login scripts}{startup scripts} login scripts
\IM{login scripts}{startup scripts} startup scripts
-\IM{WS2_32.DLL} \cw{WS2_32.DLL}
-\IM{WS2_32.DLL} WinSock version 2
-
\IM{Red Hat Linux} Red Hat Linux
\IM{Red Hat Linux} Linux, Red Hat
From 2e66a0d2601cd4275f039a7cc82c41e4add19f7f Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Wed, 24 May 2017 20:34:38 +0100
Subject: [PATCH 029/166] Fix a build failure under Visual Studio 2010.
Patch due to Brian K. White; we now condition our own declaration of
DLL_DIRECTORY_COOKIE on whether the toolchain's headers had #defined
it already, rather than trying to guess the answer to that from
version-number macros.
(Apparently everything that defines DLL_DIRECTORY_COOKIE does it by
does seem to work in all my tests.)
---
windows/winstuff.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/windows/winstuff.h b/windows/winstuff.h
index dfa032f48..10fcdabaf 100644
--- a/windows/winstuff.h
+++ b/windows/winstuff.h
@@ -533,8 +533,9 @@ GLOBAL int restricted_acl;
#ifndef LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
#define LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR 0x00000100
#endif
-#if _MSC_VER < 1400
+#ifndef DLL_DIRECTORY_COOKIE
typedef PVOID DLL_DIRECTORY_COOKIE;
+DECLSPEC_IMPORT DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory (PCWSTR NewDirectory);
#endif
/*
From 8d2755c55f9d8b854ef9051937ececb23c5a4b23 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Thu, 25 May 2017 08:17:42 +0100
Subject: [PATCH 030/166] Under clang-cl, include stdint.h regardless of
_MSC_VER.
stdint.h is one of the set of standard C headers that has more to do
with the compiler than the library, and hence, clang provides its own
version of it, even when you're using it in clang-cl mode with Visual
Studio headers, and even when those headers are old enough not to have
a stdint.h of their own. So in clang builds, including stdint.h is
always the right way to get uintptr_t defined.
---
windows/winstuff.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/windows/winstuff.h b/windows/winstuff.h
index 10fcdabaf..546c273b7 100644
--- a/windows/winstuff.h
+++ b/windows/winstuff.h
@@ -19,7 +19,7 @@
* stddef.h. So here we try to make sure _some_ standard header is
* included which defines uintptr_t. */
#include
-#if !defined _MSC_VER || _MSC_VER >= 1600
+#if !defined _MSC_VER || _MSC_VER >= 1600 || defined __clang__
#include
#endif
From f02587f7ac4f47982bf97674f5499dd3b6dede4b Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Thu, 25 May 2017 08:21:19 +0100
Subject: [PATCH 031/166] Makefile.clangcl: provide a way to tell lld-link
about crt0.obj.
I've been experimenting with using clang-cl with older versions of the
Visual Studio libraries and headers, and found that the older VS
libraries have a quirk which can cause link failure in a way that
doesn't happen with the newer one. I assume the corresponding old VS
linker must be doing some kind of special-case handling that lld isn't
mimicking.
The quirk arises because lld tries to pull in more than one of the
*crt0.obj startup objects which set things up before calling main or
WinMain (or whatever), and those objects define some of the same
symbols as each other. The fix is to explicitly ask for the right one
of those objects on the link command line, so that it's already been
loaded _before_ the linker starts searching libraries for unresolved
symbols; then the disputed symbols are never unresolved in the first
place during the library search phase.
But this means you have to pick your crt0 object differently depending
on which subsystem you're compiling for. Accordingly, here's an extra
feature in Makefile.clangcl to make that possible by means of the
right definitions on the make command line.
---
mkfiles.pl | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/mkfiles.pl b/mkfiles.pl
index 8a63c65dc..1d83912bd 100755
--- a/mkfiles.pl
+++ b/mkfiles.pl
@@ -492,6 +492,31 @@ sub manpages {
# paths in $LIB) it's reasonable to have the choice of
# compilation target driven by another environment variable
# set in parallel with that one.
+ # - for older versions of the VS libraries you may also have to
+ # set EXTRA_console and/or EXTRA_windows to the name of an
+ # object file manually extracted from one of those libraries.
+ # * This is because old VS seems to manage its startup code by
+ # having libcmt.lib contain lots of *crt0.obj objects, one
+ # for each possible user entry point (main, WinMain and the
+ # wide-char versions of both), of which the linker arranges
+ # to include the right one by special-case code. But lld
+ # only seems to mimic half of that code - it does include
+ # the right crt0 object, but it doesn't also deliberately
+ # _avoid_ including the _wrong_ ones, and since all those
+ # objects define a common set of global symbols for other
+ # parts of the library to use, lld may well select an
+ # arbitrary one of them the first time it sees a reference
+ # to one of those global symbols, and then later also select
+ # the _right_ one for the application's entry point, causing
+ # a multiple-definitions crash.
+ # * So the workaround is to explicitly include the right
+ # *crt0.obj file on the linker command line before lld even
+ # begins searching libraries. Hence, for a console
+ # application, you might extract crt0.obj from the library
+ # in question and set EXTRA_console=crt0.obj, and for a GUI
+ # application, do the same with wincrt0.obj. Then this
+ # makefile will include the right one of those objects
+ # alongside the matching /subsystem linker option.
open OUT, ">$makefiles{'clangcl'}"; select OUT;
print
@@ -539,7 +564,8 @@ sub manpages {
print &splitline("\t\$(LD) \$(LFLAGS) \$(XLFLAGS) ".
"/out:\$(BUILDDIR)$prog.exe ".
"/lldmap:\$(BUILDDIR)$prog.map ".
- "/subsystem:$subsys\$(SUBSYSVER) $objstr")."\n\n";
+ "/subsystem:$subsys\$(SUBSYSVER) ".
+ "\$(EXTRA_$subsys) $objstr")."\n\n";
}
foreach $d (&deps("\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res.o", $dirpfx, "/", "vc")) {
$extradeps = $forceobj{$d->{obj_orig}} ? ["*.c","*.h","*.rc"] : [];
From eda5364eb476d4771e1f5a35ff81f50b4e309135 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Thu, 25 May 2017 08:22:22 +0100
Subject: [PATCH 032/166] Use / in pathnames in the Wix installer source.
I've also been experimenting recently with running Wix on Linux under
Mono, rather than running it on Windows in the obvious way. Wix under
Mono insists on forward slashes in pathnames, and it turns out that
Wix on Windows doesn't object to them either, so I can safely change
them over unconditionally and then my installer source will work in
both modes.
---
windows/installer.wxs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/windows/installer.wxs b/windows/installer.wxs
index 4a720e404..e3ed8c711 100644
--- a/windows/installer.wxs
+++ b/windows/installer.wxs
@@ -191,7 +191,7 @@ https://msdn.microsoft.com/en-us/library/windows/desktop/dd391569(v=vs.85).aspx
+ Source="../doc/putty.chm" KeyPath="yes">
@@ -209,7 +209,7 @@ https://msdn.microsoft.com/en-us/library/windows/desktop/dd391569(v=vs.85).aspx
+ Source="../LICENCE" KeyPath="yes" />
From bbdb527d4dc0eeabd083242d10faa1a2aad28e5d Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sat, 27 May 2017 20:05:07 +0100
Subject: [PATCH 033/166] Turn off the Inno Setup installer build.
We've been planning to do that for a while, and this installer-builder
isn't going to work anyway in the build environment I'm about to move
everything to, so this seems like the moment.
---
Buildscr | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/Buildscr b/Buildscr
index de7f41b57..8bd680dfe 100644
--- a/Buildscr
+++ b/Buildscr
@@ -177,11 +177,8 @@ delegate windows
in putty/windows with wix do/win candle -arch x86 -dWin64=no -dBuilddir=build32\ -dWinver="$(Winver)" -dPuttytextver="$(Puttytextver)" installer.wxs && light -ext WixUIExtension -ext WixUtilExtension -sval installer.wixobj -o installer32.msi
in putty/windows with wix do/win candle -arch x64 -dWin64=yes -dBuilddir=build64\ -dWinver="$(Winver)" -dPuttytextver="$(Puttytextver)" installer.wxs && light -ext WixUIExtension -ext WixUtilExtension -sval installer.wixobj -o installer64.msi
- # Build the old Inno Setup installer, for 32-bit only.
- in putty/windows with innosetup do/win iscc putty.iss
-
# Sign the installers.
- ifneq "$(winsigncode)" "" in putty/windows do $(winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/putty/ -n "PuTTY Installer" installer32.msi installer64.msi Output/installer.exe
+ ifneq "$(winsigncode)" "" in putty/windows do $(winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/putty/ -n "PuTTY Installer" installer32.msi installer64.msi
# Finished Windows builds.
return putty/windows/buildold/*.exe
@@ -192,7 +189,6 @@ delegate windows
return putty/windows/build64/*.map
return putty/windows/installer32.msi
return putty/windows/installer64.msi
- return putty/windows/Output/installer.exe
enddelegate
in putty/doc do make mostlyclean
in putty/doc do make $(Docmakever)
@@ -210,7 +206,6 @@ deliver putty/windows/build64/*.exe putty/w64/$@
deliver putty/windows/build64/putty.zip putty/w64/$@
deliver putty/windows/installer32.msi putty/w32/$(Ifilename32).msi
deliver putty/windows/installer64.msi putty/w64/$(Ifilename64).msi
-deliver putty/windows/Output/installer.exe putty/w32/$(Ifilename32).exe
deliver putty/doc/puttydoc.zip putty/$@
deliver putty/doc/putty.chm putty/$@
deliver putty/doc/putty.hlp putty/$@
From 599ca6d726fa9c251fda6b45fd5161878a208c53 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sat, 27 May 2017 20:06:11 +0100
Subject: [PATCH 034/166] Build using clang-cl instead of Visual Studio.
This permits me to do the binary builds via cross-compilation on
Linux, which is nice from a perspective of not having my build
environment subject to the same potential pool of Windows malware that
might be interested in infecting the resulting binaries. Also, it's
quicker to build and the code generation is noticeably better.
---
Buildscr | 51 ++++++++++++++++++++++++++++-----------------------
1 file changed, 28 insertions(+), 23 deletions(-)
diff --git a/Buildscr b/Buildscr
index 8bd680dfe..4cbf6c417 100644
--- a/Buildscr
+++ b/Buildscr
@@ -156,37 +156,42 @@ in putty/icons do make
in putty do convert -size 164x312 'gradient:blue-white' -distort SRT -90 -swirl 180 \( -size 329x312 canvas:white \) +append \( icons/putty-48.png -geometry +28+24 \) -composite \( icons/pscp-48.png -geometry +88+96 \) -composite \( icons/puttygen-48.png -geometry +28+168 \) -composite \( icons/pageant-48.png -geometry +88+240 \) -composite windows/msidialog.bmp
in putty do convert -size 493x58 canvas:white \( icons/putty-48.png -geometry +440+5 \) -composite windows/msibanner.bmp
-delegate windows
- # Build the original binaries.
- in putty/windows with visualstudio do/win mkdir buildold && nmake -f Makefile.vc BUILDDIR=buildold\ $(Makeargs) all cleantestprogs
-
- # Build the VS2015 binaries. For the 32-bit ones, we set a subsystem
- # version of 5.01, which allows the resulting files to still run on
- # Windows XP.
- in putty/windows with visualstudio2015_32bit do/win mkdir build32 && nmake -f Makefile.vc BUILDDIR=build32\ SUBSYSVER=,5.01 $(Makeargs) all cleantestprogs
- in putty/windows with visualstudio2015_64bit do/win mkdir build64 && nmake -f Makefile.vc BUILDDIR=build64\ $(Makeargs) all cleantestprogs
-
- # Code-sign the binaries, if the local bob config provides a script
- # to do so. We assume here that the script accepts an -i option to
- # provide a 'more info' URL, and an optional -n option to provide a
- # program name, and that it can take multiple .exe filename
- # arguments and sign them all in place.
- ifneq "$(winsigncode)" "" in putty/windows do $(winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/putty/ build*/*.exe
+# Build the standard binaries, in both 32- and 64-bit flavours.
+#
+# For the 32-bit ones, we set a subsystem version of 5.01, which
+# allows the resulting files to still run on Windows XP.
+in putty/windows with clangcl32 do mkdir build32 && Platform=x86 make -f Makefile.clangcl BUILDDIR=build32/ SUBSYSVER=,5.01 $(Makeargs) all cleantestprogs
+in putty/windows with clangcl64 do mkdir build64 && Platform=x64 make -f Makefile.clangcl BUILDDIR=build64/ $(Makeargs) all cleantestprogs
+
+# Build the 'old' binaries, which should still run on all 32-bit
+# versions of Windows back to Win95 (but not Win32s). These link
+# against Visual Studio 2003 libraries (the more modern versions
+# assume excessively modern Win32 API calls to be available), specify
+# a subsystem version of 4.0, and compile with /arch:IA32 to prevent
+# the use of modern CPU features like MMX which older machines also
+# might not have.
+in putty/windows with clangcl32_2003 do mkdir buildold && Platform=x86 make -f Makefile.clangcl BUILDDIR=buildold/ $(Makeargs) CCTARGET=i386-pc-windows-msvc13.0.0 SUBSYSVER=,4.0 EXTRA_windows=wincrt0.obj EXTRA_console=crt0.obj XFLAGS=/arch:IA32 all cleantestprogs
+
+# Code-sign the Windows binaries, if the local bob config provides a
+# script to do so in a cross-compiling way. We assume here that the
+# script accepts an -i option to provide a 'more info' URL, an
+# optional -n option to provide a program name, and an -N option to
+# take the program name from an .exe's version resource, and that it
+# can accept multiple .exe or .msi filename arguments and sign them
+# all in place.
+ifneq "$(cross_winsigncode)" "" in putty/windows do $(cross_winsigncode) -N -i https://www.chiark.greenend.org.uk/~sgtatham/putty/ build*/*.exe
+delegate windows
# Build a WiX MSI installer, for each of build32 and build64.
in putty/windows with wix do/win candle -arch x86 -dWin64=no -dBuilddir=build32\ -dWinver="$(Winver)" -dPuttytextver="$(Puttytextver)" installer.wxs && light -ext WixUIExtension -ext WixUtilExtension -sval installer.wixobj -o installer32.msi
in putty/windows with wix do/win candle -arch x64 -dWin64=yes -dBuilddir=build64\ -dWinver="$(Winver)" -dPuttytextver="$(Puttytextver)" installer.wxs && light -ext WixUIExtension -ext WixUtilExtension -sval installer.wixobj -o installer64.msi
- # Sign the installers.
+ # Sign the installers, if the local bob config provides
+ # $(winsigncode) that can run in a Windows delegation and behaves
+ # the same as $(cross_winsigncode) used above.
ifneq "$(winsigncode)" "" in putty/windows do $(winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/putty/ -n "PuTTY Installer" installer32.msi installer64.msi
# Finished Windows builds.
- return putty/windows/buildold/*.exe
- return putty/windows/buildold/*.map
- return putty/windows/build32/*.exe
- return putty/windows/build32/*.map
- return putty/windows/build64/*.exe
- return putty/windows/build64/*.map
return putty/windows/installer32.msi
return putty/windows/installer64.msi
enddelegate
From fd6898b5865b3f7fcccfe57c6ee272984f52a34f Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sat, 27 May 2017 20:07:00 +0100
Subject: [PATCH 035/166] Build the MSI using Wix run on Linux via Mono.
I have a grubby method of getting this to work without Wine, which I
intend to get round to publishing just as soon as I finish deciding
what its best shape is. But I don't want to wait for that before
starting to actually use it, because this eliminates the last trace of
Windows in the PuTTY Windows builds.
---
Buildscr | 21 +++++++--------------
1 file changed, 7 insertions(+), 14 deletions(-)
diff --git a/Buildscr b/Buildscr
index 4cbf6c417..ab94ea92f 100644
--- a/Buildscr
+++ b/Buildscr
@@ -181,20 +181,13 @@ in putty/windows with clangcl32_2003 do mkdir buildold && Platform=x86 make -f M
# all in place.
ifneq "$(cross_winsigncode)" "" in putty/windows do $(cross_winsigncode) -N -i https://www.chiark.greenend.org.uk/~sgtatham/putty/ build*/*.exe
-delegate windows
- # Build a WiX MSI installer, for each of build32 and build64.
- in putty/windows with wix do/win candle -arch x86 -dWin64=no -dBuilddir=build32\ -dWinver="$(Winver)" -dPuttytextver="$(Puttytextver)" installer.wxs && light -ext WixUIExtension -ext WixUtilExtension -sval installer.wixobj -o installer32.msi
- in putty/windows with wix do/win candle -arch x64 -dWin64=yes -dBuilddir=build64\ -dWinver="$(Winver)" -dPuttytextver="$(Puttytextver)" installer.wxs && light -ext WixUIExtension -ext WixUtilExtension -sval installer.wixobj -o installer64.msi
-
- # Sign the installers, if the local bob config provides
- # $(winsigncode) that can run in a Windows delegation and behaves
- # the same as $(cross_winsigncode) used above.
- ifneq "$(winsigncode)" "" in putty/windows do $(winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/putty/ -n "PuTTY Installer" installer32.msi installer64.msi
-
- # Finished Windows builds.
- return putty/windows/installer32.msi
- return putty/windows/installer64.msi
-enddelegate
+# Build a WiX MSI installer, for each of build32 and build64.
+in putty/windows with wixonlinux do candle -arch x86 -dWin64=no -dBuilddir=build32/ -dWinver="$(Winver)" -dPuttytextver="$(Puttytextver)" installer.wxs && light -ext WixUIExtension -ext WixUtilExtension -sval installer.wixobj -o installer32.msi -spdb
+in putty/windows with wixonlinux do candle -arch x64 -dWin64=yes -dBuilddir=build64/ -dWinver="$(Winver)" -dPuttytextver="$(Puttytextver)" installer.wxs && light -ext WixUIExtension -ext WixUtilExtension -sval installer.wixobj -o installer64.msi -spdb
+
+# Sign the Windows installers.
+ifneq "$(cross_winsigncode)" "" in putty/windows do $(cross_winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/putty/ -n "PuTTY Installer" installer32.msi installer64.msi
+
in putty/doc do make mostlyclean
in putty/doc do make $(Docmakever)
in putty/windows/buildold do zip -k -j putty.zip `ls *.exe | grep -v puttytel` ../../doc/putty.chm ../../doc/putty.hlp ../../doc/putty.cnt
From 1da3c71474aab3296a99ae0ed40e4fa1aa425185 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Tue, 30 May 2017 22:49:25 +0100
Subject: [PATCH 036/166] Have clang-cl builds announce their _MSC_VER.
In particular, this means the w32 and w32old builds have
distinguishable buildinfo text, which should protect us against at
least one source of confusion when receiving bug reports.
---
misc.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/misc.c b/misc.c
index 9aff234b9..734ea8b19 100644
--- a/misc.c
+++ b/misc.c
@@ -1165,11 +1165,21 @@ char *buildinfo(const char *newline)
BUILDINFO_PLATFORM);
#ifdef __clang_version__
+#define FOUND_COMPILER
strbuf_catf(buf, "%sCompiler: clang %s", newline, __clang_version__);
#elif defined __GNUC__ && defined __VERSION__
+#define FOUND_COMPILER
strbuf_catf(buf, "%sCompiler: gcc %s", newline, __VERSION__);
-#elif defined _MSC_VER
- strbuf_catf(buf, "%sCompiler: Visual Studio", newline);
+#endif
+
+#if defined _MSC_VER
+#ifndef FOUND_COMPILER
+#define FOUND_COMPILER
+ strbuf_catf(buf, "%sCompiler: ", newline);
+#else
+ strbuf_catf(buf, ", emulating ");
+#endif
+ strbuf_catf(buf, "Visual Studio", newline);
#if _MSC_VER == 1900
strbuf_catf(buf, " 2015 / MSVC++ 14.0");
#elif _MSC_VER == 1800
@@ -1178,12 +1188,14 @@ char *buildinfo(const char *newline)
strbuf_catf(buf, " 2012 / MSVC++ 11.0");
#elif _MSC_VER == 1600
strbuf_catf(buf, " 2010 / MSVC++ 10.0");
-#elif _MSC_VER == 1500
+#elif _MSC_VER == 1500
strbuf_catf(buf, " 2008 / MSVC++ 9.0");
-#elif _MSC_VER == 1400
+#elif _MSC_VER == 1400
strbuf_catf(buf, " 2005 / MSVC++ 8.0");
-#elif _MSC_VER == 1310
+#elif _MSC_VER == 1310
strbuf_catf(buf, " 2003 / MSVC++ 7.1");
+#elif _MSC_VER == 1300
+ strbuf_catf(buf, " 2003 / MSVC++ 7.0");
#else
strbuf_catf(buf, ", unrecognised version");
#endif
From 05f499e55f19b82c773559ee4465ba11c898c9eb Mon Sep 17 00:00:00 2001
From: Jacob Nevins
Date: Tue, 6 Jun 2017 09:34:21 +0100
Subject: [PATCH 037/166] Add 'passthrough printing' as an index term.
---
doc/config.but | 4 ++--
doc/index.but | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/doc/config.but b/doc/config.but
index bb18b794b..bd12efb28 100644
--- a/doc/config.but
+++ b/doc/config.but
@@ -499,8 +499,8 @@ instead of relying on the automatic detection.
\cfg{winhelp-topic}{terminal.printing}
A lot of VT100-compatible terminals support printing under control
-of the remote server. PuTTY supports this feature as well, but it is
-turned off by default.
+of the remote server (sometimes called \q{passthrough printing}).
+PuTTY supports this feature as well, but it is turned off by default.
To enable remote-controlled printing, choose a printer from the
\q{Printer to send ANSI printer output to} drop-down list box. This
diff --git a/doc/index.but b/doc/index.but
index 30ebd7845..0877ee90d 100644
--- a/doc/index.but
+++ b/doc/index.but
@@ -340,6 +340,7 @@ saved sessions from
\IM{remote-controlled printing} ANSI printing
\IM{remote-controlled printing} remote-controlled printing
\IM{remote-controlled printing} printing, remote-controlled
+\IM{remote-controlled printing} passthrough printing
\IM{Home and End keys} Home key
\IM{Home and End keys} End key
From 6aac4b9cefbaa651639ef0495ebf9d098e67481c Mon Sep 17 00:00:00 2001
From: Jacob Nevins
Date: Wed, 7 Jun 2017 22:02:28 +0100
Subject: [PATCH 038/166] StartDocPrinter returns DWORD, not BOOL.
(Introduced in 793ac8727.)
---
windows/winprint.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/windows/winprint.c b/windows/winprint.c
index 115872739..a17166e69 100644
--- a/windows/winprint.c
+++ b/windows/winprint.c
@@ -23,7 +23,7 @@ DECL_WINDOWS_FUNCTION(static, BOOL, EnumPrinters,
DECL_WINDOWS_FUNCTION(static, BOOL, OpenPrinter,
(LPTSTR, LPHANDLE, LPPRINTER_DEFAULTS));
DECL_WINDOWS_FUNCTION(static, BOOL, ClosePrinter, (HANDLE));
-DECL_WINDOWS_FUNCTION(static, BOOL, StartDocPrinter, (HANDLE, DWORD, LPBYTE));
+DECL_WINDOWS_FUNCTION(static, DWORD, StartDocPrinter, (HANDLE, DWORD, LPBYTE));
DECL_WINDOWS_FUNCTION(static, BOOL, EndDocPrinter, (HANDLE));
DECL_WINDOWS_FUNCTION(static, BOOL, StartPagePrinter, (HANDLE));
DECL_WINDOWS_FUNCTION(static, BOOL, EndPagePrinter, (HANDLE));
From f31a72ba09d20e076f62e39e0f59404511bf6c86 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sat, 10 Jun 2017 11:29:21 +0100
Subject: [PATCH 039/166] Unix: use conf_dest() in 'unable to open connection'
error box.
Alamy Liu points out that asking for CONF_host will display the wrong
part of the configuration in the case where serial port setup fails.
The Windows front end's analogous message already got this right, but
I must have forgotten to change this one too when I introduced
conf_dest.
---
unix/gtkwin.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/unix/gtkwin.c b/unix/gtkwin.c
index f54289a36..9e73181e2 100644
--- a/unix/gtkwin.c
+++ b/unix/gtkwin.c
@@ -4274,7 +4274,7 @@ static void start_backend(struct gui_data *inst)
if (error) {
char *msg = dupprintf("Unable to open connection to %s:\n%s",
- conf_get_str(inst->conf, CONF_host), error);
+ conf_dest(inst->conf), error);
inst->exited = TRUE;
fatal_message_box(inst->window, msg);
sfree(msg);
From a9e1053c8ae29c80cf0827c346e7dac976fb949b Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Thu, 15 Jun 2017 18:58:01 +0100
Subject: [PATCH 040/166] Log the server's diagnostics if main channel open
fails.
This has been a FIXME in the code for ages, because back when the main
channel was always a pty session or a program run in a pipe, there
weren't that many circumstances in which the actual CHANNEL_OPEN could
return failure, so it never seemed like a priority to get round to
pulling the error information out of the CHANNEL_OPEN_FAILURE response
message and including it in PuTTY or Plink's local error message.
However, 'plink -nc' is the real reason why this is actually
important; if you tell the SSH server to make a direct-tcpip network
connection as its main channel, then that can fail for all the usual
network-unreliability reasons, and you actually do want to know which
(did you misspell the hostname, or is the target server refusing
connections, or has network connectivity failed?). This actually bit
me today when I had such a network failure, and had to debug it by
pulling that information manually out of a packet log. Time to
eliminate that FIXME.
So I've pulled the error-extracting code out of the previous handler
for OPEN_FAILURE on non-main channels into a separate function, and
arranged to call that function if the main channel open fails too. In
the process I've made a couple of minor tweaks, e.g. if the server
sends back a reason code we haven't heard of, we say _what_ that
reason code was, and also we at least make a token effort to spot if
we see a packet other than OPEN_{CONFIRMATION,FAILURE} reaching the
main loop in response to the main channel-open.
---
ssh.c | 61 ++++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 42 insertions(+), 19 deletions(-)
diff --git a/ssh.c b/ssh.c
index b6298b039..1d80e9194 100644
--- a/ssh.c
+++ b/ssh.c
@@ -8496,18 +8496,37 @@ static void ssh2_msg_channel_open_confirmation(Ssh ssh, struct Packet *pktin)
ssh_channel_try_eof(c); /* in case we had a pending EOF */
}
-static void ssh2_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
+static char *ssh2_channel_open_failure_error_text(struct Packet *pktin)
{
static const char *const reasons[] = {
- "",
- "Administratively prohibited",
- "Connect failed",
- "Unknown channel type",
- "Resource shortage",
+ NULL,
+ "Administratively prohibited",
+ "Connect failed",
+ "Unknown channel type",
+ "Resource shortage",
};
unsigned reason_code;
+ const char *reason_code_string;
+ char reason_code_buf[256];
char *reason_string;
int reason_length;
+
+ reason_code = ssh_pkt_getuint32(pktin);
+ if (reason_code < lenof(reasons) && reasons[reason_code]) {
+ reason_code_string = reasons[reason_code];
+ } else {
+ reason_code_string = reason_code_buf;
+ sprintf(reason_code_buf, "unknown reason code %#x", reason_code);
+ }
+
+ ssh_pkt_getstring(pktin, &reason_string, &reason_length);
+
+ return dupprintf("%s [%.*s]", reason_code_string,
+ reason_length, NULLTOEMPTY(reason_string));
+}
+
+static void ssh2_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
+{
struct ssh_channel *c;
c = ssh_channel_msg(ssh, pktin);
@@ -8516,14 +8535,9 @@ static void ssh2_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
assert(c->halfopen); /* ssh_channel_msg will have enforced this */
if (c->type == CHAN_SOCKDATA) {
- reason_code = ssh_pkt_getuint32(pktin);
- if (reason_code >= lenof(reasons))
- reason_code = 0; /* ensure reasons[reason_code] in range */
- ssh_pkt_getstring(pktin, &reason_string, &reason_length);
- logeventf(ssh, "Forwarded connection refused by server: %s [%.*s]",
- reasons[reason_code], reason_length,
- NULLTOEMPTY(reason_string));
-
+ char *errtext = ssh2_channel_open_failure_error_text(pktin);
+ logeventf(ssh, "Forwarded connection refused by server: %s", errtext);
+ sfree(errtext);
pfd_close(c->u.pfd.pf);
} else if (c->type == CHAN_ZOMBIE) {
/*
@@ -10727,15 +10741,24 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
ssh->ncmode = FALSE;
}
crWaitUntilV(pktin);
- if (pktin->type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) {
- bombout(("Server refused to open channel"));
+ if (pktin->type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION &&
+ pktin->type != SSH2_MSG_CHANNEL_OPEN_FAILURE) {
+ bombout(("Server sent strange packet %d in response to main "
+ "channel open request", pktin->type));
crStopV;
- /* FIXME: error data comes back in FAILURE packet */
- }
+ }
if (ssh_pkt_getuint32(pktin) != ssh->mainchan->localid) {
- bombout(("Server's channel confirmation cited wrong channel"));
+ bombout(("Server's response to main channel open cited wrong"
+ " channel number"));
+ crStopV;
+ }
+ if (pktin->type == SSH2_MSG_CHANNEL_OPEN_FAILURE) {
+ char *errtext = ssh2_channel_open_failure_error_text(pktin);
+ bombout(("Server refused to open main channel: %s", errtext));
+ sfree(errtext);
crStopV;
}
+
ssh->mainchan->remoteid = ssh_pkt_getuint32(pktin);
ssh->mainchan->halfopen = FALSE;
ssh->mainchan->type = CHAN_MAINSESSION;
From 892d4a0188ffd8aa60dc11b4bace30dfb0f9d50e Mon Sep 17 00:00:00 2001
From: Jacob Nevins
Date: Thu, 15 Jun 2017 23:33:57 +0100
Subject: [PATCH 041/166] Seek all Windows print functions in winspool.drv.
Rather than loading some from spoolss.dll, which some MSDN documentation
suggests, but which doesn't work very well in practice.
(Also, remove an unused variable.)
---
windows/winprint.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/windows/winprint.c b/windows/winprint.c
index a17166e69..6a1a74c23 100644
--- a/windows/winprint.c
+++ b/windows/winprint.c
@@ -33,20 +33,25 @@ DECL_WINDOWS_FUNCTION(static, BOOL, WritePrinter,
static void init_winfuncs(void)
{
static int initialised = FALSE;
- char buf[4096];
if (initialised)
return;
{
HMODULE winspool_module = load_system32_dll("winspool.drv");
- HMODULE spoolss_module = load_system32_dll("spoolss.dll");
+ /* Some MSDN documentation claims that some of the below functions
+ * should be loaded from spoolss.dll, but this doesn't seem to
+ * be reliable in practice.
+ * Nevertheless, we load spoolss.dll ourselves using our safe
+ * loading method, against the possibility that winspool.drv
+ * later loads it unsafely. */
+ (void) load_system32_dll("spoolss.dll");
GET_WINDOWS_FUNCTION_PP(winspool_module, EnumPrinters);
GET_WINDOWS_FUNCTION_PP(winspool_module, OpenPrinter);
- GET_WINDOWS_FUNCTION_PP(spoolss_module, ClosePrinter);
+ GET_WINDOWS_FUNCTION_PP(winspool_module, ClosePrinter);
GET_WINDOWS_FUNCTION_PP(winspool_module, StartDocPrinter);
- GET_WINDOWS_FUNCTION_PP(spoolss_module, EndDocPrinter);
- GET_WINDOWS_FUNCTION_PP(spoolss_module, StartPagePrinter);
- GET_WINDOWS_FUNCTION_PP(spoolss_module, EndPagePrinter);
- GET_WINDOWS_FUNCTION_PP(spoolss_module, WritePrinter);
+ GET_WINDOWS_FUNCTION_PP(winspool_module, EndDocPrinter);
+ GET_WINDOWS_FUNCTION_PP(winspool_module, StartPagePrinter);
+ GET_WINDOWS_FUNCTION_PP(winspool_module, EndPagePrinter);
+ GET_WINDOWS_FUNCTION_PP(winspool_module, WritePrinter);
}
initialised = TRUE;
}
From 4387b5f1617bf0222fc64e3ec73d14e252465309 Mon Sep 17 00:00:00 2001
From: Ilya Shipitsin
Date: Mon, 19 Jun 2017 20:57:28 +0500
Subject: [PATCH 042/166] resolve an issue found by cppcheck:
[unix/osxlaunch.c:133] -> [unix/osxlaunch.c:134]: (warning) Either the condition '!qhead' is redundant or there is possible null pointer dereference: qhead.
---
unix/osxlaunch.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/unix/osxlaunch.c b/unix/osxlaunch.c
index 2627c642e..285161853 100644
--- a/unix/osxlaunch.c
+++ b/unix/osxlaunch.c
@@ -130,11 +130,11 @@ char *get_unused_env_prefix(void)
char **e;
qhead = (struct bucket *)malloc(sizeof(struct bucket));
- qhead->prefixlen = 0;
if (!qhead) {
fprintf(stderr, "out of memory\n");
exit(1);
}
+ qhead->prefixlen = 0;
for (e = environ; *e; e++)
qhead->first_node = new_node(qhead->first_node, *e, strcspn(*e, "="));
From 5efee183569ede0a4155f8195e1b1be58e954b95 Mon Sep 17 00:00:00 2001
From: Ilya Shipitsin
Date: Mon, 19 Jun 2017 21:39:32 +0500
Subject: [PATCH 043/166] resolve couple of issues found by cppcheck:
[psftp.c:1135] -> [psftp.c:1134]: (warning) Either the condition '!dir' is redundant or there is possible null pointer dereference: dir.
[psftp.c:1420] -> [psftp.c:1419]: (warning) Either the condition '!dir' is redundant or there is possible null pointer dereference: dir.
---
psftp.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/psftp.c b/psftp.c
index 5394c1fbb..aa3971812 100644
--- a/psftp.c
+++ b/psftp.c
@@ -1128,12 +1128,12 @@ int sftp_cmd_cd(struct sftp_command *cmd)
if (cmd->nwords < 2)
dir = dupstr(homedir);
- else
+ else {
dir = canonify(cmd->words[1]);
-
- if (!dir) {
- printf("%s: canonify: %s\n", dir, fxp_error());
- return 0;
+ if (!dir) {
+ printf("%s: canonify: %s\n", cmd->words[1], fxp_error());
+ return 0;
+ }
}
req = fxp_opendir_send(dir);
@@ -1417,7 +1417,7 @@ int sftp_cmd_mkdir(struct sftp_command *cmd)
for (i = 1; i < cmd->nwords; i++) {
dir = canonify(cmd->words[i]);
if (!dir) {
- printf("%s: canonify: %s\n", dir, fxp_error());
+ printf("%s: canonify: %s\n", cmd->words[i], fxp_error());
return 0;
}
From 3f2df8cc9dc6ae19c6513091eb009999f4406a60 Mon Sep 17 00:00:00 2001
From: Ilya Shipitsin
Date: Mon, 19 Jun 2017 21:42:16 +0500
Subject: [PATCH 044/166] resolve (no real impact) issue found by cppcheck:
[unix/osxlaunch.c:411]: (error) Memory leak: macos
[unix/osxlaunch.c:411]: (error) Memory leak: contents
[unix/osxlaunch.c:411]: (error) Memory leak: new_argv
---
unix/osxlaunch.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/unix/osxlaunch.c b/unix/osxlaunch.c
index 285161853..8082f2dee 100644
--- a/unix/osxlaunch.c
+++ b/unix/osxlaunch.c
@@ -408,6 +408,9 @@ int main(int argc, char **argv)
execv(realbin, new_argv);
perror("execv");
+ free(new_argv);
+ free(contents);
+ free(macos);
return 127;
}
From 02043ec5ace4985fc35fef8b5d6543a871ccab3c Mon Sep 17 00:00:00 2001
From: Ilya Shipitsin
Date: Tue, 20 Jun 2017 09:36:07 +0500
Subject: [PATCH 045/166] resolve (no real impact) issue found by cppcheck:
[windows/winnet.c:589]: (error) Uninitialized variable: err
---
windows/winnet.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/windows/winnet.c b/windows/winnet.c
index ea950bba2..e2edc87a7 100644
--- a/windows/winnet.c
+++ b/windows/winnet.c
@@ -548,7 +548,7 @@ SockAddr sk_namelookup(const char *host, char **canonicalname,
if ((a = p_inet_addr(host)) == (unsigned long) INADDR_NONE) {
struct hostent *h = NULL;
- int err;
+ int err = 0;
#ifndef NO_IPV6
/*
* Use getaddrinfo when it's available
From 20e36ae4a24e06f86ce533a24c5f61f00e2ab91c Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Tue, 20 Jun 2017 07:05:39 +0100
Subject: [PATCH 046/166] Fix a collection of type / format string mismatches.
Ilya Shipitsin sent me a list of errors reported by a tool 'cppcheck',
which I hadn't seen before, together with some fixes for things
already taken off that list. This change picks out all the things from
the remaining list that I could quickly identify as actual errors,
which it turns out are all format-string goofs along the lines of
using a %d with an unsigned int, or a %u with a signed int, or (in the
cases in charset/utf8.c) an actual _size_ mismatch which could in
principle have caused trouble on a big-endian target.
---
charset/utf8.c | 4 ++--
import.c | 3 ++-
minibidi.c | 2 +-
misc.c | 3 ++-
pscp.c | 2 +-
terminal.c | 2 +-
windows/window.c | 4 ++--
7 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/charset/utf8.c b/charset/utf8.c
index 3c777292d..fe46cf988 100644
--- a/charset/utf8.c
+++ b/charset/utf8.c
@@ -267,7 +267,7 @@ void utf8_read_test(int line, char *input, int inlen, ...)
}
if (l != str[i]) {
printf("%d: char %d came out as %08x, should be %08x\n",
- line, i, str[i], l);
+ line, i, str[i], (unsigned)l);
total_errs++;
}
}
@@ -306,7 +306,7 @@ void utf8_write_test(int line, const long *input, int inlen, ...)
}
if (l != str[i]) {
printf("%d: char %d came out as %08x, should be %08x\n",
- line, i, str[i], l);
+ line, i, str[i], (unsigned)l);
total_errs++;
}
}
diff --git a/import.c b/import.c
index adf68777d..88589a71d 100644
--- a/import.c
+++ b/import.c
@@ -445,7 +445,7 @@ static struct openssh_pem_key *load_openssh_pem_key(const Filename *filename,
if (!strcmp(p, "ENCRYPTED"))
ret->encrypted = TRUE;
} else if (!strcmp(line, "DEK-Info")) {
- int i, j, ivlen;
+ int i, ivlen;
if (!strncmp(p, "DES-EDE3-CBC,", 13)) {
ret->encryption = OP_E_3DES;
@@ -459,6 +459,7 @@ static struct openssh_pem_key *load_openssh_pem_key(const Filename *filename,
}
p = strchr(p, ',') + 1;/* always non-NULL, by above checks */
for (i = 0; i < ivlen; i++) {
+ unsigned j;
if (1 != sscanf(p, "%2x", &j)) {
errmsg = "expected more iv data in DEK-Info";
goto error;
diff --git a/minibidi.c b/minibidi.c
index 8d78594d2..2bdf4deb3 100644
--- a/minibidi.c
+++ b/minibidi.c
@@ -2014,7 +2014,7 @@ int main(int argc, char **argv)
unsigned long chr = strtoul(argv[i], NULL, 0);
int type = getType(chr);
assert(typetoname[type].type == type);
- printf("U+%04x: %s\n", chr, typetoname[type].name);
+ printf("U+%04x: %s\n", (unsigned)chr, typetoname[type].name);
}
return 0;
diff --git a/misc.c b/misc.c
index 734ea8b19..469e4aeb6 100644
--- a/misc.c
+++ b/misc.c
@@ -157,7 +157,8 @@ int main(void)
passes++; \
} else { \
printf("fail: %s(%s,%s)%s = %u, expected %u\n", \
- #func, #string, #arg2, #suffix, ret, result); \
+ #func, #string, #arg2, #suffix, ret, \
+ (unsigned)result); \
fails++; \
} \
} while (0)
diff --git a/pscp.c b/pscp.c
index 454ec084c..210362df9 100644
--- a/pscp.c
+++ b/pscp.c
@@ -1476,7 +1476,7 @@ int scp_get_sink_action(struct scp_sink_action *act)
act->action = SCP_SINK_ENDDIR;
return 0;
case 'T':
- if (sscanf(act->buf, "%ld %*d %ld %*d",
+ if (sscanf(act->buf, "%lu %*d %lu %*d",
&act->mtime, &act->atime) == 2) {
act->settime = 1;
back->send(backhandle, "", 1);
diff --git a/terminal.c b/terminal.c
index f47fe1bdb..ba9dd6172 100644
--- a/terminal.c
+++ b/terminal.c
@@ -4327,7 +4327,7 @@ static void term_out(Terminal *term)
for (i = 1; i < term->esc_nargs; i++) {
if (i != 1)
strcat(term->id_string, ";");
- sprintf(lbuf, "%d", term->esc_args[i]);
+ sprintf(lbuf, "%u", term->esc_args[i]);
strcat(term->id_string, lbuf);
}
strcat(term->id_string, "c");
diff --git a/windows/window.c b/windows/window.c
index 89ddb8636..966003114 100644
--- a/windows/window.c
+++ b/windows/window.c
@@ -5199,8 +5199,8 @@ void write_clip(void *frontend, wchar_t * data, int *attr, int len, int must_des
multilen = WideCharToMultiByte(CP_ACP, 0, unitab+uindex, 1,
NULL, 0, NULL, NULL);
if (multilen != 1) {
- blen = sprintf(before, "{\\uc%d\\u%d", multilen,
- udata[uindex]);
+ blen = sprintf(before, "{\\uc%d\\u%d", (int)multilen,
+ (int)udata[uindex]);
alen = 1; strcpy(after, "}");
} else {
blen = sprintf(before, "\\u%d", udata[uindex]);
From 98cbe6963b8126659cf16c622302cbd872026936 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Tue, 20 Jun 2017 19:02:13 +0100
Subject: [PATCH 047/166] Another format-string fix.
Oops - I found this in an editor autosave file after pushing the
previous commit. I meant it to be part of the previous commit. Oh
well, better late than never.
---
tree234.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tree234.c b/tree234.c
index f1c0c2edb..d3c5293d8 100644
--- a/tree234.c
+++ b/tree234.c
@@ -681,7 +681,7 @@ static void *delpos234_internal(tree234 * t, int index)
LOG((" moving to subtree %d\n", ki));
sub = n->kids[ki];
if (!sub->elems[1]) {
- LOG((" subtree has only one element!\n", ki));
+ LOG((" subtree has only one element!\n"));
if (ki > 0 && n->kids[ki - 1]->elems[1]) {
/*
* Case 3a, left-handed variant. Child ki has
From 4696f4a40bd38386dac5bc0f8331ca9c4e579bd6 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Tue, 20 Jun 2017 19:02:48 +0100
Subject: [PATCH 048/166] Coverity build fixes.
Like every other toolchain I've tried, my Coverity scanning build has
its share of random objections to parts of my Windows API type-
checking system. I do wonder if that bright idea was worth the hassle
- but it would probably cost all the annoyance all over again to back
out now...
---
windows/wincapi.c | 9 ++++++++-
windows/winhsock.c | 5 +++--
windows/winmisc.c | 8 +++++---
windows/winnet.c | 10 ++++++++++
4 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/windows/wincapi.c b/windows/wincapi.c
index 2550b6def..2bd03470b 100644
--- a/windows/wincapi.c
+++ b/windows/wincapi.c
@@ -19,7 +19,14 @@ int got_crypt(void)
attempted = TRUE;
crypt = load_system32_dll("crypt32.dll");
successful = crypt &&
- GET_WINDOWS_FUNCTION(crypt, CryptProtectMemory);
+#ifdef COVERITY
+ /* The build toolchain I use with Coverity doesn't know
+ * about this function, so can't type-check it */
+ GET_WINDOWS_FUNCTION_NO_TYPECHECK(crypt, CryptProtectMemory)
+#else
+ GET_WINDOWS_FUNCTION(crypt, CryptProtectMemory)
+#endif
+ ;
}
return successful;
}
diff --git a/windows/winhsock.c b/windows/winhsock.c
index 799fd28d5..7c8b0ba64 100644
--- a/windows/winhsock.c
+++ b/windows/winhsock.c
@@ -284,10 +284,11 @@ static char *sk_handle_peer_info(Socket s)
if (!kernel32_module) {
kernel32_module = load_system32_dll("kernel32.dll");
-#if (defined _MSC_VER && _MSC_VER < 1900) || defined __MINGW32__
+#if (defined _MSC_VER && _MSC_VER < 1900) || defined __MINGW32__ || defined COVERITY
/* For older Visual Studio, and MinGW too (at least as of
* Ubuntu 16.04), this function isn't available in the header
- * files to type-check */
+ * files to type-check. Ditto the toolchain I use for
+ * Coveritying the Windows code. */
GET_WINDOWS_FUNCTION_NO_TYPECHECK(
kernel32_module, GetNamedPipeClientProcessId);
#else
diff --git a/windows/winmisc.c b/windows/winmisc.c
index 85fa3c95d..59d643122 100644
--- a/windows/winmisc.c
+++ b/windows/winmisc.c
@@ -177,9 +177,11 @@ void dll_hijacking_protection(void)
if (!kernel32_module) {
kernel32_module = load_system32_dll("kernel32.dll");
-#if defined _MSC_VER && _MSC_VER < 1900
- /* For older Visual Studio, this function isn't available in
- * the header files to type-check */
+#if (defined _MSC_VER && _MSC_VER < 1900) || defined COVERITY
+ /* For older Visual Studio, and also for the system I
+ * currently use for Coveritying the Windows code, this
+ * function isn't available in the header files to
+ * type-check */
GET_WINDOWS_FUNCTION_NO_TYPECHECK(
kernel32_module, SetDefaultDllDirectories);
#else
diff --git a/windows/winnet.c b/windows/winnet.c
index e2edc87a7..86f7735fa 100644
--- a/windows/winnet.c
+++ b/windows/winnet.c
@@ -305,11 +305,21 @@ void sk_init(void)
GET_WINDOWS_FUNCTION(winsock_module, WSAStartup);
GET_WINDOWS_FUNCTION(winsock_module, WSACleanup);
GET_WINDOWS_FUNCTION(winsock_module, closesocket);
+#ifndef COVERITY
GET_WINDOWS_FUNCTION(winsock_module, ntohl);
GET_WINDOWS_FUNCTION(winsock_module, htonl);
GET_WINDOWS_FUNCTION(winsock_module, htons);
GET_WINDOWS_FUNCTION(winsock_module, ntohs);
GET_WINDOWS_FUNCTION(winsock_module, gethostname);
+#else
+ /* The toolchain I use for Windows Coverity builds doesn't know
+ * the type signatures of these */
+ GET_WINDOWS_FUNCTION_NO_TYPECHECK(winsock_module, ntohl);
+ GET_WINDOWS_FUNCTION_NO_TYPECHECK(winsock_module, htonl);
+ GET_WINDOWS_FUNCTION_NO_TYPECHECK(winsock_module, htons);
+ GET_WINDOWS_FUNCTION_NO_TYPECHECK(winsock_module, ntohs);
+ GET_WINDOWS_FUNCTION_NO_TYPECHECK(winsock_module, gethostname);
+#endif
GET_WINDOWS_FUNCTION(winsock_module, gethostbyname);
GET_WINDOWS_FUNCTION(winsock_module, getservbyname);
GET_WINDOWS_FUNCTION(winsock_module, inet_addr);
From d61897414cae6e40dc39da6aac84ab48c6cdf149 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Tue, 20 Jun 2017 21:17:43 +0100
Subject: [PATCH 049/166] Fixes spotted by Coverity.
A lenof() being applied to a non-array, a couple of missing frees on
an error path, and a case in pfd_receive() where we could have gone
round a loop again after freeing the port forwarding structure it was
working on.
---
config.c | 2 +-
portfwd.c | 1 +
psftp.c | 2 ++
3 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/config.c b/config.c
index 220c1aa8f..efe1ff1ec 100644
--- a/config.c
+++ b/config.c
@@ -1005,7 +1005,7 @@ static void ttymodes_handler(union control *ctrl, void *dlg,
char type;
{
- const char *types = "ANV";
+ const char types[] = {'A', 'N', 'V'};
int button = dlg_radiobutton_get(td->valradio, dlg);
assert(button >= 0 && button < lenof(types));
type = types[button];
diff --git a/portfwd.c b/portfwd.c
index febd8af9b..b68e4bb8f 100644
--- a/portfwd.c
+++ b/portfwd.c
@@ -359,6 +359,7 @@ static void pfd_receive(Plug plug, int urgent, char *data, int len)
* close the connection rudely.
*/
pfd_close(pf);
+ break;
}
return;
diff --git a/psftp.c b/psftp.c
index aa3971812..e4e77c3af 100644
--- a/psftp.c
+++ b/psftp.c
@@ -1050,6 +1050,8 @@ int sftp_cmd_ls(struct sftp_command *cmd)
if (dirh == NULL) {
printf("Unable to open %s: %s\n", dir, fxp_error());
+ sfree(cdir);
+ sfree(unwcdir);
return 0;
} else {
nnames = namesize = 0;
From 4241734dde44caea5a9c73a79db9c6d4cae50861 Mon Sep 17 00:00:00 2001
From: David Taylor
Date: Sat, 1 Jul 2017 23:25:49 +0100
Subject: [PATCH 050/166] Update wcwidth.c with Unicode 9.0.0 data
In order to maintain compatibility with screen[1], update
wcwidth functions to use Unicode 9.0.0 character database.
Updated intervals extracted from output of [2] from ucd files[3].
The comments at the head of [2] state that the output is unrestricted.
Therefore it is not subject to the GPL as applies to the script itself.
[1] See: https://savannah.gnu.org/bugs/?func=detailitem&item_id=50044
[2] https://raw.githubusercontent.com/GNOME/glib/37d4c2941bd0326b8b6e6bb22c81bd424fcc040b/glib/gen-unicode-tables.pl
[3] http://www.unicode.org/Public/9.0.0/ucd/
---
wcwidth.c | 373 ++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 305 insertions(+), 68 deletions(-)
diff --git a/wcwidth.c b/wcwidth.c
index ec0fb2ba0..25372a79b 100644
--- a/wcwidth.c
+++ b/wcwidth.c
@@ -176,6 +176,120 @@ int mk_wcwidth(unsigned int ucs)
{ 0xE0100, 0xE01EF }
};
+ /* A sorted list of intervals of double-width characters generated by:
+ * https://raw.githubusercontent.com/GNOME/glib/37d4c2941bd0326b8b6e6bb22c81bd424fcc040b/glib/gen-unicode-tables.pl
+ * from the Unicode 9.0.0 data files available at:
+ * http://www.unicode.org/Public/9.0.0/ucd/
+ */
+ static const struct interval wide[] = {
+ {0x1100, 0x115F},
+ {0x231A, 0x231B},
+ {0x2329, 0x232A},
+ {0x23E9, 0x23EC},
+ {0x23F0, 0x23F0},
+ {0x23F3, 0x23F3},
+ {0x25FD, 0x25FE},
+ {0x2614, 0x2615},
+ {0x2648, 0x2653},
+ {0x267F, 0x267F},
+ {0x2693, 0x2693},
+ {0x26A1, 0x26A1},
+ {0x26AA, 0x26AB},
+ {0x26BD, 0x26BE},
+ {0x26C4, 0x26C5},
+ {0x26CE, 0x26CE},
+ {0x26D4, 0x26D4},
+ {0x26EA, 0x26EA},
+ {0x26F2, 0x26F3},
+ {0x26F5, 0x26F5},
+ {0x26FA, 0x26FA},
+ {0x26FD, 0x26FD},
+ {0x2705, 0x2705},
+ {0x270A, 0x270B},
+ {0x2728, 0x2728},
+ {0x274C, 0x274C},
+ {0x274E, 0x274E},
+ {0x2753, 0x2755},
+ {0x2757, 0x2757},
+ {0x2795, 0x2797},
+ {0x27B0, 0x27B0},
+ {0x27BF, 0x27BF},
+ {0x2B1B, 0x2B1C},
+ {0x2B50, 0x2B50},
+ {0x2B55, 0x2B55},
+ {0x2E80, 0x2E99},
+ {0x2E9B, 0x2EF3},
+ {0x2F00, 0x2FD5},
+ {0x2FF0, 0x2FFB},
+ {0x3000, 0x303E},
+ {0x3041, 0x3096},
+ {0x3099, 0x30FF},
+ {0x3105, 0x312D},
+ {0x3131, 0x318E},
+ {0x3190, 0x31BA},
+ {0x31C0, 0x31E3},
+ {0x31F0, 0x321E},
+ {0x3220, 0x3247},
+ {0x3250, 0x32FE},
+ {0x3300, 0x4DBF},
+ {0x4E00, 0xA48C},
+ {0xA490, 0xA4C6},
+ {0xA960, 0xA97C},
+ {0xAC00, 0xD7A3},
+ {0xF900, 0xFAFF},
+ {0xFE10, 0xFE19},
+ {0xFE30, 0xFE52},
+ {0xFE54, 0xFE66},
+ {0xFE68, 0xFE6B},
+ {0xFF01, 0xFF60},
+ {0xFFE0, 0xFFE6},
+ {0x16FE0, 0x16FE0},
+ {0x17000, 0x187EC},
+ {0x18800, 0x18AF2},
+ {0x1B000, 0x1B001},
+ {0x1F004, 0x1F004},
+ {0x1F0CF, 0x1F0CF},
+ {0x1F18E, 0x1F18E},
+ {0x1F191, 0x1F19A},
+ {0x1F200, 0x1F202},
+ {0x1F210, 0x1F23B},
+ {0x1F240, 0x1F248},
+ {0x1F250, 0x1F251},
+ {0x1F300, 0x1F320},
+ {0x1F32D, 0x1F335},
+ {0x1F337, 0x1F37C},
+ {0x1F37E, 0x1F393},
+ {0x1F3A0, 0x1F3CA},
+ {0x1F3CF, 0x1F3D3},
+ {0x1F3E0, 0x1F3F0},
+ {0x1F3F4, 0x1F3F4},
+ {0x1F3F8, 0x1F43E},
+ {0x1F440, 0x1F440},
+ {0x1F442, 0x1F4FC},
+ {0x1F4FF, 0x1F53D},
+ {0x1F54B, 0x1F54E},
+ {0x1F550, 0x1F567},
+ {0x1F57A, 0x1F57A},
+ {0x1F595, 0x1F596},
+ {0x1F5A4, 0x1F5A4},
+ {0x1F5FB, 0x1F64F},
+ {0x1F680, 0x1F6C5},
+ {0x1F6CC, 0x1F6CC},
+ {0x1F6D0, 0x1F6D2},
+ {0x1F6EB, 0x1F6EC},
+ {0x1F6F4, 0x1F6F6},
+ {0x1F910, 0x1F91E},
+ {0x1F920, 0x1F927},
+ {0x1F930, 0x1F930},
+ {0x1F933, 0x1F93E},
+ {0x1F940, 0x1F94B},
+ {0x1F950, 0x1F95E},
+ {0x1F980, 0x1F991},
+ {0x1F9C0, 0x1F9C0},
+ {0x20000, 0x2FFFD},
+ {0x30000, 0x3FFFD},
+ };
+
/* test for 8-bit control characters */
if (ucs == 0)
return 0;
@@ -189,20 +303,13 @@ int mk_wcwidth(unsigned int ucs)
/* if we arrive here, ucs is not a combining or C0/C1 control character */
- return 1 +
- (ucs >= 0x1100 &&
- (ucs <= 0x115f || /* Hangul Jamo init. consonants */
- ucs == 0x2329 || ucs == 0x232a ||
- (ucs >= 0x2e80 && ucs <= 0xa4cf &&
- ucs != 0x303f) || /* CJK ... Yi */
- (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
- (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
- (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
- (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
- (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
- (ucs >= 0xffe0 && ucs <= 0xffe6) ||
- (ucs >= 0x20000 && ucs <= 0x2fffd) ||
- (ucs >= 0x30000 && ucs <= 0x3fffd)));
+ /* binary search in table of double-width characters */
+ if (bisearch(ucs, wide,
+ sizeof(wide) / sizeof(struct interval) - 1))
+ return 2;
+
+ /* normal width character */
+ return 1;
}
@@ -231,61 +338,191 @@ int mk_wcswidth(const unsigned int *pwcs, size_t n)
*/
int mk_wcwidth_cjk(unsigned int ucs)
{
- /* sorted list of non-overlapping intervals of East Asian Ambiguous
- * characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
+ /* A sorted list of intervals of ambiguous width characters generated by:
+ * https://raw.githubusercontent.com/GNOME/glib/37d4c2941bd0326b8b6e6bb22c81bd424fcc040b/glib/gen-unicode-tables.pl
+ * from the Unicode 9.0.0 data files available at:
+ * http://www.unicode.org/Public/9.0.0/ucd/
+ */
static const struct interval ambiguous[] = {
- { 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 },
- { 0x00AA, 0x00AA }, { 0x00AE, 0x00AE }, { 0x00B0, 0x00B4 },
- { 0x00B6, 0x00BA }, { 0x00BC, 0x00BF }, { 0x00C6, 0x00C6 },
- { 0x00D0, 0x00D0 }, { 0x00D7, 0x00D8 }, { 0x00DE, 0x00E1 },
- { 0x00E6, 0x00E6 }, { 0x00E8, 0x00EA }, { 0x00EC, 0x00ED },
- { 0x00F0, 0x00F0 }, { 0x00F2, 0x00F3 }, { 0x00F7, 0x00FA },
- { 0x00FC, 0x00FC }, { 0x00FE, 0x00FE }, { 0x0101, 0x0101 },
- { 0x0111, 0x0111 }, { 0x0113, 0x0113 }, { 0x011B, 0x011B },
- { 0x0126, 0x0127 }, { 0x012B, 0x012B }, { 0x0131, 0x0133 },
- { 0x0138, 0x0138 }, { 0x013F, 0x0142 }, { 0x0144, 0x0144 },
- { 0x0148, 0x014B }, { 0x014D, 0x014D }, { 0x0152, 0x0153 },
- { 0x0166, 0x0167 }, { 0x016B, 0x016B }, { 0x01CE, 0x01CE },
- { 0x01D0, 0x01D0 }, { 0x01D2, 0x01D2 }, { 0x01D4, 0x01D4 },
- { 0x01D6, 0x01D6 }, { 0x01D8, 0x01D8 }, { 0x01DA, 0x01DA },
- { 0x01DC, 0x01DC }, { 0x0251, 0x0251 }, { 0x0261, 0x0261 },
- { 0x02C4, 0x02C4 }, { 0x02C7, 0x02C7 }, { 0x02C9, 0x02CB },
- { 0x02CD, 0x02CD }, { 0x02D0, 0x02D0 }, { 0x02D8, 0x02DB },
- { 0x02DD, 0x02DD }, { 0x02DF, 0x02DF }, { 0x0391, 0x03A1 },
- { 0x03A3, 0x03A9 }, { 0x03B1, 0x03C1 }, { 0x03C3, 0x03C9 },
- { 0x0401, 0x0401 }, { 0x0410, 0x044F }, { 0x0451, 0x0451 },
- { 0x2010, 0x2010 }, { 0x2013, 0x2016 }, { 0x2018, 0x2019 },
- { 0x201C, 0x201D }, { 0x2020, 0x2022 }, { 0x2024, 0x2027 },
- { 0x2030, 0x2030 }, { 0x2032, 0x2033 }, { 0x2035, 0x2035 },
- { 0x203B, 0x203B }, { 0x203E, 0x203E }, { 0x2074, 0x2074 },
- { 0x207F, 0x207F }, { 0x2081, 0x2084 }, { 0x20AC, 0x20AC },
- { 0x2103, 0x2103 }, { 0x2105, 0x2105 }, { 0x2109, 0x2109 },
- { 0x2113, 0x2113 }, { 0x2116, 0x2116 }, { 0x2121, 0x2122 },
- { 0x2126, 0x2126 }, { 0x212B, 0x212B }, { 0x2153, 0x2154 },
- { 0x215B, 0x215E }, { 0x2160, 0x216B }, { 0x2170, 0x2179 },
- { 0x2190, 0x2199 }, { 0x21B8, 0x21B9 }, { 0x21D2, 0x21D2 },
- { 0x21D4, 0x21D4 }, { 0x21E7, 0x21E7 }, { 0x2200, 0x2200 },
- { 0x2202, 0x2203 }, { 0x2207, 0x2208 }, { 0x220B, 0x220B },
- { 0x220F, 0x220F }, { 0x2211, 0x2211 }, { 0x2215, 0x2215 },
- { 0x221A, 0x221A }, { 0x221D, 0x2220 }, { 0x2223, 0x2223 },
- { 0x2225, 0x2225 }, { 0x2227, 0x222C }, { 0x222E, 0x222E },
- { 0x2234, 0x2237 }, { 0x223C, 0x223D }, { 0x2248, 0x2248 },
- { 0x224C, 0x224C }, { 0x2252, 0x2252 }, { 0x2260, 0x2261 },
- { 0x2264, 0x2267 }, { 0x226A, 0x226B }, { 0x226E, 0x226F },
- { 0x2282, 0x2283 }, { 0x2286, 0x2287 }, { 0x2295, 0x2295 },
- { 0x2299, 0x2299 }, { 0x22A5, 0x22A5 }, { 0x22BF, 0x22BF },
- { 0x2312, 0x2312 }, { 0x2460, 0x24E9 }, { 0x24EB, 0x254B },
- { 0x2550, 0x2573 }, { 0x2580, 0x258F }, { 0x2592, 0x2595 },
- { 0x25A0, 0x25A1 }, { 0x25A3, 0x25A9 }, { 0x25B2, 0x25B3 },
- { 0x25B6, 0x25B7 }, { 0x25BC, 0x25BD }, { 0x25C0, 0x25C1 },
- { 0x25C6, 0x25C8 }, { 0x25CB, 0x25CB }, { 0x25CE, 0x25D1 },
- { 0x25E2, 0x25E5 }, { 0x25EF, 0x25EF }, { 0x2605, 0x2606 },
- { 0x2609, 0x2609 }, { 0x260E, 0x260F }, { 0x2614, 0x2615 },
- { 0x261C, 0x261C }, { 0x261E, 0x261E }, { 0x2640, 0x2640 },
- { 0x2642, 0x2642 }, { 0x2660, 0x2661 }, { 0x2663, 0x2665 },
- { 0x2667, 0x266A }, { 0x266C, 0x266D }, { 0x266F, 0x266F },
- { 0x273D, 0x273D }, { 0x2776, 0x277F }, { 0xE000, 0xF8FF },
- { 0xFFFD, 0xFFFD }, { 0xF0000, 0xFFFFD }, { 0x100000, 0x10FFFD }
+ {0x00A1, 0x00A1},
+ {0x00A4, 0x00A4},
+ {0x00A7, 0x00A8},
+ {0x00AA, 0x00AA},
+ {0x00AD, 0x00AE},
+ {0x00B0, 0x00B4},
+ {0x00B6, 0x00BA},
+ {0x00BC, 0x00BF},
+ {0x00C6, 0x00C6},
+ {0x00D0, 0x00D0},
+ {0x00D7, 0x00D8},
+ {0x00DE, 0x00E1},
+ {0x00E6, 0x00E6},
+ {0x00E8, 0x00EA},
+ {0x00EC, 0x00ED},
+ {0x00F0, 0x00F0},
+ {0x00F2, 0x00F3},
+ {0x00F7, 0x00FA},
+ {0x00FC, 0x00FC},
+ {0x00FE, 0x00FE},
+ {0x0101, 0x0101},
+ {0x0111, 0x0111},
+ {0x0113, 0x0113},
+ {0x011B, 0x011B},
+ {0x0126, 0x0127},
+ {0x012B, 0x012B},
+ {0x0131, 0x0133},
+ {0x0138, 0x0138},
+ {0x013F, 0x0142},
+ {0x0144, 0x0144},
+ {0x0148, 0x014B},
+ {0x014D, 0x014D},
+ {0x0152, 0x0153},
+ {0x0166, 0x0167},
+ {0x016B, 0x016B},
+ {0x01CE, 0x01CE},
+ {0x01D0, 0x01D0},
+ {0x01D2, 0x01D2},
+ {0x01D4, 0x01D4},
+ {0x01D6, 0x01D6},
+ {0x01D8, 0x01D8},
+ {0x01DA, 0x01DA},
+ {0x01DC, 0x01DC},
+ {0x0251, 0x0251},
+ {0x0261, 0x0261},
+ {0x02C4, 0x02C4},
+ {0x02C7, 0x02C7},
+ {0x02C9, 0x02CB},
+ {0x02CD, 0x02CD},
+ {0x02D0, 0x02D0},
+ {0x02D8, 0x02DB},
+ {0x02DD, 0x02DD},
+ {0x02DF, 0x02DF},
+ {0x0300, 0x036F},
+ {0x0391, 0x03A1},
+ {0x03A3, 0x03A9},
+ {0x03B1, 0x03C1},
+ {0x03C3, 0x03C9},
+ {0x0401, 0x0401},
+ {0x0410, 0x044F},
+ {0x0451, 0x0451},
+ {0x2010, 0x2010},
+ {0x2013, 0x2016},
+ {0x2018, 0x2019},
+ {0x201C, 0x201D},
+ {0x2020, 0x2022},
+ {0x2024, 0x2027},
+ {0x2030, 0x2030},
+ {0x2032, 0x2033},
+ {0x2035, 0x2035},
+ {0x203B, 0x203B},
+ {0x203E, 0x203E},
+ {0x2074, 0x2074},
+ {0x207F, 0x207F},
+ {0x2081, 0x2084},
+ {0x20AC, 0x20AC},
+ {0x2103, 0x2103},
+ {0x2105, 0x2105},
+ {0x2109, 0x2109},
+ {0x2113, 0x2113},
+ {0x2116, 0x2116},
+ {0x2121, 0x2122},
+ {0x2126, 0x2126},
+ {0x212B, 0x212B},
+ {0x2153, 0x2154},
+ {0x215B, 0x215E},
+ {0x2160, 0x216B},
+ {0x2170, 0x2179},
+ {0x2189, 0x2189},
+ {0x2190, 0x2199},
+ {0x21B8, 0x21B9},
+ {0x21D2, 0x21D2},
+ {0x21D4, 0x21D4},
+ {0x21E7, 0x21E7},
+ {0x2200, 0x2200},
+ {0x2202, 0x2203},
+ {0x2207, 0x2208},
+ {0x220B, 0x220B},
+ {0x220F, 0x220F},
+ {0x2211, 0x2211},
+ {0x2215, 0x2215},
+ {0x221A, 0x221A},
+ {0x221D, 0x2220},
+ {0x2223, 0x2223},
+ {0x2225, 0x2225},
+ {0x2227, 0x222C},
+ {0x222E, 0x222E},
+ {0x2234, 0x2237},
+ {0x223C, 0x223D},
+ {0x2248, 0x2248},
+ {0x224C, 0x224C},
+ {0x2252, 0x2252},
+ {0x2260, 0x2261},
+ {0x2264, 0x2267},
+ {0x226A, 0x226B},
+ {0x226E, 0x226F},
+ {0x2282, 0x2283},
+ {0x2286, 0x2287},
+ {0x2295, 0x2295},
+ {0x2299, 0x2299},
+ {0x22A5, 0x22A5},
+ {0x22BF, 0x22BF},
+ {0x2312, 0x2312},
+ {0x2460, 0x24E9},
+ {0x24EB, 0x254B},
+ {0x2550, 0x2573},
+ {0x2580, 0x258F},
+ {0x2592, 0x2595},
+ {0x25A0, 0x25A1},
+ {0x25A3, 0x25A9},
+ {0x25B2, 0x25B3},
+ {0x25B6, 0x25B7},
+ {0x25BC, 0x25BD},
+ {0x25C0, 0x25C1},
+ {0x25C6, 0x25C8},
+ {0x25CB, 0x25CB},
+ {0x25CE, 0x25D1},
+ {0x25E2, 0x25E5},
+ {0x25EF, 0x25EF},
+ {0x2605, 0x2606},
+ {0x2609, 0x2609},
+ {0x260E, 0x260F},
+ {0x261C, 0x261C},
+ {0x261E, 0x261E},
+ {0x2640, 0x2640},
+ {0x2642, 0x2642},
+ {0x2660, 0x2661},
+ {0x2663, 0x2665},
+ {0x2667, 0x266A},
+ {0x266C, 0x266D},
+ {0x266F, 0x266F},
+ {0x269E, 0x269F},
+ {0x26BF, 0x26BF},
+ {0x26C6, 0x26CD},
+ {0x26CF, 0x26D3},
+ {0x26D5, 0x26E1},
+ {0x26E3, 0x26E3},
+ {0x26E8, 0x26E9},
+ {0x26EB, 0x26F1},
+ {0x26F4, 0x26F4},
+ {0x26F6, 0x26F9},
+ {0x26FB, 0x26FC},
+ {0x26FE, 0x26FF},
+ {0x273D, 0x273D},
+ {0x2776, 0x277F},
+ {0x2B56, 0x2B59},
+ {0x3248, 0x324F},
+ {0xE000, 0xF8FF},
+ {0xFE00, 0xFE0F},
+ {0xFFFD, 0xFFFD},
+ {0x1F100, 0x1F10A},
+ {0x1F110, 0x1F12D},
+ {0x1F130, 0x1F169},
+ {0x1F170, 0x1F18D},
+ {0x1F18F, 0x1F190},
+ {0x1F19B, 0x1F1AC},
+ {0xE0100, 0xE01EF},
+ {0xF0000, 0xFFFFD},
+ {0x100000, 0x10FFFD},
};
/* binary search in table of non-spacing characters */
From 4624115b76903b0b9ad97bee713afafcbd70a31c Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Mon, 3 Jul 2017 07:27:05 +0100
Subject: [PATCH 051/166] Make -DMINEFIELD show up in Windows buildinfo.
I listed a lot of other build options, but not that one. The release
checklist still recommends doing test builds with it, so it seems
sensible to arrange that you can tell if a build _is_ one of those or
not.
---
misc.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/misc.c b/misc.c
index 469e4aeb6..fc5b149dd 100644
--- a/misc.c
+++ b/misc.c
@@ -1214,6 +1214,9 @@ char *buildinfo(const char *newline)
}
#endif
+#if defined _WINDOWS && defined MINEFIELD
+ strbuf_catf(buf, "%sBuild option: MINEFIELD", newline);
+#endif
#ifdef NO_SECURITY
strbuf_catf(buf, "%sBuild option: NO_SECURITY", newline);
#endif
From ea0ab1c8218f28957b6e20dd84f9d2a3f19313e6 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Mon, 3 Jul 2017 07:19:07 +0100
Subject: [PATCH 052/166] Simplify running of release.pl --setver.
Previously, it demanded that your checkout was in a state where you
had run autoconf but not configure; so if you previously did have a
Makefile then you had to 'make distclean' to remove it, whereas if you
previously had no generated files at all (e.g. starting from a
completely clean checkout) then you had to run mkfiles.pl and
mkauto.sh to generate 'configure'.
This is obviously confusing, and moreover, the dependence on prior
generated files is fragile and prone to them having been generated
wrong. Adjusted the script so that it uses 'git archive' to get a
clean directory containing only the version-controlled files, and then
runs scripts itself to get that directory into the state it wants.
---
CHECKLST.txt | 1 -
release.pl | 7 +++++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/CHECKLST.txt b/CHECKLST.txt
index 8d55ac412..f757c5e0f 100644
--- a/CHECKLST.txt
+++ b/CHECKLST.txt
@@ -52,7 +52,6 @@ for it:
- Now update the version numbers and the transcripts in the docs, by
checking out the release branch and running
- make distclean
./release.pl --version=X.YZ --setver
Then check that the resulting automated git commit has updated the
diff --git a/release.pl b/release.pl
index cf73d9eb4..7c76c6ae6 100755
--- a/release.pl
+++ b/release.pl
@@ -31,8 +31,11 @@
0 == system "git", "diff-files", "--quiet" or die "working tree is dirty";
-f "Makefile" and die "run 'make distclean' first";
my $builddir = tempdir(DIR => ".", CLEANUP => 1);
- 0 == system "./mkfiles.pl" or die;
- 0 == system "cd $builddir && ../configure" or die;
+ 0 == system "git archive --format=tar HEAD | ( cd $builddir && tar xf - )"
+ or die;
+ 0 == system "cd $builddir && ./mkfiles.pl" or die;
+ 0 == system "cd $builddir && ./mkauto.sh" or die;
+ 0 == system "cd $builddir && ./configure" or die;
0 == system "cd $builddir && make pscp plink RELEASE=${version}" or die;
our $pscp_transcript = `cd $builddir && ./pscp --help`;
$pscp_transcript =~ s/^Unidentified build/Release ${version}/m or die;
From 5cac6013b702b014a063ed98ad91128308bc1b48 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Mon, 3 Jul 2017 07:38:20 +0100
Subject: [PATCH 053/166] Rework the release checklist for current practice.
In recent releases we've taken to making the actual release build (or
rather, candidates for it) ahead of time so that we can do some
slightly more thorough last-minute testing of the exact binaries that
we're going to release to everyone. It's time I actually wrote that
procedure down in the checklist, so that I remember what it is.
In particular, we had the idea that we should not properly GPG-sign
the release until the last moment, and use the presence of a set of
full GPG signatures as a means of distinguishing the real release
build from an RC that accidentally got out into the wild somehow. This
checklist update formalises that too, and documents the method I used
of ensuring the binaries weren't tampered with between RC building and
release signing (by making a signature on just the sha512sums). I also
include in this commit an extra command-line option to sign.sh to make
that preliminary signature step more convenient.
---
CHECKLST.txt | 104 +++++++++++++++++++++++++++++++--------------------
sign.sh | 43 ++++++++++++++++-----
2 files changed, 97 insertions(+), 50 deletions(-)
diff --git a/CHECKLST.txt b/CHECKLST.txt
index f757c5e0f..21f386562 100644
--- a/CHECKLST.txt
+++ b/CHECKLST.txt
@@ -24,25 +24,28 @@ pre-releases on the website:
add a news announcement in components/news. (Previous naming
convention has been to name it in the form 'X.YZ-pre.mi'.)
-Preparing to make a release
----------------------------
+Things to do during the branch-stabilisation period:
-Now that PuTTY is in git, a lot of the release preparation can be done
-in advance, in local checkouts, and not pushed until the actual
-process of _releasing_ it.
+ - Go through the source (including the documentation), and the
+ website, and review anything tagged with a comment containing the
+ word XXX-REVIEW-BEFORE-RELEASE. (Any such comments should state
+ clearly what needs to be done.)
-To begin with, before dropping the tag, make sure everything is ready
-for it:
+ - Do some testing of the Windows version with Minefield (you can
+ build a Minefield version using 'bob . XFLAGS=-DMINEFIELD'), and of
+ the Unix version with valgrind. In particular, any headline
+ features for the release should get a workout with memory checking
+ enabled!
- - First of all, go through the source (including the documentation),
- and the website, and review anything tagged with a comment
- containing the word XXX-REVIEW-BEFORE-RELEASE.
- (Any such comments should state clearly what needs to be done.)
+Making a release candidate build
+--------------------------------
- - Also, do some testing of the Windows version with Minefield, and
- of the Unix version with valgrind or efence or both. In
- particular, any headline features for the release should get a
- workout with memory checking enabled!
+ - Make a directory to hold all the release paraphernalia. I usually
+ call it ~/src/putty/X.YZ (where X.YZ will stand throughout for the
+ version number). In that directory, make a git clone of the PuTTY
+ repository, where you can make release-related commits and tags
+ tentatively, and keep them out of the way of any 'git push' you
+ might still be doing in other checkouts.
- Double-check that we have removed anything tagged with a comment
containing the words XXX-REMOVE-BEFORE-RELEASE or
@@ -50,7 +53,8 @@ for it:
hits in this file itself.)
- Now update the version numbers and the transcripts in the docs, by
- checking out the release branch and running
+ checking out the release branch in the release-specific checkout
+ and running
./release.pl --version=X.YZ --setver
@@ -71,6 +75,42 @@ for it:
- If the release is on a branch (which I expect it generally will
be), merge that branch to master.
+ - Make a release-candidate build from the release tag, and put the
+ build.out and build.log dfiles somewhere safe. Normally I store
+ these in an adjacent directory, so I'll run a command like
+ bob -o ../X.YZ/build-X.YZ-rcN.out -l ../X.YZ/build-X.YZ-rcN.log -c X.YZ . RELEASE=X.YZ
+ This should generate a basically valid release directory as
+ `build-X.YZ-rcN.out/putty', and provide link maps and sign.sh
+ alongside that.
+
+ - Double-check in build-X.YZ-rcN.log that the release was built from
+ the right git commit.
+
+ - Make a preliminary gpg signature, but don't run the full release-
+ signing procedure. (We use the presence of a full set of GPG
+ signatures to distinguish _abandoned_ release candidates from the
+ one that ended up being the release.) In the 'build.X.YZ-rcN.out'
+ directory, run
+ sh sign.sh -r -p putty
+ and you should only have to enter the release key passphrase once,
+ which will generate a clearsigned file called
+ sha512sums-preliminary.gpg _outside_ the 'putty' subdirectory.
+
+ - For my own safety, make the release candidate build read-only.
+ chmod -R a-w build-X.YZ-rcN.out build-X.YZ-rcN.log
+
+ - Now do some checking of the release binaries, and pass them to the
+ rest of the team to do some as well. Do at least these things:
+ * make sure they basically work
+ * check they report the right version number
+ * if there's any easily observable behaviour difference between
+ the release branch and master, arrange to observe it
+ * test the Windows installer
+ * test the Unix source tarball.
+
+Preparing to make the release
+-----------------------------
+
- Write a release announcement (basically a summary of the changes
since the last release). Squirrel it away in
thyestes:src/putty-local/announce- in case it's needed again
@@ -96,31 +136,15 @@ for it:
them as fixed in the new release), add appropriate Fixed-in
headers for those.
- - Make a release-candidate build from the release tag, and put the
- build.out and build.log dfiles somewhere safe. Normally I store
- these in an adjacent directory, so I'll run a command like
- bob -o ../X.YZ/build-X.YZ-rcN.out -l ../X.YZ/build-X.YZ-rcN.log -c X.YZ . RELEASE=X.YZ
- This should generate a basically valid release directory as
- `build-X.YZ-rcN.out/putty', and provide link maps and sign.sh
- alongside that.
-
- - Double-check in build-X.YZ-rcN.log that the release was built from
- the right git commit.
-
- - Do a bit of checking of the release binaries:
- * make sure they basically work
- * check they report the right version number
- * if there's any easily observable behaviour difference between
- the release branch and master, arrange to observe it
- * test the Windows installer
- * test the Unix source tarball.
-
- - Sign the release: in the `build-X.YZ-rcN.out' directory, type
+ - Sign the release in full. In the `build-X.YZ-rcN.out' directory,
+ re-verify that the preliminary signed checksums file has a correct
+ signature on it and also matches the files you're about to sign for real:
+ gpg -d sha512sums-preliminary.gpg | (cd putty; sha512sum -c)
+ If the combined output of that pipeline reports both a good
+ signature (from the release key) and a successful verification of
+ all the sha512sums, then all is well, so now run
sh sign.sh -r putty
- and enter the passphrases a lot of times.
-
- - For my own safety, make the release candidate build read-only.
- chmod -R a-w build-X.YZ-rcN.out build-X.YZ-rcN.log
+ and enter the release key passphrase a lot of times.
The actual release procedure
----------------------------
diff --git a/sign.sh b/sign.sh
index bdf6245ff..8dbdb6135 100755
--- a/sign.sh
+++ b/sign.sh
@@ -10,11 +10,27 @@
set -e
keyname=EEF20295D15F7E8A
+preliminary=false
-if test "x$1" = "x-r"; then
- shift
- keyname=9DFE2648B43434E4
-fi
+while :; do
+ case "$1" in
+ -r)
+ shift
+ keyname=9DFE2648B43434E4
+ ;;
+ -p)
+ shift
+ preliminary=true
+ ;;
+ -*)
+ echo "Unknown option '$1'" >&2
+ exit 1
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
sign() {
# Check for the prior existence of the signature, so we can
@@ -27,9 +43,16 @@ sign() {
cd "$1"
echo "===== Signing with key '$keyname'"
-for i in putty*src.zip putty*.tar.gz w32/*.exe w32/*.zip w32/*.msi w64/*.exe w64/*.zip w64/*.msi w32old/*.exe w32old/*.zip; do
- sign --detach-sign "$i" "$i.gpg"
-done
-for i in md5sums sha1sums sha256sums sha512sums; do
- sign --clearsign "$i" "$i.gpg"
-done
+if $preliminary; then
+ sign --clearsign sha512sums ../sha512sums-preliminary.gpg
+else
+ for i in putty*src.zip putty*.tar.gz \
+ w32/*.exe w32/*.zip w32/*.msi \
+ w64/*.exe w64/*.zip w64/*.msi \
+ w32old/*.exe w32old/*.zip; do
+ sign --detach-sign "$i" "$i.gpg"
+ done
+ for i in md5sums sha1sums sha256sums sha512sums; do
+ sign --clearsign "$i" "$i.gpg"
+ done
+fi
From a2b040ee094fcd43b4d53e14121c8c2301fba303 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Tue, 4 Jul 2017 19:35:18 +0100
Subject: [PATCH 054/166] Expand the About box.
It wasn't big enough to fit the full buildinfo text, when compiling
with clang-cl which has a bulky compiler identification string.
---
windows/win_res.rc2 | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/windows/win_res.rc2 b/windows/win_res.rc2
index 92d39cd5a..0c486ce51 100644
--- a/windows/win_res.rc2
+++ b/windows/win_res.rc2
@@ -16,15 +16,15 @@ IDI_MAINICON ICON "putty.ico"
IDI_CFGICON ICON "puttycfg.ico"
/* Accelerators used: clw */
-IDD_ABOUTBOX DIALOG DISCARDABLE 140, 40, 270, 106
+IDD_ABOUTBOX DIALOG DISCARDABLE 140, 40, 270, 136
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About PuTTY"
FONT 8, "MS Shell Dlg"
BEGIN
- DEFPUSHBUTTON "&Close", IDOK, 216, 88, 48, 14
- PUSHBUTTON "View &Licence", IDA_LICENCE, 6, 88, 70, 14
- PUSHBUTTON "Visit &Web Site", IDA_WEB, 140, 88, 70, 14
- EDITTEXT IDA_TEXT, 10, 6, 250, 80, ES_READONLY | ES_MULTILINE | ES_CENTER, WS_EX_STATICEDGE
+ DEFPUSHBUTTON "&Close", IDOK, 216, 118, 48, 14
+ PUSHBUTTON "View &Licence", IDA_LICENCE, 6, 118, 70, 14
+ PUSHBUTTON "Visit &Web Site", IDA_WEB, 140, 118, 70, 14
+ EDITTEXT IDA_TEXT, 10, 6, 250, 110, ES_READONLY | ES_MULTILINE | ES_CENTER, WS_EX_STATICEDGE
END
/* Accelerators used: aco */
From 3cd10509a51edf5a21cdc80aabf7e6a934522d47 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Tue, 4 Jul 2017 20:29:54 +0100
Subject: [PATCH 055/166] Update version number for 0.70 release.
---
Buildscr | 2 +-
LATEST.VER | 2 +-
doc/plink.but | 2 +-
doc/pscp.but | 2 +-
windows/putty.iss | 8 ++++----
5 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/Buildscr b/Buildscr
index ab94ea92f..8833a9c49 100644
--- a/Buildscr
+++ b/Buildscr
@@ -35,7 +35,7 @@ module putty
ifeq "$(RELEASE)" "" set Ndate $(!builddate)
ifneq "$(Ndate)" "" in . do echo $(Ndate) | perl -pe 's/(....)(..)(..)/$$1-$$2-$$3/' > date
ifneq "$(Ndate)" "" read Date date
-set Epoch 16280 # update this at every release
+set Epoch 16351 # update this at every release
ifneq "$(Ndate)" "" in . do echo $(Ndate) | perl -ne 'use Time::Local; /(....)(..)(..)/ and print timegm(0,0,0,$$3,$$2-1,$$1) / 86400 - $(Epoch)' > days
ifneq "$(Ndate)" "" read Days days
diff --git a/LATEST.VER b/LATEST.VER
index b04c64745..ac37bbeae 100644
--- a/LATEST.VER
+++ b/LATEST.VER
@@ -1 +1 @@
-0.69
+0.70
diff --git a/doc/plink.but b/doc/plink.but
index 153982e07..459ceadf2 100644
--- a/doc/plink.but
+++ b/doc/plink.but
@@ -41,7 +41,7 @@ use Plink:
\c Z:\sysosd>plink
\c Plink: command-line connection utility
-\c Release 0.69
+\c Release 0.70
\c Usage: plink [options] [user@]host [command]
\c ("host" can also be a PuTTY saved session name)
\c Options:
diff --git a/doc/pscp.but b/doc/pscp.but
index 30a47f83b..7b90810b5 100644
--- a/doc/pscp.but
+++ b/doc/pscp.but
@@ -39,7 +39,7 @@ use PSCP:
\c Z:\owendadmin>pscp
\c PuTTY Secure Copy client
-\c Release 0.69
+\c Release 0.70
\c Usage: pscp [options] [user@]host:source target
\c pscp [options] source [source...] [user@]host:target
\c pscp [options] -ls [user@]host:filespec
diff --git a/windows/putty.iss b/windows/putty.iss
index 3fadcb922..ae926310a 100644
--- a/windows/putty.iss
+++ b/windows/putty.iss
@@ -14,10 +14,10 @@
[Setup]
AppName=PuTTY
-AppVerName=PuTTY version 0.69
-VersionInfoTextVersion=Release 0.69
-AppVersion=0.69
-VersionInfoVersion=0.69.0.0
+AppVerName=PuTTY version 0.70
+VersionInfoTextVersion=Release 0.70
+AppVersion=0.70
+VersionInfoVersion=0.70.0.0
AppPublisher=Simon Tatham
AppPublisherURL=https://www.chiark.greenend.org.uk/~sgtatham/putty/
AppReadmeFile={app}\README.txt
From 7470e3bdaffc64260c0f786908682128b58c38c7 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sat, 8 Jul 2017 09:20:55 +0100
Subject: [PATCH 056/166] Stop release.pl --setver failing if Makefile exists.
This should have been part of commit ea0ab1c82; it's part of the
general revamp that we regenerate the autoconf files ourselves in a
clean directory - so we don't depend on them being present, but we
also don't depend on them being _absent_ either.
But when I made that commit my immediate priority was to get --setver
to work from a completely clean checkout, not from one already
littered with cruft, so I didn't check quite as carefully that my
changes fixed the problem in the latter case too :-)
---
release.pl | 1 -
1 file changed, 1 deletion(-)
diff --git a/release.pl b/release.pl
index 7c76c6ae6..da7d2a887 100755
--- a/release.pl
+++ b/release.pl
@@ -29,7 +29,6 @@
0 == system "git", "diff-index", "--quiet", "--cached", "HEAD"
or die "index is dirty";
0 == system "git", "diff-files", "--quiet" or die "working tree is dirty";
- -f "Makefile" and die "run 'make distclean' first";
my $builddir = tempdir(DIR => ".", CLEANUP => 1);
0 == system "git archive --format=tar HEAD | ( cd $builddir && tar xf - )"
or die;
From 0e2955ffbff083212d2a8a0d7fd829716f283081 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sat, 8 Jul 2017 09:23:51 +0100
Subject: [PATCH 057/166] Add a --no-ftp mode to the release.pl download
checks.
chiark's ftp server sometimes randomly refuses downloads. In the case
where this happens at postcheck time, this isn't really
release-blocking (all the files have been test-downloaded by precheck
already, so the main aim at this stage is to check that the 'latest'
symlink points to the right place, and even one or two successful
downloads are good enough to confirm that in practice). So now I can
add --no-ftp to the postcheck command line if that makes my life
easier.
---
release.pl | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/release.pl b/release.pl
index da7d2a887..b5ad149c3 100755
--- a/release.pl
+++ b/release.pl
@@ -15,11 +15,13 @@
my $upload = 0;
my $precheck = 0;
my $postcheck = 0;
+my $skip_ftp = 0;
GetOptions("version=s" => \$version,
"setver" => \$setver,
"upload" => \$upload,
"precheck" => \$precheck,
- "postcheck" => \$postcheck)
+ "postcheck" => \$postcheck,
+ "no-ftp" => \$skip_ftp)
or &usage();
# --set-version: construct a local commit which updates the version
@@ -163,11 +165,13 @@
}
# Now test-download the files themselves.
- my $ftpdata = `curl -s $ftp_uri`;
- printf " got %d bytes via FTP", length $ftpdata;
- die "FTP download for $ftp_uri did not match"
- if $ftpdata ne $real_content;
- print ", ok\n";
+ unless ($skip_ftp) {
+ my $ftpdata = `curl -s $ftp_uri`;
+ printf " got %d bytes via FTP", length $ftpdata;
+ die "FTP download for $ftp_uri did not match"
+ if $ftpdata ne $real_content;
+ print ", ok\n";
+ }
my $ua = LWP::UserAgent->new;
my $httpresponse = $ua->get($http_uri);
From 309c3dfd95505f1bf1e4b4d488a5f03f0cf24b3b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?=
Date: Thu, 6 Jul 2017 10:18:27 +0200
Subject: [PATCH 058/166] Add -share -noshare command line option to plink to
share SSL connections.
---
cmdline.c | 13 ++++++++++++-
doc/man-pl.but | 9 +++++++++
doc/plink.but | 24 ++++++++++++++++++++++++
unix/uxplink.c | 2 ++
windows/winplink.c | 2 ++
5 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/cmdline.c b/cmdline.c
index f288ed629..d2a815928 100644
--- a/cmdline.c
+++ b/cmdline.c
@@ -403,7 +403,18 @@ int cmdline_process_param(const char *p, char *value,
SAVEABLE(0);
conf_set_int(conf, CONF_tryagent, FALSE);
}
-
+ if (!strcmp(p, "-share")) {
+ RETURN(1);
+ UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
+ SAVEABLE(0);
+ conf_set_int(conf, CONF_ssh_connection_sharing, TRUE);
+ }
+ if (!strcmp(p, "-noshare")) {
+ RETURN(1);
+ UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
+ SAVEABLE(0);
+ conf_set_int(conf, CONF_ssh_connection_sharing, FALSE);
+ }
if (!strcmp(p, "-A")) {
RETURN(1);
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
diff --git a/doc/man-pl.but b/doc/man-pl.but
index 9f4118719..58ca7a289 100644
--- a/doc/man-pl.but
+++ b/doc/man-pl.but
@@ -182,6 +182,15 @@ which of the agent's keys to use. }
\dd Allow use of an authentication agent. (This option is only necessary
to override a setting in a saved session.)
+\dt \cw{\-noshare}
+
+\dd Don't test and try to share an existing connection, always make
+a new connection.
+
+\dt \cw{\-share}
+
+\dd Test and try to share an existing connection.
+
\dt \cw{\-hostkey} \e{key}
\dd Specify an acceptable host public key. This option may be specified
diff --git a/doc/plink.but b/doc/plink.but
index 459ceadf2..74da18a1a 100644
--- a/doc/plink.but
+++ b/doc/plink.but
@@ -75,6 +75,8 @@ use Plink:
\c -i key private key file for user authentication
\c -noagent disable use of Pageant
\c -agent enable use of Pageant
+\c -noshare disable use of connection sharing
+\c -share enable use of connection sharing
\c -hostkey aa:bb:cc:...
\c manually specify a host key (may be repeated)
\c -m file read remote command(s) from file
@@ -237,6 +239,28 @@ line.
(This option is only meaningful with the SSH-2 protocol.)
+\S2{plink-option-share} \I{-share-plink}\c{-share}:
+Test and try to share an existing connection.
+
+This option tris to detect if an existing connection can be shared
+(See \k{config-ssh-sharing} for more information about SSH connection
+sharing.) and reuses that connection.
+
+A Plink invocation of the form:
+
+\c plink -share
+\e iiiiiiiii
+
+will test whether there is currently a viable \q{upstream} for the
+session in question, which can be specified using any syntax you'd
+normally use with Plink to make an actual connection (a host/port
+number, a bare saved session name, \c{-load}, etc). If no \q{upstream}
+viable session is found and \c{-share} is specified, this connection
+will be become the \q{upstream} connection for subsequent connection
+sharing tries.
+
+(This option is only meaningful with the SSH-2 protocol.)
+
\S2{plink-option-shareexists} \I{-shareexists-plink}\c{-shareexists}:
test for connection-sharing upstream
diff --git a/unix/uxplink.c b/unix/uxplink.c
index e891d66a8..2a1926efc 100644
--- a/unix/uxplink.c
+++ b/unix/uxplink.c
@@ -579,6 +579,8 @@ static void usage(void)
printf(" -i key private key file for user authentication\n");
printf(" -noagent disable use of Pageant\n");
printf(" -agent enable use of Pageant\n");
+ printf(" -noshare disable use of connection sharing\n");
+ printf(" -share enable use of connection sharing\n");
printf(" -hostkey aa:bb:cc:...\n");
printf(" manually specify a host key (may be repeated)\n");
printf(" -m file read remote command(s) from file\n");
diff --git a/windows/winplink.c b/windows/winplink.c
index ea4175012..84e47d6ec 100644
--- a/windows/winplink.c
+++ b/windows/winplink.c
@@ -207,6 +207,8 @@ static void usage(void)
printf(" -i key private key file for user authentication\n");
printf(" -noagent disable use of Pageant\n");
printf(" -agent enable use of Pageant\n");
+ printf(" -noshare disable use of connection sharing\n");
+ printf(" -share enable use of connection sharing\n");
printf(" -hostkey aa:bb:cc:...\n");
printf(" manually specify a host key (may be repeated)\n");
printf(" -m file read remote command(s) from file\n");
From 25683f0f3d5a654c1e2a8e1d43dca3778a77e7de Mon Sep 17 00:00:00 2001
From: Jacob Nevins
Date: Wed, 12 Jul 2017 10:19:23 +0100
Subject: [PATCH 059/166] Add a FAQ about servers that don't like IUTF8.
---
doc/faq.but | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/doc/faq.but b/doc/faq.but
index cd3254a8b..4d9e14a93 100644
--- a/doc/faq.but
+++ b/doc/faq.but
@@ -1002,6 +1002,26 @@ appropriate kind of binaries in \cw{SYSTEM32}. Thus, operations in
the PuTTY suite that involve it accessing its own executables, such as
\i{\q{New Session}} and \q{Duplicate Session}, will not work.
+\S{faq-iutf8}{Question} After I upgraded PuTTY to 0.68, I can no longer
+connect to my embedded device or appliance.
+
+If your SSH server has started unexpectedly closing SSH connections
+after you enter your password, and it worked before 0.68, you may have
+a buggy server that objects to certain SSH protocol extensions.
+
+The SSH protocol recently gained a new \q{terminal mode}, \cw{IUTF8},
+which PuTTY sends by default; see \k{config-ttymodes}. This is the
+first new terminal mode since the SSH-2 protocol was defined. While
+servers are supposed to ignore modes they don't know about, some buggy
+servers will unceremoniously close the connection if they see anything
+they don't recognise. SSH servers in embedded devices, network
+appliances, and the like seem to disproportionately have this bug.
+
+If you think you have such a server, from 0.69 onwards you can disable
+sending of the \cw{IUTF8} mode: on the SSH / TTY panel, select
+\cw{IUTF8} on the list, select \q{Nothing}, and press \q{Set}. (It's
+not possible to disable sending this mode in 0.68.)
+
\H{faq-secure} Security questions
\S{faq-publicpc}{Question} Is it safe for me to download PuTTY and
From f0126dd198358f2ae351bc49e8edf056c3ce2c6e Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Mon, 17 Jul 2017 20:57:07 +0100
Subject: [PATCH 060/166] Set ssh->mainchan->type earlier.
A user reported a nonsensical assertion failure (claiming that
ssh->version != 2) which suggested that a channel had somehow outlived
its parent Ssh in the situation where the opening of the main session
channel is rejected by the server. Checking with valgrind suggested
that things start to go wrong at the point where we free the half-set-
up ssh->mainchan before having filled in its type field, so that the
switch in ssh_channel_close_local() picks an arbitrary wrong action.
I haven't reproduced the same failure the user reported, but with this
change, Unix plink is now valgrind-clean in that failure situation.
---
ssh.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ssh.c b/ssh.c
index 1d80e9194..89041f487 100644
--- a/ssh.c
+++ b/ssh.c
@@ -10722,6 +10722,7 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
} else {
ssh->mainchan = snew(struct ssh_channel);
ssh->mainchan->ssh = ssh;
+ ssh->mainchan->type = CHAN_MAINSESSION;
ssh_channel_init(ssh->mainchan);
if (*conf_get_str(ssh->conf, CONF_ssh_nc_host)) {
@@ -10761,7 +10762,6 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
ssh->mainchan->remoteid = ssh_pkt_getuint32(pktin);
ssh->mainchan->halfopen = FALSE;
- ssh->mainchan->type = CHAN_MAINSESSION;
ssh->mainchan->v.v2.remwindow = ssh_pkt_getuint32(pktin);
ssh->mainchan->v.v2.remmaxpkt = ssh_pkt_getuint32(pktin);
update_specials_menu(ssh->frontend);
From 0a93b5d9bc6131c0cd84395f4aa88cac0cb40f23 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Wed, 19 Jul 2017 07:22:03 +0100
Subject: [PATCH 061/166] Stop ssh2_msg_channel_response using a stale
ssh_channel.
When it calls through ocr->handler() to process the response to a
channel request, sometimes that call ends up back in the main SSH-2
authconn coroutine, and sometimes _that_ will call bomb_out(), which
closes the whole SSH connection and frees all the channels - so that
when control returns back up the call stack to
ssh2_msg_channel_response itself which continues working with the
channel it was passed, it's using freed memory and things go badly.
This is the sort of thing I'd _like_ to fix using some kind of
large-scale refactoring along the lines of moving all the actual
free() calls out into top-level callbacks, so that _any_ function
which is holding a pointer to something can rely on that pointer still
being valid after it calls a subroutine. But I haven't worked out all
the details of how that system should work, and doubtless it will turn
out to have problems of its own once I do, so here's a point fix which
simply checks if the whole SSH session has been closed (which is easy
- much easier than checking if that _channel_ structure still exists)
and fixes the immediate bug.
(I think this is the real fix for the problem reported by the user I
mention in commit f0126dd19, because I actually got the details wrong
in the log message for that previous commit: the user's SSH server
wasn't rejecting the _opening_ of the main session channel, it was
rejecting the "shell" channel request, so this code path was the one
being exercised. Still, the other bug was real too, so no harm done!)
---
ssh.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/ssh.c b/ssh.c
index 89041f487..aa9fd5dd9 100644
--- a/ssh.c
+++ b/ssh.c
@@ -8105,6 +8105,8 @@ static void ssh2_msg_channel_response(Ssh ssh, struct Packet *pktin)
return;
}
ocr->handler(c, pktin, ocr->ctx);
+ if (ssh->state == SSH_STATE_CLOSED)
+ return; /* in case the handler called bomb_out(), which some can */
c->v.v2.chanreq_head = ocr->next;
sfree(ocr);
/*
From 55efbc56a0f482d237b2315efac42c2f3301d986 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Fri, 4 Aug 2017 19:46:21 +0100
Subject: [PATCH 062/166] Fix filename of the 64-bit MIT Kerberos DLL.
64-bit PuTTY should be loading gssapi64.dll, not gssapi32.dll. (In
contrast to the Windows system API DLLs, such as secur32.dll which is
also mentioned in the same source file; those keep the "32" in their
name whether we're in Win32 or Win64.)
---
windows/wingss.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/windows/wingss.c b/windows/wingss.c
index ef0561671..54b1e477e 100644
--- a/windows/wingss.c
+++ b/windows/wingss.c
@@ -13,9 +13,15 @@
/* Windows code to set up the GSSAPI library list. */
+#ifdef _WIN64
+#define MIT_KERB_SUFFIX "64"
+#else
+#define MIT_KERB_SUFFIX "32"
+#endif
+
const int ngsslibs = 3;
const char *const gsslibnames[3] = {
- "MIT Kerberos GSSAPI32.DLL",
+ "MIT Kerberos GSSAPI"MIT_KERB_SUFFIX".DLL",
"Microsoft SSPI SECUR32.DLL",
"User-specified GSSAPI DLL",
};
@@ -90,7 +96,6 @@ struct ssh_gss_liblist *ssh_gss_setup(Conf *conf)
list->nlibraries = 0;
/* MIT Kerberos GSSAPI implementation */
- /* TODO: For 64-bit builds, check for gssapi64.dll */
module = NULL;
if (RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\MIT\\Kerberos", ®key)
== ERROR_SUCCESS) {
@@ -115,7 +120,7 @@ struct ssh_gss_liblist *ssh_gss_setup(Conf *conf)
p_AddDllDirectory(dllPath);
sfree(dllPath);
}
- strcat (buffer, "\\gssapi32.dll");
+ strcat (buffer, "\\gssapi"MIT_KERB_SUFFIX".dll");
module = LoadLibraryEx (buffer, NULL,
LOAD_LIBRARY_SEARCH_SYSTEM32 |
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR |
@@ -130,7 +135,7 @@ struct ssh_gss_liblist *ssh_gss_setup(Conf *conf)
&list->libraries[list->nlibraries++];
lib->id = 0;
- lib->gsslogmsg = "Using GSSAPI from GSSAPI32.DLL";
+ lib->gsslogmsg = "Using GSSAPI from GSSAPI"MIT_KERB_SUFFIX".DLL";
lib->handle = (void *)module;
#define BIND_GSS_FN(name) \
From a459fc58e844a2152cedb068d5b552bd3aabd654 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sat, 26 Aug 2017 15:23:56 +0100
Subject: [PATCH 063/166] Switch to producing .res files, not .res.o.
I've just upgraded my build process to a version of lld-link
that knows how to read .res, and I think it's a slightly more
commonly found format, so less confusing to encounter.
---
mkfiles.pl | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/mkfiles.pl b/mkfiles.pl
index 1d83912bd..02421316e 100755
--- a/mkfiles.pl
+++ b/mkfiles.pl
@@ -556,10 +556,10 @@ sub manpages {
print "\n\n";
foreach $p (&prognames("G:C")) {
($prog, $type) = split ",", $p;
- $objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res.o", undef);
+ $objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", undef);
print &splitline("\$(BUILDDIR)$prog.exe: " . $objstr), "\n";
- $objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res.o", "X.lib");
+ $objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", "X.lib");
$subsys = ($type eq "G") ? "windows" : "console";
print &splitline("\t\$(LD) \$(LFLAGS) \$(XLFLAGS) ".
"/out:\$(BUILDDIR)$prog.exe ".
@@ -567,11 +567,11 @@ sub manpages {
"/subsystem:$subsys\$(SUBSYSVER) ".
"\$(EXTRA_$subsys) $objstr")."\n\n";
}
- foreach $d (&deps("\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res.o", $dirpfx, "/", "vc")) {
+ foreach $d (&deps("\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", $dirpfx, "/", "vc")) {
$extradeps = $forceobj{$d->{obj_orig}} ? ["*.c","*.h","*.rc"] : [];
print &splitline(sprintf("%s: %s", $d->{obj},
join " ", @$extradeps, @{$d->{deps}})), "\n";
- if ($d->{obj} =~ /\.res\.o$/) {
+ if ($d->{obj} =~ /\.res$/) {
print "\t\$(RC) \$(RCFLAGS) ".$d->{deps}->[0]." -o ".$d->{obj}."\n\n";
} else {
print "\t\$(CC) /Fo\$(BUILDDIR) \$(COMPAT) \$(CFLAGS) \$(XFLAGS) /c \$<\n\n";
@@ -581,7 +581,7 @@ sub manpages {
print &def($makefile_extra{'clangcl'}->{'end'});
print "\nclean:\n".
&splitline("\trm -f \$(BUILDDIR)*.obj \$(BUILDDIR)*.exe ".
- "\$(BUILDDIR)*.res.o \$(BUILDDIR)*.map ".
+ "\$(BUILDDIR)*.res \$(BUILDDIR)*.map ".
"\$(BUILDDIR)*.exe.manifest")."\n";
select STDOUT; close OUT;
}
From 4634cd47f75e74a697840fb32f18edb7f1cf41da Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Tue, 5 Sep 2017 20:14:33 +0100
Subject: [PATCH 064/166] Avoid zero-length ldisc_send() in terminal.c.
A user reports that a remote window title query, if the window title
is empty or if the option to return it is disabled, fails the
assertion in ldisc_send that I introduced as part of commit c269dd013
to catch any lingering uses of ldisc_send with length 0 that should
have turned into ldisc_echoedit_update. Added a check for len > 0
guarding that ldisc_send call, and likewise at one or two others I
noticed on my way here.
(Probably at some point I should decide that the period of smoking out
lingering old-style ldisc_send(0) calls is over, and declare it safe
to remove that assertion again and get rid of all the cumbersome
safety checks at call sites like these ones. But not quite yet.)
---
terminal.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/terminal.c b/terminal.c
index ba9dd6172..f7bcbb957 100644
--- a/terminal.c
+++ b/terminal.c
@@ -3355,7 +3355,7 @@ static void term_out(Terminal *term)
break;
case 'Z': /* DECID: terminal type query */
compatibility(VT100);
- if (term->ldisc)
+ if (term->ldisc && term->id_string[0])
ldisc_send(term->ldisc, term->id_string,
strlen(term->id_string), 0);
break;
@@ -3662,7 +3662,7 @@ static void term_out(Terminal *term)
case 'c': /* DA: terminal type query */
compatibility(VT100);
/* This is the response for a VT102 */
- if (term->ldisc)
+ if (term->ldisc && term->id_string[0])
ldisc_send(term->ldisc, term->id_string,
strlen(term->id_string), 0);
break;
@@ -4069,7 +4069,8 @@ static void term_out(Terminal *term)
p = EMPTY_WINDOW_TITLE;
len = strlen(p);
ldisc_send(term->ldisc, "\033]L", 3, 0);
- ldisc_send(term->ldisc, p, len, 0);
+ if (len > 0)
+ ldisc_send(term->ldisc, p, len, 0);
ldisc_send(term->ldisc, "\033\\", 2, 0);
}
break;
@@ -4082,7 +4083,8 @@ static void term_out(Terminal *term)
p = EMPTY_WINDOW_TITLE;
len = strlen(p);
ldisc_send(term->ldisc, "\033]l", 3, 0);
- ldisc_send(term->ldisc, p, len, 0);
+ if (len > 0)
+ ldisc_send(term->ldisc, p, len, 0);
ldisc_send(term->ldisc, "\033\\", 2, 0);
}
break;
From 4ec27919454102386f18d24df188cac3f663dbdc Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Wed, 13 Sep 2017 19:24:17 +0100
Subject: [PATCH 065/166] Remove Makefile.bor.
After a conversation this week with a user who tried to use it, it's
clear that Borland C can't build the up-to-date PuTTY without having
to make too many compromises of functionality (unsupported API
details, no 'long long' type), even above the issues that could be
worked round with extra porting ifdefs.
---
.gitignore | 2 -
README | 4 --
Recipe | 1 -
doc/udp.but | 6 +--
mkfiles.pl | 117 +---------------------------------------------
windows/rcstuff.h | 2 +-
6 files changed, 5 insertions(+), 127 deletions(-)
diff --git a/.gitignore b/.gitignore
index 15c253c24..c04f119b7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,7 +19,6 @@
/*.tds
/*.td2
/*.map
-/Makefile.bor
/Makefile.mgw
/Makefile.vc
/Makefile.lcc
@@ -128,7 +127,6 @@
/windows/*.td2
/windows/*.map
/windows/Makefile.clangcl
-/windows/Makefile.bor
/windows/Makefile.mgw
/windows/Makefile.vc
/windows/Makefile.lcc
diff --git a/README b/README
index 50314ca63..de6eb9b06 100644
--- a/README
+++ b/README
@@ -34,10 +34,6 @@ For building on Windows:
MSVC/putty/putty.dsp builds PuTTY itself, MSVC/plink/plink.dsp
builds Plink, and so on.
- - windows/Makefile.bor is for the Borland C compiler. Type `make -f
- Makefile.bor' while in the `windows' subdirectory to build all
- the PuTTY binaries.
-
- windows/Makefile.mgw is for MinGW / Cygwin installations. Type
`make -f Makefile.mgw' while in the `windows' subdirectory to
build all the PuTTY binaries.
diff --git a/Recipe b/Recipe
index f54581223..5715938b0 100644
--- a/Recipe
+++ b/Recipe
@@ -16,7 +16,6 @@
!makefile vc windows/Makefile.vc
!makefile vcproj windows/MSVC
!makefile cygwin windows/Makefile.mgw
-!makefile borland windows/Makefile.bor
!makefile lcc windows/Makefile.lcc
!makefile gtk unix/Makefile.gtk
!makefile unix unix/Makefile.ux
diff --git a/doc/udp.but b/doc/udp.but
index 9ca8ed3f8..b71688b7e 100644
--- a/doc/udp.but
+++ b/doc/udp.but
@@ -138,9 +138,9 @@ construct. Use these wherever possible.
\H{udp-multi-compiler} Independence of specific compiler
-Windows PuTTY can currently be compiled with any of four Windows
-compilers: MS Visual C, Borland's freely downloadable C compiler,
-the Cygwin / \cw{mingw32} GNU tools, and \cw{lcc-win32}.
+Windows PuTTY can currently be compiled with any of three Windows
+compilers: MS Visual C, the Cygwin / \cw{mingw32} GNU tools, and
+\cw{clang} (in MS compatibility mode).
This is a really useful property of PuTTY, because it means people
who want to contribute to the coding don't depend on having a
diff --git a/mkfiles.pl b/mkfiles.pl
index 02421316e..6765f2a86 100755
--- a/mkfiles.pl
+++ b/mkfiles.pl
@@ -268,7 +268,7 @@ ($)
# Returns true if the argument is a known makefile type. Otherwise,
# prints a warning and returns false;
if (grep { $type eq $_ }
- ("vc","vcproj","cygwin","borland","lcc","devcppproj","gtk","unix",
+ ("vc","vcproj","cygwin","lcc","devcppproj","gtk","unix",
"am","osx","vstudio10","vstudio12","clangcl")) {
return 1;
}
@@ -659,121 +659,6 @@ sub manpages {
}
-##-- Borland makefile
-if (defined $makefiles{'borland'}) {
- $dirpfx = &dirpfx($makefiles{'borland'}, "\\");
-
- %stdlibs = ( # Borland provides many Win32 API libraries intrinsically
- "advapi32" => 1,
- "comctl32" => 1,
- "comdlg32" => 1,
- "gdi32" => 1,
- "imm32" => 1,
- "shell32" => 1,
- "user32" => 1,
- "winmm" => 1,
- "winspool" => 1,
- "wsock32" => 1,
- );
- open OUT, ">$makefiles{'borland'}"; select OUT;
- print
- "# Makefile for $project_name under Borland C.\n".
- "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n".
- "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n";
- # bcc32 command line option is -D not /D
- ($_ = $help) =~ s/([=" ])\/D/$1-D/gs;
- print $_;
- print
- "\n".
- "# If you rename this file to `Makefile', you should change this line,\n".
- "# so that the .rsp files still depend on the correct makefile.\n".
- "MAKEFILE = Makefile.bor\n".
- "\n".
- "# C compilation flags\n".
- "CFLAGS = -D_WINDOWS -DWINVER=0x0500\n".
- "# Resource compilation flags\n".
- "RCFLAGS = -DNO_WINRESRC_H -DWIN32 -D_WIN32 -DWINVER=0x0401\n".
- "\n".
- "# Get include directory for resource compiler\n".
- "!if !\$d(BCB)\n".
- "BCB = \$(MAKEDIR)\\..\n".
- "!endif\n".
- "\n".
- &def($makefile_extra{'borland'}->{'vars'}) .
- "\n".
- ".c.obj:\n".
- &splitline("\tbcc32 -w-aus -w-ccc -w-par -w-pia \$(COMPAT)".
- " \$(CFLAGS) \$(XFLAGS) ".
- (join " ", map {"-I$dirpfx$_"} @srcdirs) .
- " /c \$*.c",69)."\n".
- ".rc.res:\n".
- &splitline("\tbrcc32 \$(RCFL) -i \$(BCB)\\include -r".
- " \$(RCFLAGS) \$*.rc",69)."\n".
- "\n";
- print &splitline("all:" . join "", map { " $_.exe" } &progrealnames("G:C"));
- print "\n\n";
- foreach $p (&prognames("G:C")) {
- ($prog, $type) = split ",", $p;
- $objstr = &objects($p, "X.obj", "X.res", undef);
- print &splitline("$prog.exe: " . $objstr . " $prog.rsp"), "\n";
- my $ap = ($type eq "G") ? "-aa" : "-ap";
- print "\tilink32 $ap -Gn -L\$(BCB)\\lib \@$prog.rsp\n\n";
- }
- foreach $p (&prognames("G:C")) {
- ($prog, $type) = split ",", $p;
- print $prog, ".rsp: \$(MAKEFILE)\n";
- $objstr = &objects($p, "X.obj", undef, undef);
- @objlist = split " ", $objstr;
- @objlines = ("");
- foreach $i (@objlist) {
- if (length($objlines[$#objlines] . " $i") > 50) {
- push @objlines, "";
- }
- $objlines[$#objlines] .= " $i";
- }
- $c0w = ($type eq "G") ? "c0w32" : "c0x32";
- print "\techo $c0w + > $prog.rsp\n";
- for ($i=0; $i<=$#objlines; $i++) {
- $plus = ($i < $#objlines ? " +" : "");
- print "\techo$objlines[$i]$plus >> $prog.rsp\n";
- }
- print "\techo $prog.exe >> $prog.rsp\n";
- $objstr = &objects($p, "X.obj", "X.res", undef);
- @libs = split " ", &objects($p, undef, undef, "X");
- @libs = grep { !$stdlibs{$_} } @libs;
- unshift @libs, "cw32", "import32";
- $libstr = join ' ', @libs;
- print "\techo nul,$libstr, >> $prog.rsp\n";
- print "\techo " . &objects($p, undef, "X.res", undef) . " >> $prog.rsp\n";
- print "\n";
- }
- foreach $d (&deps("X.obj", "X.res", $dirpfx, "\\", "borland")) {
- if ($forceobj{$d->{obj_orig}}) {
- printf("%s: FORCE\n", $d->{obj});
- } else {
- print &splitline(sprintf("%s: %s", $d->{obj},
- join " ", @{$d->{deps}})), "\n";
- }
- }
- print "\n";
- print &def($makefile_extra{'borland'}->{'end'});
- print "\nclean:\n".
- "\t-del *.obj\n".
- "\t-del *.exe\n".
- "\t-del *.res\n".
- "\t-del *.pch\n".
- "\t-del *.aps\n".
- "\t-del *.il*\n".
- "\t-del *.pdb\n".
- "\t-del *.rsp\n".
- "\t-del *.tds\n".
- "\t-del *.\$\$\$\$\$\$\n".
- "\n".
- "FORCE:\n".
- "\t-rem dummy command\n";
- select STDOUT; close OUT;
-}
-
if (defined $makefiles{'vc'}) {
$dirpfx = &dirpfx($makefiles{'vc'}, "\\");
diff --git a/windows/rcstuff.h b/windows/rcstuff.h
index 22b220358..ee2c76964 100644
--- a/windows/rcstuff.h
+++ b/windows/rcstuff.h
@@ -9,7 +9,7 @@
#include
#else
-/* Some compilers, like Borland, don't have winresrc.h */
+/* Some compilers don't have winresrc.h */
#ifndef NO_WINRESRC_H
#ifndef MSVC4
#include
From ba4837dae819cffffe36fd6c0985d8df10d2873c Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Wed, 20 Sep 2017 18:04:37 +0100
Subject: [PATCH 066/166] Add a -restrict-putty-acl option to Windows Pageant.
This causes PuTTY processes spawned from its system-tray menu to run
with the -restrict-acl option (or rather, the synonymous &R prefix
used by my auto-constructed command lines for easier parsing).
The previous behaviour of Pageant was never to pass -restrict-acl to
PuTTY, even when started with -restrict-acl itself; this is not
actually a silly thing to want to do, because Pageant might well have
more need of -restrict-acl than PuTTY (it stores longer-term and more
powerful secrets) and conversely PuTTY might have more need to _not_
restrict its ACL than Pageant (in that among the things enabled by an
unrestricted ACL are various kinds of accessibility software, which is
more useful on the more user-facing PuTTY than on Pageant).
But for those who want to lock everything down with every security
option possible (even though -restrict-acl is only an ad-hoc
precaution and cannot deliver any hard guarantees), this new option
should fill in the UI gap.
---
doc/using.but | 12 ++++++++++++
windows/winpgnt.c | 26 ++++++++++++++++++++------
2 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/doc/using.but b/doc/using.but
index 7d184b7c2..f5e3b57bd 100644
--- a/doc/using.but
+++ b/doc/using.but
@@ -1042,3 +1042,15 @@ any processes started with Duplicate Session, New Session etc.
(However, if you're invoking PuTTY tools explicitly, for instance as a
proxy command, you'll need to arrange to pass them the
\c{-restrict-acl} option yourself, if that's what you want.)
+
+If Pageant is started with the \c{-restrict-acl} option, and you use
+it to launch a PuTTY session from its System Tray submenu, then
+Pageant will \e{not} default to starting the PuTTY subprocess with a
+restricted ACL. This is because PuTTY is more likely to suffer reduced
+functionality as a result of restricted ACLs (e.g. screen reader
+software will have a greater need to interact with it), whereas
+Pageant stores the more critical information (hence benefits more from
+the extra protection), so it's reasonable to want to run Pageant but
+not PuTTY with the ACL restrictions. You can force Pageant to start
+subsidiary PuTTY processes with a restricted ACL if you also pass the
+\c{-restrict-putty-acl} option.
diff --git a/windows/winpgnt.c b/windows/winpgnt.c
index ebb6c6ace..1919a9b83 100644
--- a/windows/winpgnt.c
+++ b/windows/winpgnt.c
@@ -57,6 +57,7 @@ static HMENU systray_menu, session_menu;
static int already_running;
static char *putty_path;
+static int restrict_putty_acl = FALSE;
/* CWD for "add key" file requester. */
static filereq *keypath = NULL;
@@ -847,11 +848,18 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
case WM_SYSCOMMAND:
switch (wParam & ~0xF) { /* low 4 bits reserved to Windows */
case IDM_PUTTY:
- if((INT_PTR)ShellExecute(hwnd, NULL, putty_path, _T(""), _T(""),
- SW_SHOW) <= 32) {
- MessageBox(NULL, "Unable to execute PuTTY!",
- "Error", MB_OK | MB_ICONERROR);
- }
+ {
+ TCHAR cmdline[10];
+ cmdline[0] = '\0';
+ if (restrict_putty_acl)
+ strcat(cmdline, "&R");
+
+ if((INT_PTR)ShellExecute(hwnd, NULL, putty_path, cmdline,
+ _T(""), SW_SHOW) <= 32) {
+ MessageBox(NULL, "Unable to execute PuTTY!",
+ "Error", MB_OK | MB_ICONERROR);
+ }
+ }
break;
case IDM_CLOSE:
if (passphrase_box)
@@ -912,7 +920,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
mii.cch = MAX_PATH;
mii.dwTypeData = buf;
GetMenuItemInfo(session_menu, wParam, FALSE, &mii);
- strcpy(param, "@");
+ param[0] = '\0';
+ if (restrict_putty_acl)
+ strcat(param, "&R");
+ strcat(param, "@");
strcat(param, mii.dwTypeData);
if((INT_PTR)ShellExecute(hwnd, NULL, putty_path, param,
_T(""), SW_SHOW) <= 32) {
@@ -1169,6 +1180,9 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
!strcmp(argv[i], "-restrict_acl") ||
!strcmp(argv[i], "-restrictacl")) {
restrict_process_acl();
+ } else if (!strcmp(argv[i], "-restrict-putty-acl") ||
+ !strcmp(argv[i], "-restrict_putty_acl")) {
+ restrict_putty_acl = TRUE;
} else if (!strcmp(argv[i], "-c")) {
/*
* If we see `-c', then the rest of the
From 581dd7071ea5131408420654808388ca7c42b3a2 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sat, 30 Sep 2017 17:30:11 +0100
Subject: [PATCH 067/166] Squash the 256-colour test text into fewer lines.
I'm about to want to add more stuff to that file, and it would be nice
to have it still fit on a screen after I do.
---
testdata/colours.txt | 24 ++++++++----------------
1 file changed, 8 insertions(+), 16 deletions(-)
diff --git a/testdata/colours.txt b/testdata/colours.txt
index 33709d238..2311eb83a 100644
--- a/testdata/colours.txt
+++ b/testdata/colours.txt
@@ -4,19 +4,11 @@ Normal text [1mand bold[m; [7mreverse video [1mand bold[m
ANSI plus bold: [30m0 [1mbold[m [31m1 [1mbold[m [32m2 [1mbold[m [33m3 [1mbold[m [34m4 [1mbold[m [35m5 [1mbold[m [36m6 [1mbold[m [37m7 [1mbold[m
xterm bright: [90mfg0[m [100mbg0[m [91mfg1[m [101mbg1[m [92mfg2[m [102mbg2[m [93mfg3[m [103mbg3[m [94mfg4[m [104mbg4[m [95mfg5[m [105mbg5[m [96mfg6[m [106mbg6[m [97mfg7[m [107mbg7[m
xterm 256: [48;5;16mg[48;5;232mr[48;5;233me[48;5;234my[48;5;235ms[48;5;236m [48;5;237m [48;5;238m [48;5;239m [48;5;240m [48;5;241m [48;5;242m [48;5;243m [48;5;244m [48;5;245m [48;5;246m [48;5;247m [48;5;248m [48;5;249m [48;5;250m [48;5;251m [48;5;252m [48;5;253m [48;5;254m [48;5;255m [48;5;231m [m [31;48;5;16mr[48;5;52me[48;5;88md[48;5;124ms[48;5;160m [48;5;196m [m [32;48;5;16mg[48;5;22mr[48;5;28me[48;5;34me[48;5;40mn[48;5;46ms[m [34;48;5;16mb[48;5;17ml[48;5;18mu[48;5;19me[48;5;20ms[48;5;21m [m [33;48;5;16my[48;5;58me[48;5;100ml[48;5;142ml[48;5;184mo[48;5;226mw[m [35;48;5;16mm[48;5;53ma[48;5;90mg[48;5;127me[48;5;164mn[48;5;201mt[m [36;48;5;16mc[48;5;23my[48;5;30ma[48;5;37mn[48;5;44ms[48;5;51m [m
-[38;5;0m 0[m[38;5;1m 1[m[38;5;2m 2[m[38;5;3m 3[m[38;5;4m 4[m[38;5;5m 5[m[38;5;6m 6[m[38;5;7m 7[m[38;5;8m 8[m[38;5;9m 9[m[38;5;10m 10[m[38;5;11m 11[m[38;5;12m 12[m[38;5;13m 13[m[38;5;14m 14[m[38;5;15m 15[m
-[38;5;16m 16[m[38;5;17m 17[m[38;5;18m 18[m[38;5;19m 19[m[38;5;20m 20[m[38;5;21m 21[m[38;5;22m 22[m[38;5;23m 23[m[38;5;24m 24[m[38;5;25m 25[m[38;5;26m 26[m[38;5;27m 27[m[38;5;28m 28[m[38;5;29m 29[m[38;5;30m 30[m[38;5;31m 31[m
-[38;5;32m 32[m[38;5;33m 33[m[38;5;34m 34[m[38;5;35m 35[m[38;5;36m 36[m[38;5;37m 37[m[38;5;38m 38[m[38;5;39m 39[m[38;5;40m 40[m[38;5;41m 41[m[38;5;42m 42[m[38;5;43m 43[m[38;5;44m 44[m[38;5;45m 45[m[38;5;46m 46[m[38;5;47m 47[m
-[38;5;48m 48[m[38;5;49m 49[m[38;5;50m 50[m[38;5;51m 51[m[38;5;52m 52[m[38;5;53m 53[m[38;5;54m 54[m[38;5;55m 55[m[38;5;56m 56[m[38;5;57m 57[m[38;5;58m 58[m[38;5;59m 59[m[38;5;60m 60[m[38;5;61m 61[m[38;5;62m 62[m[38;5;63m 63[m
-[38;5;64m 64[m[38;5;65m 65[m[38;5;66m 66[m[38;5;67m 67[m[38;5;68m 68[m[38;5;69m 69[m[38;5;70m 70[m[38;5;71m 71[m[38;5;72m 72[m[38;5;73m 73[m[38;5;74m 74[m[38;5;75m 75[m[38;5;76m 76[m[38;5;77m 77[m[38;5;78m 78[m[38;5;79m 79[m
-[38;5;80m 80[m[38;5;81m 81[m[38;5;82m 82[m[38;5;83m 83[m[38;5;84m 84[m[38;5;85m 85[m[38;5;86m 86[m[38;5;87m 87[m[38;5;88m 88[m[38;5;89m 89[m[38;5;90m 90[m[38;5;91m 91[m[38;5;92m 92[m[38;5;93m 93[m[38;5;94m 94[m[38;5;95m 95[m
-[38;5;96m 96[m[38;5;97m 97[m[38;5;98m 98[m[38;5;99m 99[m[38;5;100m 100[m[38;5;101m 101[m[38;5;102m 102[m[38;5;103m 103[m[38;5;104m 104[m[38;5;105m 105[m[38;5;106m 106[m[38;5;107m 107[m[38;5;108m 108[m[38;5;109m 109[m[38;5;110m 110[m[38;5;111m 111[m
-[38;5;112m 112[m[38;5;113m 113[m[38;5;114m 114[m[38;5;115m 115[m[38;5;116m 116[m[38;5;117m 117[m[38;5;118m 118[m[38;5;119m 119[m[38;5;120m 120[m[38;5;121m 121[m[38;5;122m 122[m[38;5;123m 123[m[38;5;124m 124[m[38;5;125m 125[m[38;5;126m 126[m[38;5;127m 127[m
-[38;5;128m 128[m[38;5;129m 129[m[38;5;130m 130[m[38;5;131m 131[m[38;5;132m 132[m[38;5;133m 133[m[38;5;134m 134[m[38;5;135m 135[m[38;5;136m 136[m[38;5;137m 137[m[38;5;138m 138[m[38;5;139m 139[m[38;5;140m 140[m[38;5;141m 141[m[38;5;142m 142[m[38;5;143m 143[m
-[38;5;144m 144[m[38;5;145m 145[m[38;5;146m 146[m[38;5;147m 147[m[38;5;148m 148[m[38;5;149m 149[m[38;5;150m 150[m[38;5;151m 151[m[38;5;152m 152[m[38;5;153m 153[m[38;5;154m 154[m[38;5;155m 155[m[38;5;156m 156[m[38;5;157m 157[m[38;5;158m 158[m[38;5;159m 159[m
-[38;5;160m 160[m[38;5;161m 161[m[38;5;162m 162[m[38;5;163m 163[m[38;5;164m 164[m[38;5;165m 165[m[38;5;166m 166[m[38;5;167m 167[m[38;5;168m 168[m[38;5;169m 169[m[38;5;170m 170[m[38;5;171m 171[m[38;5;172m 172[m[38;5;173m 173[m[38;5;174m 174[m[38;5;175m 175[m
-[38;5;176m 176[m[38;5;177m 177[m[38;5;178m 178[m[38;5;179m 179[m[38;5;180m 180[m[38;5;181m 181[m[38;5;182m 182[m[38;5;183m 183[m[38;5;184m 184[m[38;5;185m 185[m[38;5;186m 186[m[38;5;187m 187[m[38;5;188m 188[m[38;5;189m 189[m[38;5;190m 190[m[38;5;191m 191[m
-[38;5;192m 192[m[38;5;193m 193[m[38;5;194m 194[m[38;5;195m 195[m[38;5;196m 196[m[38;5;197m 197[m[38;5;198m 198[m[38;5;199m 199[m[38;5;200m 200[m[38;5;201m 201[m[38;5;202m 202[m[38;5;203m 203[m[38;5;204m 204[m[38;5;205m 205[m[38;5;206m 206[m[38;5;207m 207[m
-[38;5;208m 208[m[38;5;209m 209[m[38;5;210m 210[m[38;5;211m 211[m[38;5;212m 212[m[38;5;213m 213[m[38;5;214m 214[m[38;5;215m 215[m[38;5;216m 216[m[38;5;217m 217[m[38;5;218m 218[m[38;5;219m 219[m[38;5;220m 220[m[38;5;221m 221[m[38;5;222m 222[m[38;5;223m 223[m
-[38;5;224m 224[m[38;5;225m 225[m[38;5;226m 226[m[38;5;227m 227[m[38;5;228m 228[m[38;5;229m 229[m[38;5;230m 230[m[38;5;231m 231[m[38;5;232m 232[m[38;5;233m 233[m[38;5;234m 234[m[38;5;235m 235[m[38;5;236m 236[m[38;5;237m 237[m[38;5;238m 238[m[38;5;239m 239[m
-[38;5;240m 240[m[38;5;241m 241[m[38;5;242m 242[m[38;5;243m 243[m[38;5;244m 244[m[38;5;245m 245[m[38;5;246m 246[m[38;5;247m 247[m[38;5;248m 248[m[38;5;249m 249[m[38;5;250m 250[m[38;5;251m 251[m[38;5;252m 252[m[38;5;253m 253[m[38;5;254m 254[m[38;5;255m 255[m
+[38;5;0m00[38;5;1m01[38;5;2m02[38;5;3m03[38;5;4m04[38;5;5m05[38;5;6m06[38;5;7m07 [38;5;8m08[38;5;9m09[38;5;10m0a[38;5;11m0b[38;5;12m0c[38;5;13m0d[38;5;14m0e[38;5;15m0f [38;5;16m10[38;5;17m11[38;5;18m12[38;5;19m13[38;5;20m14[38;5;21m15[38;5;22m16[38;5;23m17 [38;5;24m18[38;5;25m19[38;5;26m1a[38;5;27m1b[38;5;28m1c[38;5;29m1d[38;5;30m1e[38;5;31m1f[m
+[38;5;32m20[38;5;33m21[38;5;34m22[38;5;35m23[38;5;36m24[38;5;37m25[38;5;38m26[38;5;39m27 [38;5;40m28[38;5;41m29[38;5;42m2a[38;5;43m2b[38;5;44m2c[38;5;45m2d[38;5;46m2e[38;5;47m2f [38;5;48m30[38;5;49m31[38;5;50m32[38;5;51m33[38;5;52m34[38;5;53m35[38;5;54m36[38;5;55m37 [38;5;56m38[38;5;57m39[38;5;58m3a[38;5;59m3b[38;5;60m3c[38;5;61m3d[38;5;62m3e[38;5;63m3f[m
+[38;5;64m40[38;5;65m41[38;5;66m42[38;5;67m43[38;5;68m44[38;5;69m45[38;5;70m46[38;5;71m47 [38;5;72m48[38;5;73m49[38;5;74m4a[38;5;75m4b[38;5;76m4c[38;5;77m4d[38;5;78m4e[38;5;79m4f [38;5;80m50[38;5;81m51[38;5;82m52[38;5;83m53[38;5;84m54[38;5;85m55[38;5;86m56[38;5;87m57 [38;5;88m58[38;5;89m59[38;5;90m5a[38;5;91m5b[38;5;92m5c[38;5;93m5d[38;5;94m5e[38;5;95m5f[m
+[38;5;96m60[38;5;97m61[38;5;98m62[38;5;99m63[38;5;100m64[38;5;101m65[38;5;102m66[38;5;103m67 [38;5;104m68[38;5;105m69[38;5;106m6a[38;5;107m6b[38;5;108m6c[38;5;109m6d[38;5;110m6e[38;5;111m6f [38;5;112m70[38;5;113m71[38;5;114m72[38;5;115m73[38;5;116m74[38;5;117m75[38;5;118m76[38;5;119m77 [38;5;120m78[38;5;121m79[38;5;122m7a[38;5;123m7b[38;5;124m7c[38;5;125m7d[38;5;126m7e[38;5;127m7f[m
+[38;5;128m80[38;5;129m81[38;5;130m82[38;5;131m83[38;5;132m84[38;5;133m85[38;5;134m86[38;5;135m87 [38;5;136m88[38;5;137m89[38;5;138m8a[38;5;139m8b[38;5;140m8c[38;5;141m8d[38;5;142m8e[38;5;143m8f [38;5;144m90[38;5;145m91[38;5;146m92[38;5;147m93[38;5;148m94[38;5;149m95[38;5;150m96[38;5;151m97 [38;5;152m98[38;5;153m99[38;5;154m9a[38;5;155m9b[38;5;156m9c[38;5;157m9d[38;5;158m9e[38;5;159m9f[m
+[38;5;160ma0[38;5;161ma1[38;5;162ma2[38;5;163ma3[38;5;164ma4[38;5;165ma5[38;5;166ma6[38;5;167ma7 [38;5;168ma8[38;5;169ma9[38;5;170maa[38;5;171mab[38;5;172mac[38;5;173mad[38;5;174mae[38;5;175maf [38;5;176mb0[38;5;177mb1[38;5;178mb2[38;5;179mb3[38;5;180mb4[38;5;181mb5[38;5;182mb6[38;5;183mb7 [38;5;184mb8[38;5;185mb9[38;5;186mba[38;5;187mbb[38;5;188mbc[38;5;189mbd[38;5;190mbe[38;5;191mbf[m
+[38;5;192mc0[38;5;193mc1[38;5;194mc2[38;5;195mc3[38;5;196mc4[38;5;197mc5[38;5;198mc6[38;5;199mc7 [38;5;200mc8[38;5;201mc9[38;5;202mca[38;5;203mcb[38;5;204mcc[38;5;205mcd[38;5;206mce[38;5;207mcf [38;5;208md0[38;5;209md1[38;5;210md2[38;5;211md3[38;5;212md4[38;5;213md5[38;5;214md6[38;5;215md7 [38;5;216md8[38;5;217md9[38;5;218mda[38;5;219mdb[38;5;220mdc[38;5;221mdd[38;5;222mde[38;5;223mdf[m
+[38;5;224me0[38;5;225me1[38;5;226me2[38;5;227me3[38;5;228me4[38;5;229me5[38;5;230me6[38;5;231me7 [38;5;232me8[38;5;233me9[38;5;234mea[38;5;235meb[38;5;236mec[38;5;237med[38;5;238mee[38;5;239mef [38;5;240mf0[38;5;241mf1[38;5;242mf2[38;5;243mf3[38;5;244mf4[38;5;245mf5[38;5;246mf6[38;5;247mf7 [38;5;248mf8[38;5;249mf9[38;5;250mfa[38;5;251mfb[38;5;252mfc[38;5;253mfd[38;5;254mfe[38;5;255mff[m
From a4cbd3dfdb71d258e83bbf5b03a874c06d0b3106 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sat, 30 Sep 2017 17:32:32 +0100
Subject: [PATCH 068/166] Support ESC[38;2;R;G;Bm for 24-bit true colour.
This is a heavily rewritten version of a patch originally by Lorenz
Diener; it was tidied up somewhat by Christian Brabandt, and then
tidied up more by me. The basic idea is to add to the termchar
structure a pair of small structs encoding 24-bit RGB values, each
with a flag indicating whether it's turned on; if it is, it overrides
any other specification of fg or bg colour for that character cell.
I've added a test line to colours.txt containing a few example colours
from /usr/share/X11/rgb.txt. In fact it makes quite a good demo to run
the whole of rgb.txt through this treatment, with a command such as
perl -pe 's!^\s*(\d+)\s+(\d+)\s+(\d+).*$!\e[38;2;$1;$2;$3m$&\e[m!' rgb.txt
---
LICENCE | 3 +-
fuzzterm.c | 4 +-
putty.h | 28 +++++++++-
terminal.c | 129 ++++++++++++++++++++++++++++++++++++++++---
terminal.h | 2 +
testdata/colours.txt | 1 +
unix/gtkwin.c | 38 ++++++++++---
windows/window.c | 33 ++++++-----
8 files changed, 204 insertions(+), 34 deletions(-)
diff --git a/LICENCE b/LICENCE
index 7c49ceb3b..30b1fe2b3 100644
--- a/LICENCE
+++ b/LICENCE
@@ -3,7 +3,8 @@ PuTTY is copyright 1997-2017 Simon Tatham.
Portions copyright Robert de Bath, Joris van Rantwijk, Delian
Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus
-Kuhn, Colin Watson, Christopher Staite, and CORE SDI S.A.
+Kuhn, Colin Watson, Christopher Staite, Lorenz Diener, Christian
+Brabandt, and CORE SDI S.A.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
diff --git a/fuzzterm.c b/fuzzterm.c
index 15b5d6354..480dca379 100644
--- a/fuzzterm.c
+++ b/fuzzterm.c
@@ -45,7 +45,7 @@ int from_backend(void *frontend, int is_stderr, const char *data, int len)
void request_resize(void *frontend, int x, int y) { }
void do_text(Context ctx, int x, int y, wchar_t * text, int len,
- unsigned long attr, int lattr)
+ unsigned long attr, int lattr, truecolour tc)
{
int i;
@@ -56,7 +56,7 @@ void do_text(Context ctx, int x, int y, wchar_t * text, int len,
printf("\n");
}
void do_cursor(Context ctx, int x, int y, wchar_t * text, int len,
- unsigned long attr, int lattr)
+ unsigned long attr, int lattr, truecolour tc)
{
int i;
diff --git a/putty.h b/putty.h
index fd2d02506..61d6278da 100644
--- a/putty.h
+++ b/putty.h
@@ -592,12 +592,36 @@ void prompt_ensure_result_size(prompt_t *pr, int len);
/* Burn the evidence. (Assumes _all_ strings want free()ing.) */
void free_prompts(prompts_t *p);
+/*
+ * Data type definitions for true-colour terminal display.
+ * 'optionalrgb' describes a single RGB colour, which overrides the
+ * other colour settings if 'enabled' is nonzero, and is ignored
+ * otherwise. 'truecolour' contains a pair of those for foreground and
+ * background.
+ */
+typedef struct optionalrgb {
+ unsigned char enabled;
+ unsigned char r, g, b;
+} optionalrgb;
+extern const optionalrgb optionalrgb_none;
+typedef struct truecolour {
+ optionalrgb fg, bg;
+} truecolour;
+#define optionalrgb_equal(r1,r2) ( \
+ (r1).enabled==(r2).enabled && \
+ (r1).r==(r2).r && (r1).g==(r2).g && (r1).b==(r2).b)
+#define truecolour_equal(c1,c2) ( \
+ optionalrgb_equal((c1).fg, (c2).fg) && \
+ optionalrgb_equal((c1).bg, (c2).bg))
+
/*
* Exports from the front end.
*/
void request_resize(void *frontend, int, int);
-void do_text(Context, int, int, wchar_t *, int, unsigned long, int);
-void do_cursor(Context, int, int, wchar_t *, int, unsigned long, int);
+void do_text(Context, int, int, wchar_t *, int, unsigned long, int,
+ truecolour);
+void do_cursor(Context, int, int, wchar_t *, int, unsigned long, int,
+ truecolour);
int char_width(Context ctx, int uc);
#ifdef OPTIMISE_SCROLL
void do_scroll(Context, int, int, int);
diff --git a/terminal.c b/terminal.c
index f7bcbb957..e597d472e 100644
--- a/terminal.c
+++ b/terminal.c
@@ -108,6 +108,7 @@ static void update_sbar(Terminal *);
static void deselect(Terminal *);
static void term_print_finish(Terminal *);
static void scroll(Terminal *, int, int, int, int);
+static void parse_optionalrgb(optionalrgb *out, unsigned *values);
#ifdef OPTIMISE_SCROLL
static void scroll_display(Terminal *, int, int, int);
#endif /* OPTIMISE_SCROLL */
@@ -283,6 +284,8 @@ static int termchars_equal_override(termchar *a, termchar *b,
unsigned long bchr, unsigned long battr)
{
/* FULL-TERMCHAR */
+ if (!truecolour_equal(a->truecolour, b->truecolour))
+ return FALSE;
if (a->chr != bchr)
return FALSE;
if ((a->attr &~ DATTR_MASK) != (battr &~ DATTR_MASK))
@@ -607,6 +610,24 @@ static void makeliteral_attr(struct buf *b, termchar *c, unsigned long *state)
add(b, (unsigned char)(attr & 0xFF));
}
}
+static void makeliteral_truecolour(struct buf *b, termchar *c, unsigned long *state)
+{
+ /*
+ * Put the used parts of the colour info into the buffer.
+ */
+ add(b, ((c->truecolour.fg.enabled ? 1 : 0) |
+ (c->truecolour.bg.enabled ? 2 : 0)));
+ if (c->truecolour.fg.enabled) {
+ add(b, c->truecolour.fg.r);
+ add(b, c->truecolour.fg.g);
+ add(b, c->truecolour.fg.b);
+ }
+ if (c->truecolour.bg.enabled) {
+ add(b, c->truecolour.bg.r);
+ add(b, c->truecolour.bg.g);
+ add(b, c->truecolour.bg.b);
+ }
+}
static void makeliteral_cc(struct buf *b, termchar *c, unsigned long *state)
{
/*
@@ -681,6 +702,7 @@ static unsigned char *compressline(termline *ldata)
*/
makerle(b, ldata, makeliteral_chr);
makerle(b, ldata, makeliteral_attr);
+ makerle(b, ldata, makeliteral_truecolour);
makerle(b, ldata, makeliteral_cc);
/*
@@ -826,6 +848,29 @@ static void readliteral_attr(struct buf *b, termchar *c, termline *ldata,
c->attr = attr;
}
+static void readliteral_truecolour(struct buf *b, termchar *c, termline *ldata,
+ unsigned long *state)
+{
+ int flags = get(b);
+
+ if (flags & 1) {
+ c->truecolour.fg.enabled = TRUE;
+ c->truecolour.fg.r = get(b);
+ c->truecolour.fg.g = get(b);
+ c->truecolour.fg.b = get(b);
+ } else {
+ c->truecolour.fg = optionalrgb_none;
+ }
+
+ if (flags & 2) {
+ c->truecolour.bg.enabled = TRUE;
+ c->truecolour.bg.r = get(b);
+ c->truecolour.bg.g = get(b);
+ c->truecolour.bg.b = get(b);
+ } else {
+ c->truecolour.bg = optionalrgb_none;
+ }
+}
static void readliteral_cc(struct buf *b, termchar *c, termline *ldata,
unsigned long *state)
{
@@ -899,6 +944,7 @@ static termline *decompressline(unsigned char *data, int *bytes_used)
*/
readrle(b, ldata, readliteral_chr);
readrle(b, ldata, readliteral_attr);
+ readrle(b, ldata, readliteral_truecolour);
readrle(b, ldata, readliteral_cc);
/* Return the number of bytes read, for diagnostic purposes. */
@@ -1570,6 +1616,8 @@ void term_clrsb(Terminal *term)
update_sbar(term);
}
+const optionalrgb optionalrgb_none = {0, 0, 0, 0};
+
/*
* Initialise the terminal.
*/
@@ -1646,6 +1694,8 @@ Terminal *term_init(Conf *myconf, struct unicode_data *ucsdata,
term->basic_erase_char.chr = CSET_ASCII | ' ';
term->basic_erase_char.attr = ATTR_DEFAULT;
term->basic_erase_char.cc_next = 0;
+ term->basic_erase_char.truecolour.fg = optionalrgb_none;
+ term->basic_erase_char.truecolour.bg = optionalrgb_none;
term->erase_char = term->basic_erase_char;
return term;
@@ -3212,6 +3262,8 @@ static void term_out(Terminal *term)
clear_cc(cline, term->curs.x);
cline->chars[term->curs.x].chr = c;
cline->chars[term->curs.x].attr = term->curr_attr;
+ cline->chars[term->curs.x].truecolour =
+ term->curr_truecolour;
term->curs.x++;
@@ -3219,6 +3271,8 @@ static void term_out(Terminal *term)
clear_cc(cline, term->curs.x);
cline->chars[term->curs.x].chr = UCSWIDE;
cline->chars[term->curs.x].attr = term->curr_attr;
+ cline->chars[term->curs.x].truecolour =
+ term->curr_truecolour;
break;
case 1:
@@ -3229,6 +3283,8 @@ static void term_out(Terminal *term)
clear_cc(cline, term->curs.x);
cline->chars[term->curs.x].chr = c;
cline->chars[term->curs.x].attr = term->curr_attr;
+ cline->chars[term->curs.x].truecolour =
+ term->curr_truecolour;
break;
case 0:
@@ -3799,6 +3855,8 @@ static void term_out(Terminal *term)
switch (def(term->esc_args[i], 0)) {
case 0: /* restore defaults */
term->curr_attr = term->default_attr;
+ term->curr_truecolour =
+ term->basic_erase_char.truecolour;
break;
case 1: /* enable bold */
compatibility(VT100AVO);
@@ -3860,6 +3918,7 @@ static void term_out(Terminal *term)
case 36:
case 37:
/* foreground */
+ term->curr_truecolour.fg.enabled = FALSE;
term->curr_attr &= ~ATTR_FGMASK;
term->curr_attr |=
(term->esc_args[i] - 30)<curr_truecolour.fg.enabled = FALSE;
term->curr_attr &= ~ATTR_FGMASK;
term->curr_attr |=
((term->esc_args[i] - 90 + 8)
<< ATTR_FGSHIFT);
break;
case 39: /* default-foreground */
+ term->curr_truecolour.fg.enabled = FALSE;
term->curr_attr &= ~ATTR_FGMASK;
term->curr_attr |= ATTR_DEFFG;
break;
@@ -3891,6 +3952,7 @@ static void term_out(Terminal *term)
case 46:
case 47:
/* background */
+ term->curr_truecolour.bg.enabled = FALSE;
term->curr_attr &= ~ATTR_BGMASK;
term->curr_attr |=
(term->esc_args[i] - 40)<curr_truecolour.bg.enabled = FALSE;
term->curr_attr &= ~ATTR_BGMASK;
term->curr_attr |=
((term->esc_args[i] - 100 + 8)
<< ATTR_BGSHIFT);
break;
case 49: /* default-background */
+ term->curr_truecolour.bg.enabled = FALSE;
term->curr_attr &= ~ATTR_BGMASK;
term->curr_attr |= ATTR_DEFBG;
break;
- case 38: /* xterm 256-colour mode */
+
+ /*
+ * 256-colour and true-colour
+ * sequences. A 256-colour
+ * foreground is selected by a
+ * sequence of 3 arguments in the
+ * form 38;5;n, where n is in the
+ * range 0-255. A true-colour RGB
+ * triple is selected by 5 args of
+ * the form 38;2;r;g;b. Replacing
+ * the initial 38 with 48 in both
+ * cases selects the same colour
+ * as the background.
+ */
+ case 38:
if (i+2 < term->esc_nargs &&
term->esc_args[i+1] == 5) {
term->curr_attr &= ~ATTR_FGMASK;
@@ -3921,9 +3999,16 @@ static void term_out(Terminal *term)
((term->esc_args[i+2] & 0xFF)
<< ATTR_FGSHIFT);
i += 2;
+ }
+ if (i + 4 < term->esc_nargs &&
+ term->esc_args[i + 1] == 2) {
+ parse_optionalrgb(
+ &term->curr_truecolour.fg,
+ term->esc_args + (i+2));
+ i += 4;
}
break;
- case 48: /* xterm 256-colour mode */
+ case 48:
if (i+2 < term->esc_nargs &&
term->esc_args[i+1] == 5) {
term->curr_attr &= ~ATTR_BGMASK;
@@ -3932,6 +4017,13 @@ static void term_out(Terminal *term)
<< ATTR_BGSHIFT);
i += 2;
}
+ if (i + 4 < term->esc_nargs &&
+ term->esc_args[i+1] == 2) {
+ parse_optionalrgb(
+ &term->curr_truecolour.bg,
+ term->esc_args + (i+2));
+ i += 4;
+ }
break;
}
}
@@ -4733,6 +4825,19 @@ static void term_out(Terminal *term)
logflush(term->logctx);
}
+/*
+ * Small subroutine to parse three consecutive escape-sequence
+ * arguments representing a true-colour RGB triple into an
+ * optionalrgb.
+ */
+static void parse_optionalrgb(optionalrgb *out, unsigned *values)
+{
+ out->enabled = TRUE;
+ out->r = values[0] < 256 ? values[0] : 0;
+ out->g = values[1] < 256 ? values[1] : 0;
+ out->b = values[2] < 256 ? values[2] : 0;
+}
+
/*
* To prevent having to run the reasonably tricky bidi algorithm
* too many times, we maintain a cache of the last lineful of data
@@ -5035,6 +5140,7 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
int last_run_dirty = 0;
int laststart, dirtyrect;
int *backward;
+ truecolour tc;
scrpos.y = i + term->disptop;
ldata = lineptr(scrpos.y);
@@ -5064,6 +5170,7 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
tattr = (tattr & ~(ATTR_FGMASK | ATTR_BGMASK)) |
ATTR_DEFFG | ATTR_DEFBG;
+ tc = d->truecolour;
if (!term->xterm_256_colour) {
int colour;
colour = (tattr & ATTR_FGMASK) >> ATTR_FGSHIFT;
@@ -5131,6 +5238,7 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
/* FULL-TERMCHAR */
newline[j].attr = tattr;
newline[j].chr = tchar;
+ newline[j].truecolour = tc;
/* Combining characters are still read from lchars */
newline[j].cc_next = 0;
}
@@ -5181,6 +5289,7 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
term->disptext[i]->lattr);
term->disptext[i]->lattr = ldata->lattr;
+ tc = term->erase_char.truecolour;
for (j = 0; j < term->cols; j++) {
unsigned long tattr, tchar;
int break_run, do_copy;
@@ -5194,6 +5303,9 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
break_run = ((tattr ^ attr) & term->attr_mask) != 0;
+ if (!truecolour_equal(newline[j].truecolour, tc))
+ break_run = TRUE;
+
#ifdef USES_VTLINE_HACK
/* Special hack for VT100 Linedraw glyphs */
if ((tchar >= 0x23BA && tchar <= 0x23BD) ||
@@ -5226,15 +5338,15 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
if (break_run) {
if ((dirty_run || last_run_dirty) && ccount > 0) {
- do_text(ctx, start, i, ch, ccount, attr,
- ldata->lattr);
+ do_text(ctx, start, i, ch, ccount, attr, ldata->lattr, tc);
if (attr & (TATTR_ACTCURS | TATTR_PASCURS))
do_cursor(ctx, start, i, ch, ccount, attr,
- ldata->lattr);
+ ldata->lattr, tc);
}
start = j;
ccount = 0;
attr = tattr;
+ tc = newline[j].truecolour;
cset = CSET_OF(tchar);
if (term->ucsdata->dbcs_screenfont)
last_run_dirty = dirty_run;
@@ -5303,6 +5415,7 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
copy_termchar(term->disptext[i], j, d);
term->disptext[i]->chars[j].chr = tchar;
term->disptext[i]->chars[j].attr = tattr;
+ term->disptext[i]->chars[j].truecolour = tc;
if (start == j)
term->disptext[i]->chars[j].attr |= DATTR_STARTRUN;
}
@@ -5324,11 +5437,9 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
}
}
if (dirty_run && ccount > 0) {
- do_text(ctx, start, i, ch, ccount, attr,
- ldata->lattr);
+ do_text(ctx, start, i, ch, ccount, attr, ldata->lattr, tc);
if (attr & (TATTR_ACTCURS | TATTR_PASCURS))
- do_cursor(ctx, start, i, ch, ccount, attr,
- ldata->lattr);
+ do_cursor(ctx, start, i, ch, ccount, attr, ldata->lattr, tc);
}
unlineptr(ldata);
diff --git a/terminal.h b/terminal.h
index 2ed9e6ef5..21b8774a2 100644
--- a/terminal.h
+++ b/terminal.h
@@ -40,6 +40,7 @@ struct termchar {
*/
unsigned long chr;
unsigned long attr;
+ truecolour truecolour;
/*
* The cc_next field is used to link multiple termchars
@@ -102,6 +103,7 @@ struct terminal_tag {
#endif /* OPTIMISE_SCROLL */
int default_attr, curr_attr, save_attr;
+ truecolour curr_truecolour;
termchar basic_erase_char, erase_char;
bufchain inbuf; /* terminal input buffer */
diff --git a/testdata/colours.txt b/testdata/colours.txt
index 2311eb83a..34dff8a5a 100644
--- a/testdata/colours.txt
+++ b/testdata/colours.txt
@@ -12,3 +12,4 @@ xterm 256: [48;5;16mg[48;5;232mr[48;5;233me[48;5;234my[48;5;235ms[48;5;236
[38;5;160ma0[38;5;161ma1[38;5;162ma2[38;5;163ma3[38;5;164ma4[38;5;165ma5[38;5;166ma6[38;5;167ma7 [38;5;168ma8[38;5;169ma9[38;5;170maa[38;5;171mab[38;5;172mac[38;5;173mad[38;5;174mae[38;5;175maf [38;5;176mb0[38;5;177mb1[38;5;178mb2[38;5;179mb3[38;5;180mb4[38;5;181mb5[38;5;182mb6[38;5;183mb7 [38;5;184mb8[38;5;185mb9[38;5;186mba[38;5;187mbb[38;5;188mbc[38;5;189mbd[38;5;190mbe[38;5;191mbf[m
[38;5;192mc0[38;5;193mc1[38;5;194mc2[38;5;195mc3[38;5;196mc4[38;5;197mc5[38;5;198mc6[38;5;199mc7 [38;5;200mc8[38;5;201mc9[38;5;202mca[38;5;203mcb[38;5;204mcc[38;5;205mcd[38;5;206mce[38;5;207mcf [38;5;208md0[38;5;209md1[38;5;210md2[38;5;211md3[38;5;212md4[38;5;213md5[38;5;214md6[38;5;215md7 [38;5;216md8[38;5;217md9[38;5;218mda[38;5;219mdb[38;5;220mdc[38;5;221mdd[38;5;222mde[38;5;223mdf[m
[38;5;224me0[38;5;225me1[38;5;226me2[38;5;227me3[38;5;228me4[38;5;229me5[38;5;230me6[38;5;231me7 [38;5;232me8[38;5;233me9[38;5;234mea[38;5;235meb[38;5;236mec[38;5;237med[38;5;238mee[38;5;239mef [38;5;240mf0[38;5;241mf1[38;5;242mf2[38;5;243mf3[38;5;244mf4[38;5;245mf5[38;5;246mf6[38;5;247mf7 [38;5;248mf8[38;5;249mf9[38;5;250mfa[38;5;251mfb[38;5;252mfc[38;5;253mfd[38;5;254mfe[38;5;255mff[m
+24-bit colour: [38;2;112;128;144mSlateGrey[m [38;2;107;142;35mOliveDrab[m [38;2;218;165;32mgoldenrod[m [38;2;139;69;19mSaddleBrown[m [30;48;2;148;0;211mDarkViolet (bg)[m
diff --git a/unix/gtkwin.c b/unix/gtkwin.c
index 9e73181e2..f49f92af6 100644
--- a/unix/gtkwin.c
+++ b/unix/gtkwin.c
@@ -3029,6 +3029,24 @@ static void draw_set_colour(struct draw_ctx *dctx, int col)
#endif
}
+static void draw_set_colour_rgb(struct draw_ctx *dctx, optionalrgb orgb)
+{
+#ifdef DRAW_TEXT_GDK
+ if (dctx->uctx.type == DRAWTYPE_GDK) {
+ GdkColor color;
+ color.red = orgb.r * 256;
+ color.green = orgb.g * 256;
+ color.blue = orgb.b * 256;
+ gdk_gc_set_rgb_fg_color(dctx->uctx.u.gdk.gc, &color);
+ }
+#endif
+#ifdef DRAW_TEXT_CAIRO
+ if (dctx->uctx.type == DRAWTYPE_CAIRO)
+ cairo_set_source_rgb(dctx->uctx.u.cairo.cr,
+ orgb.r / 255.0, orgb.g / 255.0, orgb.b / 255.0);
+#endif
+}
+
static void draw_rectangle(struct draw_ctx *dctx, int filled,
int x, int y, int w, int h)
{
@@ -3222,7 +3240,7 @@ static void draw_backing_rect(struct gui_data *inst)
* We are allowed to fiddle with the contents of `text'.
*/
void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
- unsigned long attr, int lattr)
+ unsigned long attr, int lattr, truecolour truecolour)
{
struct draw_ctx *dctx = (struct draw_ctx *)ctx;
struct gui_data *inst = dctx->inst;
@@ -3316,13 +3334,19 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
((lattr & LATTR_MODE) == LATTR_BOT));
}
- draw_set_colour(dctx, nbg);
+ if (truecolour.bg.enabled)
+ draw_set_colour_rgb(dctx, truecolour.bg);
+ else
+ draw_set_colour(dctx, nbg);
draw_rectangle(dctx, TRUE,
x*inst->font_width+inst->window_border,
y*inst->font_height+inst->window_border,
rlen*widefactor*inst->font_width, inst->font_height);
- draw_set_colour(dctx, nfg);
+ if (truecolour.fg.enabled)
+ draw_set_colour_rgb(dctx, truecolour.fg);
+ else
+ draw_set_colour(dctx, nfg);
if (ncombining > 1) {
assert(len == 1);
unifont_draw_combining(&dctx->uctx, inst->fonts[fontid],
@@ -3362,13 +3386,13 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
}
void do_text(Context ctx, int x, int y, wchar_t *text, int len,
- unsigned long attr, int lattr)
+ unsigned long attr, int lattr, truecolour truecolour)
{
struct draw_ctx *dctx = (struct draw_ctx *)ctx;
struct gui_data *inst = dctx->inst;
int widefactor;
- do_text_internal(ctx, x, y, text, len, attr, lattr);
+ do_text_internal(ctx, x, y, text, len, attr, lattr, truecolour);
if (attr & ATTR_WIDE) {
widefactor = 2;
@@ -3392,7 +3416,7 @@ void do_text(Context ctx, int x, int y, wchar_t *text, int len,
}
void do_cursor(Context ctx, int x, int y, wchar_t *text, int len,
- unsigned long attr, int lattr)
+ unsigned long attr, int lattr, truecolour truecolour)
{
struct draw_ctx *dctx = (struct draw_ctx *)ctx;
struct gui_data *inst = dctx->inst;
@@ -3409,7 +3433,7 @@ void do_cursor(Context ctx, int x, int y, wchar_t *text, int len,
active = 1;
} else
active = 0;
- do_text_internal(ctx, x, y, text, len, attr, lattr);
+ do_text_internal(ctx, x, y, text, len, attr, lattr, truecolour);
if (attr & TATTR_COMBINING)
len = 1;
diff --git a/windows/window.c b/windows/window.c
index 966003114..452eb7716 100644
--- a/windows/window.c
+++ b/windows/window.c
@@ -3395,7 +3395,7 @@ static void sys_cursor_update(void)
* We are allowed to fiddle with the contents of `text'.
*/
void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
- unsigned long attr, int lattr)
+ unsigned long attr, int lattr, truecolour truecolour)
{
COLORREF fg, bg, t;
int nfg, nbg, nfont;
@@ -3522,8 +3522,16 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
if (nbg < 16) nbg |= 8;
else if (nbg >= 256) nbg |= 1;
}
- fg = colours[nfg];
- bg = colours[nbg];
+ if (truecolour.fg.enabled)
+ fg = RGB(truecolour.fg.r, truecolour.fg.g, truecolour.fg.b);
+ else
+ fg = colours[nfg];
+
+ if (truecolour.bg.enabled)
+ bg = RGB(truecolour.bg.r, truecolour.bg.g, truecolour.bg.b);
+ else
+ bg = colours[nbg];
+
SelectObject(hdc, fonts[nfont]);
SetTextColor(hdc, fg);
SetBkColor(hdc, bg);
@@ -3768,7 +3776,7 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
* Wrapper that handles combining characters.
*/
void do_text(Context ctx, int x, int y, wchar_t *text, int len,
- unsigned long attr, int lattr)
+ unsigned long attr, int lattr, truecolour truecolour)
{
if (attr & TATTR_COMBINING) {
unsigned long a = 0;
@@ -3778,13 +3786,13 @@ void do_text(Context ctx, int x, int y, wchar_t *text, int len,
len0 = 2;
if (len-len0 >= 1 && IS_LOW_VARSEL(text[len0])) {
attr &= ~TATTR_COMBINING;
- do_text_internal(ctx, x, y, text, len0+1, attr, lattr);
+ do_text_internal(ctx, x, y, text, len0+1, attr, lattr, truecolour);
text += len0+1;
len -= len0+1;
a = TATTR_COMBINING;
} else if (len-len0 >= 2 && IS_HIGH_VARSEL(text[len0], text[len0+1])) {
attr &= ~TATTR_COMBINING;
- do_text_internal(ctx, x, y, text, len0+2, attr, lattr);
+ do_text_internal(ctx, x, y, text, len0+2, attr, lattr, truecolour);
text += len0+2;
len -= len0+2;
a = TATTR_COMBINING;
@@ -3794,22 +3802,21 @@ void do_text(Context ctx, int x, int y, wchar_t *text, int len,
while (len--) {
if (len >= 1 && IS_SURROGATE_PAIR(text[0], text[1])) {
- do_text_internal(ctx, x, y, text, 2, attr | a, lattr);
+ do_text_internal(ctx, x, y, text, 2, attr | a, lattr, truecolour);
len--;
text++;
- } else {
- do_text_internal(ctx, x, y, text, 1, attr | a, lattr);
- }
+ } else
+ do_text_internal(ctx, x, y, text, 1, attr | a, lattr, truecolour);
text++;
a = TATTR_COMBINING;
}
} else
- do_text_internal(ctx, x, y, text, len, attr, lattr);
+ do_text_internal(ctx, x, y, text, len, attr, lattr, truecolour);
}
void do_cursor(Context ctx, int x, int y, wchar_t *text, int len,
- unsigned long attr, int lattr)
+ unsigned long attr, int lattr, truecolour truecolour)
{
int fnt_width;
@@ -3821,7 +3828,7 @@ void do_cursor(Context ctx, int x, int y, wchar_t *text, int len,
if ((attr & TATTR_ACTCURS) && (ctype == 0 || term->big_cursor)) {
if (*text != UCSWIDE) {
- do_text(ctx, x, y, text, len, attr, lattr);
+ do_text(ctx, x, y, text, len, attr, lattr, truecolour);
return;
}
ctype = 2;
From 16214ea0f5de7023c7e08fba57e7a49c2d518583 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sun, 1 Oct 2017 20:59:00 +0100
Subject: [PATCH 069/166] Initialise term->curr_truecolour at startup.
Somehow I managed to miss _that_ really obvious bug in the true-
colour patch.
---
terminal.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/terminal.c b/terminal.c
index e597d472e..0eb1a9a6c 100644
--- a/terminal.c
+++ b/terminal.c
@@ -1296,6 +1296,7 @@ static void power_on(Terminal *term, int clear)
term->big_cursor = 0;
term->default_attr = term->save_attr =
term->alt_save_attr = term->curr_attr = ATTR_DEFAULT;
+ term->curr_truecolour.fg = term->curr_truecolour.bg = optionalrgb_none;
term->term_editing = term->term_echoing = FALSE;
term->app_cursor_keys = conf_get_int(term->conf, CONF_app_cursor);
term->app_keypad_keys = conf_get_int(term->conf, CONF_app_keypad);
From f813e9f937b5b6198659c8c64b3090dc3902b930 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sun, 1 Oct 2017 21:05:25 +0100
Subject: [PATCH 070/166] uxnet.c: don't close a socket's fd if it is -1.
This is harmless in principle (you just get EBADF back from close(2)
and ignore it), but it leads to warnings in valgrind.
---
unix/uxnet.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/unix/uxnet.c b/unix/uxnet.c
index ddcd92280..f3498527f 100644
--- a/unix/uxnet.c
+++ b/unix/uxnet.c
@@ -1023,9 +1023,11 @@ static void sk_tcp_close(Socket sock)
if (s->child)
sk_tcp_close((Socket)s->child);
- uxsel_del(s->s);
del234(sktree, s);
- close(s->s);
+ if (s->s >= 0) {
+ uxsel_del(s->s);
+ close(s->s);
+ }
if (s->addr)
sk_addr_free(s->addr);
sfree(s);
From 6b824713d56bf105cede71daa186593aa9906718 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sun, 1 Oct 2017 21:53:32 +0100
Subject: [PATCH 071/166] term_mouse: make special treatment of x < 0 more
selective.
A mouse drag which manages to reach x < 0 (via SetCapture or
equivalent) was treated as having the coordinates of (x_max, y-1).
This is intended to be useful when the mouse drag is part of ordinary
raster-ordered selection.
But we were leaving that treatment enabled even for mouse actions that
went to xterm mouse tracking mode - thanks to Markus Gans for
reporting that - and when I investigated, I realised that this isn't a
sensible transformation in _rectangular_ selection mode either. Fixed
both.
---
terminal.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/terminal.c b/terminal.c
index 0eb1a9a6c..433b3fa52 100644
--- a/terminal.c
+++ b/terminal.c
@@ -6088,7 +6088,18 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,
term_scroll(term, 0, +1);
}
if (x < 0) {
- if (y > 0) {
+ if (y > 0 && !raw_mouse && term->seltype != RECTANGULAR) {
+ /*
+ * When we're using the mouse for normal raster-based
+ * selection, dragging off the left edge of a terminal row
+ * is treated the same as the right-hand end of the
+ * previous row, in that it's considered to identify a
+ * point _before_ the first character on row y.
+ *
+ * But if the mouse action is going to be used for
+ * anything else - rectangular selection, or xterm mouse
+ * tracking - then we disable this special treatment.
+ */
x = term->cols - 1;
y--;
} else
From 2f9738a282c9b738b135198d34c61f7d81aa69c1 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Thu, 5 Oct 2017 20:27:27 +0100
Subject: [PATCH 072/166] Make terminal true-colour mode configurable.
I know some users don't like any colour _at all_, and we have a
separate option to turn off xterm-style 256-colour sequences, so it
seems remiss not to have an option to disable true colour as well.
---
config.c | 3 +++
doc/config.but | 9 +++++++++
putty.h | 1 +
settings.c | 2 ++
terminal.c | 8 +++++++-
terminal.h | 1 +
windows/winhelp.h | 1 +
7 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/config.c b/config.c
index efe1ff1ec..cc5e726b3 100644
--- a/config.c
+++ b/config.c
@@ -1898,6 +1898,9 @@ void setup_config_box(struct controlbox *b, int midsession,
ctrl_checkbox(s, "Allow terminal to use xterm 256-colour mode", '2',
HELPCTX(colours_xterm256), conf_checkbox_handler,
I(CONF_xterm_256_colour));
+ ctrl_checkbox(s, "Allow terminal to use 24-bit colours", '4',
+ HELPCTX(colours_truecolour), conf_checkbox_handler,
+ I(CONF_true_colour));
ctrl_radiobuttons(s, "Indicate bolded text by changing:", 'b', 3,
HELPCTX(colours_bold),
conf_radiobutton_handler, I(CONF_bold_style),
diff --git a/doc/config.but b/doc/config.but
index bd12efb28..7ad5e2822 100644
--- a/doc/config.but
+++ b/doc/config.but
@@ -1549,6 +1549,15 @@ If you do not see \cq{colors#256} in the output, you may need to
change your terminal setting. On modern Linux machines, you could
try \cq{xterm-256color}.
+\S{config-truecolour} \q{Allow terminal to use 24-bit colour}
+
+\cfg{winhelp-topic}{colours.truecolour}
+
+This option is enabled by default. If it is disabled, PuTTY will
+ignore any control sequences sent by the server which use the control
+sequences supported by modern terminals to specify arbitrary 24-bit
+RGB colour value.
+
\S{config-boldcolour} \q{Indicate bolded text by changing...}
\cfg{winhelp-topic}{colours.bold}
diff --git a/putty.h b/putty.h
index 61d6278da..8a8b54254 100644
--- a/putty.h
+++ b/putty.h
@@ -859,6 +859,7 @@ void cleanup_exit(int);
/* Colour options */ \
X(INT, NONE, ansi_colour) \
X(INT, NONE, xterm_256_colour) \
+ X(INT, NONE, true_colour) \
X(INT, NONE, system_colour) \
X(INT, NONE, try_palette) \
X(INT, NONE, bold_style) \
diff --git a/settings.c b/settings.c
index 00c01c546..47e5b9f75 100644
--- a/settings.c
+++ b/settings.c
@@ -609,6 +609,7 @@ void save_open_settings(void *sesskey, Conf *conf)
write_setting_i(sesskey, "TryPalette", conf_get_int(conf, CONF_try_palette));
write_setting_i(sesskey, "ANSIColour", conf_get_int(conf, CONF_ansi_colour));
write_setting_i(sesskey, "Xterm256Colour", conf_get_int(conf, CONF_xterm_256_colour));
+ write_setting_i(sesskey, "TrueColour", conf_get_int(conf, CONF_true_colour));
write_setting_i(sesskey, "BoldAsColour", conf_get_int(conf, CONF_bold_style)-1);
for (i = 0; i < 22; i++) {
@@ -1005,6 +1006,7 @@ void load_open_settings(void *sesskey, Conf *conf)
gppi(sesskey, "TryPalette", 0, conf, CONF_try_palette);
gppi(sesskey, "ANSIColour", 1, conf, CONF_ansi_colour);
gppi(sesskey, "Xterm256Colour", 1, conf, CONF_xterm_256_colour);
+ gppi(sesskey, "TrueColour", 1, conf, CONF_true_colour);
i = gppi_raw(sesskey, "BoldAsColour", 1); conf_set_int(conf, CONF_bold_style, i+1);
for (i = 0; i < 22; i++) {
diff --git a/terminal.c b/terminal.c
index 433b3fa52..5102db12a 100644
--- a/terminal.c
+++ b/terminal.c
@@ -1458,6 +1458,7 @@ void term_copy_stuff_from_conf(Terminal *term)
term->scroll_on_disp = conf_get_int(term->conf, CONF_scroll_on_disp);
term->scroll_on_key = conf_get_int(term->conf, CONF_scroll_on_key);
term->xterm_256_colour = conf_get_int(term->conf, CONF_xterm_256_colour);
+ term->true_colour = conf_get_int(term->conf, CONF_true_colour);
/*
* Parse the control-character escapes in the configured
@@ -5171,7 +5172,6 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
tattr = (tattr & ~(ATTR_FGMASK | ATTR_BGMASK)) |
ATTR_DEFFG | ATTR_DEFBG;
- tc = d->truecolour;
if (!term->xterm_256_colour) {
int colour;
colour = (tattr & ATTR_FGMASK) >> ATTR_FGSHIFT;
@@ -5182,6 +5182,12 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
tattr = (tattr &~ ATTR_BGMASK) | ATTR_DEFBG;
}
+ if (term->true_colour) {
+ tc = d->truecolour;
+ } else {
+ tc.fg = tc.bg = optionalrgb_none;
+ }
+
switch (tchar & CSET_MASK) {
case CSET_ASCII:
tchar = term->ucsdata->unitab_line[tchar & 0xFF];
diff --git a/terminal.h b/terminal.h
index 21b8774a2..4a205a776 100644
--- a/terminal.h
+++ b/terminal.h
@@ -325,6 +325,7 @@ struct terminal_tag {
int scroll_on_disp;
int scroll_on_key;
int xterm_256_colour;
+ int true_colour;
};
#define in_utf(term) ((term)->utf || (term)->ucsdata->line_codepage==CP_UTF8)
diff --git a/windows/winhelp.h b/windows/winhelp.h
index 761c8c76a..dbe32c919 100644
--- a/windows/winhelp.h
+++ b/windows/winhelp.h
@@ -125,6 +125,7 @@
#define WINHELP_CTX_selection_rtf "selection.rtf:config-rtfpaste"
#define WINHELP_CTX_colours_ansi "colours.ansi:config-ansicolour"
#define WINHELP_CTX_colours_xterm256 "colours.xterm256:config-xtermcolour"
+#define WINHELP_CTX_colours_truecolour "colours.truecolour:config-truecolour"
#define WINHELP_CTX_colours_bold "colours.bold:config-boldcolour"
#define WINHELP_CTX_colours_system "colours.system:config-syscolour"
#define WINHELP_CTX_colours_logpal "colours.logpal:config-logpalette"
From 1adf211d70e162b50b18ede5a9c6ba6ae73ac8b2 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Thu, 5 Oct 2017 20:30:09 +0100
Subject: [PATCH 073/166] Disable true colour on monochrome or paletted
displays.
I'm not sure if any X11 monochrome visuals or Windows paletted display
modes are still around, but just in case they are, we shouldn't
attempt true colour on either kind of display.
---
unix/gtkwin.c | 3 +++
windows/window.c | 4 ++--
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/unix/gtkwin.c b/unix/gtkwin.c
index f49f92af6..94ba4069b 100644
--- a/unix/gtkwin.c
+++ b/unix/gtkwin.c
@@ -3255,6 +3255,9 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
} else
ncombining = 1;
+ if (monochrome)
+ truecolour.fg = truecolour.bg = optionalrgb_none;
+
nfg = ((monochrome ? ATTR_DEFFG : (attr & ATTR_FGMASK)) >> ATTR_FGSHIFT);
nbg = ((monochrome ? ATTR_DEFBG : (attr & ATTR_BGMASK)) >> ATTR_BGSHIFT);
if (!!(attr & ATTR_REVERSE) ^ (monochrome && (attr & TATTR_ACTCURS))) {
diff --git a/windows/window.c b/windows/window.c
index 452eb7716..79738ff9d 100644
--- a/windows/window.c
+++ b/windows/window.c
@@ -3522,12 +3522,12 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
if (nbg < 16) nbg |= 8;
else if (nbg >= 256) nbg |= 1;
}
- if (truecolour.fg.enabled)
+ if (!pal && truecolour.fg.enabled)
fg = RGB(truecolour.fg.r, truecolour.fg.g, truecolour.fg.b);
else
fg = colours[nfg];
- if (truecolour.bg.enabled)
+ if (!pal && truecolour.bg.enabled)
bg = RGB(truecolour.bg.r, truecolour.bg.g, truecolour.bg.b);
else
bg = colours[nbg];
From 262376a054719f0c248032df97be66142f0208e3 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Thu, 5 Oct 2017 20:30:04 +0100
Subject: [PATCH 074/166] Make the cursor colour override true colour.
Otherwise, moving the cursor (at least in active, filled-cell mode) on
to a true-coloured character cell causes it to vanish completely
because the cell's colours override the thing that differentiates the
cursor.
---
unix/gtkwin.c | 1 +
windows/window.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/unix/gtkwin.c b/unix/gtkwin.c
index 94ba4069b..dcff614ff 100644
--- a/unix/gtkwin.c
+++ b/unix/gtkwin.c
@@ -3274,6 +3274,7 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
else if (nbg >= 256) nbg |= 1;
}
if ((attr & TATTR_ACTCURS) && !monochrome) {
+ truecolour.fg = truecolour.bg = optionalrgb_none;
nfg = 260;
nbg = 261;
}
diff --git a/windows/window.c b/windows/window.c
index 79738ff9d..97c4d462a 100644
--- a/windows/window.c
+++ b/windows/window.c
@@ -3429,6 +3429,7 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
y += offset_height;
if ((attr & TATTR_ACTCURS) && (cursor_type == 0 || term->big_cursor)) {
+ truecolour.fg = truecolour.bg = optionalrgb_none;
attr &= ~(ATTR_REVERSE|ATTR_BLINK|ATTR_COLOURS);
/* cursor fg and bg */
attr |= (260 << ATTR_FGSHIFT) | (261 << ATTR_BGSHIFT);
From 4743798400e3eeae2902c4540da905a565f05c47 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Thu, 5 Oct 2017 20:43:02 +0100
Subject: [PATCH 075/166] Support OSC 4 terminal colour-palette queries.
Markus Gans points out that some applications which (not at all
unreasonably) don't trust $TERM to tell them the full capabilities of
their terminal will use the sequence "OSC 4 ; nn ; ? BEL" to ask for
the colour-palette value in position nn, and they may not particularly
care _what_ the results are but they will use them to decide whether
the right number of colour palette entries even exist.
---
fuzzterm.c | 1 +
putty.h | 1 +
terminal.c | 66 +++++++++++++++++++++++++++++++++++-------------
unix/gtkwin.c | 11 ++++++++
windows/window.c | 52 +++++++++++++++++++++++++-------------
5 files changed, 96 insertions(+), 35 deletions(-)
diff --git a/fuzzterm.c b/fuzzterm.c
index 480dca379..c57412c46 100644
--- a/fuzzterm.c
+++ b/fuzzterm.c
@@ -81,6 +81,7 @@ Context get_ctx(void *frontend) {
void free_ctx(Context ctx) { }
void palette_set(void *frontend, int a, int b, int c, int d) { }
void palette_reset(void *frontend) { }
+int palette_get(void *frontend, int n, int *r, int *g, int *b) {return FALSE;}
void write_clip(void *frontend, wchar_t *a, int *b, int c, int d) { }
void get_clip(void *frontend, wchar_t **w, int *i) { }
void set_raw_mouse_mode(void *frontend, int m) { }
diff --git a/putty.h b/putty.h
index 8a8b54254..f89d07097 100644
--- a/putty.h
+++ b/putty.h
@@ -633,6 +633,7 @@ Context get_ctx(void *frontend);
void free_ctx(Context);
void palette_set(void *frontend, int, int, int, int);
void palette_reset(void *frontend);
+int palette_get(void *frontend, int n, int *r, int *g, int *b);
void write_aclip(void *frontend, char *, int, int);
void write_clip(void *frontend, wchar_t *, int *, int, int);
void get_clip(void *frontend, wchar_t **, int *);
diff --git a/terminal.c b/terminal.c
index 5102db12a..0fa52e172 100644
--- a/terminal.c
+++ b/terminal.c
@@ -2727,6 +2727,22 @@ static void do_osc(Terminal *term)
if (!term->no_remote_wintitle)
set_title(term->frontend, term->osc_string);
break;
+ case 4:
+ if (term->ldisc && !strcmp(term->osc_string, "?")) {
+ int r, g, b;
+ if (palette_get(term->frontend, toint(term->esc_args[1]),
+ &r, &g, &b)) {
+ char *reply_buf = dupprintf(
+ "\033]4;%u;rgb:%04x/%04x/%04x\007",
+ term->esc_args[1],
+ (unsigned)r * 0x0101,
+ (unsigned)g * 0x0101,
+ (unsigned)b * 0x0101);
+ ldisc_send(term->ldisc, reply_buf, strlen(reply_buf), 0);
+ sfree(reply_buf);
+ }
+ }
+ break;
}
}
}
@@ -3365,6 +3381,7 @@ static void term_out(Terminal *term)
compatibility(OTHER);
term->termstate = SEEN_OSC;
term->esc_args[0] = 0;
+ term->esc_nargs = 1;
break;
case '7': /* DECSC: save cursor */
compatibility(VT100);
@@ -4470,25 +4487,40 @@ static void term_out(Terminal *term)
case '7':
case '8':
case '9':
- if (term->esc_args[0] <= UINT_MAX / 10 &&
- term->esc_args[0] * 10 <= UINT_MAX - c - '0')
- term->esc_args[0] = 10 * term->esc_args[0] + c - '0';
+ if (term->esc_args[term->esc_nargs-1] <= UINT_MAX / 10 &&
+ term->esc_args[term->esc_nargs-1] * 10 <= UINT_MAX - c - '0')
+ term->esc_args[term->esc_nargs-1] =
+ 10 * term->esc_args[term->esc_nargs-1] + c - '0';
else
- term->esc_args[0] = UINT_MAX;
+ term->esc_args[term->esc_nargs-1] = UINT_MAX;
break;
- case 'L':
- /*
- * Grotty hack to support xterm and DECterm title
- * sequences concurrently.
- */
- if (term->esc_args[0] == 2) {
- term->esc_args[0] = 1;
- break;
- }
- /* else fall through */
- default:
- term->termstate = OSC_STRING;
- term->osc_strlen = 0;
+ default:
+ /*
+ * _Most_ other characters here terminate the
+ * immediate parsing of the OSC sequence and go
+ * into OSC_STRING state, but we deal with a
+ * couple of exceptions first.
+ */
+ if (c == 'L' && term->esc_args[0] == 2) {
+ /*
+ * Grotty hack to support xterm and DECterm title
+ * sequences concurrently.
+ */
+ term->esc_args[0] = 1;
+ } else if (c == ';' && term->esc_nargs == 1 &&
+ term->esc_args[0] == 4) {
+ /*
+ * xterm's OSC 4 sequence to query the current
+ * RGB value of a colour takes a second
+ * numeric argument which is easiest to parse
+ * using the existing system rather than in
+ * do_osc.
+ */
+ term->esc_args[term->esc_nargs++] = 0;
+ } else {
+ term->termstate = OSC_STRING;
+ term->osc_strlen = 0;
+ }
}
break;
case OSC_STRING:
diff --git a/unix/gtkwin.c b/unix/gtkwin.c
index dcff614ff..969c42ffe 100644
--- a/unix/gtkwin.c
+++ b/unix/gtkwin.c
@@ -2222,6 +2222,17 @@ void palette_set(void *frontend, int n, int r, int g, int b)
}
}
+int palette_get(void *frontend, int n, int *r, int *g, int *b)
+{
+ struct gui_data *inst = (struct gui_data *)frontend;
+ if (n < 0 || n >= NALLCOLOURS)
+ return FALSE;
+ *r = inst->cols[n].red >> 8;
+ *g = inst->cols[n].green >> 8;
+ *b = inst->cols[n].blue >> 8;
+ return TRUE;
+}
+
void palette_reset(void *frontend)
{
struct gui_data *inst = (struct gui_data *)frontend;
diff --git a/windows/window.c b/windows/window.c
index 97c4d462a..aa96a5789 100644
--- a/windows/window.c
+++ b/windows/window.c
@@ -198,6 +198,9 @@ static int descent;
#define NEXTCOLOURS 240
#define NALLCOLOURS (NCFGCOLOURS + NEXTCOLOURS)
static COLORREF colours[NALLCOLOURS];
+struct rgb {
+ int r, g, b;
+} colours_rgb[NALLCOLOURS];
static HPALETTE pal;
static LPLOGPALETTE logpal;
static RGBTRIPLE defpal[NALLCOLOURS];
@@ -1264,6 +1267,19 @@ static void systopalette(void)
}
}
+static void internal_set_colour(int i, int r, int g, int b)
+{
+ assert(i >= 0);
+ assert(i < NALLCOLOURS);
+ if (pal)
+ colours[i] = PALETTERGB(r, g, b);
+ else
+ colours[i] = RGB(r, g, b);
+ colours_rgb[i].r = r;
+ colours_rgb[i].g = g;
+ colours_rgb[i].b = b;
+}
+
/*
* Set up the colour palette.
*/
@@ -1298,15 +1314,9 @@ static void init_palette(void)
}
ReleaseDC(hwnd, hdc);
}
- if (pal)
- for (i = 0; i < NALLCOLOURS; i++)
- colours[i] = PALETTERGB(defpal[i].rgbtRed,
- defpal[i].rgbtGreen,
- defpal[i].rgbtBlue);
- else
- for (i = 0; i < NALLCOLOURS; i++)
- colours[i] = RGB(defpal[i].rgbtRed,
- defpal[i].rgbtGreen, defpal[i].rgbtBlue);
+ for (i = 0; i < NALLCOLOURS; i++)
+ internal_set_colour(i, defpal[i].rgbtRed,
+ defpal[i].rgbtGreen, defpal[i].rgbtBlue);
}
/*
@@ -4865,15 +4875,24 @@ void free_ctx(Context ctx)
static void real_palette_set(int n, int r, int g, int b)
{
+ internal_set_colour(n, r, g, b);
if (pal) {
logpal->palPalEntry[n].peRed = r;
logpal->palPalEntry[n].peGreen = g;
logpal->palPalEntry[n].peBlue = b;
logpal->palPalEntry[n].peFlags = PC_NOCOLLAPSE;
- colours[n] = PALETTERGB(r, g, b);
SetPaletteEntries(pal, 0, NALLCOLOURS, logpal->palPalEntry);
- } else
- colours[n] = RGB(r, g, b);
+ }
+}
+
+int palette_get(void *frontend, int n, int *r, int *g, int *b)
+{
+ if (n < 0 || n >= NALLCOLOURS)
+ return FALSE;
+ *r = colours_rgb[n].r;
+ *g = colours_rgb[n].g;
+ *b = colours_rgb[n].b;
+ return TRUE;
}
void palette_set(void *frontend, int n, int r, int g, int b)
@@ -4903,17 +4922,14 @@ void palette_reset(void *frontend)
/* And this */
for (i = 0; i < NALLCOLOURS; i++) {
+ internal_set_colour(i, defpal[i].rgbtRed,
+ defpal[i].rgbtGreen, defpal[i].rgbtBlue);
if (pal) {
logpal->palPalEntry[i].peRed = defpal[i].rgbtRed;
logpal->palPalEntry[i].peGreen = defpal[i].rgbtGreen;
logpal->palPalEntry[i].peBlue = defpal[i].rgbtBlue;
logpal->palPalEntry[i].peFlags = 0;
- colours[i] = PALETTERGB(defpal[i].rgbtRed,
- defpal[i].rgbtGreen,
- defpal[i].rgbtBlue);
- } else
- colours[i] = RGB(defpal[i].rgbtRed,
- defpal[i].rgbtGreen, defpal[i].rgbtBlue);
+ }
}
if (pal) {
From 1a718403d40ccb88a1436eff98c82bf92268ef96 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Thu, 5 Oct 2017 21:02:56 +0100
Subject: [PATCH 076/166] Support SGR 2 to dim the foreground colour.
I've done this on a 'where possible' basis: in Windows paletted mode
(in case anyone is still using an old enough graphics card to need
that!) I simply haven't bothered, and will completely ignore the dim
flag.
---
putty.h | 19 ++++++++-------
terminal.c | 8 +++++--
unix/gtkwin.c | 61 ++++++++++++++++++++++++++++++++++--------------
windows/window.c | 8 ++++++-
4 files changed, 67 insertions(+), 29 deletions(-)
diff --git a/putty.h b/putty.h
index f89d07097..a9433fa70 100644
--- a/putty.h
+++ b/putty.h
@@ -104,15 +104,16 @@ typedef struct terminal_tag Terminal;
*/
#define UCSWIDE 0xDFFF
-#define ATTR_NARROW 0x800000U
-#define ATTR_WIDE 0x400000U
-#define ATTR_BOLD 0x040000U
-#define ATTR_UNDER 0x080000U
-#define ATTR_REVERSE 0x100000U
-#define ATTR_BLINK 0x200000U
-#define ATTR_FGMASK 0x0001FFU
-#define ATTR_BGMASK 0x03FE00U
-#define ATTR_COLOURS 0x03FFFFU
+#define ATTR_NARROW 0x0800000U
+#define ATTR_WIDE 0x0400000U
+#define ATTR_BOLD 0x0040000U
+#define ATTR_UNDER 0x0080000U
+#define ATTR_REVERSE 0x0100000U
+#define ATTR_BLINK 0x0200000U
+#define ATTR_FGMASK 0x00001FFU
+#define ATTR_BGMASK 0x003FE00U
+#define ATTR_COLOURS 0x003FFFFU
+#define ATTR_DIM 0x1000000U
#define ATTR_FGSHIFT 0
#define ATTR_BGSHIFT 9
diff --git a/terminal.c b/terminal.c
index 0fa52e172..de5748e96 100644
--- a/terminal.c
+++ b/terminal.c
@@ -3881,6 +3881,10 @@ static void term_out(Terminal *term)
compatibility(VT100AVO);
term->curr_attr |= ATTR_BOLD;
break;
+ case 2: /* enable dim */
+ compatibility(OTHER);
+ term->curr_attr |= ATTR_DIM;
+ break;
case 21: /* (enable double underline) */
compatibility(OTHER);
case 4: /* enable underline */
@@ -3912,9 +3916,9 @@ static void term_out(Terminal *term)
compatibility(SCOANSI);
if (term->no_remote_charset) break;
term->sco_acs = 2; break;
- case 22: /* disable bold */
+ case 22: /* disable bold and dim */
compatibility2(OTHER, VT220);
- term->curr_attr &= ~ATTR_BOLD;
+ term->curr_attr &= ~(ATTR_BOLD | ATTR_DIM);
break;
case 24: /* disable underline */
compatibility2(OTHER, VT220);
diff --git a/unix/gtkwin.c b/unix/gtkwin.c
index 969c42ffe..5c6295190 100644
--- a/unix/gtkwin.c
+++ b/unix/gtkwin.c
@@ -3023,24 +3023,44 @@ static void draw_update(struct draw_ctx *dctx, int x, int y, int w, int h)
gtk_widget_queue_draw_area(dctx->inst->area, x, y, w, h);
}
-static void draw_set_colour(struct draw_ctx *dctx, int col)
+#ifdef DRAW_TEXT_CAIRO
+static void cairo_set_source_rgb_dim(cairo_t *cr, double r, double g, double b,
+ int dim)
+{
+ if (dim)
+ cairo_set_source_rgb(cr, r * 2 / 3, g * 2 / 3, b * 2 / 3);
+ else
+ cairo_set_source_rgb(cr, r, g, b);
+}
+#endif
+
+static void draw_set_colour(struct draw_ctx *dctx, int col, int dim)
{
#ifdef DRAW_TEXT_GDK
if (dctx->uctx.type == DRAWTYPE_GDK) {
- gdk_gc_set_foreground(dctx->uctx.u.gdk.gc, &dctx->inst->cols[col]);
+ if (dim) {
+ GdkColor color;
+ color.red = dctx->inst->cols[col].red * 2 / 3;
+ color.green = dctx->inst->cols[col].green * 2 / 3;
+ color.blue = dctx->inst->cols[col].blue * 2 / 3;
+ gdk_gc_set_rgb_fg_color(dctx->uctx.u.gdk.gc, &color);
+ } else {
+ gdk_gc_set_foreground(dctx->uctx.u.gdk.gc, &dctx->inst->cols[col]);
+ }
}
#endif
#ifdef DRAW_TEXT_CAIRO
if (dctx->uctx.type == DRAWTYPE_CAIRO) {
- cairo_set_source_rgb(dctx->uctx.u.cairo.cr,
- dctx->inst->cols[col].red / 65535.0,
- dctx->inst->cols[col].green / 65535.0,
- dctx->inst->cols[col].blue / 65535.0);
+ cairo_set_source_rgb_dim(dctx->uctx.u.cairo.cr,
+ dctx->inst->cols[col].red / 65535.0,
+ dctx->inst->cols[col].green / 65535.0,
+ dctx->inst->cols[col].blue / 65535.0, dim);
}
#endif
}
-static void draw_set_colour_rgb(struct draw_ctx *dctx, optionalrgb orgb)
+static void draw_set_colour_rgb(struct draw_ctx *dctx, optionalrgb orgb,
+ int dim)
{
#ifdef DRAW_TEXT_GDK
if (dctx->uctx.type == DRAWTYPE_GDK) {
@@ -3048,13 +3068,19 @@ static void draw_set_colour_rgb(struct draw_ctx *dctx, optionalrgb orgb)
color.red = orgb.r * 256;
color.green = orgb.g * 256;
color.blue = orgb.b * 256;
+ if (dim) {
+ color.red = color.red * 2 / 3;
+ color.green = color.green * 2 / 3;
+ color.blue = color.blue * 2 / 3;
+ }
gdk_gc_set_rgb_fg_color(dctx->uctx.u.gdk.gc, &color);
}
#endif
#ifdef DRAW_TEXT_CAIRO
- if (dctx->uctx.type == DRAWTYPE_CAIRO)
- cairo_set_source_rgb(dctx->uctx.u.cairo.cr,
- orgb.r / 255.0, orgb.g / 255.0, orgb.b / 255.0);
+ if (dctx->uctx.type == DRAWTYPE_CAIRO) {
+ cairo_set_source_rgb_dim(dctx->uctx.u.cairo.cr, orgb.r / 255.0,
+ orgb.g / 255.0, orgb.b / 255.0, dim);
+ }
#endif
}
@@ -3238,7 +3264,7 @@ static void draw_backing_rect(struct gui_data *inst)
struct draw_ctx *dctx = get_ctx(inst);
int w = inst->width * inst->font_width + 2*inst->window_border;
int h = inst->height * inst->font_height + 2*inst->window_border;
- draw_set_colour(dctx, 258);
+ draw_set_colour(dctx, 258, FALSE);
draw_rectangle(dctx, 1, 0, 0, w, h);
draw_update(dctx, 0, 0, w, h);
free_ctx(dctx);
@@ -3288,6 +3314,7 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
truecolour.fg = truecolour.bg = optionalrgb_none;
nfg = 260;
nbg = 261;
+ attr &= ~ATTR_DIM; /* don't dim the cursor */
}
fontid = shadow = 0;
@@ -3350,18 +3377,18 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
}
if (truecolour.bg.enabled)
- draw_set_colour_rgb(dctx, truecolour.bg);
+ draw_set_colour_rgb(dctx, truecolour.bg, attr & ATTR_DIM);
else
- draw_set_colour(dctx, nbg);
+ draw_set_colour(dctx, nbg, attr & ATTR_DIM);
draw_rectangle(dctx, TRUE,
x*inst->font_width+inst->window_border,
y*inst->font_height+inst->window_border,
rlen*widefactor*inst->font_width, inst->font_height);
if (truecolour.fg.enabled)
- draw_set_colour_rgb(dctx, truecolour.fg);
+ draw_set_colour_rgb(dctx, truecolour.fg, attr & ATTR_DIM);
else
- draw_set_colour(dctx, nfg);
+ draw_set_colour(dctx, nfg, attr & ATTR_DIM);
if (ncombining > 1) {
assert(len == 1);
unifont_draw_combining(&dctx->uctx, inst->fonts[fontid],
@@ -3475,7 +3502,7 @@ void do_cursor(Context ctx, int x, int y, wchar_t *text, int len,
* if it's passive.
*/
if (passive) {
- draw_set_colour(dctx, 261);
+ draw_set_colour(dctx, 261, FALSE);
draw_rectangle(dctx, FALSE,
x*inst->font_width+inst->window_border,
y*inst->font_height+inst->window_border,
@@ -3514,7 +3541,7 @@ void do_cursor(Context ctx, int x, int y, wchar_t *text, int len,
length = inst->font_height;
}
- draw_set_colour(dctx, 261);
+ draw_set_colour(dctx, 261, FALSE);
if (passive) {
for (i = 0; i < length; i++) {
if (i % 2 == 0) {
diff --git a/windows/window.c b/windows/window.c
index aa96a5789..be7b4379e 100644
--- a/windows/window.c
+++ b/windows/window.c
@@ -3440,7 +3440,7 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
if ((attr & TATTR_ACTCURS) && (cursor_type == 0 || term->big_cursor)) {
truecolour.fg = truecolour.bg = optionalrgb_none;
- attr &= ~(ATTR_REVERSE|ATTR_BLINK|ATTR_COLOURS);
+ attr &= ~(ATTR_REVERSE|ATTR_BLINK|ATTR_COLOURS|ATTR_DIM);
/* cursor fg and bg */
attr |= (260 << ATTR_FGSHIFT) | (261 << ATTR_BGSHIFT);
is_cursor = TRUE;
@@ -3543,6 +3543,12 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
else
bg = colours[nbg];
+ if (!pal && (attr & ATTR_DIM)) {
+ fg = RGB(GetRValue(fg) * 2 / 3,
+ GetGValue(fg) * 2 / 3,
+ GetBValue(fg) * 2 / 3);
+ }
+
SelectObject(hdc, fonts[nfont]);
SetTextColor(hdc, fg);
SetBkColor(hdc, bg);
From 96a088195fe86cb31347b42b1c262c1aa2ee0a2f Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sun, 8 Oct 2017 13:43:27 +0100
Subject: [PATCH 077/166] Make true colour work with background-colour erase.
Thanks to Markus Gans for reporting this bug.
---
terminal.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/terminal.c b/terminal.c
index de5748e96..8c44b9062 100644
--- a/terminal.c
+++ b/terminal.c
@@ -1407,9 +1407,11 @@ void term_pwron(Terminal *term, int clear)
static void set_erase_char(Terminal *term)
{
term->erase_char = term->basic_erase_char;
- if (term->use_bce)
+ if (term->use_bce) {
term->erase_char.attr = (term->curr_attr &
(ATTR_FGMASK | ATTR_BGMASK));
+ term->erase_char.truecolour.bg = term->curr_truecolour.bg;
+ }
}
/*
From e3d92df936b97aef3cd51f1e85eb3c47409069c5 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sun, 8 Oct 2017 13:45:08 +0100
Subject: [PATCH 078/166] Save and restore true-colour state with the cursor.
I spotted this myself while looking through the code in search of the
cause of the background-colour-erase bug: saving and restoring the
cursor via ESC 7 / ESC 8 ought to also save and restore the current
graphics rendition attributes including foreground and background
colour settings, but it was not saving and restoring the new
term->curr_truecolour along with term->curr_attr.
So there's now a term->save_truecolour to keep that in, and also a
term->alt_save_truecolour to take account of the fact that all the
saved cursor state variables get swapped out _again_ when switching
between the main and alternate screens.
(However, there is not a term->alt_truecolour to complete the cross
product, because the _active_ graphics rendition is carried over when
switching between the terminal screens; it's only the _saved_ one from
ESC 7 / ESC 8 that is saved separately. That's consistent with the
behaviour we've had all along for ordinary fg/bg colour selection.)
---
terminal.c | 8 ++++++++
terminal.h | 1 +
2 files changed, 9 insertions(+)
diff --git a/terminal.c b/terminal.c
index 8c44b9062..7a7207a0d 100644
--- a/terminal.c
+++ b/terminal.c
@@ -1297,6 +1297,7 @@ static void power_on(Terminal *term, int clear)
term->default_attr = term->save_attr =
term->alt_save_attr = term->curr_attr = ATTR_DEFAULT;
term->curr_truecolour.fg = term->curr_truecolour.bg = optionalrgb_none;
+ term->save_truecolour = term->alt_save_truecolour = term->curr_truecolour;
term->term_editing = term->term_echoing = FALSE;
term->app_cursor_keys = conf_get_int(term->conf, CONF_app_cursor);
term->app_keypad_keys = conf_get_int(term->conf, CONF_app_keypad);
@@ -1987,6 +1988,7 @@ static void swap_screen(Terminal *term, int which, int reset, int keep_cur_pos)
{
int t;
pos tp;
+ truecolour ttc;
tree234 *ttr;
if (!which)
@@ -2051,6 +2053,10 @@ static void swap_screen(Terminal *term, int which, int reset, int keep_cur_pos)
if (!reset && !keep_cur_pos)
term->save_attr = term->alt_save_attr;
term->alt_save_attr = t;
+ ttc = term->save_truecolour;
+ if (!reset && !keep_cur_pos)
+ term->save_truecolour = term->alt_save_truecolour;
+ term->alt_save_truecolour = ttc;
t = term->save_utf;
if (!reset && !keep_cur_pos)
term->save_utf = term->alt_save_utf;
@@ -2346,6 +2352,7 @@ static void save_cursor(Terminal *term, int save)
if (save) {
term->savecurs = term->curs;
term->save_attr = term->curr_attr;
+ term->save_truecolour = term->curr_truecolour;
term->save_cset = term->cset;
term->save_utf = term->utf;
term->save_wnext = term->wrapnext;
@@ -2360,6 +2367,7 @@ static void save_cursor(Terminal *term, int save)
term->curs.y = term->rows - 1;
term->curr_attr = term->save_attr;
+ term->curr_truecolour = term->save_truecolour;
term->cset = term->save_cset;
term->utf = term->save_utf;
term->wrapnext = term->save_wnext;
diff --git a/terminal.h b/terminal.h
index 4a205a776..fcb321c41 100644
--- a/terminal.h
+++ b/terminal.h
@@ -140,6 +140,7 @@ struct terminal_tag {
/* ESC 7 saved state for the alternate screen */
pos alt_savecurs;
int alt_save_attr;
+ truecolour alt_save_truecolour;
int alt_save_cset, alt_save_csattr;
int alt_save_utf, alt_save_wnext;
int alt_save_sco_acs;
From f353e2219e4371cda176bc37a11ddc4bb7e32516 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sun, 8 Oct 2017 13:47:39 +0100
Subject: [PATCH 079/166] Turn off true colour on SCO and VT52 colour
sequences.
After fixing the previous two bugs, I thought it was probably a good
idea to re-check _everywhere_ in terminal.c where curr_attr is used,
to make sure that if curr_truecolour also needed updating at the same
time then that was being done.
---
terminal.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/terminal.c b/terminal.c
index 7a7207a0d..a55b6e6ac 100644
--- a/terminal.c
+++ b/terminal.c
@@ -4370,6 +4370,7 @@ static void term_out(Terminal *term)
ATTR_FGSHIFT;
term->curr_attr &= ~ATTR_FGMASK;
term->curr_attr |= colour;
+ term->curr_truecolour.fg = optionalrgb_none;
term->default_attr &= ~ATTR_FGMASK;
term->default_attr |= colour;
set_erase_char(term);
@@ -4384,6 +4385,7 @@ static void term_out(Terminal *term)
ATTR_BGSHIFT;
term->curr_attr &= ~ATTR_BGMASK;
term->curr_attr |= colour;
+ term->curr_truecolour.bg = optionalrgb_none;
term->default_attr &= ~ATTR_BGMASK;
term->default_attr |= colour;
set_erase_char(term);
@@ -4811,6 +4813,8 @@ static void term_out(Terminal *term)
/* compatibility(OTHER) */
term->vt52_bold = FALSE;
term->curr_attr = ATTR_DEFAULT;
+ term->curr_truecolour.fg = optionalrgb_none;
+ term->curr_truecolour.bg = optionalrgb_none;
set_erase_char(term);
break;
case 'S':
From 916a2574d5fb40ee9ce899ac93e8d31738f5bed4 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sun, 8 Oct 2017 13:49:54 +0100
Subject: [PATCH 080/166] Make reverse video interact correctly with true
colour.
ATTR_REVERSE was being handled in the front ends, and was causing the
foreground and background colours to be switched. (I'm not completely
sure why I made that design decision; it might be purely historical,
but then again, it might also be because reverse video is one effect
on the fg and bg colours that must still be performed even in unusual
frontend-specific situations like display-driven monochrome mode.)
This affected both explicit reverse video enabled using SGR 7, and
also the transient reverse video arising from mouse selection. Thanks
to Markus Gans for reporting the bug in the latter, which when I
investigated it turned out to affect the former as well.
---
terminal.h | 2 +-
unix/gtkwin.c | 6 ++++++
windows/window.c | 6 ++++++
3 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/terminal.h b/terminal.h
index fcb321c41..03659744b 100644
--- a/terminal.h
+++ b/terminal.h
@@ -103,7 +103,7 @@ struct terminal_tag {
#endif /* OPTIMISE_SCROLL */
int default_attr, curr_attr, save_attr;
- truecolour curr_truecolour;
+ truecolour curr_truecolour, save_truecolour;
termchar basic_erase_char, erase_char;
bufchain inbuf; /* terminal input buffer */
diff --git a/unix/gtkwin.c b/unix/gtkwin.c
index 5c6295190..3e12a4ba9 100644
--- a/unix/gtkwin.c
+++ b/unix/gtkwin.c
@@ -3298,9 +3298,15 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
nfg = ((monochrome ? ATTR_DEFFG : (attr & ATTR_FGMASK)) >> ATTR_FGSHIFT);
nbg = ((monochrome ? ATTR_DEFBG : (attr & ATTR_BGMASK)) >> ATTR_BGSHIFT);
if (!!(attr & ATTR_REVERSE) ^ (monochrome && (attr & TATTR_ACTCURS))) {
+ struct optionalrgb trgb;
+
t = nfg;
nfg = nbg;
nbg = t;
+
+ trgb = truecolour.fg;
+ truecolour.fg = truecolour.bg;
+ truecolour.bg = trgb;
}
if ((inst->bold_style & 2) && (attr & ATTR_BOLD)) {
if (nfg < 16) nfg |= 8;
diff --git a/windows/window.c b/windows/window.c
index be7b4379e..73f0751c9 100644
--- a/windows/window.c
+++ b/windows/window.c
@@ -3521,9 +3521,15 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
if (!fonts[nfont])
nfont = FONT_NORMAL;
if (attr & ATTR_REVERSE) {
+ struct optionalrgb trgb;
+
t = nfg;
nfg = nbg;
nbg = t;
+
+ trgb = truecolour.fg;
+ truecolour.fg = truecolour.bg;
+ truecolour.bg = trgb;
}
if (bold_colours && (attr & ATTR_BOLD) && !is_cursor) {
if (nfg < 16) nfg |= 8;
From 298b9fd4d40a86b192a23a6bceac1f06f89f9eaf Mon Sep 17 00:00:00 2001
From: Jeff Smith
Date: Fri, 13 Oct 2017 22:49:25 -0500
Subject: [PATCH 081/166] Setting an 8-bit colour should cancel a 24-bit colour
---
terminal.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/terminal.c b/terminal.c
index a55b6e6ac..2106d10a3 100644
--- a/terminal.c
+++ b/terminal.c
@@ -4031,6 +4031,8 @@ static void term_out(Terminal *term)
term->curr_attr |=
((term->esc_args[i+2] & 0xFF)
<< ATTR_FGSHIFT);
+ term->curr_truecolour.fg =
+ optionalrgb_none;
i += 2;
}
if (i + 4 < term->esc_nargs &&
@@ -4048,6 +4050,8 @@ static void term_out(Terminal *term)
term->curr_attr |=
((term->esc_args[i+2] & 0xFF)
<< ATTR_BGSHIFT);
+ term->curr_truecolour.bg =
+ optionalrgb_none;
i += 2;
}
if (i + 4 < term->esc_nargs &&
From 7bdfdabb5e1c7418074ff43d9b436033c96aa00c Mon Sep 17 00:00:00 2001
From: Jeff Smith
Date: Wed, 14 Jun 2017 08:11:05 -0500
Subject: [PATCH 082/166] Update clipping interface for true-colour
---
fuzzterm.c | 2 +-
putty.h | 2 +-
terminal.c | 19 ++++++++++++++-----
unix/gtkwin.c | 8 ++++----
windows/window.c | 3 ++-
5 files changed, 22 insertions(+), 12 deletions(-)
diff --git a/fuzzterm.c b/fuzzterm.c
index c57412c46..255fc6fb7 100644
--- a/fuzzterm.c
+++ b/fuzzterm.c
@@ -82,7 +82,7 @@ void free_ctx(Context ctx) { }
void palette_set(void *frontend, int a, int b, int c, int d) { }
void palette_reset(void *frontend) { }
int palette_get(void *frontend, int n, int *r, int *g, int *b) {return FALSE;}
-void write_clip(void *frontend, wchar_t *a, int *b, int c, int d) { }
+void write_clip(void *frontend, wchar_t *a, int *b, truecolour *c, int d, int e) { }
void get_clip(void *frontend, wchar_t **w, int *i) { }
void set_raw_mouse_mode(void *frontend, int m) { }
void request_paste(void *frontend) { }
diff --git a/putty.h b/putty.h
index a9433fa70..ac35eb73f 100644
--- a/putty.h
+++ b/putty.h
@@ -636,7 +636,7 @@ void palette_set(void *frontend, int, int, int, int);
void palette_reset(void *frontend);
int palette_get(void *frontend, int n, int *r, int *g, int *b);
void write_aclip(void *frontend, char *, int, int);
-void write_clip(void *frontend, wchar_t *, int *, int, int);
+void write_clip(void *frontend, wchar_t *, int *, truecolour *, int, int);
void get_clip(void *frontend, wchar_t **, int *);
void optimised_move(void *frontend, int, int, int);
void set_raw_mouse_mode(void *frontend, int);
diff --git a/terminal.c b/terminal.c
index 2106d10a3..d32d4f423 100644
--- a/terminal.c
+++ b/terminal.c
@@ -5616,9 +5616,11 @@ typedef struct {
wchar_t *textptr; /* = textbuf + bufpos (current insertion point) */
int *attrbuf; /* buffer for copied attributes */
int *attrptr; /* = attrbuf + bufpos */
+ truecolour *tcbuf; /* buffer for copied colours */
+ truecolour *tcptr; /* = tcbuf + bufpos */
} clip_workbuf;
-static void clip_addchar(clip_workbuf *b, wchar_t chr, int attr)
+static void clip_addchar(clip_workbuf *b, wchar_t chr, int attr, truecolour tc)
{
if (b->bufpos >= b->buflen) {
b->buflen *= 2;
@@ -5626,9 +5628,12 @@ static void clip_addchar(clip_workbuf *b, wchar_t chr, int attr)
b->textptr = b->textbuf + b->bufpos;
b->attrbuf = sresize(b->attrbuf, b->buflen, int);
b->attrptr = b->attrbuf + b->bufpos;
+ b->tcbuf = sresize(b->tcbuf, b->buflen, truecolour);
+ b->tcptr = b->tcbuf + b->bufpos;
}
*b->textptr++ = chr;
*b->attrptr++ = attr;
+ *b->tcptr++ = tc;
b->bufpos++;
}
@@ -5637,11 +5642,13 @@ static void clipme(Terminal *term, pos top, pos bottom, int rect, int desel)
clip_workbuf buf;
int old_top_x;
int attr;
+ truecolour tc;
buf.buflen = 5120;
buf.bufpos = 0;
buf.textptr = buf.textbuf = snewn(buf.buflen, wchar_t);
buf.attrptr = buf.attrbuf = snewn(buf.buflen, int);
+ buf.tcptr = buf.tcbuf = snewn(buf.buflen, truecolour);
old_top_x = top.x; /* needed for rect==1 */
@@ -5707,6 +5714,7 @@ static void clipme(Terminal *term, pos top, pos bottom, int rect, int desel)
while (1) {
int uc = ldata->chars[x].chr;
attr = ldata->chars[x].attr;
+ tc = ldata->chars[x].truecolour;
switch (uc & CSET_MASK) {
case CSET_LINEDRW:
@@ -5767,7 +5775,7 @@ static void clipme(Terminal *term, pos top, pos bottom, int rect, int desel)
#endif
for (p = cbuf; *p; p++)
- clip_addchar(&buf, *p, attr);
+ clip_addchar(&buf, *p, attr, tc);
if (ldata->chars[x].cc_next)
x += ldata->chars[x].cc_next;
@@ -5779,7 +5787,7 @@ static void clipme(Terminal *term, pos top, pos bottom, int rect, int desel)
if (nl) {
int i;
for (i = 0; i < sel_nl_sz; i++)
- clip_addchar(&buf, sel_nl[i], 0);
+ clip_addchar(&buf, sel_nl[i], 0, term->basic_erase_char.truecolour);
}
top.y++;
top.x = rect ? old_top_x : 0;
@@ -5787,12 +5795,13 @@ static void clipme(Terminal *term, pos top, pos bottom, int rect, int desel)
unlineptr(ldata);
}
#if SELECTION_NUL_TERMINATED
- clip_addchar(&buf, 0, 0);
+ clip_addchar(&buf, 0, 0, term->basic_erase_char.truecolour);
#endif
/* Finally, transfer all that to the clipboard. */
- write_clip(term->frontend, buf.textbuf, buf.attrbuf, buf.bufpos, desel);
+ write_clip(term->frontend, buf.textbuf, buf.attrbuf, buf.tcbuf, buf.bufpos, desel);
sfree(buf.textbuf);
sfree(buf.attrbuf);
+ sfree(buf.tcbuf);
}
void term_copyall(Terminal *term)
diff --git a/unix/gtkwin.c b/unix/gtkwin.c
index 3e12a4ba9..3a3c2a546 100644
--- a/unix/gtkwin.c
+++ b/unix/gtkwin.c
@@ -2360,8 +2360,8 @@ static void clipboard_clear(GtkClipboard *clipboard, gpointer data)
sfree(cdi);
}
-void write_clip(void *frontend, wchar_t *data, int *attr, int len,
- int must_deselect)
+void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour,
+ int len, int must_deselect)
{
struct gui_data *inst = (struct gui_data *)frontend;
struct clipboard_data_instance *cdi;
@@ -2488,8 +2488,8 @@ static char *retrieve_cutbuffer(int *nbytes)
#endif
}
-void write_clip(void *frontend, wchar_t *data, int *attr, int len,
- int must_deselect)
+void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour,
+ int len, int must_deselect)
{
struct gui_data *inst = (struct gui_data *)frontend;
if (inst->pasteout_data)
diff --git a/windows/window.c b/windows/window.c
index 73f0751c9..8faa57e93 100644
--- a/windows/window.c
+++ b/windows/window.c
@@ -4989,7 +4989,8 @@ void write_aclip(void *frontend, char *data, int len, int must_deselect)
/*
* Note: unlike write_aclip() this will not append a nul.
*/
-void write_clip(void *frontend, wchar_t * data, int *attr, int len, int must_deselect)
+void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour,
+ int len, int must_deselect)
{
HGLOBAL clipdata, clipdata2, clipdata3;
int len2;
From 891d909b3d7fb206e1055feaafbb25e771393ce2 Mon Sep 17 00:00:00 2001
From: Jeff Smith
Date: Mon, 12 Jun 2017 23:55:57 -0500
Subject: [PATCH 083/166] Implement true-colour in write_clip for Windows
This allows text copied from PuTTY to a rich-text program to retain the
true-colour attribute.
---
windows/window.c | 126 +++++++++++++++++++++++++++++++++++++++++------
1 file changed, 111 insertions(+), 15 deletions(-)
diff --git a/windows/window.c b/windows/window.c
index 8faa57e93..88a29dd40 100644
--- a/windows/window.c
+++ b/windows/window.c
@@ -24,6 +24,7 @@
#include "storage.h"
#include "win_res.h"
#include "winsecur.h"
+#include "tree234.h"
#ifndef NO_MULTIMON
#include
@@ -4986,6 +4987,18 @@ void write_aclip(void *frontend, char *data, int len, int must_deselect)
SendMessage(hwnd, WM_IGNORE_CLIP, FALSE, 0);
}
+typedef struct _rgbindex {
+ int index;
+ COLORREF ref;
+} rgbindex;
+
+int cmpCOLORREF(void *va, void *vb)
+{
+ COLORREF a = ((rgbindex *)va)->ref;
+ COLORREF b = ((rgbindex *)vb)->ref;
+ return (a < b) ? -1 : (a > b) ? +1 : 0;
+}
+
/*
* Note: unlike write_aclip() this will not append a nul.
*/
@@ -5033,12 +5046,15 @@ void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour
int rtfsize = 0;
int multilen, blen, alen, totallen, i;
char before[16], after[4];
- int fgcolour, lastfgcolour = 0;
- int bgcolour, lastbgcolour = 0;
+ int fgcolour, lastfgcolour = -1;
+ int bgcolour, lastbgcolour = -1;
+ COLORREF fg, lastfg = -1;
+ COLORREF bg, lastbg = -1;
int attrBold, lastAttrBold = 0;
int attrUnder, lastAttrUnder = 0;
int palette[NALLCOLOURS];
int numcolours;
+ tree234 *rgbtree = NULL;
FontSpec *font = conf_get_fontspec(conf, CONF_font);
get_unitab(CP_ACP, unitab, 0);
@@ -5076,7 +5092,7 @@ void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour
fgcolour ++;
}
- if (attr[i] & ATTR_BLINK) {
+ if ((attr[i] & ATTR_BLINK)) {
if (bgcolour < 8) /* ANSI colours */
bgcolour += 8;
else if (bgcolour >= 256) /* Default colours */
@@ -5087,6 +5103,28 @@ void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour
palette[bgcolour]++;
}
+ if (truecolour) {
+ rgbtree = newtree234(cmpCOLORREF);
+ for (i = 0; i < (len-1); i++) {
+ if (truecolour[i].fg.enabled) {
+ rgbindex *rgbp = snew(rgbindex);
+ rgbp->ref = RGB(truecolour[i].fg.r,
+ truecolour[i].fg.g,
+ truecolour[i].fg.b);
+ if (add234(rgbtree, rgbp) != rgbp)
+ sfree(rgbp);
+ }
+ if (truecolour[i].bg.enabled) {
+ rgbindex *rgbp = snew(rgbindex);
+ rgbp->ref = RGB(truecolour[i].bg.r,
+ truecolour[i].bg.g,
+ truecolour[i].bg.b);
+ if (add234(rgbtree, rgbp) != rgbp)
+ sfree(rgbp);
+ }
+ }
+ }
+
/*
* Next - Create a reduced palette
*/
@@ -5096,6 +5134,12 @@ void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour
palette[i] = ++numcolours;
}
+ if (rgbtree) {
+ rgbindex *rgbp;
+ for (i = 0; (rgbp = index234(rgbtree, i)) != NULL; i++)
+ rgbp->index = ++numcolours;
+ }
+
/*
* Finally - Write the colour table
*/
@@ -5108,6 +5152,12 @@ void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour
rtflen += sprintf(&rtf[rtflen], "\\red%d\\green%d\\blue%d;", defpal[i].rgbtRed, defpal[i].rgbtGreen, defpal[i].rgbtBlue);
}
}
+ if (rgbtree) {
+ rgbindex *rgbp;
+ for (i = 0; (rgbp = index234(rgbtree, i)) != NULL; i++)
+ rtflen += sprintf(&rtf[rtflen], "\\red%d\\green%d\\blue%d;",
+ GetRValue(rgbp->ref), GetGValue(rgbp->ref), GetBValue(rgbp->ref));
+ }
strcpy(&rtf[rtflen], "}");
rtflen ++;
}
@@ -5151,23 +5201,44 @@ void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour
/*
* Determine foreground and background colours
*/
- fgcolour = ((attr[tindex] & ATTR_FGMASK) >> ATTR_FGSHIFT);
- bgcolour = ((attr[tindex] & ATTR_BGMASK) >> ATTR_BGSHIFT);
+ if (truecolour && truecolour[tindex].fg.enabled) {
+ fgcolour = -1;
+ fg = RGB(truecolour[tindex].fg.r,
+ truecolour[tindex].fg.g,
+ truecolour[tindex].fg.b);
+ } else {
+ fgcolour = ((attr[tindex] & ATTR_FGMASK) >> ATTR_FGSHIFT);
+ fg = -1;
+ }
+
+ if (truecolour && truecolour[tindex].bg.enabled) {
+ bgcolour = -1;
+ bg = RGB(truecolour[tindex].bg.r,
+ truecolour[tindex].bg.g,
+ truecolour[tindex].bg.b);
+ } else {
+ bgcolour = ((attr[tindex] & ATTR_BGMASK) >> ATTR_BGSHIFT);
+ bg = -1;
+ }
if (attr[tindex] & ATTR_REVERSE) {
int tmpcolour = fgcolour; /* Swap foreground and background */
fgcolour = bgcolour;
bgcolour = tmpcolour;
+
+ COLORREF tmpref = fg;
+ fg = bg;
+ bg = tmpref;
}
- if (bold_colours && (attr[tindex] & ATTR_BOLD)) {
+ if (bold_colours && (attr[tindex] & ATTR_BOLD) && (fgcolour >= 0)) {
if (fgcolour < 8) /* ANSI colours */
fgcolour += 8;
else if (fgcolour >= 256) /* Default colours */
fgcolour ++;
}
- if (attr[tindex] & ATTR_BLINK) {
+ if ((attr[tindex] & ATTR_BLINK) && (bgcolour >= 0)) {
if (bgcolour < 8) /* ANSI colours */
bgcolour += 8;
else if (bgcolour >= 256) /* Default colours */
@@ -5206,15 +5277,33 @@ void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour
/*
* Write RTF text attributes
*/
- if (lastfgcolour != fgcolour) {
- lastfgcolour = fgcolour;
- rtflen += sprintf(&rtf[rtflen], "\\cf%d ", (fgcolour >= 0) ? palette[fgcolour] : 0);
- }
+ if ((lastfgcolour != fgcolour) || (lastfg != fg)) {
+ lastfgcolour = fgcolour;
+ lastfg = fg;
+ if (fg == -1)
+ rtflen += sprintf(&rtf[rtflen], "\\cf%d ",
+ (fgcolour >= 0) ? palette[fgcolour] : 0);
+ else {
+ rgbindex rgb, *rgbp;
+ rgb.ref = fg;
+ if ((rgbp = find234(rgbtree, &rgb, NULL)) != NULL)
+ rtflen += sprintf(&rtf[rtflen], "\\cf%d ", rgbp->index);
+ }
+ }
- if (lastbgcolour != bgcolour) {
- lastbgcolour = bgcolour;
- rtflen += sprintf(&rtf[rtflen], "\\highlight%d ", (bgcolour >= 0) ? palette[bgcolour] : 0);
- }
+ if ((lastbgcolour != bgcolour) || (lastbg != bg)) {
+ lastbgcolour = bgcolour;
+ lastbg = bg;
+ if (bg == -1)
+ rtflen += sprintf(&rtf[rtflen], "\\highlight%d ",
+ (bgcolour >= 0) ? palette[bgcolour] : 0);
+ else {
+ rgbindex rgb, *rgbp;
+ rgb.ref = bg;
+ if ((rgbp = find234(rgbtree, &rgb, NULL)) != NULL)
+ rtflen += sprintf(&rtf[rtflen], "\\highlight%d ", rgbp->index);
+ }
+ }
if (lastAttrBold != attrBold) {
lastAttrBold = attrBold;
@@ -5295,6 +5384,13 @@ void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour
GlobalUnlock(clipdata3);
}
sfree(rtf);
+
+ if (rgbtree) {
+ rgbindex *rgbp;
+ while ((rgbp = delpos234(rgbtree, 0)) != NULL)
+ sfree(rgbp);
+ freetree234(rgbtree);
+ }
} else
clipdata3 = NULL;
From b4e5485caa1ba9286db3f51ba1b8a5498db52411 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Thu, 19 Oct 2017 18:27:03 +0100
Subject: [PATCH 084/166] Add Jeff Smith as a copyright holder.
---
LICENCE | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/LICENCE b/LICENCE
index 30b1fe2b3..05fbb7d39 100644
--- a/LICENCE
+++ b/LICENCE
@@ -4,7 +4,7 @@ Portions copyright Robert de Bath, Joris van Rantwijk, Delian
Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus
Kuhn, Colin Watson, Christopher Staite, Lorenz Diener, Christian
-Brabandt, and CORE SDI S.A.
+Brabandt, Jeff Smith, and CORE SDI S.A.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
From ea5425939297e0f41de4be3168fbb8d68854bb64 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Thu, 19 Oct 2017 18:55:22 +0100
Subject: [PATCH 085/166] sshaes.c: fix file name in header comment.
Apparently I forgot to edit that when I originally imported this AES
implementation into PuTTY's SSH code from the more generically named
source file in which I'd originally developed it.
---
sshaes.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sshaes.c b/sshaes.c
index 904cbdb2b..0368d6e9f 100644
--- a/sshaes.c
+++ b/sshaes.c
@@ -1,5 +1,5 @@
/*
- * aes.c - implementation of AES / Rijndael
+ * sshaes.c - implementation of AES / Rijndael
*
* AES is a flexible algorithm as regards endianness: it has no
* inherent preference as to which way round you should form words
From 4dfadcfb2643fe3b54bb29277ca73bc5ba647208 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Thu, 19 Oct 2017 19:13:02 +0100
Subject: [PATCH 086/166] sshaes.c: remove completely unused #define MAX_NK.
---
sshaes.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/sshaes.c b/sshaes.c
index 0368d6e9f..9be58dabf 100644
--- a/sshaes.c
+++ b/sshaes.c
@@ -33,7 +33,6 @@
#include "ssh.h"
#define MAX_NR 14 /* max no of rounds */
-#define MAX_NK 8 /* max no of words in input key */
#define MAX_NB 8 /* max no of words in cipher blk */
#define mulby2(x) ( ((x&0x7F) << 1) ^ (x & 0x80 ? 0x1B : 0) )
From 5592312636988869517026b6b8ead0a0dfd45266 Mon Sep 17 00:00:00 2001
From: "Pavel I. Kryukov"
Date: Fri, 20 Oct 2017 19:13:21 +0100
Subject: [PATCH 087/166] AES: remove support for block sizes other than 128
bits.
They're not really part of AES at all, in that they were part of the
Rijndael design but not part of the subset standardised by NIST. More
relevantly, they're not used by any SSH cipher definition, so they're
just adding complexity to the code which is about to get in the way of
refactoring it.
Removing them means there's only one pair of core encrypt/decrypt
functions, so the 'encrypt' and 'decrypt' function pointer fields can
be completely removed from AESContext.
---
sshaes.c | 277 ++++++++-----------------------------------------------
1 file changed, 40 insertions(+), 237 deletions(-)
diff --git a/sshaes.c b/sshaes.c
index 9be58dabf..48d0ca16c 100644
--- a/sshaes.c
+++ b/sshaes.c
@@ -33,19 +33,17 @@
#include "ssh.h"
#define MAX_NR 14 /* max no of rounds */
-#define MAX_NB 8 /* max no of words in cipher blk */
+#define NB 4 /* no of words in cipher blk */
#define mulby2(x) ( ((x&0x7F) << 1) ^ (x & 0x80 ? 0x1B : 0) )
typedef struct AESContext AESContext;
struct AESContext {
- word32 keysched[(MAX_NR + 1) * MAX_NB];
- word32 invkeysched[(MAX_NR + 1) * MAX_NB];
- void (*encrypt) (AESContext * ctx, word32 * block);
- void (*decrypt) (AESContext * ctx, word32 * block);
- word32 iv[MAX_NB];
- int Nb, Nr;
+ word32 keysched[(MAX_NR + 1) * NB];
+ word32 invkeysched[(MAX_NR + 1) * NB];
+ word32 iv[NB];
+ int Nr; /* number of rounds */
};
static const unsigned char Sbox[256] = {
@@ -652,36 +650,28 @@ static const word32 D3[256] = {
*/
#define ADD_ROUND_KEY_4 (block[0]^=*keysched++, block[1]^=*keysched++, \
block[2]^=*keysched++, block[3]^=*keysched++)
-#define ADD_ROUND_KEY_6 (block[0]^=*keysched++, block[1]^=*keysched++, \
- block[2]^=*keysched++, block[3]^=*keysched++, \
- block[4]^=*keysched++, block[5]^=*keysched++)
-#define ADD_ROUND_KEY_8 (block[0]^=*keysched++, block[1]^=*keysched++, \
- block[2]^=*keysched++, block[3]^=*keysched++, \
- block[4]^=*keysched++, block[5]^=*keysched++, \
- block[6]^=*keysched++, block[7]^=*keysched++)
#define MOVEWORD(i) ( block[i] = newstate[i] )
/*
- * Macros for the encryption routine. There are three encryption
- * cores, for Nb=4,6,8.
+ * Macros for the encryption routine.
*/
#define MAKEWORD(i) ( newstate[i] = (E0[(block[i] >> 24) & 0xFF] ^ \
- E1[(block[(i+C1)%Nb] >> 16) & 0xFF] ^ \
- E2[(block[(i+C2)%Nb] >> 8) & 0xFF] ^ \
- E3[block[(i+C3)%Nb] & 0xFF]) )
+ E1[(block[(i+C1)%NB] >> 16) & 0xFF] ^ \
+ E2[(block[(i+C2)%NB] >> 8) & 0xFF] ^ \
+ E3[block[(i+C3)%NB] & 0xFF]) )
#define LASTWORD(i) ( newstate[i] = (Sbox[(block[i] >> 24) & 0xFF] << 24) | \
- (Sbox[(block[(i+C1)%Nb] >> 16) & 0xFF] << 16) | \
- (Sbox[(block[(i+C2)%Nb] >> 8) & 0xFF] << 8) | \
- (Sbox[(block[(i+C3)%Nb] ) & 0xFF] ) )
+ (Sbox[(block[(i+C1)%NB] >> 16) & 0xFF] << 16) | \
+ (Sbox[(block[(i+C2)%NB] >> 8) & 0xFF] << 8) | \
+ (Sbox[(block[(i+C3)%NB] ) & 0xFF] ) )
/*
- * Core encrypt routines, expecting word32 inputs read big-endian
+ * Core encrypt routine, expecting word32 inputs read big-endian
* from the byte-oriented input stream.
*/
-static void aes_encrypt_nb_4(AESContext * ctx, word32 * block)
+static void aes_encrypt(AESContext * ctx, word32 * block)
{
int i;
- static const int C1 = 1, C2 = 2, C3 = 3, Nb = 4;
+ static const int C1 = 1, C2 = 2, C3 = 3;
word32 *keysched = ctx->keysched;
word32 newstate[4];
for (i = 0; i < ctx->Nr - 1; i++) {
@@ -706,111 +696,30 @@ static void aes_encrypt_nb_4(AESContext * ctx, word32 * block)
MOVEWORD(3);
ADD_ROUND_KEY_4;
}
-static void aes_encrypt_nb_6(AESContext * ctx, word32 * block)
-{
- int i;
- static const int C1 = 1, C2 = 2, C3 = 3, Nb = 6;
- word32 *keysched = ctx->keysched;
- word32 newstate[6];
- for (i = 0; i < ctx->Nr - 1; i++) {
- ADD_ROUND_KEY_6;
- MAKEWORD(0);
- MAKEWORD(1);
- MAKEWORD(2);
- MAKEWORD(3);
- MAKEWORD(4);
- MAKEWORD(5);
- MOVEWORD(0);
- MOVEWORD(1);
- MOVEWORD(2);
- MOVEWORD(3);
- MOVEWORD(4);
- MOVEWORD(5);
- }
- ADD_ROUND_KEY_6;
- LASTWORD(0);
- LASTWORD(1);
- LASTWORD(2);
- LASTWORD(3);
- LASTWORD(4);
- LASTWORD(5);
- MOVEWORD(0);
- MOVEWORD(1);
- MOVEWORD(2);
- MOVEWORD(3);
- MOVEWORD(4);
- MOVEWORD(5);
- ADD_ROUND_KEY_6;
-}
-static void aes_encrypt_nb_8(AESContext * ctx, word32 * block)
-{
- int i;
- static const int C1 = 1, C2 = 3, C3 = 4, Nb = 8;
- word32 *keysched = ctx->keysched;
- word32 newstate[8];
- for (i = 0; i < ctx->Nr - 1; i++) {
- ADD_ROUND_KEY_8;
- MAKEWORD(0);
- MAKEWORD(1);
- MAKEWORD(2);
- MAKEWORD(3);
- MAKEWORD(4);
- MAKEWORD(5);
- MAKEWORD(6);
- MAKEWORD(7);
- MOVEWORD(0);
- MOVEWORD(1);
- MOVEWORD(2);
- MOVEWORD(3);
- MOVEWORD(4);
- MOVEWORD(5);
- MOVEWORD(6);
- MOVEWORD(7);
- }
- ADD_ROUND_KEY_8;
- LASTWORD(0);
- LASTWORD(1);
- LASTWORD(2);
- LASTWORD(3);
- LASTWORD(4);
- LASTWORD(5);
- LASTWORD(6);
- LASTWORD(7);
- MOVEWORD(0);
- MOVEWORD(1);
- MOVEWORD(2);
- MOVEWORD(3);
- MOVEWORD(4);
- MOVEWORD(5);
- MOVEWORD(6);
- MOVEWORD(7);
- ADD_ROUND_KEY_8;
-}
#undef MAKEWORD
#undef LASTWORD
/*
- * Macros for the decryption routine. There are three decryption
- * cores, for Nb=4,6,8.
+ * Macros for the decryption routine.
*/
#define MAKEWORD(i) ( newstate[i] = (D0[(block[i] >> 24) & 0xFF] ^ \
- D1[(block[(i+C1)%Nb] >> 16) & 0xFF] ^ \
- D2[(block[(i+C2)%Nb] >> 8) & 0xFF] ^ \
- D3[block[(i+C3)%Nb] & 0xFF]) )
+ D1[(block[(i+C1)%NB] >> 16) & 0xFF] ^ \
+ D2[(block[(i+C2)%NB] >> 8) & 0xFF] ^ \
+ D3[block[(i+C3)%NB] & 0xFF]) )
#define LASTWORD(i) (newstate[i] = (Sboxinv[(block[i] >> 24) & 0xFF] << 24) | \
- (Sboxinv[(block[(i+C1)%Nb] >> 16) & 0xFF] << 16) | \
- (Sboxinv[(block[(i+C2)%Nb] >> 8) & 0xFF] << 8) | \
- (Sboxinv[(block[(i+C3)%Nb] ) & 0xFF] ) )
+ (Sboxinv[(block[(i+C1)%NB] >> 16) & 0xFF] << 16) | \
+ (Sboxinv[(block[(i+C2)%NB] >> 8) & 0xFF] << 8) | \
+ (Sboxinv[(block[(i+C3)%NB] ) & 0xFF] ) )
/*
- * Core decrypt routines, expecting word32 inputs read big-endian
+ * Core decrypt routine, expecting word32 inputs read big-endian
* from the byte-oriented input stream.
*/
-static void aes_decrypt_nb_4(AESContext * ctx, word32 * block)
+static void aes_decrypt(AESContext * ctx, word32 * block)
{
int i;
- static const int C1 = 4 - 1, C2 = 4 - 2, C3 = 4 - 3, Nb = 4;
+ static const int C1 = 4 - 1, C2 = 4 - 2, C3 = 4 - 3;
word32 *keysched = ctx->invkeysched;
word32 newstate[4];
for (i = 0; i < ctx->Nr - 1; i++) {
@@ -835,126 +744,30 @@ static void aes_decrypt_nb_4(AESContext * ctx, word32 * block)
MOVEWORD(3);
ADD_ROUND_KEY_4;
}
-static void aes_decrypt_nb_6(AESContext * ctx, word32 * block)
-{
- int i;
- static const int C1 = 6 - 1, C2 = 6 - 2, C3 = 6 - 3, Nb = 6;
- word32 *keysched = ctx->invkeysched;
- word32 newstate[6];
- for (i = 0; i < ctx->Nr - 1; i++) {
- ADD_ROUND_KEY_6;
- MAKEWORD(0);
- MAKEWORD(1);
- MAKEWORD(2);
- MAKEWORD(3);
- MAKEWORD(4);
- MAKEWORD(5);
- MOVEWORD(0);
- MOVEWORD(1);
- MOVEWORD(2);
- MOVEWORD(3);
- MOVEWORD(4);
- MOVEWORD(5);
- }
- ADD_ROUND_KEY_6;
- LASTWORD(0);
- LASTWORD(1);
- LASTWORD(2);
- LASTWORD(3);
- LASTWORD(4);
- LASTWORD(5);
- MOVEWORD(0);
- MOVEWORD(1);
- MOVEWORD(2);
- MOVEWORD(3);
- MOVEWORD(4);
- MOVEWORD(5);
- ADD_ROUND_KEY_6;
-}
-static void aes_decrypt_nb_8(AESContext * ctx, word32 * block)
-{
- int i;
- static const int C1 = 8 - 1, C2 = 8 - 3, C3 = 8 - 4, Nb = 8;
- word32 *keysched = ctx->invkeysched;
- word32 newstate[8];
- for (i = 0; i < ctx->Nr - 1; i++) {
- ADD_ROUND_KEY_8;
- MAKEWORD(0);
- MAKEWORD(1);
- MAKEWORD(2);
- MAKEWORD(3);
- MAKEWORD(4);
- MAKEWORD(5);
- MAKEWORD(6);
- MAKEWORD(7);
- MOVEWORD(0);
- MOVEWORD(1);
- MOVEWORD(2);
- MOVEWORD(3);
- MOVEWORD(4);
- MOVEWORD(5);
- MOVEWORD(6);
- MOVEWORD(7);
- }
- ADD_ROUND_KEY_8;
- LASTWORD(0);
- LASTWORD(1);
- LASTWORD(2);
- LASTWORD(3);
- LASTWORD(4);
- LASTWORD(5);
- LASTWORD(6);
- LASTWORD(7);
- MOVEWORD(0);
- MOVEWORD(1);
- MOVEWORD(2);
- MOVEWORD(3);
- MOVEWORD(4);
- MOVEWORD(5);
- MOVEWORD(6);
- MOVEWORD(7);
- ADD_ROUND_KEY_8;
-}
#undef MAKEWORD
#undef LASTWORD
/*
- * Set up an AESContext. `keylen' and `blocklen' are measured in
- * bytes; each can be either 16 (128-bit), 24 (192-bit), or 32
+ * Set up an AESContext. `keylen' is measured in
+ * bytes; it can be either 16 (128-bit), 24 (192-bit), or 32
* (256-bit).
*/
-static void aes_setup(AESContext * ctx, int blocklen,
- unsigned char *key, int keylen)
+static void aes_setup(AESContext * ctx, unsigned char *key, int keylen)
{
int i, j, Nk, rconst;
- assert(blocklen == 16 || blocklen == 24 || blocklen == 32);
- assert(keylen == 16 || keylen == 24 || keylen == 32);
-
- /*
- * Basic parameters. Words per block, words in key, rounds.
- */
- Nk = keylen / 4;
- ctx->Nb = blocklen / 4;
- ctx->Nr = 6 + (ctx->Nb > Nk ? ctx->Nb : Nk);
+ ctx->Nr = 6 + (keylen / 4); /* Number of rounds */
- /*
- * Assign core-function pointers.
- */
- if (ctx->Nb == 8)
- ctx->encrypt = aes_encrypt_nb_8, ctx->decrypt = aes_decrypt_nb_8;
- else if (ctx->Nb == 6)
- ctx->encrypt = aes_encrypt_nb_6, ctx->decrypt = aes_decrypt_nb_6;
- else if (ctx->Nb == 4)
- ctx->encrypt = aes_encrypt_nb_4, ctx->decrypt = aes_decrypt_nb_4;
+ assert(keylen == 16 || keylen == 24 || keylen == 32);
/*
* Now do the key setup itself.
*/
+ Nk = keylen / 4;
rconst = 1;
- for (i = 0; i < (ctx->Nr + 1) * ctx->Nb; i++) {
+ for (i = 0; i < (ctx->Nr + 1) * NB; i++) {
if (i < Nk)
ctx->keysched[i] = GET_32BIT_MSB_FIRST(key + 4 * i);
else {
@@ -989,9 +802,9 @@ static void aes_setup(AESContext * ctx, int blocklen,
* Now prepare the modified keys for the inverse cipher.
*/
for (i = 0; i <= ctx->Nr; i++) {
- for (j = 0; j < ctx->Nb; j++) {
+ for (j = 0; j < NB; j++) {
word32 temp;
- temp = ctx->keysched[(ctx->Nr - i) * ctx->Nb + j];
+ temp = ctx->keysched[(ctx->Nr - i) * NB + j];
if (i != 0 && i != ctx->Nr) {
/*
* Perform the InvMixColumn operation on i. The D
@@ -1009,21 +822,11 @@ static void aes_setup(AESContext * ctx, int blocklen,
temp ^= D2[Sbox[c]];
temp ^= D3[Sbox[d]];
}
- ctx->invkeysched[i * ctx->Nb + j] = temp;
+ ctx->invkeysched[i * NB + j] = temp;
}
}
}
-static void aes_encrypt(AESContext * ctx, word32 * block)
-{
- ctx->encrypt(ctx, block);
-}
-
-static void aes_decrypt(AESContext * ctx, word32 * block)
-{
- ctx->decrypt(ctx, block);
-}
-
static void aes_encrypt_cbc(unsigned char *blk, int len, AESContext * ctx)
{
word32 iv[4];
@@ -1109,19 +912,19 @@ void aes_free_context(void *handle)
void aes128_key(void *handle, unsigned char *key)
{
AESContext *ctx = (AESContext *)handle;
- aes_setup(ctx, 16, key, 16);
+ aes_setup(ctx, key, 16);
}
void aes192_key(void *handle, unsigned char *key)
{
AESContext *ctx = (AESContext *)handle;
- aes_setup(ctx, 16, key, 24);
+ aes_setup(ctx, key, 24);
}
void aes256_key(void *handle, unsigned char *key)
{
AESContext *ctx = (AESContext *)handle;
- aes_setup(ctx, 16, key, 32);
+ aes_setup(ctx, key, 32);
}
void aes_iv(void *handle, unsigned char *iv)
@@ -1153,7 +956,7 @@ static void aes_ssh2_sdctr(void *handle, unsigned char *blk, int len)
void aes256_encrypt_pubkey(unsigned char *key, unsigned char *blk, int len)
{
AESContext ctx;
- aes_setup(&ctx, 16, key, 32);
+ aes_setup(&ctx, key, 32);
memset(ctx.iv, 0, sizeof(ctx.iv));
aes_encrypt_cbc(blk, len, &ctx);
smemclr(&ctx, sizeof(ctx));
@@ -1162,7 +965,7 @@ void aes256_encrypt_pubkey(unsigned char *key, unsigned char *blk, int len)
void aes256_decrypt_pubkey(unsigned char *key, unsigned char *blk, int len)
{
AESContext ctx;
- aes_setup(&ctx, 16, key, 32);
+ aes_setup(&ctx, key, 32);
memset(ctx.iv, 0, sizeof(ctx.iv));
aes_decrypt_cbc(blk, len, &ctx);
smemclr(&ctx, sizeof(ctx));
From 0816e2b1a019e97b37eb6007c34f0c58c257635c Mon Sep 17 00:00:00 2001
From: "Pavel I. Kryukov"
Date: Fri, 20 Oct 2017 19:13:39 +0100
Subject: [PATCH 088/166] AES: fold the core and outer routines together.
The outer routines are the ones which handle the CBC encrypt, CBC
decrypt and SDCTR cipher modes. Previously each of those had to be
able to dispatch to one of the per-block-size core routines, which
made it worth dividing the system up into two layers. But now there's
only one set of core routines, they may as well be inlined into the
outer ones.
Also as part of this commit, the nasty undef/redef of MAKEWORD and
LASTWORD have been removed, and the different macro definitions now
have different macro _names_, to make it clearer which one is used
where.
---
sshaes.c | 277 ++++++++++++++++++++++++++++---------------------------
1 file changed, 142 insertions(+), 135 deletions(-)
diff --git a/sshaes.c b/sshaes.c
index 48d0ca16c..443031844 100644
--- a/sshaes.c
+++ b/sshaes.c
@@ -645,110 +645,6 @@ static const word32 D3[256] = {
0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0,
};
-/*
- * Common macros in both the encryption and decryption routines.
- */
-#define ADD_ROUND_KEY_4 (block[0]^=*keysched++, block[1]^=*keysched++, \
- block[2]^=*keysched++, block[3]^=*keysched++)
-#define MOVEWORD(i) ( block[i] = newstate[i] )
-
-/*
- * Macros for the encryption routine.
- */
-#define MAKEWORD(i) ( newstate[i] = (E0[(block[i] >> 24) & 0xFF] ^ \
- E1[(block[(i+C1)%NB] >> 16) & 0xFF] ^ \
- E2[(block[(i+C2)%NB] >> 8) & 0xFF] ^ \
- E3[block[(i+C3)%NB] & 0xFF]) )
-#define LASTWORD(i) ( newstate[i] = (Sbox[(block[i] >> 24) & 0xFF] << 24) | \
- (Sbox[(block[(i+C1)%NB] >> 16) & 0xFF] << 16) | \
- (Sbox[(block[(i+C2)%NB] >> 8) & 0xFF] << 8) | \
- (Sbox[(block[(i+C3)%NB] ) & 0xFF] ) )
-
-/*
- * Core encrypt routine, expecting word32 inputs read big-endian
- * from the byte-oriented input stream.
- */
-static void aes_encrypt(AESContext * ctx, word32 * block)
-{
- int i;
- static const int C1 = 1, C2 = 2, C3 = 3;
- word32 *keysched = ctx->keysched;
- word32 newstate[4];
- for (i = 0; i < ctx->Nr - 1; i++) {
- ADD_ROUND_KEY_4;
- MAKEWORD(0);
- MAKEWORD(1);
- MAKEWORD(2);
- MAKEWORD(3);
- MOVEWORD(0);
- MOVEWORD(1);
- MOVEWORD(2);
- MOVEWORD(3);
- }
- ADD_ROUND_KEY_4;
- LASTWORD(0);
- LASTWORD(1);
- LASTWORD(2);
- LASTWORD(3);
- MOVEWORD(0);
- MOVEWORD(1);
- MOVEWORD(2);
- MOVEWORD(3);
- ADD_ROUND_KEY_4;
-}
-
-#undef MAKEWORD
-#undef LASTWORD
-
-/*
- * Macros for the decryption routine.
- */
-#define MAKEWORD(i) ( newstate[i] = (D0[(block[i] >> 24) & 0xFF] ^ \
- D1[(block[(i+C1)%NB] >> 16) & 0xFF] ^ \
- D2[(block[(i+C2)%NB] >> 8) & 0xFF] ^ \
- D3[block[(i+C3)%NB] & 0xFF]) )
-#define LASTWORD(i) (newstate[i] = (Sboxinv[(block[i] >> 24) & 0xFF] << 24) | \
- (Sboxinv[(block[(i+C1)%NB] >> 16) & 0xFF] << 16) | \
- (Sboxinv[(block[(i+C2)%NB] >> 8) & 0xFF] << 8) | \
- (Sboxinv[(block[(i+C3)%NB] ) & 0xFF] ) )
-
-/*
- * Core decrypt routine, expecting word32 inputs read big-endian
- * from the byte-oriented input stream.
- */
-static void aes_decrypt(AESContext * ctx, word32 * block)
-{
- int i;
- static const int C1 = 4 - 1, C2 = 4 - 2, C3 = 4 - 3;
- word32 *keysched = ctx->invkeysched;
- word32 newstate[4];
- for (i = 0; i < ctx->Nr - 1; i++) {
- ADD_ROUND_KEY_4;
- MAKEWORD(0);
- MAKEWORD(1);
- MAKEWORD(2);
- MAKEWORD(3);
- MOVEWORD(0);
- MOVEWORD(1);
- MOVEWORD(2);
- MOVEWORD(3);
- }
- ADD_ROUND_KEY_4;
- LASTWORD(0);
- LASTWORD(1);
- LASTWORD(2);
- LASTWORD(3);
- MOVEWORD(0);
- MOVEWORD(1);
- MOVEWORD(2);
- MOVEWORD(3);
- ADD_ROUND_KEY_4;
-}
-
-#undef MAKEWORD
-#undef LASTWORD
-
-
/*
* Set up an AESContext. `keylen' is measured in
* bytes; it can be either 16 (128-bit), 24 (192-bit), or 32
@@ -762,9 +658,6 @@ static void aes_setup(AESContext * ctx, unsigned char *key, int keylen)
assert(keylen == 16 || keylen == 24 || keylen == 32);
- /*
- * Now do the key setup itself.
- */
Nk = keylen / 4;
rconst = 1;
for (i = 0; i < (ctx->Nr + 1) * NB; i++) {
@@ -827,73 +720,187 @@ static void aes_setup(AESContext * ctx, unsigned char *key, int keylen)
}
}
+/*
+ * Software encrypt/decrypt macros
+ */
+#define ADD_ROUND_KEY (block[0]^=*keysched++, \
+ block[1]^=*keysched++, \
+ block[2]^=*keysched++, \
+ block[3]^=*keysched++)
+#define MOVEWORD(i) ( block[i] = newstate[i] )
+
+#define ENCWORD(i) ( newstate[i] = (E0[(block[i ] >> 24) & 0xFF] ^ \
+ E1[(block[(i+1)%NB] >> 16) & 0xFF] ^ \
+ E2[(block[(i+2)%NB] >> 8) & 0xFF] ^ \
+ E3[ block[(i+3)%NB] & 0xFF]) )
+#define ENCROUND { ENCWORD(0); ENCWORD(1); ENCWORD(2); ENCWORD(3); \
+ MOVEWORD(0); MOVEWORD(1); MOVEWORD(2); MOVEWORD(3); ADD_ROUND_KEY; }
+
+#define ENCLASTWORD(i) ( newstate[i] = \
+ (Sbox[(block[i] >> 24) & 0xFF] << 24) | \
+ (Sbox[(block[(i+1)%NB] >> 16) & 0xFF] << 16) | \
+ (Sbox[(block[(i+2)%NB] >> 8) & 0xFF] << 8) | \
+ (Sbox[(block[(i+3)%NB] ) & 0xFF] ) )
+#define ENCLASTROUND { ENCLASTWORD(0); ENCLASTWORD(1); ENCLASTWORD(2); ENCLASTWORD(3); \
+ MOVEWORD(0); MOVEWORD(1); MOVEWORD(2); MOVEWORD(3); ADD_ROUND_KEY; }
+
+#define DECWORD(i) ( newstate[i] = (D0[(block[i] >> 24) & 0xFF] ^ \
+ D1[(block[(i+3)%NB] >> 16) & 0xFF] ^ \
+ D2[(block[(i+2)%NB] >> 8) & 0xFF] ^ \
+ D3[ block[(i+1)%NB] & 0xFF]) )
+#define DECROUND { DECWORD(0); DECWORD(1); DECWORD(2); DECWORD(3); \
+ MOVEWORD(0); MOVEWORD(1); MOVEWORD(2); MOVEWORD(3); ADD_ROUND_KEY; }
+
+#define DECLASTWORD(i) (newstate[i] = \
+ (Sboxinv[(block[i] >> 24) & 0xFF] << 24) | \
+ (Sboxinv[(block[(i+3)%NB] >> 16) & 0xFF] << 16) | \
+ (Sboxinv[(block[(i+2)%NB] >> 8) & 0xFF] << 8) | \
+ (Sboxinv[(block[(i+1)%NB] ) & 0xFF] ) )
+#define DECLASTROUND { DECLASTWORD(0); DECLASTWORD(1); DECLASTWORD(2); DECLASTWORD(3); \
+ MOVEWORD(0); MOVEWORD(1); MOVEWORD(2); MOVEWORD(3); ADD_ROUND_KEY; }
+
+/*
+ * Software AES encrypt/decrypt core
+ */
static void aes_encrypt_cbc(unsigned char *blk, int len, AESContext * ctx)
{
- word32 iv[4];
+ word32 block[4];
+ unsigned char* finish = blk + len;
int i;
assert((len & 15) == 0);
- memcpy(iv, ctx->iv, sizeof(iv));
+ memcpy(block, ctx->iv, sizeof(block));
- while (len > 0) {
+ while (blk < finish) {
+ word32 *keysched = ctx->keysched;
+ word32 newstate[4];
for (i = 0; i < 4; i++)
- iv[i] ^= GET_32BIT_MSB_FIRST(blk + 4 * i);
- aes_encrypt(ctx, iv);
+ block[i] ^= GET_32BIT_MSB_FIRST(blk + 4 * i);
+ ADD_ROUND_KEY;
+ switch (ctx->Nr) {
+ case 14:
+ ENCROUND;
+ ENCROUND;
+ case 12:
+ ENCROUND;
+ ENCROUND;
+ case 10:
+ ENCROUND;
+ ENCROUND;
+ ENCROUND;
+ ENCROUND;
+ ENCROUND;
+ ENCROUND;
+ ENCROUND;
+ ENCROUND;
+ ENCROUND;
+ ENCLASTROUND;
+ break;
+ default:
+ assert(0);
+ }
for (i = 0; i < 4; i++)
- PUT_32BIT_MSB_FIRST(blk + 4 * i, iv[i]);
+ PUT_32BIT_MSB_FIRST(blk + 4 * i, block[i]);
blk += 16;
- len -= 16;
}
- memcpy(ctx->iv, iv, sizeof(iv));
+ memcpy(ctx->iv, block, sizeof(block));
}
-static void aes_decrypt_cbc(unsigned char *blk, int len, AESContext * ctx)
+static void aes_sdctr(unsigned char *blk, int len, AESContext *ctx)
{
- word32 iv[4], x[4], ct[4];
+ word32 iv[4];
+ unsigned char* finish = blk + len;
int i;
assert((len & 15) == 0);
memcpy(iv, ctx->iv, sizeof(iv));
- while (len > 0) {
- for (i = 0; i < 4; i++)
- x[i] = ct[i] = GET_32BIT_MSB_FIRST(blk + 4 * i);
- aes_decrypt(ctx, x);
+ while (blk < finish) {
+ word32 *keysched = ctx->keysched;
+ word32 newstate[4], block[4], tmp;
+ memcpy(block, iv, sizeof(block));
+ ADD_ROUND_KEY;
+ switch (ctx->Nr) {
+ case 14:
+ ENCROUND;
+ ENCROUND;
+ case 12:
+ ENCROUND;
+ ENCROUND;
+ case 10:
+ ENCROUND;
+ ENCROUND;
+ ENCROUND;
+ ENCROUND;
+ ENCROUND;
+ ENCROUND;
+ ENCROUND;
+ ENCROUND;
+ ENCROUND;
+ ENCLASTROUND;
+ break;
+ default:
+ assert(0);
+ }
for (i = 0; i < 4; i++) {
- PUT_32BIT_MSB_FIRST(blk + 4 * i, iv[i] ^ x[i]);
- iv[i] = ct[i];
+ tmp = GET_32BIT_MSB_FIRST(blk + 4 * i);
+ PUT_32BIT_MSB_FIRST(blk + 4 * i, tmp ^ block[i]);
}
+ for (i = 3; i >= 0; i--)
+ if ((iv[i] = (iv[i] + 1) & 0xffffffff) != 0)
+ break;
blk += 16;
- len -= 16;
}
memcpy(ctx->iv, iv, sizeof(iv));
}
-static void aes_sdctr(unsigned char *blk, int len, AESContext *ctx)
+static void aes_decrypt_cbc(unsigned char *blk, int len, AESContext * ctx)
{
- word32 iv[4], b[4], tmp;
+ word32 iv[4];
+ unsigned char* finish = blk + len;
int i;
assert((len & 15) == 0);
memcpy(iv, ctx->iv, sizeof(iv));
- while (len > 0) {
- memcpy(b, iv, sizeof(b));
- aes_encrypt(ctx, b);
+ while (blk < finish) {
+ word32 *keysched = ctx->invkeysched;
+ word32 newstate[4], ct[4], block[4];
+ for (i = 0; i < 4; i++)
+ block[i] = ct[i] = GET_32BIT_MSB_FIRST(blk + 4 * i);
+ ADD_ROUND_KEY;
+ switch (ctx->Nr) {
+ case 14:
+ DECROUND;
+ DECROUND;
+ case 12:
+ DECROUND;
+ DECROUND;
+ case 10:
+ DECROUND;
+ DECROUND;
+ DECROUND;
+ DECROUND;
+ DECROUND;
+ DECROUND;
+ DECROUND;
+ DECROUND;
+ DECROUND;
+ DECLASTROUND;
+ break;
+ default:
+ assert(0);
+ }
for (i = 0; i < 4; i++) {
- tmp = GET_32BIT_MSB_FIRST(blk + 4 * i);
- PUT_32BIT_MSB_FIRST(blk + 4 * i, tmp ^ b[i]);
+ PUT_32BIT_MSB_FIRST(blk + 4 * i, iv[i] ^ block[i]);
+ iv[i] = ct[i];
}
- for (i = 3; i >= 0; i--)
- if ((iv[i] = (iv[i] + 1) & 0xffffffff) != 0)
- break;
blk += 16;
- len -= 16;
}
memcpy(ctx->iv, iv, sizeof(iv));
From e8be7ea98a4c21a839dcd4b75dc62688778bdde8 Mon Sep 17 00:00:00 2001
From: "Pavel I. Kryukov"
Date: Fri, 20 Oct 2017 19:13:47 +0100
Subject: [PATCH 089/166] AES: 16-byte align the key schedule arrays.
This is going to be important in the next commit, when we start
accessing them using x86 SSE instructions.
---
sshaes.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/sshaes.c b/sshaes.c
index 443031844..488e32a34 100644
--- a/sshaes.c
+++ b/sshaes.c
@@ -40,8 +40,9 @@
typedef struct AESContext AESContext;
struct AESContext {
- word32 keysched[(MAX_NR + 1) * NB];
- word32 invkeysched[(MAX_NR + 1) * NB];
+ word32 keysched_buf[(MAX_NR + 1) * NB + 3];
+ word32 invkeysched_buf[(MAX_NR + 1) * NB + 3];
+ word32 *keysched, *invkeysched;
word32 iv[NB];
int Nr; /* number of rounds */
};
@@ -653,9 +654,20 @@ static const word32 D3[256] = {
static void aes_setup(AESContext * ctx, unsigned char *key, int keylen)
{
int i, j, Nk, rconst;
+ size_t bufaddr;
ctx->Nr = 6 + (keylen / 4); /* Number of rounds */
+ /* Ensure the key schedule arrays are 16-byte aligned */
+ bufaddr = (size_t)ctx->keysched_buf;
+ ctx->keysched = ctx->keysched_buf +
+ (0xF & -bufaddr) / sizeof(word32);
+ assert((size_t)ctx->keysched % 16 == 0);
+ bufaddr = (size_t)ctx->invkeysched_buf;
+ ctx->invkeysched = ctx->invkeysched_buf +
+ (0xF & -bufaddr) / sizeof(word32);
+ assert((size_t)ctx->invkeysched % 16 == 0);
+
assert(keylen == 16 || keylen == 24 || keylen == 32);
Nk = keylen / 4;
From 2d31305af9d3bf4096bb0c30e8a8336caaa70673 Mon Sep 17 00:00:00 2001
From: "Pavel I. Kryukov"
Date: Fri, 20 Oct 2017 19:13:54 +0100
Subject: [PATCH 090/166] Alternative AES routines, using x86 hardware support.
The new AES routines are compiled into the code on any platform where
the compiler can be made to generate the necessary AES-NI and SSE
instructions. But not every CPU will support those instructions, so
the pure-software routines haven't gone away: both sets of functions
sit side by side in the code, and at key setup time we check the CPUID
bitmap to decide which set to select.
(This reintroduces function pointers into AESContext, replacing the
ones that we managed to remove a few commits ago.)
---
sshaes.c | 667 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 661 insertions(+), 6 deletions(-)
diff --git a/sshaes.c b/sshaes.c
index 488e32a34..7ebeb5be0 100644
--- a/sshaes.c
+++ b/sshaes.c
@@ -37,6 +37,17 @@
#define mulby2(x) ( ((x&0x7F) << 1) ^ (x & 0x80 ? 0x1B : 0) )
+/*
+ * Select appropriate inline keyword for the compiler
+ */
+#if defined __GNUC__ || defined __clang__
+# define INLINE __inline__
+#elif defined (_MSC_VER)
+# define INLINE __forceinline
+#else
+# define INLINE
+#endif
+
typedef struct AESContext AESContext;
struct AESContext {
@@ -45,8 +56,37 @@ struct AESContext {
word32 *keysched, *invkeysched;
word32 iv[NB];
int Nr; /* number of rounds */
+ void (*encrypt_cbc)(unsigned char*, int, AESContext*);
+ void (*decrypt_cbc)(unsigned char*, int, AESContext*);
+ void (*sdctr)(unsigned char*, int, AESContext*);
+ int isNI;
};
+static void aes_encrypt_cbc_sw(unsigned char*, int, AESContext*);
+static void aes_decrypt_cbc_sw(unsigned char*, int, AESContext*);
+static void aes_sdctr_sw(unsigned char*, int, AESContext*);
+
+INLINE static int supports_aes_ni();
+static void aes_setup_ni(AESContext * ctx, unsigned char *key, int keylen);
+
+INLINE static void aes_encrypt_cbc(unsigned char *blk, int len, AESContext * ctx)
+{
+ ctx->encrypt_cbc(blk, len, ctx);
+}
+
+INLINE static void aes_decrypt_cbc(unsigned char *blk, int len, AESContext * ctx)
+{
+ ctx->decrypt_cbc(blk, len, ctx);
+}
+
+INLINE static void aes_sdctr(unsigned char *blk, int len, AESContext * ctx)
+{
+ ctx->sdctr(blk, len, ctx);
+}
+
+/*
+ * SW AES lookup tables
+ */
static const unsigned char Sbox[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
@@ -668,8 +708,19 @@ static void aes_setup(AESContext * ctx, unsigned char *key, int keylen)
(0xF & -bufaddr) / sizeof(word32);
assert((size_t)ctx->invkeysched % 16 == 0);
+ ctx->isNI = supports_aes_ni();
+
+ if (ctx->isNI) {
+ aes_setup_ni(ctx, key, keylen);
+ return;
+ }
+
assert(keylen == 16 || keylen == 24 || keylen == 32);
+ ctx->encrypt_cbc = aes_encrypt_cbc_sw;
+ ctx->decrypt_cbc = aes_decrypt_cbc_sw;
+ ctx->sdctr = aes_sdctr_sw;
+
Nk = keylen / 4;
rconst = 1;
for (i = 0; i < (ctx->Nr + 1) * NB; i++) {
@@ -774,7 +825,7 @@ static void aes_setup(AESContext * ctx, unsigned char *key, int keylen)
/*
* Software AES encrypt/decrypt core
*/
-static void aes_encrypt_cbc(unsigned char *blk, int len, AESContext * ctx)
+static void aes_encrypt_cbc_sw(unsigned char *blk, int len, AESContext * ctx)
{
word32 block[4];
unsigned char* finish = blk + len;
@@ -820,7 +871,7 @@ static void aes_encrypt_cbc(unsigned char *blk, int len, AESContext * ctx)
memcpy(ctx->iv, block, sizeof(block));
}
-static void aes_sdctr(unsigned char *blk, int len, AESContext *ctx)
+static void aes_sdctr_sw(unsigned char *blk, int len, AESContext *ctx)
{
word32 iv[4];
unsigned char* finish = blk + len;
@@ -870,7 +921,7 @@ static void aes_sdctr(unsigned char *blk, int len, AESContext *ctx)
memcpy(ctx->iv, iv, sizeof(iv));
}
-static void aes_decrypt_cbc(unsigned char *blk, int len, AESContext * ctx)
+static void aes_decrypt_cbc_sw(unsigned char *blk, int len, AESContext * ctx)
{
word32 iv[4];
unsigned char* finish = blk + len;
@@ -949,9 +1000,14 @@ void aes256_key(void *handle, unsigned char *key)
void aes_iv(void *handle, unsigned char *iv)
{
AESContext *ctx = (AESContext *)handle;
- int i;
- for (i = 0; i < 4; i++)
- ctx->iv[i] = GET_32BIT_MSB_FIRST(iv + 4 * i);
+ if (ctx->isNI) {
+ memcpy(ctx->iv, iv, sizeof(ctx->iv));
+ }
+ else {
+ int i;
+ for (i = 0; i < 4; i++)
+ ctx->iv[i] = GET_32BIT_MSB_FIRST(iv + 4 * i);
+ }
}
void aes_ssh2_encrypt_blk(void *handle, unsigned char *blk, int len)
@@ -1060,3 +1116,602 @@ const struct ssh2_ciphers ssh2_aes = {
sizeof(aes_list) / sizeof(*aes_list),
aes_list
};
+
+/*
+ * Implementation of AES for PuTTY using AES-NI
+ * instuction set expansion was made by:
+ * @author Pavel Kryukov
+ * @author Maxim Kuznetsov
+ * @author Svyatoslav Kuzmich
+ *
+ * For Putty AES NI project
+ * http://pavelkryukov.github.io/putty-aes-ni/
+ */
+
+/*
+ * Check of compiler version
+ */
+#ifdef _FORCE_AES_NI
+# define COMPILER_SUPPORTS_AES_NI
+#elif defined(__clang__)
+# if (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 8)) && (defined(__x86_64__) || defined(__i386))
+# define COMPILER_SUPPORTS_AES_NI
+# endif
+#elif defined(__GNUC__)
+# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) && (defined(__x86_64__) || defined(__i386))
+# define COMPILER_SUPPORTS_AES_NI
+# endif
+#elif defined (_MSC_VER)
+# if (defined(_M_X64) || defined(_M_IX86)) && _MSC_FULL_VER >= 150030729
+# define COMPILER_SUPPORTS_AES_NI
+# endif
+#endif
+
+#ifdef _FORCE_SOFTWARE_AES
+# undef COMPILER_SUPPORTS_AES_NI
+#endif
+
+#ifdef COMPILER_SUPPORTS_AES_NI
+
+/*
+ * Set target architecture for Clang and GCC
+ */
+#if !defined(__clang__) && defined(__GNUC__)
+# pragma GCC target("aes")
+# pragma GCC target("sse4.1")
+#endif
+
+#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))
+# define FUNC_ISA __attribute__ ((target("sse4.1,aes")))
+#else
+# define FUNC_ISA
+#endif
+
+#include
+#include
+
+/*
+ * Determinators of CPU type
+ */
+#if defined(__clang__) || defined(__GNUC__)
+
+#include
+INLINE static int supports_aes_ni()
+{
+ unsigned int CPUInfo[4];
+ __cpuid(1, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
+ return (CPUInfo[2] & (1 << 25)) && (CPUInfo[2] & (1 << 19)); /* Check AES and SSE4.1 */
+}
+
+#else /* defined(__clang__) || defined(__GNUC__) */
+
+INLINE static int supports_aes_ni()
+{
+ unsigned int CPUInfo[4];
+ __cpuid(CPUInfo, 1);
+ return (CPUInfo[2] & (1 << 25)) && (CPUInfo[2] & (1 << 19)); /* Check AES and SSE4.1 */
+}
+
+#endif /* defined(__clang__) || defined(__GNUC__) */
+
+/*
+ * Wrapper of SHUFPD instruction for MSVC
+ */
+#ifdef _MSC_VER
+INLINE static __m128i mm_shuffle_pd_i0(__m128i a, __m128i b)
+{
+ union {
+ __m128i i;
+ __m128d d;
+ } au, bu, ru;
+ au.i = a;
+ bu.i = b;
+ ru.d = _mm_shuffle_pd(au.d, bu.d, 0);
+ return ru.i;
+}
+
+INLINE static __m128i mm_shuffle_pd_i1(__m128i a, __m128i b)
+{
+ union {
+ __m128i i;
+ __m128d d;
+ } au, bu, ru;
+ au.i = a;
+ bu.i = b;
+ ru.d = _mm_shuffle_pd(au.d, bu.d, 1);
+ return ru.i;
+}
+#else
+#define mm_shuffle_pd_i0(a, b) ((__m128i)_mm_shuffle_pd((__m128d)a, (__m128d)b, 0));
+#define mm_shuffle_pd_i1(a, b) ((__m128i)_mm_shuffle_pd((__m128d)a, (__m128d)b, 1));
+#endif
+
+/*
+ * AES-NI key expansion assist functions
+ */
+FUNC_ISA
+INLINE static __m128i AES_128_ASSIST (__m128i temp1, __m128i temp2)
+{
+ __m128i temp3;
+ temp2 = _mm_shuffle_epi32 (temp2 ,0xff);
+ temp3 = _mm_slli_si128 (temp1, 0x4);
+ temp1 = _mm_xor_si128 (temp1, temp3);
+ temp3 = _mm_slli_si128 (temp3, 0x4);
+ temp1 = _mm_xor_si128 (temp1, temp3);
+ temp3 = _mm_slli_si128 (temp3, 0x4);
+ temp1 = _mm_xor_si128 (temp1, temp3);
+ temp1 = _mm_xor_si128 (temp1, temp2);
+ return temp1;
+}
+
+FUNC_ISA
+INLINE static void KEY_192_ASSIST(__m128i* temp1, __m128i * temp2, __m128i * temp3)
+{
+ __m128i temp4;
+ *temp2 = _mm_shuffle_epi32 (*temp2, 0x55);
+ temp4 = _mm_slli_si128 (*temp1, 0x4);
+ *temp1 = _mm_xor_si128 (*temp1, temp4);
+ temp4 = _mm_slli_si128 (temp4, 0x4);
+ *temp1 = _mm_xor_si128 (*temp1, temp4);
+ temp4 = _mm_slli_si128 (temp4, 0x4);
+ *temp1 = _mm_xor_si128 (*temp1, temp4);
+ *temp1 = _mm_xor_si128 (*temp1, *temp2);
+ *temp2 = _mm_shuffle_epi32(*temp1, 0xff);
+ temp4 = _mm_slli_si128 (*temp3, 0x4);
+ *temp3 = _mm_xor_si128 (*temp3, temp4);
+ *temp3 = _mm_xor_si128 (*temp3, *temp2);
+}
+
+FUNC_ISA
+INLINE static void KEY_256_ASSIST_1(__m128i* temp1, __m128i * temp2)
+{
+ __m128i temp4;
+ *temp2 = _mm_shuffle_epi32(*temp2, 0xff);
+ temp4 = _mm_slli_si128 (*temp1, 0x4);
+ *temp1 = _mm_xor_si128 (*temp1, temp4);
+ temp4 = _mm_slli_si128 (temp4, 0x4);
+ *temp1 = _mm_xor_si128 (*temp1, temp4);
+ temp4 = _mm_slli_si128 (temp4, 0x4);
+ *temp1 = _mm_xor_si128 (*temp1, temp4);
+ *temp1 = _mm_xor_si128 (*temp1, *temp2);
+}
+
+FUNC_ISA
+INLINE static void KEY_256_ASSIST_2(__m128i* temp1, __m128i * temp3)
+{
+ __m128i temp2,temp4;
+ temp4 = _mm_aeskeygenassist_si128 (*temp1, 0x0);
+ temp2 = _mm_shuffle_epi32(temp4, 0xaa);
+ temp4 = _mm_slli_si128 (*temp3, 0x4);
+ *temp3 = _mm_xor_si128 (*temp3, temp4);
+ temp4 = _mm_slli_si128 (temp4, 0x4);
+ *temp3 = _mm_xor_si128 (*temp3, temp4);
+ temp4 = _mm_slli_si128 (temp4, 0x4);
+ *temp3 = _mm_xor_si128 (*temp3, temp4);
+ *temp3 = _mm_xor_si128 (*temp3, temp2);
+}
+
+/*
+ * AES-NI key expansion core
+ */
+FUNC_ISA
+static void AES_128_Key_Expansion (unsigned char *userkey, __m128i *key)
+{
+ __m128i temp1, temp2;
+ temp1 = _mm_loadu_si128((__m128i*)userkey);
+ key[0] = temp1;
+ temp2 = _mm_aeskeygenassist_si128 (temp1 ,0x1);
+ temp1 = AES_128_ASSIST(temp1, temp2);
+ key[1] = temp1;
+ temp2 = _mm_aeskeygenassist_si128 (temp1,0x2);
+ temp1 = AES_128_ASSIST(temp1, temp2);
+ key[2] = temp1;
+ temp2 = _mm_aeskeygenassist_si128 (temp1,0x4);
+ temp1 = AES_128_ASSIST(temp1, temp2);
+ key[3] = temp1;
+ temp2 = _mm_aeskeygenassist_si128 (temp1,0x8);
+ temp1 = AES_128_ASSIST(temp1, temp2);
+ key[4] = temp1;
+ temp2 = _mm_aeskeygenassist_si128 (temp1,0x10);
+ temp1 = AES_128_ASSIST(temp1, temp2);
+ key[5] = temp1;
+ temp2 = _mm_aeskeygenassist_si128 (temp1,0x20);
+ temp1 = AES_128_ASSIST(temp1, temp2);
+ key[6] = temp1;
+ temp2 = _mm_aeskeygenassist_si128 (temp1,0x40);
+ temp1 = AES_128_ASSIST(temp1, temp2);
+ key[7] = temp1;
+ temp2 = _mm_aeskeygenassist_si128 (temp1,0x80);
+ temp1 = AES_128_ASSIST(temp1, temp2);
+ key[8] = temp1;
+ temp2 = _mm_aeskeygenassist_si128 (temp1,0x1b);
+ temp1 = AES_128_ASSIST(temp1, temp2);
+ key[9] = temp1;
+ temp2 = _mm_aeskeygenassist_si128 (temp1,0x36);
+ temp1 = AES_128_ASSIST(temp1, temp2);
+ key[10] = temp1;
+}
+
+FUNC_ISA
+static void AES_192_Key_Expansion (unsigned char *userkey, __m128i *key)
+{
+ __m128i temp1, temp2, temp3;
+ temp1 = _mm_loadu_si128((__m128i*)userkey);
+ temp3 = _mm_loadu_si128((__m128i*)(userkey+16));
+ key[0]=temp1;
+ key[1]=temp3;
+ temp2=_mm_aeskeygenassist_si128 (temp3,0x1);
+ KEY_192_ASSIST(&temp1, &temp2, &temp3);
+ key[1] = mm_shuffle_pd_i0(key[1], temp1);
+ key[2] = mm_shuffle_pd_i1(temp1, temp3);
+ temp2=_mm_aeskeygenassist_si128 (temp3,0x2);
+ KEY_192_ASSIST(&temp1, &temp2, &temp3);
+ key[3]=temp1;
+ key[4]=temp3;
+ temp2=_mm_aeskeygenassist_si128 (temp3,0x4);
+ KEY_192_ASSIST(&temp1, &temp2, &temp3);
+ key[4] = mm_shuffle_pd_i0(key[4], temp1);
+ key[5] = mm_shuffle_pd_i1(temp1, temp3);
+ temp2=_mm_aeskeygenassist_si128 (temp3,0x8);
+ KEY_192_ASSIST(&temp1, &temp2, &temp3);
+ key[6]=temp1;
+ key[7]=temp3;
+ temp2=_mm_aeskeygenassist_si128 (temp3,0x10);
+ KEY_192_ASSIST(&temp1, &temp2, &temp3);
+ key[7] = mm_shuffle_pd_i0(key[7], temp1);
+ key[8] = mm_shuffle_pd_i1(temp1, temp3);
+ temp2=_mm_aeskeygenassist_si128 (temp3,0x20);
+ KEY_192_ASSIST(&temp1, &temp2, &temp3);
+ key[9]=temp1;
+ key[10]=temp3;
+ temp2=_mm_aeskeygenassist_si128 (temp3,0x40);
+ KEY_192_ASSIST(&temp1, &temp2, &temp3);
+ key[10] = mm_shuffle_pd_i0(key[10], temp1);
+ key[11] = mm_shuffle_pd_i1(temp1, temp3);
+ temp2=_mm_aeskeygenassist_si128 (temp3,0x80);
+ KEY_192_ASSIST(&temp1, &temp2, &temp3);
+ key[12]=temp1;
+ key[13]=temp3;
+}
+
+FUNC_ISA
+static void AES_256_Key_Expansion (unsigned char *userkey, __m128i *key)
+{
+ __m128i temp1, temp2, temp3;
+ temp1 = _mm_loadu_si128((__m128i*)userkey);
+ temp3 = _mm_loadu_si128((__m128i*)(userkey+16));
+ key[0] = temp1;
+ key[1] = temp3;
+ temp2 = _mm_aeskeygenassist_si128 (temp3,0x01);
+ KEY_256_ASSIST_1(&temp1, &temp2);
+ key[2]=temp1;
+ KEY_256_ASSIST_2(&temp1, &temp3);
+ key[3]=temp3;
+ temp2 = _mm_aeskeygenassist_si128 (temp3,0x02);
+ KEY_256_ASSIST_1(&temp1, &temp2);
+ key[4]=temp1;
+ KEY_256_ASSIST_2(&temp1, &temp3);
+ key[5]=temp3;
+ temp2 = _mm_aeskeygenassist_si128 (temp3,0x04);
+ KEY_256_ASSIST_1(&temp1, &temp2);
+ key[6]=temp1;
+ KEY_256_ASSIST_2(&temp1, &temp3);
+ key[7]=temp3;
+ temp2 = _mm_aeskeygenassist_si128 (temp3,0x08);
+ KEY_256_ASSIST_1(&temp1, &temp2);
+ key[8]=temp1;
+ KEY_256_ASSIST_2(&temp1, &temp3);
+ key[9]=temp3;
+ temp2 = _mm_aeskeygenassist_si128 (temp3,0x10);
+ KEY_256_ASSIST_1(&temp1, &temp2);
+ key[10]=temp1;
+ KEY_256_ASSIST_2(&temp1, &temp3);
+ key[11]=temp3;
+ temp2 = _mm_aeskeygenassist_si128 (temp3,0x20);
+ KEY_256_ASSIST_1(&temp1, &temp2);
+ key[12]=temp1;
+ KEY_256_ASSIST_2(&temp1, &temp3);
+ key[13]=temp3;
+ temp2 = _mm_aeskeygenassist_si128 (temp3,0x40);
+ KEY_256_ASSIST_1(&temp1, &temp2);
+ key[14]=temp1;
+}
+
+/*
+ * AES-NI encrypt/decrypt core
+ */
+FUNC_ISA
+static void aes_encrypt_cbc_ni(unsigned char *blk, int len, AESContext * ctx)
+{
+ __m128i enc;
+ __m128i* block = (__m128i*)blk;
+ const __m128i* finish = (__m128i*)(blk + len);
+
+ assert((len & 15) == 0);
+
+ /* Load IV */
+ enc = _mm_loadu_si128((__m128i*)(ctx->iv));
+ while (block < finish) {
+ /* Key schedule ptr */
+ __m128i* keysched = (__m128i*)ctx->keysched;
+
+ /* Xor data with IV */
+ enc = _mm_xor_si128(_mm_loadu_si128(block), enc);
+
+ /* Perform rounds */
+ enc = _mm_xor_si128(enc, *keysched);
+ switch (ctx->Nr) {
+ case 14:
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ case 12:
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ case 10:
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenclast_si128(enc, *(++keysched));
+ break;
+ default:
+ assert(0);
+ }
+
+ /* Store and go to next block */
+ _mm_storeu_si128(block, enc);
+ ++block;
+ }
+
+ /* Update IV */
+ _mm_storeu_si128((__m128i*)(ctx->iv), enc);
+}
+
+FUNC_ISA
+static void aes_decrypt_cbc_ni(unsigned char *blk, int len, AESContext * ctx)
+{
+ __m128i dec = _mm_setzero_si128();
+ __m128i last, iv;
+ __m128i* block = (__m128i*)blk;
+ const __m128i* finish = (__m128i*)(blk + len);
+
+ assert((len & 15) == 0);
+
+ /* Load IV */
+ iv = _mm_loadu_si128((__m128i*)(ctx->iv));
+ while (block < finish) {
+ /* Key schedule ptr */
+ __m128i* keysched = (__m128i*)ctx->invkeysched;
+ last = _mm_loadu_si128(block);
+ dec = _mm_xor_si128(last, *keysched);
+ switch (ctx->Nr) {
+ case 14:
+ dec = _mm_aesdec_si128(dec, *(++keysched));
+ dec = _mm_aesdec_si128(dec, *(++keysched));
+ case 12:
+ dec = _mm_aesdec_si128(dec, *(++keysched));
+ dec = _mm_aesdec_si128(dec, *(++keysched));
+ case 10:
+ dec = _mm_aesdec_si128(dec, *(++keysched));
+ dec = _mm_aesdec_si128(dec, *(++keysched));
+ dec = _mm_aesdec_si128(dec, *(++keysched));
+ dec = _mm_aesdec_si128(dec, *(++keysched));
+ dec = _mm_aesdec_si128(dec, *(++keysched));
+ dec = _mm_aesdec_si128(dec, *(++keysched));
+ dec = _mm_aesdec_si128(dec, *(++keysched));
+ dec = _mm_aesdec_si128(dec, *(++keysched));
+ dec = _mm_aesdec_si128(dec, *(++keysched));
+ dec = _mm_aesdeclast_si128(dec, *(++keysched));
+ break;
+ default:
+ assert(0);
+ }
+
+ /* Xor data with IV */
+ dec = _mm_xor_si128(iv, dec);
+
+ /* Store data */
+ _mm_storeu_si128(block, dec);
+ iv = last;
+
+ /* Go to next block */
+ ++block;
+ }
+
+ /* Update IV */
+ _mm_storeu_si128((__m128i*)(ctx->iv), dec);
+}
+
+FUNC_ISA
+static void aes_sdctr_ni(unsigned char *blk, int len, AESContext *ctx)
+{
+ const __m128i BSWAP_EPI64 = _mm_setr_epi8(3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12);
+ const __m128i ONE = _mm_setr_epi32(0,0,0,1);
+ const __m128i ZERO = _mm_setzero_si128();
+ __m128i iv;
+ __m128i* block = (__m128i*)blk;
+ const __m128i* finish = (__m128i*)(blk + len);
+
+ assert((len & 15) == 0);
+
+ iv = _mm_loadu_si128((__m128i*)ctx->iv);
+
+ while (block < finish) {
+ __m128i enc;
+ __m128i* keysched = (__m128i*)ctx->keysched;/* Key schedule ptr */
+
+ /* Perform rounds */
+ enc = _mm_xor_si128(iv, *keysched); /* Note that we use IV */
+ switch (ctx->Nr) {
+ case 14:
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ case 12:
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ case 10:
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenc_si128(enc, *(++keysched));
+ enc = _mm_aesenclast_si128(enc, *(++keysched));
+ break;
+ default:
+ assert(0);
+ }
+
+ /* Xor with block and store result */
+ enc = _mm_xor_si128(enc, _mm_loadu_si128(block));
+ _mm_storeu_si128(block, enc);
+
+ /* Increment of IV */
+ iv = _mm_shuffle_epi8(iv, BSWAP_EPI64); /* Swap endianess */
+ iv = _mm_add_epi64(iv, ONE); /* Inc low part */
+ enc = _mm_cmpeq_epi64(iv, ZERO); /* Check for carry */
+ enc = _mm_unpacklo_epi64(ZERO, enc); /* Pack carry reg */
+ iv = _mm_sub_epi64(iv, enc); /* Sub carry reg */
+ iv = _mm_shuffle_epi8(iv, BSWAP_EPI64); /* Swap enianess back */
+
+ /* Go to next block */
+ ++block;
+ }
+
+ /* Update IV */
+ _mm_storeu_si128((__m128i*)ctx->iv, iv);
+}
+
+FUNC_ISA
+static void aes_inv_key_10(AESContext * ctx)
+{
+ __m128i* keysched = (__m128i*)ctx->keysched;
+ __m128i* invkeysched = (__m128i*)ctx->invkeysched;
+
+ *(invkeysched + 10) = *(keysched + 0);
+ *(invkeysched + 9) = _mm_aesimc_si128(*(keysched + 1));
+ *(invkeysched + 8) = _mm_aesimc_si128(*(keysched + 2));
+ *(invkeysched + 7) = _mm_aesimc_si128(*(keysched + 3));
+ *(invkeysched + 6) = _mm_aesimc_si128(*(keysched + 4));
+ *(invkeysched + 5) = _mm_aesimc_si128(*(keysched + 5));
+ *(invkeysched + 4) = _mm_aesimc_si128(*(keysched + 6));
+ *(invkeysched + 3) = _mm_aesimc_si128(*(keysched + 7));
+ *(invkeysched + 2) = _mm_aesimc_si128(*(keysched + 8));
+ *(invkeysched + 1) = _mm_aesimc_si128(*(keysched + 9));
+ *(invkeysched + 0) = *(keysched + 10);
+}
+
+FUNC_ISA
+static void aes_inv_key_12(AESContext * ctx)
+{
+ __m128i* keysched = (__m128i*)ctx->keysched;
+ __m128i* invkeysched = (__m128i*)ctx->invkeysched;
+
+ *(invkeysched + 12) = *(keysched + 0);
+ *(invkeysched + 11) = _mm_aesimc_si128(*(keysched + 1));
+ *(invkeysched + 10) = _mm_aesimc_si128(*(keysched + 2));
+ *(invkeysched + 9) = _mm_aesimc_si128(*(keysched + 3));
+ *(invkeysched + 8) = _mm_aesimc_si128(*(keysched + 4));
+ *(invkeysched + 7) = _mm_aesimc_si128(*(keysched + 5));
+ *(invkeysched + 6) = _mm_aesimc_si128(*(keysched + 6));
+ *(invkeysched + 5) = _mm_aesimc_si128(*(keysched + 7));
+ *(invkeysched + 4) = _mm_aesimc_si128(*(keysched + 8));
+ *(invkeysched + 3) = _mm_aesimc_si128(*(keysched + 9));
+ *(invkeysched + 2) = _mm_aesimc_si128(*(keysched + 10));
+ *(invkeysched + 1) = _mm_aesimc_si128(*(keysched + 11));
+ *(invkeysched + 0) = *(keysched + 12);
+}
+
+FUNC_ISA
+static void aes_inv_key_14(AESContext * ctx)
+{
+ __m128i* keysched = (__m128i*)ctx->keysched;
+ __m128i* invkeysched = (__m128i*)ctx->invkeysched;
+
+ *(invkeysched + 14) = *(keysched + 0);
+ *(invkeysched + 13) = _mm_aesimc_si128(*(keysched + 1));
+ *(invkeysched + 12) = _mm_aesimc_si128(*(keysched + 2));
+ *(invkeysched + 11) = _mm_aesimc_si128(*(keysched + 3));
+ *(invkeysched + 10) = _mm_aesimc_si128(*(keysched + 4));
+ *(invkeysched + 9) = _mm_aesimc_si128(*(keysched + 5));
+ *(invkeysched + 8) = _mm_aesimc_si128(*(keysched + 6));
+ *(invkeysched + 7) = _mm_aesimc_si128(*(keysched + 7));
+ *(invkeysched + 6) = _mm_aesimc_si128(*(keysched + 8));
+ *(invkeysched + 5) = _mm_aesimc_si128(*(keysched + 9));
+ *(invkeysched + 4) = _mm_aesimc_si128(*(keysched + 10));
+ *(invkeysched + 3) = _mm_aesimc_si128(*(keysched + 11));
+ *(invkeysched + 2) = _mm_aesimc_si128(*(keysched + 12));
+ *(invkeysched + 1) = _mm_aesimc_si128(*(keysched + 13));
+ *(invkeysched + 0) = *(keysched + 14);
+}
+
+/*
+ * Set up an AESContext. `keylen' is measured in
+ * bytes; it can be either 16 (128-bit), 24 (192-bit), or 32
+ * (256-bit).
+ */
+FUNC_ISA
+static void aes_setup_ni(AESContext * ctx, unsigned char *key, int keylen)
+{
+ __m128i *keysched = (__m128i*)ctx->keysched;
+
+ ctx->encrypt_cbc = aes_encrypt_cbc_ni;
+ ctx->decrypt_cbc = aes_decrypt_cbc_ni;
+ ctx->sdctr = aes_sdctr_ni;
+
+ /*
+ * Now do the key setup itself.
+ */
+ switch (keylen) {
+ case 16:
+ AES_128_Key_Expansion (key, keysched);
+ break;
+ case 24:
+ AES_192_Key_Expansion (key, keysched);
+ break;
+ case 32:
+ AES_256_Key_Expansion (key, keysched);
+ break;
+ default:
+ assert(0);
+ }
+
+ /*
+ * Now prepare the modified keys for the inverse cipher.
+ */
+ switch (ctx->Nr) {
+ case 10:
+ aes_inv_key_10(ctx);
+ break;
+ case 12:
+ aes_inv_key_12(ctx);
+ break;
+ case 14:
+ aes_inv_key_14(ctx);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+#else /* COMPILER_SUPPORTS_AES_NI */
+
+static void aes_setup_ni(AESContext * ctx, unsigned char *key, int keylen)
+{
+ assert(0);
+}
+
+INLINE static int supports_aes_ni()
+{
+ return 0;
+}
+
+#endif /* COMPILER_SUPPORTS_AES_NI */
From 0a0a1c01d7cc6ca750d39f43b902e86987c5d376 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Fri, 20 Oct 2017 19:14:41 +0100
Subject: [PATCH 091/166] Additional copyright holders, from the AES-NI work.
---
LICENCE | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/LICENCE b/LICENCE
index 05fbb7d39..c473a6a40 100644
--- a/LICENCE
+++ b/LICENCE
@@ -4,7 +4,8 @@ Portions copyright Robert de Bath, Joris van Rantwijk, Delian
Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus
Kuhn, Colin Watson, Christopher Staite, Lorenz Diener, Christian
-Brabandt, Jeff Smith, and CORE SDI S.A.
+Brabandt, Jeff Smith, Pavel Kryukov, Maxim Kuznetsov, Svyatoslav
+Kuzmich, and CORE SDI S.A.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
From 4d15d46473907515d31cd0dc92b3ce86e5c5cb1e Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sun, 26 Nov 2017 08:45:19 +0000
Subject: [PATCH 092/166] Memory leak: free conn->retbuf in uxagentc.c.
While debugging some new code, I ran valgrind in leak-checking mode
and it pointed out a handful of existing memory leaks, which got in the
way of spotting any _new_ leaks I might be introducing :-)
This was one: in the case where an asynchronous agent query on Unix is
aborted, the dynamically allocated buffer holding the response was not
freed.
---
unix/uxagentc.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/unix/uxagentc.c b/unix/uxagentc.c
index 51f9a1ebe..2c7483437 100644
--- a/unix/uxagentc.c
+++ b/unix/uxagentc.c
@@ -95,6 +95,8 @@ void agent_cancel_query(agent_pending_query *conn)
uxsel_del(conn->fd);
close(conn->fd);
del234(agent_pending_queries, conn);
+ if (conn->retbuf && conn->retbuf != conn->sizebuf)
+ sfree(conn->retbuf);
sfree(conn);
}
@@ -114,11 +116,12 @@ static void agent_select_result(int fd, int event)
return; /* more data to come */
/*
- * We have now completed the agent query. Do the callback, and
- * clean up. (Of course we don't free retbuf, since ownership
- * of that passes to the callback.)
+ * We have now completed the agent query. Do the callback.
*/
conn->callback(conn->callback_ctx, conn->retbuf, conn->retlen);
+ /* Null out conn->retbuf, since ownership of that buffer has
+ * passed to the callback. */
+ conn->retbuf = NULL;
agent_cancel_query(conn);
}
From 90a402c017b6b262b0b2181cf193dd8188fac5c7 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sun, 26 Nov 2017 08:45:37 +0000
Subject: [PATCH 093/166] Memory leak: free term->answerback in term_free().
Not a large leak as these things go, but valgrind's error dump for a
memory leak is just as annoying regardless of the size of the leaked
object!
---
terminal.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/terminal.c b/terminal.c
index d32d4f423..d5d5314a1 100644
--- a/terminal.c
+++ b/terminal.c
@@ -1739,6 +1739,7 @@ void term_free(Terminal *term)
sfree(term->ltemp);
sfree(term->wcFrom);
sfree(term->wcTo);
+ sfree(term->answerback);
for (i = 0; i < term->bidi_cache_size; i++) {
sfree(term->pre_bidi_cache[i].chars);
From f1eeeff8cfea1001a1791ba95782ba7bbed3b976 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sun, 26 Nov 2017 08:45:45 +0000
Subject: [PATCH 094/166] Memory leak: add a columns_finalize() method.
My custom GTK layout class 'Columns' includes a linked list of
dynamically allocated data, and apparently I forgot to write a
destructor that frees it all when the class is deallocated, and have
never noticed until now.
---
unix/gtkcols.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 53 insertions(+), 2 deletions(-)
diff --git a/unix/gtkcols.c b/unix/gtkcols.c
index e8223a726..ef060d639 100644
--- a/unix/gtkcols.c
+++ b/unix/gtkcols.c
@@ -8,6 +8,11 @@
static void columns_init(Columns *cols);
static void columns_class_init(ColumnsClass *klass);
+#if !GTK_CHECK_VERSION(2,0,0)
+static void columns_finalize(GtkObject *object);
+#else
+static void columns_finalize(GObject *object);
+#endif
static void columns_map(GtkWidget *widget);
static void columns_unmap(GtkWidget *widget);
#if !GTK_CHECK_VERSION(2,0,0)
@@ -96,11 +101,11 @@ static gint (*columns_inherited_focus)(GtkContainer *container,
static void columns_class_init(ColumnsClass *klass)
{
#if !GTK_CHECK_VERSION(2,0,0)
- /* GtkObjectClass *object_class = (GtkObjectClass *)klass; */
+ GtkObjectClass *object_class = (GtkObjectClass *)klass;
GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
GtkContainerClass *container_class = (GtkContainerClass *)klass;
#else
- /* GObjectClass *object_class = G_OBJECT_CLASS(klass); */
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS(klass);
#endif
@@ -111,6 +116,7 @@ static void columns_class_init(ColumnsClass *klass)
parent_class = g_type_class_peek_parent(klass);
#endif
+ object_class->finalize = columns_finalize;
widget_class->map = columns_map;
widget_class->unmap = columns_unmap;
#if !GTK_CHECK_VERSION(2,0,0)
@@ -149,6 +155,50 @@ static void columns_init(Columns *cols)
cols->spacing = 0;
}
+static void columns_child_free(gpointer vchild)
+{
+ ColumnsChild *child = (ColumnsChild *)vchild;
+ if (child->percentages)
+ g_free(child->percentages);
+ g_free(child);
+}
+
+static void columns_finalize(
+#if !GTK_CHECK_VERSION(2,0,0)
+ GtkObject *object
+#else
+ GObject *object
+#endif
+ )
+{
+ Columns *cols;
+
+ g_return_if_fail(object != NULL);
+ g_return_if_fail(IS_COLUMNS(object));
+
+ cols = COLUMNS(object);
+
+#if !GTK_CHECK_VERSION(2,0,0)
+ {
+ GList *node;
+ for (node = cols->children; node; node = node->next)
+ if (node->data)
+ columns_child_free(node->data);
+ }
+ g_list_free(cols->children);
+#else
+ g_list_free_full(cols->children, columns_child_free);
+#endif
+
+ cols->children = NULL;
+
+#if !GTK_CHECK_VERSION(2,0,0)
+ GTK_OBJECT_CLASS(parent_class)->finalize(object);
+#else
+ G_OBJECT_CLASS(parent_class)->finalize(object);
+#endif
+}
+
/*
* These appear to be thoroughly tedious functions; the only reason
* we have to reimplement them at all is because we defined our own
@@ -406,6 +456,7 @@ void columns_add(Columns *cols, GtkWidget *child,
childdata->colspan = colspan;
childdata->force_left = FALSE;
childdata->same_height_as = NULL;
+ childdata->percentages = NULL;
cols->children = g_list_append(cols->children, childdata);
cols->taborder = g_list_append(cols->taborder, child);
From 9909077be131c5dc7b3dee14cb25b8a799040616 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sun, 26 Nov 2017 08:56:16 +0000
Subject: [PATCH 095/166] Make the current code compile again under GTK1.
Apparently I haven't tested this compile mode in a while: I had a
couple of compile errors due to new code not properly #ifdeffed (the
true-colour mode has to be effectively disabled in the palette-based
GTK1 graphics model) and one for an unused static function
(get_monitor_geometry is only used in GTK2 and above, and with -Werror
that means I mustn't even _define_ it in GTK1).
With these changes, I still didn't get a clean compile unless I also
configured CFLAGS=-std=gnu89, due to the GTK1 headers having an
outdated set of ifdefs to figure out the compiler's semantics of
'inline'. (They seem to expect old-style gcc, which inconveniently
treats 'inline' and 'extern inline' more or less the opposite way
round from the version standardised by C99.)
---
unix/gtkwin.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/unix/gtkwin.c b/unix/gtkwin.c
index 3a3c2a546..a851c2584 100644
--- a/unix/gtkwin.c
+++ b/unix/gtkwin.c
@@ -3039,11 +3039,16 @@ static void draw_set_colour(struct draw_ctx *dctx, int col, int dim)
#ifdef DRAW_TEXT_GDK
if (dctx->uctx.type == DRAWTYPE_GDK) {
if (dim) {
+#if GTK_CHECK_VERSION(2,0,0)
GdkColor color;
color.red = dctx->inst->cols[col].red * 2 / 3;
color.green = dctx->inst->cols[col].green * 2 / 3;
color.blue = dctx->inst->cols[col].blue * 2 / 3;
gdk_gc_set_rgb_fg_color(dctx->uctx.u.gdk.gc, &color);
+#else
+ /* Poor GTK1 fallback */
+ gdk_gc_set_foreground(dctx->uctx.u.gdk.gc, &dctx->inst->cols[col]);
+#endif
} else {
gdk_gc_set_foreground(dctx->uctx.u.gdk.gc, &dctx->inst->cols[col]);
}
@@ -3064,6 +3069,7 @@ static void draw_set_colour_rgb(struct draw_ctx *dctx, optionalrgb orgb,
{
#ifdef DRAW_TEXT_GDK
if (dctx->uctx.type == DRAWTYPE_GDK) {
+#if GTK_CHECK_VERSION(2,0,0)
GdkColor color;
color.red = orgb.r * 256;
color.green = orgb.g * 256;
@@ -3074,6 +3080,10 @@ static void draw_set_colour_rgb(struct draw_ctx *dctx, optionalrgb orgb,
color.blue = color.blue * 2 / 3;
}
gdk_gc_set_rgb_fg_color(dctx->uctx.u.gdk.gc, &color);
+#else
+ /* Poor GTK1 fallback */
+ gdk_gc_set_foreground(dctx->uctx.u.gdk.gc, &dctx->inst->cols[256]);
+#endif
}
#endif
#ifdef DRAW_TEXT_CAIRO
@@ -4374,6 +4384,7 @@ static void start_backend(struct gui_data *inst)
gtk_widget_set_sensitive(inst->restartitem, FALSE);
}
+#if GTK_CHECK_VERSION(2,0,0)
static void get_monitor_geometry(GtkWidget *widget, GdkRectangle *geometry)
{
#if GTK_CHECK_VERSION(3,4,0)
@@ -4397,6 +4408,7 @@ static void get_monitor_geometry(GtkWidget *widget, GdkRectangle *geometry)
geometry->height = gdk_screen_height();
#endif
}
+#endif
struct gui_data *new_session_window(Conf *conf, const char *geometry_string)
{
From c74d1e3c6a0aa2c4ef275e18fcdc5844f536bab6 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sun, 26 Nov 2017 09:16:22 +0000
Subject: [PATCH 096/166] GTK1 runtime fix: widen extent of ignore_sbar.
ignore_sbar is a flag that we set while manually changing the
scrollbar settings, so that when those half-finished changes trigger
GTK event callbacks, we know to ignore them, and wait until we've
finished setting everything up before actually updating the window.
But somehow I had managed to leave the functions that actually _have
the effect_ (at least in GTK1) outside the pair of statements that set
and unset the ignore flag.
The effect was that compiling pterm for GTK1, starting it up, and
issuing a command like 'ls -l' that scrolls off the bottom of the
window would lead to the _top_ half of the ls output being visible,
and the scrollbar at the top of the scrollback rather than the bottom.
---
unix/gtkwin.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/unix/gtkwin.c b/unix/gtkwin.c
index a851c2584..1038e7569 100644
--- a/unix/gtkwin.c
+++ b/unix/gtkwin.c
@@ -2884,13 +2884,13 @@ void set_sbar(void *frontend, int total, int start, int page)
struct gui_data *inst = (struct gui_data *)frontend;
if (!conf_get_int(inst->conf, CONF_scrollbar))
return;
+ inst->ignore_sbar = TRUE;
gtk_adjustment_set_lower(inst->sbar_adjust, 0);
gtk_adjustment_set_upper(inst->sbar_adjust, total);
gtk_adjustment_set_value(inst->sbar_adjust, start);
gtk_adjustment_set_page_size(inst->sbar_adjust, page);
gtk_adjustment_set_step_increment(inst->sbar_adjust, 1);
gtk_adjustment_set_page_increment(inst->sbar_adjust, page/2);
- inst->ignore_sbar = TRUE;
#if !GTK_CHECK_VERSION(3,18,0)
gtk_adjustment_changed(inst->sbar_adjust);
#endif
From 116dac29ccc99ff498edd7dfcda0f456ce47c3ef Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sat, 25 Nov 2017 21:49:31 +0000
Subject: [PATCH 097/166] Reinstate the SIGCHLD handler in ptermapp.
Detecting that the child process in a pterm has terminated is
important for _any_ kind of pterm, so it's a mistake to put the signal
handler setup _solely_ inside the optional pty_pre_init function which
does the privileged setup and forks off a utmp watchdog process. Now
the signal handler is installed even in the GtkApplication-based
multi-window front end to pterm, meaning it will exist even on OS X.
---
unix/uxpty.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/unix/uxpty.c b/unix/uxpty.c
index 618fe9bd7..4387ad8fa 100644
--- a/unix/uxpty.c
+++ b/unix/uxpty.c
@@ -261,13 +261,20 @@ static void cleanup_utmp(void)
}
#endif
-#ifndef NO_PTY_PRE_INIT
static void sigchld_handler(int signum)
{
if (write(pty_signal_pipe[1], "x", 1) <= 0)
/* not much we can do about it */;
}
-#endif
+
+static void pty_setup_sigchld_handler(void)
+{
+ static int setup = FALSE;
+ if (!setup) {
+ putty_signal(SIGCHLD, sigchld_handler);
+ setup = TRUE;
+ }
+}
#ifndef OMIT_UTMP
static void fatal_sig_handler(int signum)
@@ -433,7 +440,7 @@ void pty_pre_init(void)
/* set the child signal handler straight away; it needs to be set
* before we ever fork. */
- putty_signal(SIGCHLD, sigchld_handler);
+ pty_setup_sigchld_handler();
pty->master_fd = pty->slave_fd = -1;
#ifndef OMIT_UTMP
pty_stamped_utmp = FALSE;
@@ -790,6 +797,12 @@ static const char *pty_init(void *frontend, void **backend_handle, Conf *conf,
windowid = get_windowid(pty->frontend);
#endif
+ /*
+ * Set up the signal handler to catch SIGCHLD, if pty_pre_init
+ * didn't already do it.
+ */
+ pty_setup_sigchld_handler();
+
/*
* Fork and execute the command.
*/
From 5b13a1b01518c23f38525ec2ae9b4ac9ca3110cd Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sat, 25 Nov 2017 21:51:45 +0000
Subject: [PATCH 098/166] Add a missing conf_copy in gtkapp's Duplicate
Session.
Without this, the Conf objects in a session and its duplicate were
aliases of each other, which could lead to confusing semantic effects
if one of the sessions was reconfigured in mid-run, and worse still, a
crash if one session got cleaned up and called conf_free on a Conf
that the other was still using.
None of that was intentional; it was just a matter of forgetting to
clone the Conf for the duplicated session. Now we do.
---
unix/gtkapp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/unix/gtkapp.c b/unix/gtkapp.c
index 8b2a794fc..b544684ed 100644
--- a/unix/gtkapp.c
+++ b/unix/gtkapp.c
@@ -196,7 +196,7 @@ void launch_duplicate_session(Conf *conf)
{
extern const int dup_check_launchable;
assert(!dup_check_launchable || conf_launchable(conf));
- new_session_window(conf, NULL);
+ new_session_window(conf_copy(conf), NULL);
}
void launch_new_session(void)
From b6b91b8e177958d870caa116e10cec537892eba8 Mon Sep 17 00:00:00 2001
From: Simon Tatham
Date: Sun, 26 Nov 2017 10:58:56 +0000
Subject: [PATCH 099/166] OS X makefile: stop depending on JHBUILD_PREFIX.
People who use a packaging system other than jhbuild still ought to be
able to run the OS X GTK3 build, so now the gtk-mac-bundler command
finds out the locations of things by a more portable method.
(I've had this change lurking around uncommitted in a working tree for
a while, and only just found it in the course of doing other OS X-
related work. Oops.)
---
Recipe | 4 ++--
unix/pterm.bundle | 6 +++++-
unix/putty.bundle | 36 +++++++++++++++++++++++++++++++++++-
3 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/Recipe b/Recipe
index 5715938b0..33d0f2f7e 100644
--- a/Recipe
+++ b/Recipe
@@ -208,9 +208,9 @@ endif
if HAVE_QUARTZ
noinst_SCRIPTS = unix/PuTTY.app unix/Pterm.app
unix/PuTTY.app: unix/putty.bundle puttyapp osxlaunch
- rm -rf $@ && gtk-mac-bundler $<
+ rm -rf $@ && PUTTY_GTK_PREFIX_FROM_MAKEFILE=$$(pkg-config --variable=prefix gtk+-3.0) gtk-mac-bundler $<
unix/Pterm.app: unix/pterm.bundle ptermapp osxlaunch
- rm -rf $@ && gtk-mac-bundler $<
+ rm -rf $@ && PUTTY_GTK_PREFIX_FROM_MAKEFILE=$$(pkg-config --variable=prefix gtk+-3.0) gtk-mac-bundler $<
endif
!end
diff --git a/unix/pterm.bundle b/unix/pterm.bundle
index 377fee0dc..0d7012160 100644
--- a/unix/pterm.bundle
+++ b/unix/pterm.bundle
@@ -2,7 +2,11 @@
- ${env:JHBUILD_PREFIX}
+
+ ${env:PUTTY_GTK_PREFIX_FROM_MAKEFILE}
+
gtk+-3.0
+ ${env:PUTTY_GTK_PREFIX_FROM_MAKEFILE}
+
gtk+-3.0