Compile PuTTY on your own

The beginning: Source Code

Find the original source archive at https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html or get the Windows-Archive directly here: https://the.earth.li/~sgtatham/putty/latest/putty-src.zip

Modify the Source Code

For example: Tweak the modal „Fatal Connection Error“ Dialog: Relax PuTTY: Suppress „Fatal Error“ Dialog

Next step: GCC-Compiler

I’d chose MinGW to compile native Windows Applications: MinGW as build-environment for native Windows Applications

Compile it

Using MinGw:

run MinGw

In PuTTY it’s all prepared for us – go to the „windows“ subdirectory:

  • mingw32-make -f Makefile.mgw
C:\Program Files\mingw-w64\x86_64-8.1.0-win32-seh-rt_v6-rev0>echo off
Microsoft Windows [Version 10.0.19042.1110]
(c) Microsoft Corporation. Alle Rechte vorbehalten.

C:\> cd C:\\Users\\user\\Downloads\\putty-src_0-76\

C:\Users\user\Downloads\putty-src_0-76> cd windows

C:\Users\user\Downloads\putty-src_0-76\windows> mingw32-make -f Makefile.mgw
gcc  -Wall -O2 -std=gnu99 -Wvla -D_WINDOWS -DWIN32S_COMPAT -D_NO_OLDNAMES -D__USE_MINGW_ANSI_STDIO=1 -I.././ -I../charset/ -I../windows/ -I../unix/ -D_WIN32_IE=0x0500 -DWINVER=0x0500 -D_WIN32_WINDOWS=0x0410 -D_WIN32_WINNT=0x0500  -c ../ssh2userauth.c
gcc -s -o plink.exe -Wl,-Map,plink.map agentf.o aqsync.o \
        be_all_s.o be_misc.o callback.o clicons.o cmdline.o conf.o \
        console.o cproxy.o ecc.o errsock.o ldisc.o logging.o \
        mainchan.o marshal.o memory.o misc.o miscucs.o mpint.o \
        noterm.o nullplug.o pgssapi.o pinger.o plink.res.o portfwd.o \
        proxy.o raw.o rlogin.o sessprep.o settings.o ssh.o ssh1bpp.o \
        ssh1censor.o ssh1connection.o ssh1connection-client.o \
        ssh1login.o ssh2bpp.o ssh2bpp-bare.o ssh2censor.o \
        ssh2connection.o ssh2connection-client.o ssh2kex-client.o \
        ssh2transhk.o ssh2transport.o ssh2userauth.o sshaes.o \
        ssharcf.o sshargon2.o sshauxcrypt.o sshblake2.o sshblowf.o \
        sshccp.o sshcommon.o sshcrc.o sshcrcda.o sshdes.o sshdh.o \
        sshdss.o sshecc.o sshgssc.o sshhmac.o sshmac.o sshmd5.o \
        sshprng.o sshpubk.o sshrand.o sshrsa.o sshsh256.o sshsh512.o \
        sshsha.o sshsha3.o sshshare.o sshutils.o sshverstring.o \
        sshzlib.o stripctrl.o supdup.o telnet.o timing.o tree234.o \
        utils.o version.o wcwidth.o wildcard.o wincapi.o \
        wincliloop.o wincons.o windefs.o wingss.o winhandl.o \
        winhsock.o winmisc.o winmiscs.o winnet.o winnohlp.o \
        winnoise.o winnojmp.o winnpc.o winnps.o winpgntc.o \
        winplink.o winproxy.o winsecur.o winselcli.o winser.o \
        winshare.o winstore.o wintime.o winucs.o winx11.o x11fwd.o \
        -ladvapi32 -lcomdlg32 -lgdi32 -limm32 -lole32 -lshell32 \
        -luser32
gcc -s -o pscp.exe -Wl,-Map,pscp.map agentf.o aqsync.o be_misc.o \
        be_ssh.o callback.o clicons.o cmdline.o conf.o console.o \
        cproxy.o ecc.o errsock.o logging.o mainchan.o marshal.o \
        memory.o misc.o miscucs.o mpint.o nullplug.o pgssapi.o \
        pinger.o portfwd.o proxy.o pscp.o pscp.res.o psftpcommon.o \
        settings.o sftp.o sftpcommon.o ssh.o ssh1bpp.o ssh1censor.o \
        ssh1connection.o ssh1connection-client.o ssh1login.o \
        ssh2bpp.o ssh2bpp-bare.o ssh2censor.o ssh2connection.o \
        ssh2connection-client.o ssh2kex-client.o ssh2transhk.o \
        ssh2transport.o ssh2userauth.o sshaes.o ssharcf.o \
        sshargon2.o sshauxcrypt.o sshblake2.o sshblowf.o sshccp.o \
        sshcommon.o sshcrc.o sshcrcda.o sshdes.o sshdh.o sshdss.o \
        sshecc.o sshgssc.o sshhmac.o sshmac.o sshmd5.o sshprng.o \
        sshpubk.o sshrand.o sshrsa.o sshsh256.o sshsh512.o sshsha.o \
        sshsha3.o sshshare.o sshutils.o sshverstring.o sshzlib.o \
        stripctrl.o timing.o tree234.o utils.o version.o wcwidth.o \
        wildcard.o wincapi.o wincliloop.o wincons.o windefs.o \
        wingss.o winhandl.o winhsock.o winmisc.o winmiscs.o winnet.o \
        winnohlp.o winnoise.o winnojmp.o winnpc.o winnps.o \
        winpgntc.o winproxy.o winsecur.o winselcli.o winsftp.o \
        winshare.o winstore.o wintime.o winucs.o x11fwd.o -ladvapi32 \
        -lcomdlg32 -lgdi32 -limm32 -lole32 -lshell32 -luser32
gcc -s -o psftp.exe -Wl,-Map,psftp.map agentf.o aqsync.o \
        be_misc.o be_ssh.o callback.o clicons.o cmdline.o conf.o \
        console.o cproxy.o ecc.o errsock.o logging.o mainchan.o \
        marshal.o memory.o misc.o miscucs.o mpint.o nullplug.o \
        pgssapi.o pinger.o portfwd.o proxy.o psftp.o psftp.res.o \
        psftpcommon.o settings.o sftp.o sftpcommon.o ssh.o ssh1bpp.o \
        ssh1censor.o ssh1connection.o ssh1connection-client.o \
        ssh1login.o ssh2bpp.o ssh2bpp-bare.o ssh2censor.o \
        ssh2connection.o ssh2connection-client.o ssh2kex-client.o \
        ssh2transhk.o ssh2transport.o ssh2userauth.o sshaes.o \
        ssharcf.o sshargon2.o sshauxcrypt.o sshblake2.o sshblowf.o \
        sshccp.o sshcommon.o sshcrc.o sshcrcda.o sshdes.o sshdh.o \
        sshdss.o sshecc.o sshgssc.o sshhmac.o sshmac.o sshmd5.o \
        sshprng.o sshpubk.o sshrand.o sshrsa.o sshsh256.o sshsh512.o \
        sshsha.o sshsha3.o sshshare.o sshutils.o sshverstring.o \
        sshzlib.o stripctrl.o timing.o tree234.o utils.o version.o \
        wcwidth.o wildcard.o wincapi.o wincliloop.o wincons.o \
        windefs.o wingss.o winhandl.o winhsock.o winmisc.o \
        winmiscs.o winnet.o winnohlp.o winnoise.o winnojmp.o \
        winnpc.o winnps.o winpgntc.o winproxy.o winsecur.o \
        winselcli.o winsftp.o winshare.o winstore.o wintime.o \
        winucs.o x11fwd.o -ladvapi32 -lcomdlg32 -lgdi32 -limm32 \
        -lole32 -lshell32 -luser32
gcc -mwindows -s -o putty.exe -Wl,-Map,putty.map agentf.o \
        aqsync.o be_all_s.o be_misc.o callback.o cmdline.o conf.o \
        config.o cproxy.o dialog.o ecc.o errsock.o ldisc.o logging.o \
        mainchan.o marshal.o memory.o minibidi.o misc.o miscucs.o \
        mpint.o nullplug.o pgssapi.o pinger.o portfwd.o proxy.o \
        putty.res.o raw.o rlogin.o sessprep.o settings.o sizetip.o \
        ssh.o ssh1bpp.o ssh1censor.o ssh1connection.o \
        ssh1connection-client.o ssh1login.o ssh2bpp.o ssh2bpp-bare.o \
        ssh2censor.o ssh2connection.o ssh2connection-client.o \
        ssh2kex-client.o ssh2transhk.o ssh2transport.o \
        ssh2userauth.o sshaes.o ssharcf.o sshargon2.o sshauxcrypt.o \
        sshblake2.o sshblowf.o sshccp.o sshcommon.o sshcrc.o \
        sshcrcda.o sshdes.o sshdh.o sshdss.o sshecc.o sshgssc.o \
        sshhmac.o sshmac.o sshmd5.o sshprng.o sshpubk.o sshrand.o \
        sshrsa.o sshsh256.o sshsh512.o sshsha.o sshsha3.o sshshare.o \
        sshutils.o sshverstring.o sshzlib.o stripctrl.o supdup.o \
        telnet.o terminal.o timing.o tree234.o utils.o version.o \
        wcwidth.o wildcard.o wincapi.o wincfg.o winctrls.o windefs.o \
        windlg.o window.o wingss.o winhandl.o winhelp.o winhsock.o \
        winjump.o winmisc.o winmiscs.o winnet.o winnoise.o winnpc.o \
        winnps.o winpgntc.o winprint.o winproxy.o winsecur.o \
        winselgui.o winser.o winshare.o winstore.o wintime.o \
        winucs.o winutils.o winx11.o x11fwd.o -ladvapi32 -lcomdlg32 \
        -lgdi32 -limm32 -lole32 -lshell32 -luser32

C:\Users\user\Downloads\putty-src_0-76\windows>

Check the result

C:\Users\user\Downloads\putty-src_0-76\windows> dir putty.exe
 Datenträger in Laufwerk C: ist Windows
 Volumeseriennummer: 1E1B-0142

 Verzeichnis von C:\Users\user\Downloads\putty-src_0-76\windows

16.08.2021  20:16           981.504 putty.exe
               1 Datei(en),        981.504 Bytes
               0 Verzeichnis(se), 265.798.283.264 Bytes frei

C:\Users\user\Downloads\putty-src_0-76\windows>

EXEcute it

C:\Users\user\Downloads\putty-src_0-76\windows> putty.exe
Putty 0.76 – compiled on my own using „gcc 8.1.0“

Final thought: Donate PuTTY

It is possible 😉 to donate to the original PuTTY developers – look here: https://www.chiark.greenend.org.uk/~sgtatham/putty/faq.html#faq-donations

MinGW as build-environment for native Windows Applications

It is possible to complie open source software like „PuTTY“ using the famous gcc open source compiler.

Choose your favourite MinGW „distribution“

There are several  „distribution“-like packages available on the web.

I found https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/installer/mingw-w64-install.exe/download which worked „out of the box“.

Install MinGw

Just a few settings to think about, I chose:

I changed from the default-settings:

  • Version:8.1.0
  • Architecture:i686
  • Threads:posix
  • Exception:dwarf
  • Build Revision:0

to

  • Architecture:x86_64
  • Threads:win32
  • Exception:seh

Check the Windows „PATH“-Environment Variable

I should contain C:\\Program Files\\mingw-w64\\x86\_64-8.1.0-win32-seh-rt\_v6-rev0\\mingw64\\bin

Run a „MinGW-Terminal“

Using the following shortcut

Relax PuTTY: Suppress „Fatal Error“ Dialog

When using PuTTY in „Multi-Tabbed“-Wrapper-Applications like MRemote-NG, Super-Putty, Putty-Connection-Manager, you name it, it’s absolute annoying that every connection-timeout pushes a modal pop-up window to the front (for every opened connection!) like this:

Since in those Applications the PuTTY-Window/Tab won’t get closed, or with „only on clean exit“

putty: close window only on clean exit

these modal alerts are absolutely pointless – when:

  1. PuTTY is running as standalone application
  2. the config-parameters set to „close window“ the original implemtation makes sense indeed.

So there is some code required, to distinguish between:

  • a quiet (Text-)Message, inline within the PuTTY-Screen when the window wont get closed
  • an modal alert before closing the putty window.

Original Code

Find it in „/windows/window.c“ – notice, that the modal popup will appear even when the PuTTY-Window won’t get closed.

/*
 * Print a message box and close the connection.
 */
static void win_seat_connection_fatal(Seat *seat, const char *msg)
{
    char *title = dupprintf("%s Fatal Error", appname);
    show_mouseptr(true);
    MessageBox(wgs.term_hwnd, msg, title, MB_ICONERROR | MB_OK);
    sfree(title);

    if (conf_get_int(conf, CONF_close_on_exit) == FORCE_ON)
        PostQuitMessage(1);
    else {
        queue_toplevel_callback(close_session, NULL);
    }
}

Improvement: Show the Dialog only, when PuTTY-Window will get closed

Much better for daily use – no annoyance anymore:

/*
 * Print a message box and close the connection.
 */
static void win_seat_connection_fatal(Seat *seat, const char *msg)
{
    char *title = dupprintf("%s Fatal Error", appname);

    if (conf_get_int(conf, CONF_close_on_exit) == FORCE_ON) {
        //show MessageBox before closing the PuTTY-Window
        show_mouseptr(true);
        MessageBox(wgs.term_hwnd, msg, title, MB_ICONERROR | MB_OK);

        PostQuitMessage(1);
    } else {
        //print message into the PuTTY-Console
        win_seat_output(seat,true,"\r\n\r\n",4);
        win_seat_output(seat,0,"------------------- ",20);
        win_seat_output(seat,0,title,strlen(title));
        win_seat_output(seat,0," ------------------\r\n",22);
        win_seat_output(seat,0,"- ",2);
        win_seat_output(seat,0,msg,strlen(msg));
        win_seat_output(seat,0,"\r\n\r\n",4);

        queue_toplevel_callback(close_session, NULL);
    }

    sfree(title);
}

Result: Relaxed Putty

Take a deep breath 🙂

relaxed putty

isn’t it beautiful?

Donate PuTTY

It is possible 😉 to donate to the original PuTTY developers – look here: https://www.chiark.greenend.org.uk/~sgtatham/putty/faq.html#faq-donations