├── .gitignore ├── Buildscr ├── Buildscr.cv ├── CHECKLST.txt ├── LATEST.VER ├── LICENCE ├── README ├── README.md ├── Recipe ├── adb.c ├── be_all.c ├── be_all_s.c ├── be_all_u.c ├── be_none.c ├── be_nos_s.c ├── be_nos_u.c ├── be_nossh.c ├── be_ssh.c ├── callback.c ├── charset ├── README ├── charset.h ├── enum.c ├── fromucs.c ├── internal.h ├── localenc.c ├── macenc.c ├── mimeenc.c ├── sbcs.c ├── sbcs.dat ├── sbcsgen.pl ├── slookup.c ├── toucs.c ├── utf8.c └── xenc.c ├── cmdgen.c ├── cmdline.c ├── conf.c ├── config.c ├── configure.ac ├── contrib ├── cygtermd │ ├── Makefile │ ├── README │ ├── main.c │ ├── malloc.c │ ├── malloc.h │ ├── pty.c │ ├── pty.h │ ├── sel.c │ ├── sel.h │ ├── telnet.c │ └── telnet.h ├── encodelib.py ├── kh2reg.py ├── logparse.pl ├── nice-ibeam.cur └── samplekex.py ├── cproxy.c ├── dialog.c ├── dialog.h ├── doc ├── .gitignore ├── Makefile ├── blurb.but ├── chm.but ├── chm.css ├── config.but ├── errors.but ├── faq.but ├── feedback.but ├── gs.but ├── index.but ├── intro.but ├── licence.but ├── man-pg.but ├── man-pl.but ├── man-pscp.but ├── man-psft.but ├── man-ptel.but ├── man-pter.but ├── man-putt.but ├── mancfg.but ├── manpages.but ├── pageant.but ├── pgpkeys.but ├── plink.but ├── pscp.but ├── psftp.but ├── pubkey.but ├── site.but ├── sshnames.but ├── udp.but ├── using.but └── vids.but ├── errsock.c ├── icons ├── Makefile ├── cicon.pl ├── icon.pl └── mkicon.py ├── import.c ├── int64.c ├── int64.h ├── ldisc.c ├── ldisc.h ├── ldiscucs.c ├── logging.c ├── macosx ├── README.OSX ├── info.plist ├── osx.h ├── osxclass.h ├── osxctrls.m ├── osxdlg.m ├── osxmain.m ├── osxsel.m ├── osxwin.m └── putty.icns ├── minibidi.c ├── misc.c ├── misc.h ├── mkauto.sh ├── mkfiles.pl ├── mksrcarc.sh ├── mkunxarc.sh ├── network.h ├── nocproxy.c ├── nogss.c ├── noprint.c ├── noshare.c ├── noterm.c ├── notiming.c ├── pgssapi.c ├── pgssapi.h ├── pinger.c ├── portfwd.c ├── pproxy.c ├── proxy.c ├── proxy.h ├── pscp.c ├── psftp.c ├── psftp.h ├── putty.h ├── puttymem.h ├── puttyps.h ├── raw.c ├── resource.h ├── rlogin.c ├── sercfg.c ├── settings.c ├── sftp.c ├── sftp.h ├── sign.sh ├── ssh.c ├── ssh.h ├── sshaes.c ├── ssharcf.c ├── sshblowf.c ├── sshbn.c ├── sshbn.h ├── sshcrc.c ├── sshcrcda.c ├── sshdes.c ├── sshdh.c ├── sshdss.c ├── sshdssg.c ├── sshgss.h ├── sshgssc.c ├── sshgssc.h ├── sshmd5.c ├── sshnogss.c ├── sshprime.c ├── sshpubk.c ├── sshrand.c ├── sshrsa.c ├── sshrsag.c ├── sshsh256.c ├── sshsh512.c ├── sshsha.c ├── sshshare.c ├── sshzlib.c ├── storage.h ├── telnet.c ├── terminal.c ├── terminal.h ├── testback.c ├── testdata ├── bignum.py ├── colours.txt ├── lattrs.txt ├── scocols.txt ├── utf8.txt └── vt100.txt ├── time.c ├── timing.c ├── tree234.c ├── tree234.h ├── unix ├── .gitignore ├── configure ├── gtkcfg.c ├── gtkcols.c ├── gtkcols.h ├── gtkdlg.c ├── gtkfont.c ├── gtkfont.h ├── gtkwin.c ├── unix.h ├── urlhack_unix.c ├── ux_x11.c ├── uxagentc.c ├── uxcfg.c ├── uxcons.c ├── uxgen.c ├── uxgss.c ├── uxmisc.c ├── uxnet.c ├── uxnoise.c ├── uxpeer.c ├── uxplink.c ├── uxprint.c ├── uxproxy.c ├── uxpterm.c ├── uxpty.c ├── uxputty.c ├── uxsel.c ├── uxser.c ├── uxsftp.c ├── uxshare.c ├── uxsignal.c ├── uxstore.c ├── uxucs.c ├── xkeysym.c ├── xpmptcfg.c ├── xpmpterm.c ├── xpmpucfg.c └── xpmputty.c ├── urlhack.c ├── version.c ├── version.h ├── wcwidth.c ├── wildcard.c ├── windows ├── README.txt ├── build-debug.bat ├── build-release.bat ├── clean.bat ├── cthelper │ ├── BUILDING │ ├── Makefile │ ├── README.txt │ ├── TODO │ ├── buffer.c │ ├── buffer.h │ ├── cthelper.c │ ├── cthelper.h │ ├── dbug.h │ ├── debug.h │ ├── dump.c │ ├── error.c │ ├── message.c │ ├── message.h │ ├── mm.h │ ├── ourhdr.h │ ├── ptyfork.c │ ├── ptyfork.h │ └── ptyopen.c ├── cygcfg.c ├── cygterm.c ├── fatty.c ├── pageant.ico ├── pageant.mft ├── pageant.rc ├── pageant64.mft ├── pickicondialog.c ├── pickicondialog.h ├── plink.rc ├── pscp.ico ├── pscp.rc ├── psftp.rc ├── putty.ico ├── putty.ico.svg ├── putty.iss ├── putty.mft ├── putty.rc ├── putty64.mft ├── puttycfg.ico ├── puttycyg.ico ├── puttygen.ico ├── puttygen.mft ├── puttygen.rc ├── puttygen64.mft ├── puttyins.ico ├── puttytel.rc ├── rcstuff.h ├── re_lib │ ├── regexp.c │ ├── regexp.h │ └── regmagic.h ├── sizetip.c ├── urlhack.h ├── urlhack_win.c ├── version.rc2 ├── website.url ├── win_res.h ├── win_res.rc2 ├── wincfg.c ├── wincons.c ├── winctrls.c ├── windefs.c ├── windlg.c ├── window.c ├── wingss.c ├── winhandl.c ├── winhelp.c ├── winhelp.h ├── winhsock.c ├── winjump.c ├── winmisc.c ├── winnet.c ├── winnoise.c ├── winnojmp.c ├── winnpc.c ├── winnps.c ├── winpgen.c ├── winpgnt.c ├── winpgntc.c ├── winplink.c ├── winprint.c ├── winproxy.c ├── winsecur.c ├── winsecur.h ├── winser.c ├── winsftp.c ├── winshare.c ├── winstore.c ├── winstuff.h ├── wintime.c ├── winucs.c ├── winutils.c └── winx11.c └── x11fwd.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.pyc 3 | .dirstamp 4 | .deps 5 | /*.pdb 6 | /*.ilk 7 | /*.res 8 | /*.RES 9 | /*.pch 10 | /*.rsp 11 | /*.obj 12 | /*.exe 13 | /*.ncb 14 | /*.plg 15 | /*.dsw 16 | /*.opt 17 | /*.dsp 18 | /*.tds 19 | /*.td2 20 | /*.map 21 | /Makefile.bor 22 | /Makefile.cyg 23 | /Makefile.vc 24 | /Makefile.lcc 25 | /MSVC 26 | /*.log 27 | /*.GID 28 | /local 29 | /Output 30 | /pageant 31 | /plink 32 | /pscp 33 | /psftp 34 | /putty 35 | /puttytel 36 | /puttygen 37 | /pterm 38 | /*.DSA 39 | /*.RSA 40 | /*.cnt 41 | /*.hlp 42 | /.bmake 43 | /build.log 44 | /build.out 45 | /uxconfig.h 46 | /empty.h 47 | /config.status 48 | /Makefile.am 49 | /Makefile.in 50 | /Makefile 51 | /compile 52 | /config.status 53 | /configure 54 | /stamp-h1 55 | /aclocal.m4 56 | /ar-lib 57 | /autom4te.cache 58 | /depcomp 59 | /install-sh 60 | /local 61 | /missing 62 | /uxconfig.in 63 | /uxconfig.h 64 | /*.a 65 | /charset/sbcsdat.c 66 | /contrib/cygtermd/cygtermd.exe 67 | /doc/*.html 68 | /doc/*.txt 69 | /doc/*.cnt 70 | /doc/*.hlp 71 | /doc/*.gid 72 | /doc/*.GID 73 | /doc/*.chm 74 | /doc/*.log 75 | /doc/*.1 76 | /doc/*.info 77 | /doc/vstr.but 78 | /doc/*.hhp 79 | /doc/*.hhc 80 | /doc/*.hhk 81 | /icons/*.png 82 | /icons/*.ico 83 | /icons/*.xpm 84 | /icons/*.c 85 | /macosx/Makefile 86 | /macosx/*.app 87 | /macosx/puttygen 88 | /macosx/plink 89 | /macosx/psftp 90 | /macosx/pscp 91 | /testdata/bignum.txt 92 | /unix/Makefile.gtk 93 | /unix/Makefile.ux 94 | /unix/Makefile.local 95 | /unix/empty.h 96 | /unix/plink 97 | /unix/pterm 98 | /unix/putty 99 | /unix/puttytel 100 | /unix/psftp 101 | /unix/pscp 102 | /unix/puttygen 103 | /unix/stamp-h1 104 | /unix/*.log 105 | /unix/.deps 106 | /windows/*.pdb 107 | /windows/*.ilk 108 | /windows/*.res 109 | /windows/*.RES 110 | /windows/*.pch 111 | /windows/*.rsp 112 | /windows/*.obj 113 | /windows/*.exe 114 | /windows/*.ncb 115 | /windows/*.plg 116 | /windows/*.dsw 117 | /windows/*.opt 118 | /windows/*.dsp 119 | /windows/*.tds 120 | /windows/*.td2 121 | /windows/*.map 122 | /windows/Makefile.bor 123 | /windows/Makefile.cyg 124 | /windows/Makefile.vc 125 | /windows/Makefile.lcc 126 | /windows/MSVC 127 | /windows/DEVCPP 128 | /windows/VS2010 129 | /windows/VS2012 130 | /windows/*.log 131 | /windows/*.GID 132 | /windows/local 133 | /windows/Output 134 | /windows/*.DSA 135 | /windows/*.RSA 136 | /windows/*.cnt 137 | /windows/*.hlp 138 | /windows/.bmake 139 | /windows/*.sln 140 | /windows/*.suo 141 | -------------------------------------------------------------------------------- /Buildscr.cv: -------------------------------------------------------------------------------- 1 | # -*- sh -*- 2 | 3 | # Build script to scan PuTTY with the downloadable Coverity scanner 4 | # and generate a tar file to upload to their open-source scanning 5 | # service. 6 | 7 | module putty 8 | 9 | # Preparations. 10 | in putty do ./mkfiles.pl 11 | in putty do ./mkauto.sh 12 | in putty/doc do make 13 | 14 | # Scan the Unix build, on a 64-bit system to differentiate as much as 15 | # possible from the other scan of the cross-platform files. 16 | delegate covscan64 17 | in putty do ./configure 18 | in putty do cov-build --dir cov-int make 19 | in putty do tar czvf cov-int.tar.gz cov-int 20 | return putty/cov-int.tar.gz 21 | enddelegate 22 | 23 | # Scan the Windows build, by means of building with Winelib (since as 24 | # of 2013-07-22, the Coverity Scan website doesn't offer a 32-bit 25 | # Windows scanner for download). 26 | delegate covscan32wine 27 | in putty do tar xzvf cov-int.tar.gz 28 | in putty/windows do cov-build --dir ../cov-int make -f Makefile.cyg CC=winegcc RC=wrc XFLAGS=-DCOVERITY 29 | in putty do tar czvf cov-int.tar.gz cov-int 30 | return putty/cov-int.tar.gz 31 | enddelegate 32 | 33 | # Provide the revision number as one of the build outputs, to make it 34 | # easy to construct a curl upload command which will annotate it 35 | # appropriately when uploaded. 36 | in putty do echo $(vcsfullid) > revision.txt 37 | 38 | deliver putty/revision.txt $@ 39 | deliver putty/cov-int.tar.gz $@ 40 | -------------------------------------------------------------------------------- /LATEST.VER: -------------------------------------------------------------------------------- 1 | 0.65 2 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | PuTTY is copyright 1997-2015 Simon Tatham. 2 | 3 | Portions copyright Robert de Bath, Joris van Rantwijk, Delian 4 | Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, 5 | Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus 6 | Kuhn, Colin Watson, and CORE SDI S.A. 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation files 10 | (the "Software"), to deal in the Software without restriction, 11 | including without limitation the rights to use, copy, modify, merge, 12 | publish, distribute, sublicense, and/or sell copies of the Software, 13 | and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE 23 | FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 24 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PuTTYTray 2 | 3 | This is [PuTTYTray][1], a fork of [Simon Tatham's PuTTY][2]. 4 | 5 | ## Documentation 6 | 7 | * For a list of current features, see the [PuTTYTray website][1]. 8 | * The [github wiki][3] has documentation for some of these features, and help for other things, including contributing. 9 | * Please feel free to report any problems or feature requests using the [github issue tracker][5]. 10 | 11 | ## Aims 12 | 13 | There are a lot of patches against PuTTY that have never been submitted to, or have been rejected from, upstream. PuTTYTray is collecting these, with the aim of eventually getting them merged back in. 14 | 15 | I'm looking to take ownership of any patches that are: 16 | 17 | * Cool or useful to someone, even if that someone is just you, 18 | * Maintainable against the PuTTY code; i.e. mostly independent with some hooks or appends to some functionality, 19 | * Are at least vaguely following the original design goals of PuTTY, and follow the coding style a bit, and 20 | * Not security related, or, at least, there not being any visible security risk. PuTTY is a security product, and the security is critical. I want everyone, even very paranoid people, to be able to use PuTTYTray. 21 | 22 | 23 | ## Building 24 | 25 | Visual Studio 2010 project files are included. These should **just work**, there are absolutely no dependencies beyond what Visual Studio ships; even the Express edition works fine. There is a [full walkthrough of building PuTTYTray][4] on the wiki. 26 | 27 | The original build system for PuTTY is intact, i.e. you can run `perl mkfiles.pl` and it will regenerate all the other build systems, including VS6 and various flavours of makefiles. 28 | 29 | My released builds are still done with VS2010's `nmake` (using `windows/build-release.bat`), and will continue to be done so until XP drops out of support. 30 | 31 | ## License 32 | 33 | This compilation is released under the same license as PuTTY itself; 34 | the MIT license. Individual contributions may be copyrighted by the original authors. 35 | 36 | See `LICENSE.MIT` for the full text. 37 | 38 | 39 | [1]: https://puttytray.goeswhere.com/ 40 | [2]: http://www.chiark.greenend.org.uk/~sgtatham/putty/ 41 | [3]: https://github.com/FauxFaux/PuTTYTray/wiki 42 | [4]: https://github.com/FauxFaux/PuTTYTray/wiki/Building-with-VS2010-Express 43 | [5]: https://github.com/FauxFaux/PuTTYTray/issues 44 | -------------------------------------------------------------------------------- /be_all.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Linking module for PuTTY proper: list the available backends 3 | * including ssh. 4 | */ 5 | 6 | #include 7 | #include "putty.h" 8 | 9 | /* 10 | * This appname is not strictly in the right place, since Plink 11 | * also uses this module. However, Plink doesn't currently use any 12 | * of the dialog-box sorts of things that make use of appname, so 13 | * it shouldn't do any harm here. I'm trying to avoid having to 14 | * have tiny little source modules containing nothing but 15 | * declarations of appname, for as long as I can... 16 | */ 17 | const char *const appname = "FuTTY"; 18 | 19 | #ifdef TELNET_DEFAULT 20 | const int be_default_protocol = PROT_TELNET; 21 | #else 22 | const int be_default_protocol = PROT_SSH; 23 | #endif 24 | 25 | Backend *backends[] = { 26 | &ssh_backend, 27 | &telnet_backend, 28 | &rlogin_backend, 29 | &raw_backend, 30 | &adb_backend, 31 | NULL 32 | }; 33 | -------------------------------------------------------------------------------- /be_all_s.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Linking module for PuTTY proper: list the available backends 3 | * including ssh, plus the serial backend. 4 | */ 5 | 6 | #include 7 | #include "putty.h" 8 | 9 | /* 10 | * This appname is not strictly in the right place, since Plink 11 | * also uses this module. However, Plink doesn't currently use any 12 | * of the dialog-box sorts of things that make use of appname, so 13 | * it shouldn't do any harm here. I'm trying to avoid having to 14 | * have tiny little source modules containing nothing but 15 | * declarations of appname, for as long as I can... 16 | */ 17 | const char *const appname = "FuTTY"; 18 | 19 | #ifdef TELNET_DEFAULT 20 | const int be_default_protocol = PROT_TELNET; 21 | #else 22 | const int be_default_protocol = PROT_SSH; 23 | #endif 24 | 25 | Backend *backends[] = { 26 | &ssh_backend, 27 | &telnet_backend, 28 | &rlogin_backend, 29 | &raw_backend, 30 | &adb_backend, 31 | &serial_backend, 32 | &cygterm_backend, 33 | NULL 34 | }; 35 | -------------------------------------------------------------------------------- /be_all_u.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Linking module for PuTTY on unix: list the available backends 3 | * including ssh, plus the serial backend, but no cygwin. 4 | */ 5 | 6 | #include 7 | #include "putty.h" 8 | 9 | /* 10 | * This appname is not strictly in the right place, since Plink 11 | * also uses this module. However, Plink doesn't currently use any 12 | * of the dialog-box sorts of things that make use of appname, so 13 | * it shouldn't do any harm here. I'm trying to avoid having to 14 | * have tiny little source modules containing nothing but 15 | * declarations of appname, for as long as I can... 16 | */ 17 | const char *const appname = "PuTTY"; 18 | 19 | #ifdef TELNET_DEFAULT 20 | const int be_default_protocol = PROT_TELNET; 21 | #else 22 | const int be_default_protocol = PROT_SSH; 23 | #endif 24 | 25 | Backend *backends[] = { 26 | &ssh_backend, 27 | &telnet_backend, 28 | &rlogin_backend, 29 | &raw_backend, 30 | &adb_backend, 31 | &serial_backend, 32 | NULL 33 | }; 34 | -------------------------------------------------------------------------------- /be_none.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Linking module for programs that do not support selection of backend 3 | * (such as pterm). 4 | */ 5 | 6 | #include 7 | #include "putty.h" 8 | 9 | Backend *backends[] = { 10 | NULL 11 | }; 12 | -------------------------------------------------------------------------------- /be_nos_s.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Linking module for PuTTYtel: list the available backends not 3 | * including ssh. 4 | */ 5 | 6 | #include 7 | #include "putty.h" 8 | 9 | const int be_default_protocol = PROT_TELNET; 10 | 11 | const char *const appname = "FuTTYtel"; 12 | 13 | Backend *backends[] = { 14 | &telnet_backend, 15 | &rlogin_backend, 16 | &raw_backend, 17 | &adb_backend, 18 | &serial_backend, 19 | &cygterm_backend, 20 | NULL 21 | }; 22 | 23 | /* 24 | * Stub implementations of functions not used in non-ssh versions. 25 | */ 26 | void random_save_seed(void) 27 | { 28 | } 29 | 30 | void random_destroy_seed(void) 31 | { 32 | } 33 | 34 | void noise_ultralight(unsigned long data) 35 | { 36 | } 37 | -------------------------------------------------------------------------------- /be_nos_u.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Linking module for PuTTYtel unix: list the available backends not 3 | * including ssh or cygterm. 4 | */ 5 | 6 | #include 7 | #include "putty.h" 8 | 9 | const int be_default_protocol = PROT_TELNET; 10 | 11 | const char *const appname = "PuTTYtel"; 12 | 13 | Backend *backends[] = { 14 | &telnet_backend, 15 | &rlogin_backend, 16 | &raw_backend, 17 | &adb_backend, 18 | &serial_backend, 19 | NULL 20 | }; 21 | 22 | /* 23 | * Stub implementations of functions not used in non-ssh versions. 24 | */ 25 | void random_save_seed(void) 26 | { 27 | } 28 | 29 | void random_destroy_seed(void) 30 | { 31 | } 32 | 33 | void noise_ultralight(unsigned long data) 34 | { 35 | } 36 | -------------------------------------------------------------------------------- /be_nossh.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Linking module for PuTTYtel: list the available backends not 3 | * including ssh. 4 | */ 5 | 6 | #include 7 | #include "putty.h" 8 | 9 | const int be_default_protocol = PROT_TELNET; 10 | 11 | const char *const appname = "FuTTYtel"; 12 | 13 | Backend *backends[] = { 14 | &telnet_backend, 15 | &rlogin_backend, 16 | &raw_backend, 17 | &cygterm_backend, 18 | &adb_backend, 19 | NULL 20 | }; 21 | 22 | /* 23 | * Stub implementations of functions not used in non-ssh versions. 24 | */ 25 | void random_save_seed(void) 26 | { 27 | } 28 | 29 | void random_destroy_seed(void) 30 | { 31 | } 32 | 33 | void noise_ultralight(unsigned long data) 34 | { 35 | } 36 | -------------------------------------------------------------------------------- /be_ssh.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Linking module for programs that are restricted to only using SSH 3 | * (pscp and psftp). These do not support selection of backend, but 4 | * must still have a backends[] array mentioning SSH because 5 | * settings.c will want to consult it during session load. 6 | */ 7 | 8 | #include 9 | #include "putty.h" 10 | 11 | const int be_default_protocol = PROT_SSH; 12 | 13 | Backend *backends[] = { 14 | &ssh_backend, 15 | NULL 16 | }; 17 | -------------------------------------------------------------------------------- /callback.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Facility for queueing callback functions to be run from the 3 | * top-level event loop after the current top-level activity finishes. 4 | */ 5 | 6 | #include 7 | 8 | #include "putty.h" 9 | 10 | struct callback { 11 | struct callback *next; 12 | 13 | toplevel_callback_fn_t fn; 14 | void *ctx; 15 | }; 16 | 17 | struct callback *cbhead = NULL, *cbtail = NULL; 18 | 19 | toplevel_callback_notify_fn_t notify_frontend = NULL; 20 | void *frontend = NULL; 21 | 22 | void request_callback_notifications(toplevel_callback_notify_fn_t fn, 23 | void *fr) 24 | { 25 | notify_frontend = fn; 26 | frontend = fr; 27 | } 28 | 29 | void queue_toplevel_callback(toplevel_callback_fn_t fn, void *ctx) 30 | { 31 | struct callback *cb; 32 | 33 | cb = snew(struct callback); 34 | cb->fn = fn; 35 | cb->ctx = ctx; 36 | 37 | /* If the front end has requested notification of pending 38 | * callbacks, and we didn't already have one queued, let it know 39 | * we do have one now. */ 40 | if (notify_frontend && !cbhead) 41 | notify_frontend(frontend); 42 | 43 | if (cbtail) 44 | cbtail->next = cb; 45 | else 46 | cbhead = cb; 47 | cbtail = cb; 48 | cb->next = NULL; 49 | } 50 | 51 | void run_toplevel_callbacks(void) 52 | { 53 | if (cbhead) { 54 | struct callback *cb = cbhead; 55 | /* 56 | * Careful ordering here. We call the function _before_ 57 | * advancing cbhead (though, of course, we must free cb 58 | * _after_ advancing it). This means that if the very last 59 | * callback schedules another callback, cbhead does not become 60 | * NULL at any point, and so the frontend notification 61 | * function won't be needlessly pestered. 62 | */ 63 | cb->fn(cb->ctx); 64 | cbhead = cb->next; 65 | sfree(cb); 66 | if (!cbhead) 67 | cbtail = NULL; 68 | } 69 | } 70 | 71 | int toplevel_callback_pending(void) 72 | { 73 | return cbhead != NULL; 74 | } 75 | -------------------------------------------------------------------------------- /charset/README: -------------------------------------------------------------------------------- 1 | This subdirectory contains a general character-set conversion 2 | library, used in the Unix port of PuTTY, and available for use in 3 | other ports if it should happen to be useful. 4 | 5 | This is a variant of a library that's currently used in some other 6 | programs such as Timber and Halibut. At some future date, we would 7 | like to merge the two libraries, so that all programs use the same 8 | libcharset. 9 | 10 | It is therefore a _strong_ design goal that this library should remain 11 | perfectly general, and not tied to particulars of PuTTY. It must not 12 | reference any code outside its own subdirectory; it should not have 13 | PuTTY-specific helper routines added to it unless they can be 14 | documented in a general manner which might make them useful in other 15 | circumstances as well. 16 | -------------------------------------------------------------------------------- /charset/enum.c: -------------------------------------------------------------------------------- 1 | /* 2 | * enum.c - enumerate all charsets defined by the library. 3 | * 4 | * This file maintains a list of every other source file which 5 | * contains ENUM_CHARSET definitions. It #includes each one with 6 | * ENUM_CHARSETS defined, which causes those source files to do 7 | * nothing at all except call the ENUM_CHARSET macro on each 8 | * charset they define. 9 | * 10 | * This file in turn is included from various other places, with 11 | * the ENUM_CHARSET macro defined to various different things. This 12 | * allows us to have multiple implementations of the master charset 13 | * lookup table (a static one and a dynamic one). 14 | */ 15 | 16 | #define ENUM_CHARSETS 17 | #include "sbcsdat.c" 18 | #include "utf8.c" 19 | #undef ENUM_CHARSETS 20 | -------------------------------------------------------------------------------- /charset/fromucs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * fromucs.c - convert Unicode to other character sets. 3 | */ 4 | 5 | #include "charset.h" 6 | #include "internal.h" 7 | 8 | struct charset_emit_param { 9 | char *output; 10 | int outlen; 11 | const char *errstr; 12 | int errlen; 13 | int stopped; 14 | }; 15 | 16 | static void charset_emit(void *ctx, long int output) 17 | { 18 | struct charset_emit_param *param = (struct charset_emit_param *)ctx; 19 | char outval; 20 | char const *p; 21 | int outlen; 22 | 23 | if (output == ERROR) { 24 | p = param->errstr; 25 | outlen = param->errlen; 26 | } else { 27 | outval = output; 28 | p = &outval; 29 | outlen = 1; 30 | } 31 | 32 | if (param->outlen >= outlen) { 33 | while (outlen > 0) { 34 | *param->output++ = *p++; 35 | param->outlen--; 36 | outlen--; 37 | } 38 | } else { 39 | param->stopped = 1; 40 | } 41 | } 42 | 43 | int charset_from_unicode(const wchar_t **input, int *inlen, 44 | char *output, int outlen, 45 | int charset, charset_state *state, 46 | const char *errstr, int errlen) 47 | { 48 | charset_spec const *spec = charset_find_spec(charset); 49 | charset_state localstate; 50 | struct charset_emit_param param; 51 | 52 | param.output = output; 53 | param.outlen = outlen; 54 | param.stopped = 0; 55 | 56 | /* 57 | * charset_emit will expect a valid errstr. 58 | */ 59 | if (!errstr) { 60 | /* *shrug* this is good enough, and consistent across all SBCS... */ 61 | param.errstr = "."; 62 | param.errlen = 1; 63 | } 64 | param.errstr = errstr; 65 | param.errlen = errlen; 66 | 67 | if (!state) { 68 | localstate.s0 = 0; 69 | } else { 70 | localstate = *state; /* structure copy */ 71 | } 72 | state = &localstate; 73 | 74 | while (*inlen > 0) { 75 | int lenbefore = param.output - output; 76 | spec->write(spec, **input, &localstate, charset_emit, ¶m); 77 | if (param.stopped) { 78 | /* 79 | * The emit function has _tried_ to output some 80 | * characters, but ran up against the end of the 81 | * buffer. Leave immediately, and return what happened 82 | * _before_ attempting to process this character. 83 | */ 84 | return lenbefore; 85 | } 86 | if (state) 87 | *state = localstate; /* structure copy */ 88 | (*input)++; 89 | (*inlen)--; 90 | } 91 | return param.output - output; 92 | } 93 | -------------------------------------------------------------------------------- /charset/internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * internal.h - internal header stuff for the charset library. 3 | */ 4 | 5 | #ifndef charset_internal_h 6 | #define charset_internal_h 7 | 8 | /* This invariably comes in handy */ 9 | #define lenof(x) ( sizeof((x)) / sizeof(*(x)) ) 10 | 11 | /* This is an invalid Unicode value used to indicate an error. */ 12 | #define ERROR 0xFFFFL /* Unicode value representing error */ 13 | 14 | typedef struct charset_spec charset_spec; 15 | typedef struct sbcs_data sbcs_data; 16 | 17 | struct charset_spec { 18 | int charset; /* numeric identifier */ 19 | 20 | /* 21 | * A function to read the character set and output Unicode 22 | * characters. The `emit' function expects to get Unicode chars 23 | * passed to it; it should be sent ERROR for any encoding error 24 | * on the input. 25 | */ 26 | void (*read)(charset_spec const *charset, long int input_chr, 27 | charset_state *state, 28 | void (*emit)(void *ctx, long int output), void *emitctx); 29 | /* 30 | * A function to read Unicode characters and output in this 31 | * character set. The `emit' function expects to get byte 32 | * values passed to it; it should be sent ERROR for any 33 | * non-representable characters on the input. 34 | */ 35 | void (*write)(charset_spec const *charset, long int input_chr, 36 | charset_state *state, 37 | void (*emit)(void *ctx, long int output), void *emitctx); 38 | void const *data; 39 | }; 40 | 41 | /* 42 | * This is the format of `data' used by the SBCS read and write 43 | * functions; so it's the format used in all SBCS definitions. 44 | */ 45 | struct sbcs_data { 46 | /* 47 | * This is a simple mapping table converting each SBCS position 48 | * to a Unicode code point. Some positions may contain ERROR, 49 | * indicating that that byte value is not defined in the SBCS 50 | * in question and its occurrence in input is an error. 51 | */ 52 | unsigned long sbcs2ucs[256]; 53 | 54 | /* 55 | * This lookup table is used to convert Unicode back to the 56 | * SBCS. It consists of the valid byte values in the SBCS, 57 | * sorted in order of their Unicode translation. So given a 58 | * Unicode value U, you can do a binary search on this table 59 | * using the above table as a lookup: when testing the Xth 60 | * position in this table, you branch according to whether 61 | * sbcs2ucs[ucs2sbcs[X]] is less than, greater than, or equal 62 | * to U. 63 | * 64 | * Note that since there may be fewer than 256 valid byte 65 | * values in a particular SBCS, we must supply the length of 66 | * this table as well as the contents. 67 | */ 68 | unsigned char ucs2sbcs[256]; 69 | int nvalid; 70 | }; 71 | 72 | /* 73 | * Prototypes for internal library functions. 74 | */ 75 | charset_spec const *charset_find_spec(int charset); 76 | void read_sbcs(charset_spec const *charset, long int input_chr, 77 | charset_state *state, 78 | void (*emit)(void *ctx, long int output), void *emitctx); 79 | void write_sbcs(charset_spec const *charset, long int input_chr, 80 | charset_state *state, 81 | void (*emit)(void *ctx, long int output), void *emitctx); 82 | 83 | /* 84 | * Placate compiler warning about unused parameters, of which we 85 | * expect to have some in this library. 86 | */ 87 | #define UNUSEDARG(x) ( (x) = (x) ) 88 | 89 | #endif /* charset_internal_h */ 90 | -------------------------------------------------------------------------------- /charset/sbcs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * sbcs.c - routines to handle single-byte character sets. 3 | */ 4 | 5 | #include "charset.h" 6 | #include "internal.h" 7 | 8 | /* 9 | * The charset_spec for any single-byte character set should 10 | * provide read_sbcs() as its read function, and its `data' field 11 | * should be a wchar_t string constant containing the 256 entries 12 | * of the translation table. 13 | */ 14 | 15 | void read_sbcs(charset_spec const *charset, long int input_chr, 16 | charset_state *state, 17 | void (*emit)(void *ctx, long int output), void *emitctx) 18 | { 19 | const struct sbcs_data *sd = charset->data; 20 | 21 | UNUSEDARG(state); 22 | 23 | emit(emitctx, sd->sbcs2ucs[input_chr]); 24 | } 25 | 26 | void write_sbcs(charset_spec const *charset, long int input_chr, 27 | charset_state *state, 28 | void (*emit)(void *ctx, long int output), void *emitctx) 29 | { 30 | const struct sbcs_data *sd = charset->data; 31 | int i, j, k, c; 32 | 33 | UNUSEDARG(state); 34 | 35 | /* 36 | * Binary-search in the ucs2sbcs table. 37 | */ 38 | i = -1; 39 | j = sd->nvalid; 40 | while (i+1 < j) { 41 | k = (i+j)/2; 42 | c = sd->ucs2sbcs[k]; 43 | if (input_chr < sd->sbcs2ucs[c]) 44 | j = k; 45 | else if (input_chr > sd->sbcs2ucs[c]) 46 | i = k; 47 | else { 48 | emit(emitctx, c); 49 | return; 50 | } 51 | } 52 | emit(emitctx, ERROR); 53 | } 54 | -------------------------------------------------------------------------------- /charset/sbcsgen.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl -w 2 | 3 | # This script generates sbcsdat.c (the data for all the SBCSes) from its 4 | # source form sbcs.dat. 5 | 6 | $infile = "sbcs.dat"; 7 | $outfile = "sbcsdat.c"; 8 | 9 | open FOO, $infile; 10 | open BAR, ">$outfile"; 11 | select BAR; 12 | 13 | print "/*\n"; 14 | print " * sbcsdat.c - data definitions for single-byte character sets.\n"; 15 | print " *\n"; 16 | print " * Generated by sbcsgen.pl from sbcs.dat.\n"; 17 | print " * You should edit those files rather than editing this one.\n"; 18 | print " */\n"; 19 | print "\n"; 20 | print "#ifndef ENUM_CHARSETS\n"; 21 | print "\n"; 22 | print "#include \"charset.h\"\n"; 23 | print "#include \"internal.h\"\n"; 24 | print "\n"; 25 | 26 | my $charsetname = undef; 27 | my @vals = (); 28 | 29 | my @charsetnames = (); 30 | my @sortpriority = (); 31 | 32 | while () { 33 | chomp; 34 | if (/^charset (.*)$/) { 35 | $charsetname = $1; 36 | @vals = (); 37 | @sortpriority = map { 0 } 0..255; 38 | } elsif (/^sortpriority ([^-]*)-([^-]*) (.*)$/) { 39 | for ($i = hex $1; $i <= hex $2; $i++) { 40 | $sortpriority[$i] += $3; 41 | } 42 | } elsif (/^[0-9a-fA-FX]/) { 43 | push @vals, map { $_ eq "XXXX" ? -1 : hex $_ } split / +/, $_; 44 | if (scalar @vals > 256) { 45 | die "$infile:$.: charset $charsetname has more than 256 values\n"; 46 | } elsif (scalar @vals == 256) { 47 | &outcharset($charsetname, \@vals, \@sortpriority); 48 | push @charsetnames, $charsetname; 49 | $charsetname = undef; 50 | @vals = (); 51 | @sortpriority = map { 0 } 0..255; 52 | } 53 | } 54 | } 55 | 56 | print "#else /* ENUM_CHARSETS */\n"; 57 | print "\n"; 58 | 59 | foreach $i (@charsetnames) { 60 | print "ENUM_CHARSET($i)\n"; 61 | } 62 | 63 | print "\n"; 64 | print "#endif /* ENUM_CHARSETS */\n"; 65 | 66 | sub outcharset($$$) { 67 | my ($name, $vals, $sortpriority) = @_; 68 | my ($prefix, $i, @sorted); 69 | 70 | print "static const sbcs_data data_$name = {\n"; 71 | print " {\n"; 72 | $prefix = " "; 73 | @sorted = (); 74 | for ($i = 0; $i < 256; $i++) { 75 | if ($vals->[$i] < 0) { 76 | printf "%sERROR ", $prefix; 77 | } else { 78 | printf "%s0x%04x", $prefix, $vals->[$i]; 79 | die "ooh? $i\n" unless defined $sortpriority->[$i]; 80 | push @sorted, [$i, $vals->[$i], 0+$sortpriority->[$i]]; 81 | } 82 | if ($i % 8 == 7) { 83 | $prefix = ",\n "; 84 | } else { 85 | $prefix = ", "; 86 | } 87 | } 88 | print "\n },\n {\n"; 89 | @sorted = sort { ($a->[1] == $b->[1] ? 90 | $b->[2] <=> $a->[2] : 91 | $a->[1] <=> $b->[1]) || 92 | $a->[0] <=> $b->[0] } @sorted; 93 | $prefix = " "; 94 | $uval = -1; 95 | for ($i = $j = 0; $i < scalar @sorted; $i++) { 96 | next if ($uval == $sorted[$i]->[1]); # low-priority alternative 97 | $uval = $sorted[$i]->[1]; 98 | printf "%s0x%02x", $prefix, $sorted[$i]->[0]; 99 | if ($j % 8 == 7) { 100 | $prefix = ",\n "; 101 | } else { 102 | $prefix = ", "; 103 | } 104 | $j++; 105 | } 106 | printf "\n },\n %d\n", $j; 107 | print "};\n"; 108 | print "const charset_spec charset_$name = {\n" . 109 | " $name, read_sbcs, write_sbcs, &data_$name\n};\n\n"; 110 | } 111 | -------------------------------------------------------------------------------- /charset/slookup.c: -------------------------------------------------------------------------------- 1 | /* 2 | * slookup.c - static lookup of character sets. 3 | */ 4 | 5 | #include "charset.h" 6 | #include "internal.h" 7 | 8 | #define ENUM_CHARSET(x) extern charset_spec const charset_##x; 9 | #include "enum.c" 10 | #undef ENUM_CHARSET 11 | 12 | static charset_spec const *const cs_table[] = { 13 | 14 | #define ENUM_CHARSET(x) &charset_##x, 15 | #include "enum.c" 16 | #undef ENUM_CHARSET 17 | 18 | }; 19 | 20 | charset_spec const *charset_find_spec(int charset) 21 | { 22 | int i; 23 | 24 | for (i = 0; i < (int)lenof(cs_table); i++) 25 | if (cs_table[i]->charset == charset) 26 | return cs_table[i]; 27 | 28 | return NULL; 29 | } 30 | -------------------------------------------------------------------------------- /charset/toucs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * toucs.c - convert charsets to Unicode. 3 | */ 4 | 5 | #include "charset.h" 6 | #include "internal.h" 7 | 8 | struct unicode_emit_param { 9 | wchar_t *output; 10 | int outlen; 11 | const wchar_t *errstr; 12 | int errlen; 13 | int stopped; 14 | }; 15 | 16 | static void unicode_emit(void *ctx, long int output) 17 | { 18 | struct unicode_emit_param *param = (struct unicode_emit_param *)ctx; 19 | wchar_t outval; 20 | wchar_t const *p; 21 | int outlen; 22 | 23 | if (output == ERROR) { 24 | if (param->errstr) { 25 | p = param->errstr; 26 | outlen = param->errlen; 27 | } else { 28 | outval = 0xFFFD; /* U+FFFD REPLACEMENT CHARACTER */ 29 | p = &outval; 30 | outlen = 1; 31 | } 32 | } else { 33 | outval = output; 34 | p = &outval; 35 | outlen = 1; 36 | } 37 | 38 | if (param->outlen >= outlen) { 39 | while (outlen > 0) { 40 | *param->output++ = *p++; 41 | param->outlen--; 42 | outlen--; 43 | } 44 | } else { 45 | param->stopped = 1; 46 | } 47 | } 48 | 49 | int charset_to_unicode(const char **input, int *inlen, 50 | wchar_t *output, int outlen, 51 | int charset, charset_state *state, 52 | const wchar_t *errstr, int errlen) 53 | { 54 | charset_spec const *spec = charset_find_spec(charset); 55 | charset_state localstate; 56 | struct unicode_emit_param param; 57 | 58 | param.output = output; 59 | param.outlen = outlen; 60 | param.errstr = errstr; 61 | param.errlen = errlen; 62 | param.stopped = 0; 63 | 64 | if (!state) { 65 | localstate.s0 = 0; 66 | } else { 67 | localstate = *state; /* structure copy */ 68 | } 69 | 70 | while (*inlen > 0) { 71 | int lenbefore = param.output - output; 72 | spec->read(spec, (unsigned char)**input, &localstate, 73 | unicode_emit, ¶m); 74 | if (param.stopped) { 75 | /* 76 | * The emit function has _tried_ to output some 77 | * characters, but ran up against the end of the 78 | * buffer. Leave immediately, and return what happened 79 | * _before_ attempting to process this character. 80 | */ 81 | return lenbefore; 82 | } 83 | if (state) 84 | *state = localstate; /* structure copy */ 85 | (*input)++; 86 | (*inlen)--; 87 | } 88 | 89 | return param.output - output; 90 | } 91 | -------------------------------------------------------------------------------- /charset/xenc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * xenc.c - translate our internal character set codes to and from 3 | * X11 character encoding names. 4 | * 5 | */ 6 | 7 | #include 8 | #include "charset.h" 9 | #include "internal.h" 10 | 11 | static const struct { 12 | const char *name; 13 | int charset; 14 | } xencs[] = { 15 | /* 16 | * Officially registered encoding names. This list is derived 17 | * from the font encodings section of 18 | * 19 | * http://ftp.x.org/pub/DOCS/registry 20 | * 21 | * Where multiple encoding names map to the same encoding id 22 | * (such as iso8859-15 and fcd8859-15), the first is considered 23 | * canonical and will be returned when translating the id to a 24 | * string. 25 | */ 26 | { "iso8859-1", CS_ISO8859_1 }, 27 | { "iso8859-2", CS_ISO8859_2 }, 28 | { "iso8859-3", CS_ISO8859_3 }, 29 | { "iso8859-4", CS_ISO8859_4 }, 30 | { "iso8859-5", CS_ISO8859_5 }, 31 | { "iso8859-6", CS_ISO8859_6 }, 32 | { "iso8859-7", CS_ISO8859_7 }, 33 | { "iso8859-8", CS_ISO8859_8 }, 34 | { "iso8859-9", CS_ISO8859_9 }, 35 | { "iso8859-10", CS_ISO8859_10 }, 36 | { "iso8859-13", CS_ISO8859_13 }, 37 | { "iso8859-14", CS_ISO8859_14 }, 38 | { "iso8859-15", CS_ISO8859_15 }, 39 | { "fcd8859-15", CS_ISO8859_15 }, 40 | { "hp-roman8", CS_HP_ROMAN8 }, 41 | { "koi8-r", CS_KOI8_R }, 42 | /* 43 | * Unofficial encoding names found in the wild. 44 | */ 45 | { "iso8859-16", CS_ISO8859_16 }, 46 | { "koi8-u", CS_KOI8_U }, 47 | { "ibm-cp437", CS_CP437 }, 48 | { "ibm-cp850", CS_CP850 }, 49 | { "ibm-cp852", CS_CP852 }, 50 | { "ibm-cp866", CS_CP866 }, 51 | { "microsoft-cp1250", CS_CP1250 }, 52 | { "microsoft-cp1251", CS_CP1251 }, 53 | { "microsoft-cp1252", CS_CP1252 }, 54 | { "microsoft-cp1253", CS_CP1253 }, 55 | { "microsoft-cp1254", CS_CP1254 }, 56 | { "microsoft-cp1255", CS_CP1255 }, 57 | { "microsoft-cp1256", CS_CP1256 }, 58 | { "microsoft-cp1257", CS_CP1257 }, 59 | { "microsoft-cp1258", CS_CP1258 }, 60 | { "mac-roman", CS_MAC_ROMAN }, 61 | { "viscii1.1-1", CS_VISCII }, 62 | { "viscii1-1", CS_VISCII }, 63 | }; 64 | 65 | const char *charset_to_xenc(int charset) 66 | { 67 | int i; 68 | 69 | for (i = 0; i < (int)lenof(xencs); i++) 70 | if (charset == xencs[i].charset) 71 | return xencs[i].name; 72 | 73 | return NULL; /* not found */ 74 | } 75 | 76 | int charset_from_xenc(const char *name) 77 | { 78 | int i; 79 | 80 | for (i = 0; i < (int)lenof(xencs); i++) { 81 | const char *p, *q; 82 | p = name; 83 | q = xencs[i].name; 84 | while (*p || *q) { 85 | if (tolower((unsigned char)*p) != tolower((unsigned char)*q)) 86 | break; 87 | p++; q++; 88 | } 89 | if (!*p && !*q) 90 | return xencs[i].charset; 91 | } 92 | 93 | return CS_NONE; /* not found */ 94 | } 95 | -------------------------------------------------------------------------------- /contrib/cygtermd/Makefile: -------------------------------------------------------------------------------- 1 | cygtermd.exe: main.c sel.c telnet.c pty.c malloc.c 2 | gcc -o cygtermd.exe main.c sel.c telnet.c pty.c malloc.c 3 | -------------------------------------------------------------------------------- /contrib/cygtermd/README: -------------------------------------------------------------------------------- 1 | This directory contains 'cygtermd', a small and specialist Telnet 2 | server designed to act as middleware between PuTTY and a Cygwin shell 3 | session running on the same machine, so that PuTTY can act as an 4 | xterm-alike for Cygwin. 5 | 6 | To install it, you must compile it from source using Cygwin gcc, 7 | install it in Cygwin's /bin, and configure PuTTY to use it as a local 8 | proxy process. For detailed instructions, see the PuTTY Wishlist page 9 | at 10 | 11 | http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/cygwin-terminal-window.html 12 | -------------------------------------------------------------------------------- /contrib/cygtermd/malloc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * malloc.c: implementation of malloc.h 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #include "malloc.h" 9 | 10 | extern void fatal(const char *, ...); 11 | 12 | void *smalloc(size_t size) { 13 | void *p; 14 | p = malloc(size); 15 | if (!p) { 16 | fatal("out of memory"); 17 | } 18 | return p; 19 | } 20 | 21 | void sfree(void *p) { 22 | if (p) { 23 | free(p); 24 | } 25 | } 26 | 27 | void *srealloc(void *p, size_t size) { 28 | void *q; 29 | if (p) { 30 | q = realloc(p, size); 31 | } else { 32 | q = malloc(size); 33 | } 34 | if (!q) 35 | fatal("out of memory"); 36 | return q; 37 | } 38 | 39 | char *dupstr(const char *s) { 40 | char *r = smalloc(1+strlen(s)); 41 | strcpy(r,s); 42 | return r; 43 | } 44 | -------------------------------------------------------------------------------- /contrib/cygtermd/malloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * malloc.h: safe wrappers around malloc, realloc, free, strdup 3 | */ 4 | 5 | #ifndef UMLWRAP_MALLOC_H 6 | #define UMLWRAP_MALLOC_H 7 | 8 | #include 9 | 10 | /* 11 | * smalloc should guarantee to return a useful pointer - Halibut 12 | * can do nothing except die when it's out of memory anyway. 13 | */ 14 | void *smalloc(size_t size); 15 | 16 | /* 17 | * srealloc should guaranteeably be able to realloc NULL 18 | */ 19 | void *srealloc(void *p, size_t size); 20 | 21 | /* 22 | * sfree should guaranteeably deal gracefully with freeing NULL 23 | */ 24 | void sfree(void *p); 25 | 26 | /* 27 | * dupstr is like strdup, but with the never-return-NULL property 28 | * of smalloc (and also reliably defined in all environments :-) 29 | */ 30 | char *dupstr(const char *s); 31 | 32 | /* 33 | * snew allocates one instance of a given type, and casts the 34 | * result so as to type-check that you're assigning it to the 35 | * right kind of pointer. Protects against allocation bugs 36 | * involving allocating the wrong size of thing. 37 | */ 38 | #define snew(type) \ 39 | ( (type *) smalloc (sizeof (type)) ) 40 | 41 | /* 42 | * snewn allocates n instances of a given type, for arrays. 43 | */ 44 | #define snewn(number, type) \ 45 | ( (type *) smalloc ((number) * sizeof (type)) ) 46 | 47 | /* 48 | * sresize wraps realloc so that you specify the new number of 49 | * elements and the type of the element, with the same type- 50 | * checking advantages. Also type-checks the input pointer. 51 | */ 52 | #define sresize(array, number, type) \ 53 | ( (void)sizeof((array)-(type *)0), \ 54 | (type *) srealloc ((array), (number) * sizeof (type)) ) 55 | 56 | #endif /* UMLWRAP_MALLOC_H */ 57 | -------------------------------------------------------------------------------- /contrib/cygtermd/pty.h: -------------------------------------------------------------------------------- 1 | /* 2 | * pty.h - FIXME 3 | */ 4 | 5 | #ifndef FIXME_PTY_H 6 | #define FIXME_PTY_H 7 | 8 | #include "telnet.h" /* for struct shdata */ 9 | 10 | /* 11 | * Called at program startup to actually allocate a pty, so that 12 | * we can start passing in resize events as soon as they arrive. 13 | */ 14 | void pty_preinit(void); 15 | 16 | /* 17 | * Set the terminal size for the pty. 18 | */ 19 | void pty_resize(int w, int h); 20 | 21 | /* 22 | * Start a program in a subprocess running in the pty we allocated. 23 | * Returns the fd of the pty master. 24 | */ 25 | int run_program_in_pty(const struct shell_data *shdata, 26 | char *directory, char **program_args); 27 | 28 | #endif /* FIXME_PTY_H */ 29 | -------------------------------------------------------------------------------- /contrib/cygtermd/telnet.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Header declaring Telnet-handling functions. 3 | */ 4 | 5 | #ifndef FIXME_TELNET_H 6 | #define FIXME_TELNET_H 7 | 8 | #include "sel.h" 9 | 10 | typedef struct telnet_tag *Telnet; 11 | 12 | struct shell_data { 13 | char **envvars; /* array of "VAR=value" terms */ 14 | int nenvvars; 15 | char *termtype; 16 | }; 17 | 18 | /* 19 | * Create and destroy a Telnet structure. 20 | */ 21 | Telnet telnet_new(sel_wfd *net, sel_wfd *pty); 22 | void telnet_free(Telnet telnet); 23 | 24 | /* 25 | * Process data read from the pty. 26 | */ 27 | void telnet_from_pty(Telnet telnet, char *buf, int len); 28 | 29 | /* 30 | * Process Telnet protocol data received from the network. 31 | */ 32 | void telnet_from_net(Telnet telnet, char *buf, int len); 33 | 34 | /* 35 | * Return true if pre-shell-startup negotiations are complete and 36 | * it's safe to start the shell subprocess now. On a true return, 37 | * also fills in the shell_data structure. 38 | */ 39 | int telnet_shell_ok(Telnet telnet, struct shell_data *shdata); 40 | 41 | #endif /* FIXME_TELNET_H */ 42 | -------------------------------------------------------------------------------- /contrib/encodelib.py: -------------------------------------------------------------------------------- 1 | # Python module to make it easy to manually encode SSH packets, by 2 | # supporting the various uint32, string, mpint primitives. 3 | # 4 | # The idea of this is that you can use it to manually construct key 5 | # exchange sequences of interesting kinds, for testing purposes. 6 | 7 | import struct, random 8 | 9 | def boolean(b): 10 | return "\1" if b else "\0" 11 | 12 | def byte(b): 13 | assert 0 <= b < 0x100 14 | return chr(b) 15 | 16 | def uint32(u): 17 | assert 0 <= u < 0x100000000 18 | return struct.pack(">I", u) 19 | 20 | def uint64(u): 21 | assert 0 <= u < 0x10000000000000000 22 | return struct.pack(">L", u) 23 | 24 | def string(s): 25 | return uint32(len(s)) + s 26 | 27 | def mpint(m): 28 | s = "" 29 | lastbyte = 0 30 | while m > 0: 31 | lastbyte = m & 0xFF 32 | s = chr(lastbyte) + s 33 | m >>= 8 34 | if lastbyte & 0x80: 35 | s = "\0" + s 36 | return string(s) 37 | 38 | def name_list(ns): 39 | s = "" 40 | for n in ns: 41 | assert "," not in n 42 | if s != "": 43 | s += "," 44 | s += n 45 | return string(s) 46 | 47 | def ssh_rsa_key_blob(modulus, exponent): 48 | return string(string("ssh-rsa") + mpint(modulus) + mpint(exponent)) 49 | 50 | def ssh_rsa_signature_blob(signature): 51 | return string(string("ssh-rsa") + mpint(signature)) 52 | 53 | def greeting(string): 54 | # Greeting at the start of an SSH connection. 55 | return string + "\r\n" 56 | 57 | # Packet types. 58 | SSH2_MSG_DISCONNECT = 1 59 | SSH2_MSG_IGNORE = 2 60 | SSH2_MSG_UNIMPLEMENTED = 3 61 | SSH2_MSG_DEBUG = 4 62 | SSH2_MSG_SERVICE_REQUEST = 5 63 | SSH2_MSG_SERVICE_ACCEPT = 6 64 | SSH2_MSG_KEXINIT = 20 65 | SSH2_MSG_NEWKEYS = 21 66 | SSH2_MSG_KEXDH_INIT = 30 67 | SSH2_MSG_KEXDH_REPLY = 31 68 | SSH2_MSG_KEX_DH_GEX_REQUEST = 30 69 | SSH2_MSG_KEX_DH_GEX_GROUP = 31 70 | SSH2_MSG_KEX_DH_GEX_INIT = 32 71 | SSH2_MSG_KEX_DH_GEX_REPLY = 33 72 | SSH2_MSG_KEXRSA_PUBKEY = 30 73 | SSH2_MSG_KEXRSA_SECRET = 31 74 | SSH2_MSG_KEXRSA_DONE = 32 75 | SSH2_MSG_USERAUTH_REQUEST = 50 76 | SSH2_MSG_USERAUTH_FAILURE = 51 77 | SSH2_MSG_USERAUTH_SUCCESS = 52 78 | SSH2_MSG_USERAUTH_BANNER = 53 79 | SSH2_MSG_USERAUTH_PK_OK = 60 80 | SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ = 60 81 | SSH2_MSG_USERAUTH_INFO_REQUEST = 60 82 | SSH2_MSG_USERAUTH_INFO_RESPONSE = 61 83 | SSH2_MSG_GLOBAL_REQUEST = 80 84 | SSH2_MSG_REQUEST_SUCCESS = 81 85 | SSH2_MSG_REQUEST_FAILURE = 82 86 | SSH2_MSG_CHANNEL_OPEN = 90 87 | SSH2_MSG_CHANNEL_OPEN_CONFIRMATION = 91 88 | SSH2_MSG_CHANNEL_OPEN_FAILURE = 92 89 | SSH2_MSG_CHANNEL_WINDOW_ADJUST = 93 90 | SSH2_MSG_CHANNEL_DATA = 94 91 | SSH2_MSG_CHANNEL_EXTENDED_DATA = 95 92 | SSH2_MSG_CHANNEL_EOF = 96 93 | SSH2_MSG_CHANNEL_CLOSE = 97 94 | SSH2_MSG_CHANNEL_REQUEST = 98 95 | SSH2_MSG_CHANNEL_SUCCESS = 99 96 | SSH2_MSG_CHANNEL_FAILURE = 100 97 | SSH2_MSG_USERAUTH_GSSAPI_RESPONSE = 60 98 | SSH2_MSG_USERAUTH_GSSAPI_TOKEN = 61 99 | SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE = 63 100 | SSH2_MSG_USERAUTH_GSSAPI_ERROR = 64 101 | SSH2_MSG_USERAUTH_GSSAPI_ERRTOK = 65 102 | SSH2_MSG_USERAUTH_GSSAPI_MIC = 66 103 | 104 | def clearpkt(msgtype, *stuff): 105 | # SSH-2 binary packet, in the cleartext format used for initial 106 | # setup and kex. 107 | s = byte(msgtype) 108 | for thing in stuff: 109 | s += thing 110 | padlen = 0 111 | while padlen < 4 or len(s) % 8 != 3: 112 | padlen += 1 113 | s += byte(random.randint(0,255)) 114 | s = byte(padlen) + s 115 | return string(s) 116 | -------------------------------------------------------------------------------- /contrib/nice-ibeam.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FireEgl/FuTTY/c536b357184be8a9faff2c87fa17a5f2b707092d/contrib/nice-ibeam.cur -------------------------------------------------------------------------------- /contrib/samplekex.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Example Python script to synthesise the server end of an SSH key exchange. 4 | 5 | # This is an output-only script; you run it by means of saying 6 | # something like 7 | # 8 | # samplekex.py | nc -l 2222 | hex dump utility of your choice 9 | # 10 | # and then connecting PuTTY to port 2222. Being output-only, of 11 | # course, it cannot possibly get the key exchange _right_, so PuTTY 12 | # will terminate with an error when the signature in the final message 13 | # doesn't validate. But everything until then should be processed as 14 | # if it was a normal SSH-2 connection, which means you can use this 15 | # script as a starting point for constructing interestingly malformed 16 | # key exchanges to test bug fixes. 17 | 18 | import sys, random 19 | from encodelib import * 20 | 21 | # A random Diffie-Hellman group, taken from an SSH server I made a 22 | # test connection to. 23 | groupgen = 5 24 | group = 0xf5d3849d2092fd427b4ebd838ea4830397a55f80b644626320dbbe51e8f63ed88148d787c94e7e67e4f393f26c565e1992b0cff8a47a953439462a4d0ffa5763ef60ff908f8ee6c4f6ef9f32b9ba50f01ad56fe7ebe90876a5cf61813a4ad4ba7ec0704303c9bf887d36abbd6c2aa9545fc2263232927e731060f5c701c96dc34016636df438ce30973715f121d767cfb98b5d09ae7b86fa36a051ad3c2941a295a68e2f583a56bc69913ec9d25abef4fdf1e31ede827a02620db058b9f041da051c8c0f13b132c17ceb893fa7c4cd8d8feebd82c5f9120cb221b8e88c5fe4dc17ca020a535484c92c7d4bee69c7703e1fa9a652d444c80065342c6ec0fac23c24de246e3dee72ca8bc8beccdade2b36771efcc350558268f5352ae53f2f71db62249ad9ac4fabdd6dfb099c6cff8c05bdea894390f9860f011cca046dfeb2f6ef81094e7980be526742706d1f3db920db107409291bb4c11f9a7dcbfaf26d808e6f9fe636b26b939de419129e86b1e632c60ec23b65c815723c5d861af068fd0ac8b37f4c06ecbd5cb2ef069ca8daac5cbd67c6182a65fed656d0dfbbb8a430b1dbac7bd6303bec8de078fe69f443a7bc8131a284d25dc2844f096240bfc61b62e91a87802987659b884c094c68741d29aa5ca19b9457e1f9df61c7dbbb13a61a79e4670b086027f20da2af4f5b020725f8828726379f429178926a1f0ea03f 25 | 26 | # An RSA key, generated specially for this script. 27 | rsaexp = 0x10001 28 | rsamod = 0xB98FE0C0BEE1E05B35FDDF5517B3E29D8A9A6A7834378B6783A19536968968F755E341B5822CAE15B465DECB80EE4116CF8D22DB5A6C85444A68D0D45D9D42008329619BE3CAC3B192EF83DD2B75C4BB6B567E11B841073BACE92108DA7E97E543ED7F032F454F7AC3C6D3F27DB34BC9974A85C7963C546662AE300A61CBABEE274481FD041C41D0145704F5FA9C77A5A442CD7A64827BB0F21FB56FDE388B596A20D7A7D1C5F22DA96C6C2171D90A673DABC66596CD99499D75AD82FEFDBE04DEC2CC7E1414A95388F668591B3F4D58249F80489646ED2C318E77D4F4E37EE8A588E79F2960620E6D28BF53653F1C974C91845F0BABFE5D167E1CA7044EE20D 29 | 30 | # 16 bytes of random data for the start of KEXINIT. 31 | cookie = "".join([chr(random.randint(0,255)) for i in range(16)]) 32 | 33 | sys.stdout.write(greeting("SSH-2.0-Example KEX synthesis")) 34 | 35 | # Expect client to send KEXINIT 36 | 37 | sys.stdout.write( 38 | clearpkt(SSH2_MSG_KEXINIT, 39 | cookie, 40 | name_list(("diffie-hellman-group-exchange-sha256",)), # kex 41 | name_list(("ssh-rsa",)), # host keys 42 | name_list(("aes128-ctr",)), # client->server ciphers 43 | name_list(("aes128-ctr",)), # server->client ciphers 44 | name_list(("hmac-sha2-256",)), # client->server MACs 45 | name_list(("hmac-sha2-256",)), # server->client MACs 46 | name_list(("none",)), # client->server compression 47 | name_list(("none",)), # server->client compression 48 | name_list(()), # client->server languages 49 | name_list(()), # server->client languages 50 | boolean(False), # first kex packet does not follow 51 | uint32(0))) 52 | 53 | # Expect client to send SSH2_MSG_KEX_DH_GEX_REQUEST(0x1000) 54 | 55 | sys.stdout.write( 56 | clearpkt(SSH2_MSG_KEX_DH_GEX_GROUP, 57 | mpint(group), 58 | mpint(groupgen))) 59 | 60 | # Expect client to send SSH2_MSG_KEX_DH_GEX_INIT 61 | 62 | sys.stdout.write( 63 | clearpkt(SSH2_MSG_KEX_DH_GEX_REPLY, 64 | ssh_rsa_key_blob(rsaexp, rsamod), 65 | mpint(random.randint(2, group-2)), 66 | ssh_rsa_signature_blob(random.randint(2, rsamod-2)))) 67 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.1 3 | *.hlp 4 | *.cnt 5 | puttydoc.txt 6 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | all: man index.html 2 | 3 | # Decide on the versionid policy. 4 | # 5 | # If the user has passed in $(VERSION) on the command line (`make 6 | # VERSION="Release 0.56"'), we use that as an explicit version string. 7 | # Otherwise, we use `svnversion' to examine the checked-out 8 | # documentation source, and if that returns a single revision number 9 | # then we invent a version string reflecting just that number. Failing 10 | # _that_, we resort to versionids.but which gives 'version 11 | # unavailable'. 12 | # 13 | # So here, we define VERSION using svnversion if it isn't already 14 | # defined ... 15 | ifndef VERSION 16 | SVNVERSION=$(shell test -d .svn && svnversion .) 17 | BADCHARS=$(findstring :,$(SVNVERSION))$(findstring S,$(SVNVERSION)) 18 | ifeq ($(BADCHARS),) 19 | ifneq ($(SVNVERSION),) 20 | ifneq ($(SVNVERSION),exported) 21 | VERSION=Built from revision $(patsubst M,,$(SVNVERSION)) 22 | endif 23 | endif 24 | endif 25 | endif 26 | # ... and now, we condition our build behaviour on whether or not 27 | # VERSION _is_ defined. 28 | ifdef VERSION 29 | VERSIONIDS=vstr 30 | vstr.but: FORCE 31 | printf '\\versionid $(VERSION)\n' > vstr.but 32 | FORCE:; 33 | else 34 | VERSIONIDS=vids 35 | endif 36 | 37 | CHAPTERS := $(SITE) blurb intro gs using config pscp psftp plink pubkey 38 | CHAPTERS += pageant errors faq feedback licence udp pgpkeys sshnames 39 | CHAPTERS += index $(VERSIONIDS) 40 | 41 | INPUTS = $(patsubst %,%.but,$(CHAPTERS)) 42 | 43 | # This is temporary. Hack it locally or something. 44 | HALIBUT = halibut 45 | 46 | index.html: $(INPUTS) 47 | $(HALIBUT) --text --html --winhelp $(INPUTS) 48 | 49 | # During formal builds it's useful to be able to build this one alone. 50 | putty.hlp: $(INPUTS) 51 | $(HALIBUT) --winhelp $(INPUTS) 52 | 53 | putty.info: $(INPUTS) 54 | $(HALIBUT) --info $(INPUTS) 55 | 56 | chm: putty.hhp 57 | putty.hhp: $(INPUTS) chm.but 58 | $(HALIBUT) --html $(INPUTS) chm.but 59 | 60 | MKMAN = $(HALIBUT) --man=$@ mancfg.but $< 61 | MANPAGES = putty.1 puttygen.1 plink.1 pscp.1 psftp.1 puttytel.1 pterm.1 62 | man: $(MANPAGES) 63 | 64 | putty.1: man-putt.but mancfg.but; $(MKMAN) 65 | puttygen.1: man-pg.but mancfg.but; $(MKMAN) 66 | plink.1: man-pl.but mancfg.but; $(MKMAN) 67 | pscp.1: man-pscp.but mancfg.but; $(MKMAN) 68 | psftp.1: man-psft.but mancfg.but; $(MKMAN) 69 | puttytel.1: man-ptel.but mancfg.but; $(MKMAN) 70 | pterm.1: man-pter.but mancfg.but; $(MKMAN) 71 | 72 | mostlyclean: 73 | rm -f *.html *.txt *.hlp *.cnt *.1 *.info vstr.but *.hh[pck] 74 | clean: mostlyclean 75 | rm -f *.chm 76 | -------------------------------------------------------------------------------- /doc/blurb.but: -------------------------------------------------------------------------------- 1 | \define{dash} \u2013{-} 2 | 3 | \title PuTTY User Manual 4 | 5 | \cfg{xhtml-leaf-level}{1} 6 | \cfg{xhtml-leaf-smallest-contents}{2} 7 | \cfg{xhtml-leaf-contains-contents}{true} 8 | \cfg{xhtml-body-end}{

If you want to provide feedback on this manual 9 | or on the PuTTY tools themselves, see the 10 | Feedback 11 | page.

} 12 | 13 | \cfg{html-template-fragment}{%k}{%b} 14 | 15 | \cfg{info-max-file-size}{0} 16 | 17 | \cfg{xhtml-contents-filename}{index.html} 18 | \cfg{text-filename}{puttydoc.txt} 19 | \cfg{winhelp-filename}{putty.hlp} 20 | \cfg{info-filename}{putty.info} 21 | 22 | PuTTY is a free (MIT-licensed) Win32 Telnet and SSH client. This 23 | manual documents PuTTY, and its companion utilities PSCP, PSFTP, 24 | Plink, Pageant and PuTTYgen. 25 | 26 | \e{Note to Unix users:} this manual currently primarily documents the 27 | Windows versions of the PuTTY utilities. Some options are therefore 28 | mentioned that are absent from the \i{Unix version}; the Unix version has 29 | features not described here; and the \i\cw{pterm} and command-line 30 | \cw{puttygen} utilities are not described at all. The only 31 | Unix-specific documentation that currently exists is the 32 | \I{man pages for PuTTY tools}man pages. 33 | 34 | \copyright This manual is copyright 2001-2015 Simon Tatham. All 35 | rights reserved. You may distribute this documentation under the MIT 36 | licence. See \k{licence} for the licence text in full. 37 | -------------------------------------------------------------------------------- /doc/chm.but: -------------------------------------------------------------------------------- 1 | \# File containing the magic HTML configuration directives to create 2 | \# an MS HTML Help project. We put this on the end of the PuTTY 3 | \# docs build command line to build the HHP and friends. 4 | 5 | \cfg{html-leaf-level}{infinite} 6 | \cfg{html-leaf-contains-contents}{false} 7 | \cfg{html-suppress-navlinks}{true} 8 | \cfg{html-suppress-address}{true} 9 | 10 | \cfg{html-contents-filename}{index.html} 11 | \cfg{html-template-filename}{%k.html} 12 | \cfg{html-template-fragment}{%k} 13 | 14 | \cfg{html-mshtmlhelp-chm}{putty.chm} 15 | \cfg{html-mshtmlhelp-project}{putty.hhp} 16 | \cfg{html-mshtmlhelp-contents}{putty.hhc} 17 | \cfg{html-mshtmlhelp-index}{putty.hhk} 18 | 19 | \cfg{html-body-end}{} 20 | 21 | \cfg{html-head-end}{} 22 | 23 | -------------------------------------------------------------------------------- /doc/chm.css: -------------------------------------------------------------------------------- 1 | /* Stylesheet for a Windows .CHM help file */ 2 | 3 | body { font-size: 75%; font-family: Verdana, Arial, Helvetica, Sans-Serif; } 4 | 5 | h1 { font-weight: bold; font-size: 150%; } 6 | h2 { font-weight: bold; font-size: 130%; } 7 | h3 { font-weight: bold; font-size: 120%; } 8 | -------------------------------------------------------------------------------- /doc/intro.but: -------------------------------------------------------------------------------- 1 | \C{intro} Introduction to PuTTY 2 | 3 | PuTTY is a free SSH, Telnet and Rlogin client for 32-bit Windows 4 | systems. 5 | 6 | \H{you-what} What are SSH, Telnet and Rlogin? 7 | 8 | If you already know what SSH, Telnet and Rlogin are, you can safely 9 | skip on to the next section. 10 | 11 | SSH, Telnet and Rlogin are three ways of doing the same thing: 12 | logging in to a multi-user computer from another computer, over a 13 | network. 14 | 15 | Multi-user operating systems, such as Unix and VMS, usually present 16 | a \i{command-line interface} to the user, much like the \q{\i{Command 17 | Prompt}} or \q{\i{MS-DOS Prompt}} in Windows. The system prints a 18 | prompt, and you type commands which the system will obey. 19 | 20 | Using this type of interface, there is no need for you to be sitting 21 | at the same machine you are typing commands to. The commands, and 22 | responses, can be sent over a network, so you can sit at one 23 | computer and give commands to another one, or even to more than one. 24 | 25 | SSH, Telnet and Rlogin are \i\e{network protocols} that allow you to 26 | do this. On the computer you sit at, you run a \i\e{client}, which 27 | makes a network connection to the other computer (the \i\e{server}). 28 | The network connection carries your keystrokes and commands from the 29 | client to the server, and carries the server's responses back to 30 | you. 31 | 32 | These protocols can also be used for other types of keyboard-based 33 | interactive session. In particular, there are a lot of bulletin 34 | boards, \i{talker systems} and \i{MUDs} (Multi-User Dungeons) which support 35 | access using Telnet. There are even a few that support SSH. 36 | 37 | You might want to use SSH, Telnet or Rlogin if: 38 | 39 | \b you have an account on a Unix or VMS system which you want to be 40 | able to access from somewhere else 41 | 42 | \b your Internet Service Provider provides you with a login account 43 | on a \i{web server}. (This might also be known as a \i\e{shell account}. 44 | A \e{shell} is the program that runs on the server and interprets 45 | your commands for you.) 46 | 47 | \b you want to use a \i{bulletin board system}, talker or MUD which can 48 | be accessed using Telnet. 49 | 50 | You probably do \e{not} want to use SSH, Telnet or Rlogin if: 51 | 52 | \b you only use Windows. Windows computers have their own 53 | ways of networking between themselves, and unless you are doing 54 | something fairly unusual, you will not need to use any of these 55 | remote login protocols. 56 | 57 | \H{which-one} How do SSH, Telnet and Rlogin differ? 58 | 59 | This list summarises some of the \i{differences between SSH, Telnet 60 | and Rlogin}. 61 | 62 | \b SSH (which stands for \q{\i{secure shell}}) is a recently designed, 63 | high-security protocol. It uses strong cryptography to protect your 64 | connection against eavesdropping, hijacking and other attacks. Telnet 65 | and Rlogin are both older protocols offering minimal security. 66 | 67 | \b SSH and Rlogin both allow you to \I{passwordless login}log in to the 68 | server without having to type a password. (Rlogin's method of doing this is 69 | insecure, and can allow an attacker to access your account on the 70 | server. SSH's method is much more secure, and typically breaking the 71 | security requires the attacker to have gained access to your actual 72 | client machine.) 73 | 74 | \b SSH allows you to connect to the server and automatically send a 75 | command, so that the server will run that command and then 76 | disconnect. So you can use it in automated processing. 77 | 78 | The Internet is a hostile environment and security is everybody's 79 | responsibility. If you are connecting across the open Internet, then 80 | we recommend you use SSH. If the server you want to connect to 81 | doesn't support SSH, it might be worth trying to persuade the 82 | administrator to install it. 83 | 84 | If your client and server are both behind the same (good) firewall, 85 | it is more likely to be safe to use Telnet or Rlogin, but we still 86 | recommend you use SSH. 87 | -------------------------------------------------------------------------------- /doc/licence.but: -------------------------------------------------------------------------------- 1 | \A{licence} PuTTY \ii{Licence} 2 | 3 | PuTTY is \i{copyright} 1997-2015 Simon Tatham. 4 | 5 | Portions copyright Robert de Bath, Joris van Rantwijk, Delian 6 | Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, 7 | Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus 8 | Kuhn, Colin Watson, and CORE SDI S.A. 9 | 10 | Permission is hereby granted, free of charge, to any person 11 | obtaining a copy of this software and associated documentation files 12 | (the \q{Software}), to deal in the Software without restriction, 13 | including without limitation the rights to use, copy, modify, merge, 14 | publish, distribute, sublicense, and/or sell copies of the Software, 15 | and to permit persons to whom the Software is furnished to do so, 16 | subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED \q{AS IS}, WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE 25 | FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 26 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | -------------------------------------------------------------------------------- /doc/man-pscp.but: -------------------------------------------------------------------------------- 1 | \cfg{man-identity}{pscp}{1}{2004-03-24}{PuTTY tool suite}{PuTTY tool suite} 2 | 3 | \H{pscp-manpage} Man page for PSCP 4 | 5 | \S{pscp-manpage-name} NAME 6 | 7 | \cw{pscp} \- command-line SCP (secure copy) / SFTP client 8 | 9 | \S{pscp-manpage-synopsis} SYNOPSIS 10 | 11 | \c pscp [options] [user@]host:source target 12 | \e bbbb iiiiiii iiiib iiiibiiiiii iiiiii 13 | \c pscp [options] source [source...] [user@]host:target 14 | \e bbbb iiiiiii iiiiii iiiiii iiiib iiiibiiiiii 15 | \c pscp [options] -ls [user@]host:filespec 16 | \e bbbb iiiiiii bbb iiiib iiiibiiiiiiii 17 | 18 | \S{pscp-manpage-description} DESCRIPTION 19 | 20 | \cw{pscp} is a command-line client for the SSH-based SCP (secure 21 | copy) and SFTP (secure file transfer protocol) protocols. 22 | 23 | \S{pscp-manpage-options} OPTIONS 24 | 25 | The command-line options supported by \e{pscp} are: 26 | 27 | \dt \cw{-V} 28 | 29 | \dd Show version information and exit. 30 | 31 | \dt \cw{-pgpfp} 32 | 33 | \dd Display the fingerprints of the PuTTY PGP Master Keys and exit, 34 | to aid in verifying new files released by the PuTTY team. 35 | 36 | \dt \cw{-ls} 37 | 38 | \dd Remote directory listing. 39 | 40 | \dt \cw{-p} 41 | 42 | \dd Preserve file attributes. 43 | 44 | \dt \cw{-q} 45 | 46 | \dd Quiet, don't show statistics. 47 | 48 | \dt \cw{-r} 49 | 50 | \dd Copy directories recursively. 51 | 52 | \dt \cw{-unsafe} 53 | 54 | \dd Allow server-side wildcards (DANGEROUS). 55 | 56 | \dt \cw{-v} 57 | 58 | \dd Show verbose messages. 59 | 60 | \dt \cw{-load} \e{session} 61 | 62 | \dd Load settings from saved session. 63 | 64 | \dt \cw{-P} \e{port} 65 | 66 | \dd Connect to port \e{port}. 67 | 68 | \dt \cw{-l} \e{user} 69 | 70 | \dd Set remote username to \e{user}. 71 | 72 | \dt \cw{-batch} 73 | 74 | \dd Disable interactive prompts. 75 | 76 | \dt \cw{-pw} \e{password} 77 | 78 | \dd Set remote password to \e{password}. \e{CAUTION:} this will likely 79 | make the password visible to other users of the local machine (via 80 | commands such as \q{\c{w}}). 81 | 82 | \dt \cw{-1} 83 | 84 | \dd Force use of SSH protocol version 1. 85 | 86 | \dt \cw{-2} 87 | 88 | \dd Force use of SSH protocol version 2. 89 | 90 | \dt \cw{-C} 91 | 92 | \dd Enable SSH compression. 93 | 94 | \dt \cw{-i} \e{path} 95 | 96 | \dd Private key file for user authentication. 97 | 98 | \dt \cw{\-hostkey} \e{key} 99 | 100 | \dd Specify an acceptable host public key. This option may be specified 101 | multiple times; each key can be either a fingerprint (\cw{99:aa:bb:...}) or 102 | a base64-encoded blob in OpenSSH's one-line format. 103 | 104 | \lcont{ Specifying this option overrides automated host key 105 | management; \e{only} the key(s) specified on the command-line will be 106 | accepted (unless a saved session also overrides host keys, in which 107 | case those will be added to), and the host key cache will not be 108 | written. } 109 | 110 | \dt \cw{-scp} 111 | 112 | \dd Force use of SCP protocol. 113 | 114 | \dt \cw{-sftp} 115 | 116 | \dd Force use of SFTP protocol. 117 | 118 | \S{pscp-manpage-more-information} MORE INFORMATION 119 | 120 | For more information on \cw{pscp} it's probably best to go and look at 121 | the manual on the PuTTY web page: 122 | 123 | \W{http://www.chiark.greenend.org.uk/~sgtatham/putty/}\cw{http://www.chiark.greenend.org.uk/~sgtatham/putty/} 124 | 125 | \S{pscp-manpage-bugs} BUGS 126 | 127 | This man page isn't terribly complete. See the above web link for 128 | better documentation. 129 | -------------------------------------------------------------------------------- /doc/man-psft.but: -------------------------------------------------------------------------------- 1 | \cfg{man-identity}{psftp}{1}{2004-03-24}{PuTTY tool suite}{PuTTY tool suite} 2 | 3 | \H{psftp-manpage} Man page for PSFTP 4 | 5 | \S{psftp-manpage-name} NAME 6 | 7 | \cw{psftp} \- interactive SFTP (secure file transfer protocol) client 8 | 9 | \S{psftp-manpage-synopsis} SYNOPSIS 10 | 11 | \c psftp [options] [user@]host 12 | \e bbbbb iiiiiii iiiib iiii 13 | 14 | \S{psftp-manpage-description} DESCRIPTION 15 | 16 | \cw{psftp} is an interactive text-based client for the SSH-based SFTP 17 | (secure file transfer) protocol. 18 | 19 | \S{psftp-manpage-options} OPTIONS 20 | 21 | The command-line options supported by \cw{psftp} are: 22 | 23 | \dt \cw{-V} 24 | 25 | \dd Show version information and exit. 26 | 27 | \dt \cw{-pgpfp} 28 | 29 | \dd Display the fingerprints of the PuTTY PGP Master Keys and exit, 30 | to aid in verifying new files released by the PuTTY team. 31 | 32 | \dt \cw{-b} \e{batchfile} 33 | 34 | \dd Use specified batchfile. 35 | 36 | \dt \cw{-bc} 37 | 38 | \dd Output batchfile commands. 39 | 40 | \dt \cw{-be} 41 | 42 | \dd Don't stop batchfile processing on errors. 43 | 44 | \dt \cw{-v} 45 | 46 | \dd Show verbose messages. 47 | 48 | \dt \cw{-load} \e{session} 49 | 50 | \dd Load settings from saved session. 51 | 52 | \dt \cw{-P} \e{port} 53 | 54 | \dd Connect to port \e{port}. 55 | 56 | \dt \cw{-l} \e{user} 57 | 58 | \dd Set remote username to \e{user}. 59 | 60 | \dt \cw{-batch} 61 | 62 | \dd Disable interactive prompts. 63 | 64 | \dt \cw{-pw} \e{password} 65 | 66 | \dd Set remote password to \e{password}. \e{CAUTION:} this will likely 67 | make the password visible to other users of the local machine (via 68 | commands such as \q{\c{w}}). 69 | 70 | \dt \cw{-1} 71 | 72 | \dd Force use of SSH protocol version 1. 73 | 74 | \dt \cw{-2} 75 | 76 | \dd Force use of SSH protocol version 2. 77 | 78 | \dt \cw{-C} 79 | 80 | \dd Enable SSH compression. 81 | 82 | \dt \cw{-i} \e{path} 83 | 84 | \dd Private key file for user authentication. 85 | 86 | \dt \cw{\-hostkey} \e{key} 87 | 88 | \dd Specify an acceptable host public key. This option may be specified 89 | multiple times; each key can be either a fingerprint (\cw{99:aa:bb:...}) or 90 | a base64-encoded blob in OpenSSH's one-line format. 91 | 92 | \lcont{ Specifying this option overrides automated host key 93 | management; \e{only} the key(s) specified on the command-line will be 94 | accepted (unless a saved session also overrides host keys, in which 95 | case those will be added to), and the host key cache will not be 96 | written. } 97 | 98 | \S{psftp-manpage-commands} COMMANDS 99 | 100 | For a list of commands available inside \cw{psftp}, type \cw{help} 101 | at the \cw{psftp>} prompt. 102 | 103 | \S{psftp-manpage-more-information} MORE INFORMATION 104 | 105 | For more information on \cw{psftp} it's probably best to go and look at 106 | the manual on the PuTTY web page: 107 | 108 | \cw{http://www.chiark.greenend.org.uk/~sgtatham/putty/} 109 | 110 | \S{psftp-manpage-bugs} BUGS 111 | 112 | This man page isn't terribly complete. See the above web link for 113 | better documentation. 114 | -------------------------------------------------------------------------------- /doc/mancfg.but: -------------------------------------------------------------------------------- 1 | \cfg{man-mindepth}{2} 2 | 3 | \C{not-shown} Chapter title which is not shown 4 | -------------------------------------------------------------------------------- /doc/manpages.but: -------------------------------------------------------------------------------- 1 | \A{man-pages} Man pages for Unix PuTTY 2 | 3 | This appendix contains all the man pages for Unix PuTTY. 4 | -------------------------------------------------------------------------------- /doc/site.but: -------------------------------------------------------------------------------- 1 | \# Additional configuration for the version of the PuTTY docs 2 | \# actually published as HTML on the website. 3 | 4 | \cfg{xhtml-head-end}{} 5 | -------------------------------------------------------------------------------- /doc/sshnames.but: -------------------------------------------------------------------------------- 1 | \A{sshnames} SSH-2 names specified for PuTTY 2 | 3 | There are various parts of the SSH-2 protocol where things are specified 4 | using a textual name. Names ending in \cw{@putty.projects.tartarus.org} 5 | are reserved for allocation by the PuTTY team. Allocated names are 6 | documented here. 7 | 8 | \H{sshnames-channel} Connection protocol channel request names 9 | 10 | These names can be sent in a \cw{SSH_MSG_CHANNEL_REQUEST} message. 11 | 12 | \dt \cw{simple@putty.projects.tartarus.org} 13 | 14 | \dd This is sent by a client to announce that it will not have more than 15 | one channel open at a time in the current connection (that one being 16 | the one the request is sent on). The intention is that the server, 17 | knowing this, can set the window on that one channel to something very 18 | large, and leave flow control to TCP. There is no message-specific data. 19 | 20 | \dt \cw{winadj@putty.projects.tartarus.org} 21 | 22 | \dd PuTTY sends this request along with some 23 | \cw{SSH_MSG_CHANNEL_WINDOW_ADJUST} messages as part of its window-size 24 | tuning. It can be sent on any type of channel. There is no 25 | message-specific data. Servers MUST treat it as an unrecognised request 26 | and respond with \cw{SSH_MSG_CHANNEL_FAILURE}. 27 | 28 | \lcont{ 29 | (Some SSH servers get confused by this message, so there is a 30 | bug-compatibility mode for disabling it. See \k{config-ssh-bug-winadj}.) 31 | } 32 | 33 | \H{sshnames-kex} Key exchange method names 34 | 35 | \dt \cw{rsa-sha1-draft-00@putty.projects.tartarus.org} 36 | 37 | \dt \cw{rsa-sha256-draft-00@putty.projects.tartarus.org} 38 | 39 | \dt \cw{rsa1024-sha1-draft-01@putty.projects.tartarus.org} 40 | 41 | \dt \cw{rsa1024-sha256-draft-01@putty.projects.tartarus.org} 42 | 43 | \dt \cw{rsa2048-sha256-draft-01@putty.projects.tartarus.org} 44 | 45 | \dt \cw{rsa1024-sha1-draft-02@putty.projects.tartarus.org} 46 | 47 | \dt \cw{rsa2048-sha512-draft-02@putty.projects.tartarus.org} 48 | 49 | \dt \cw{rsa1024-sha1-draft-03@putty.projects.tartarus.org} 50 | 51 | \dt \cw{rsa2048-sha256-draft-03@putty.projects.tartarus.org} 52 | 53 | \dt \cw{rsa1024-sha1-draft-04@putty.projects.tartarus.org} 54 | 55 | \dt \cw{rsa2048-sha256-draft-04@putty.projects.tartarus.org} 56 | 57 | \dd These appeared in various drafts of what eventually became RFC\_4432. 58 | They have been superseded by \cw{rsa1024-sha1} and \cw{rsa2048-sha256}. 59 | 60 | \H{sshnames-encrypt} Encryption algorithm names 61 | 62 | \dt \cw{arcfour128-draft-00@putty.projects.tartarus.org} 63 | 64 | \dt \cw{arcfour256-draft-00@putty.projects.tartarus.org} 65 | 66 | \dd These were used in drafts of what eventually became RFC\_4345. 67 | They have been superseded by \cw{arcfour128} and \cw{arcfour256}. 68 | -------------------------------------------------------------------------------- /doc/vids.but: -------------------------------------------------------------------------------- 1 | \# Fallback versionid for use when the build system hasn't provided a 2 | better one. 3 | 4 | \versionid no version information available 5 | -------------------------------------------------------------------------------- /errsock.c: -------------------------------------------------------------------------------- 1 | /* 2 | * A dummy Socket implementation which just holds an error message. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #define DEFINE_PLUG_METHOD_MACROS 9 | #include "tree234.h" 10 | #include "putty.h" 11 | #include "network.h" 12 | 13 | typedef struct Socket_error_tag *Error_Socket; 14 | 15 | struct Socket_error_tag { 16 | const struct socket_function_table *fn; 17 | /* the above variable absolutely *must* be the first in this structure */ 18 | 19 | char *error; 20 | Plug plug; 21 | }; 22 | 23 | static Plug sk_error_plug(Socket s, Plug p) 24 | { 25 | Error_Socket ps = (Error_Socket) s; 26 | Plug ret = ps->plug; 27 | if (p) 28 | ps->plug = p; 29 | return ret; 30 | } 31 | 32 | static void sk_error_close(Socket s) 33 | { 34 | Error_Socket ps = (Error_Socket) s; 35 | 36 | sfree(ps->error); 37 | sfree(ps); 38 | } 39 | 40 | static const char *sk_error_socket_error(Socket s) 41 | { 42 | Error_Socket ps = (Error_Socket) s; 43 | return ps->error; 44 | } 45 | 46 | static char *sk_error_peer_info(Socket s) 47 | { 48 | return NULL; 49 | } 50 | 51 | Socket new_error_socket(const char *errmsg, Plug plug) 52 | { 53 | static const struct socket_function_table socket_fn_table = { 54 | sk_error_plug, 55 | sk_error_close, 56 | NULL /* write */, 57 | NULL /* write_oob */, 58 | NULL /* write_eof */, 59 | NULL /* flush */, 60 | NULL /* set_frozen */, 61 | sk_error_socket_error, 62 | sk_error_peer_info, 63 | }; 64 | 65 | Error_Socket ret; 66 | 67 | ret = snew(struct Socket_error_tag); 68 | ret->fn = &socket_fn_table; 69 | ret->plug = plug; 70 | ret->error = dupstr(errmsg); 71 | 72 | return (Socket) ret; 73 | } 74 | -------------------------------------------------------------------------------- /icons/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for the PuTTY icon suite. 2 | 3 | ICONS = putty puttycfg puttygen pscp pageant pterm ptermcfg puttyins 4 | SIZES = 16 32 48 5 | 6 | MODE = # override to -it on command line for opaque testing 7 | 8 | PNGS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S).png)) 9 | MONOPNGS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S)-mono.png)) 10 | TRUEPNGS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S)-true.png)) 11 | 12 | ICOS = putty.ico puttygen.ico pscp.ico pageant.ico pageants.ico puttycfg.ico \ 13 | puttyins.ico 14 | CICONS = xpmputty.c xpmpucfg.c xpmpterm.c xpmptcfg.c 15 | 16 | base: icos cicons 17 | 18 | all: pngs monopngs base # truepngs currently disabled by default 19 | 20 | pngs: $(PNGS) 21 | monopngs: $(MONOPNGS) 22 | truepngs: $(TRUEPNGS) 23 | 24 | icos: $(ICOS) 25 | cicons: $(CICONS) 26 | 27 | install: icos cicons 28 | cp $(ICOS) ../windows 29 | cp $(CICONS) ../unix 30 | 31 | $(PNGS): %.png: mkicon.py 32 | ./mkicon.py $(MODE) $(join $(subst -, ,$(basename $@)),_icon) $@ 33 | 34 | $(MONOPNGS): %.png: mkicon.py 35 | ./mkicon.py -2 $(MODE) $(join $(subst -, ,$(subst -mono,,$(basename $@))),_icon) $@ 36 | 37 | $(TRUEPNGS): %.png: mkicon.py 38 | ./mkicon.py -T $(MODE) $(join $(subst -, ,$(subst -true,,$(basename $@))),_icon) $@ 39 | 40 | putty.ico: putty-16.png putty-32.png putty-48.png \ 41 | putty-16-mono.png putty-32-mono.png putty-48-mono.png 42 | ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@ 43 | 44 | puttycfg.ico: puttycfg-16.png puttycfg-32.png puttycfg-48.png \ 45 | puttycfg-16-mono.png puttycfg-32-mono.png puttycfg-48-mono.png 46 | ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@ 47 | 48 | puttygen.ico: puttygen-16.png puttygen-32.png puttygen-48.png \ 49 | puttygen-16-mono.png puttygen-32-mono.png puttygen-48-mono.png 50 | ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@ 51 | 52 | pageant.ico: pageant-16.png pageant-32.png pageant-48.png \ 53 | pageant-16-mono.png pageant-32-mono.png pageant-48-mono.png 54 | ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@ 55 | 56 | pageants.ico: pageant-16.png pageant-16-mono.png 57 | ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@ 58 | 59 | pscp.ico: pscp-16.png pscp-32.png pscp-48.png \ 60 | pscp-16-mono.png pscp-32-mono.png pscp-48-mono.png 61 | ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@ 62 | 63 | # Because the installer icon makes heavy use of brown when drawing 64 | # the cardboard box, it's worth having 8-bit versions of it in 65 | # addition to the 4- and 1-bit ones. 66 | puttyins.ico: puttyins-16.png puttyins-32.png puttyins-48.png \ 67 | puttyins-16-mono.png puttyins-32-mono.png \ 68 | puttyins-48-mono.png \ 69 | puttyins-16-true.png puttyins-32-true.png \ 70 | puttyins-48-true.png 71 | ./icon.pl -8 $(filter %-true.png, $^) \ 72 | -4 $(filter-out %-true.png, $(filter-out %-mono.png, $^)) \ 73 | -1 $(filter %-mono.png, $^) > $@ 74 | 75 | # Icon for the website. (This isn't linked into "make all".) 76 | website.ico: putty-16.png 77 | ./icon.pl -4 $^ >$@ 78 | 79 | xpmputty.c: putty-16.png putty-32.png putty-48.png 80 | ./cicon.pl main_icon $^ > $@ 81 | 82 | xpmpucfg.c: puttycfg-16.png puttycfg-32.png puttycfg-48.png 83 | ./cicon.pl cfg_icon $^ > $@ 84 | 85 | xpmpterm.c: pterm-16.png pterm-32.png pterm-48.png 86 | ./cicon.pl main_icon $^ > $@ 87 | 88 | xpmptcfg.c: ptermcfg-16.png ptermcfg-32.png ptermcfg-48.png 89 | ./cicon.pl cfg_icon $^ > $@ 90 | 91 | clean: 92 | rm -f *.png *.ico *.c 93 | -------------------------------------------------------------------------------- /icons/cicon.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Given a list of input PNGs, create a C source file containing a 4 | # const array of XPMs, named by a given C identifier. 5 | 6 | $id = shift @ARGV; 7 | $k = 0; 8 | @xpms = (); 9 | foreach $f (@ARGV) { 10 | # XPM format is generated directly by ImageMagick, so that's easy 11 | # enough. We just have to adjust the declaration line so that it 12 | # has the right name, linkage and storage class. 13 | @lines = (); 14 | open XPM, "convert $f xpm:- |"; 15 | push @lines, $_ while ; 16 | close XPM; 17 | die "XPM from $f in unexpected format\n" unless $lines[1] =~ /^static.*\{$/; 18 | $lines[1] = "static const char *const ${id}_$k"."[] = {\n"; 19 | $k++; 20 | push @xpms, @lines, "\n"; 21 | } 22 | 23 | # Now output. 24 | foreach $line (@xpms) { print $line; } 25 | print "const char *const *const ${id}[] = {\n"; 26 | for ($i = 0; $i < $k; $i++) { print " ${id}_$i,\n"; } 27 | print "};\n"; 28 | print "const int n_${id} = $k;\n"; 29 | -------------------------------------------------------------------------------- /int64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Handling of the int64 and uint64 types. Done in 32-bit integers, 3 | * for (pre-C99) portability. Hopefully once C99 becomes widespread 4 | * we can kiss this lot goodbye... 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include "int64.h" 11 | 12 | uint64 uint64_div10(uint64 x, int *remainder) 13 | { 14 | uint64 y; 15 | unsigned int rem, r2; 16 | y.hi = x.hi / 10; 17 | y.lo = x.lo / 10; 18 | rem = x.lo % 10; 19 | /* 20 | * Now we have to add in the remainder left over from x.hi. 21 | */ 22 | r2 = x.hi % 10; 23 | y.lo += r2 * 429496729; 24 | rem += r2 * 6; 25 | y.lo += rem / 10; 26 | rem %= 10; 27 | 28 | if (remainder) 29 | *remainder = rem; 30 | return y; 31 | } 32 | 33 | void uint64_decimal(uint64 x, char *buffer) 34 | { 35 | char buf[20]; 36 | int start = 20; 37 | int d; 38 | 39 | do { 40 | x = uint64_div10(x, &d); 41 | assert(start > 0); 42 | buf[--start] = d + '0'; 43 | } while (x.hi || x.lo); 44 | 45 | memcpy(buffer, buf + start, sizeof(buf) - start); 46 | buffer[sizeof(buf) - start] = '\0'; 47 | } 48 | 49 | uint64 uint64_make(unsigned long hi, unsigned long lo) 50 | { 51 | uint64 y; 52 | y.hi = hi & 0xFFFFFFFFU; 53 | y.lo = lo & 0xFFFFFFFFU; 54 | return y; 55 | } 56 | 57 | uint64 uint64_add(uint64 x, uint64 y) 58 | { 59 | x.lo = (x.lo + y.lo) & 0xFFFFFFFFU; 60 | x.hi += y.hi + (x.lo < y.lo ? 1 : 0); 61 | return x; 62 | } 63 | 64 | uint64 uint64_add32(uint64 x, unsigned long y) 65 | { 66 | uint64 yy; 67 | yy.hi = 0; 68 | yy.lo = y; 69 | return uint64_add(x, yy); 70 | } 71 | 72 | int uint64_compare(uint64 x, uint64 y) 73 | { 74 | if (x.hi != y.hi) 75 | return x.hi < y.hi ? -1 : +1; 76 | if (x.lo != y.lo) 77 | return x.lo < y.lo ? -1 : +1; 78 | return 0; 79 | } 80 | 81 | uint64 uint64_subtract(uint64 x, uint64 y) 82 | { 83 | x.lo = (x.lo - y.lo) & 0xFFFFFFFFU; 84 | x.hi = (x.hi - y.hi - (x.lo > (y.lo ^ 0xFFFFFFFFU) ? 1 : 0)) & 0xFFFFFFFFU; 85 | return x; 86 | } 87 | 88 | double uint64_to_double(uint64 x) 89 | { 90 | return (4294967296.0 * x.hi) + (double)x.lo; 91 | } 92 | 93 | uint64 uint64_shift_right(uint64 x, int shift) 94 | { 95 | if (shift < 32) { 96 | x.lo >>= shift; 97 | x.lo |= (x.hi << (32-shift)) & 0xFFFFFFFFU; 98 | x.hi >>= shift; 99 | } else { 100 | x.lo = x.hi >> (shift-32); 101 | x.hi = 0; 102 | } 103 | return x; 104 | } 105 | 106 | uint64 uint64_shift_left(uint64 x, int shift) 107 | { 108 | if (shift < 32) { 109 | x.hi = (x.hi << shift) & 0xFFFFFFFFU; 110 | x.hi |= (x.lo >> (32-shift)); 111 | x.lo = (x.lo << shift) & 0xFFFFFFFFU; 112 | } else { 113 | x.hi = (x.lo << (shift-32)) & 0xFFFFFFFFU; 114 | x.lo = 0; 115 | } 116 | return x; 117 | } 118 | 119 | uint64 uint64_from_decimal(char *str) 120 | { 121 | uint64 ret; 122 | ret.hi = ret.lo = 0; 123 | while (*str >= '0' && *str <= '9') { 124 | ret = uint64_add(uint64_shift_left(ret, 3), 125 | uint64_shift_left(ret, 1)); 126 | ret = uint64_add32(ret, *str - '0'); 127 | str++; 128 | } 129 | return ret; 130 | } 131 | 132 | #ifdef TESTMODE 133 | 134 | #include 135 | 136 | int main(void) 137 | { 138 | uint64 x, y, z; 139 | char buf[80]; 140 | 141 | x = uint64_make(0x3456789AUL, 0xDEF01234UL); 142 | printf("%08lx.%08lx\n", x.hi, x.lo); 143 | uint64_decimal(x, buf); 144 | printf("%s\n", buf); 145 | 146 | y = uint64_add32(x, 0xFFFFFFFFU); 147 | printf("%08lx.%08lx\n", y.hi, y.lo); 148 | uint64_decimal(y, buf); 149 | printf("%s\n", buf); 150 | 151 | z = uint64_subtract(y, x); 152 | printf("%08lx.%08lx\n", z.hi, z.lo); 153 | uint64_decimal(z, buf); 154 | printf("%s\n", buf); 155 | 156 | z = uint64_subtract(x, y); 157 | printf("%08lx.%08lx\n", z.hi, z.lo); 158 | uint64_decimal(z, buf); 159 | printf("%s\n", buf); 160 | 161 | y = uint64_shift_right(x, 4); 162 | printf("%08lx.%08lx\n", y.hi, y.lo); 163 | 164 | y = uint64_shift_right(x, 36); 165 | printf("%08lx.%08lx\n", y.hi, y.lo); 166 | 167 | y = uint64_shift_left(x, 4); 168 | printf("%08lx.%08lx\n", x.hi, x.lo); 169 | 170 | y = uint64_shift_left(x, 36); 171 | printf("%08lx.%08lx\n", x.hi, x.lo); 172 | 173 | return 0; 174 | } 175 | #endif 176 | -------------------------------------------------------------------------------- /int64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Header for int64.c. 3 | */ 4 | 5 | #ifndef PUTTY_INT64_H 6 | #define PUTTY_INT64_H 7 | 8 | typedef struct { 9 | unsigned long hi, lo; 10 | } uint64; 11 | 12 | uint64 uint64_div10(uint64 x, int *remainder); 13 | void uint64_decimal(uint64 x, char *buffer); 14 | uint64 uint64_make(unsigned long hi, unsigned long lo); 15 | uint64 uint64_add(uint64 x, uint64 y); 16 | uint64 uint64_add32(uint64 x, unsigned long y); 17 | int uint64_compare(uint64 x, uint64 y); 18 | uint64 uint64_subtract(uint64 x, uint64 y); 19 | double uint64_to_double(uint64 x); 20 | uint64 uint64_shift_right(uint64 x, int shift); 21 | uint64 uint64_shift_left(uint64 x, int shift); 22 | uint64 uint64_from_decimal(char *str); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /ldisc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ldisc.h: defines the Ldisc data structure used by ldisc.c and 3 | * ldiscucs.c. (Unfortunately it was necessary to split the ldisc 4 | * module in two, to avoid unnecessarily linking in the Unicode 5 | * stuff in tools that don't require it.) 6 | */ 7 | 8 | #ifndef PUTTY_LDISC_H 9 | #define PUTTY_LDISC_H 10 | 11 | typedef struct ldisc_tag { 12 | Terminal *term; 13 | Backend *back; 14 | void *backhandle; 15 | void *frontend; 16 | 17 | /* 18 | * Values cached out of conf. 19 | */ 20 | int telnet_keyboard, telnet_newline, protocol, localecho, localedit; 21 | 22 | char *buf; 23 | int buflen, bufsiz, quotenext; 24 | } *Ldisc; 25 | 26 | #endif /* PUTTY_LDISC_H */ 27 | -------------------------------------------------------------------------------- /ldiscucs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ldisc.c: PuTTY line discipline. Sits between the input coming 3 | * from keypresses in the window, and the output channel leading to 4 | * the back end. Implements echo and/or local line editing, 5 | * depending on what's currently configured. 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include "putty.h" 12 | #include "terminal.h" 13 | #include "ldisc.h" 14 | 15 | void lpage_send(void *handle, 16 | int codepage, char *buf, int len, int interactive) 17 | { 18 | Ldisc ldisc = (Ldisc)handle; 19 | wchar_t *widebuffer = 0; 20 | int widesize = 0; 21 | int wclen; 22 | 23 | if (codepage < 0) { 24 | ldisc_send(ldisc, buf, len, interactive); 25 | return; 26 | } 27 | 28 | widesize = len * 2; 29 | widebuffer = snewn(widesize, wchar_t); 30 | 31 | wclen = mb_to_wc(codepage, 0, buf, len, widebuffer, widesize); 32 | luni_send(ldisc, widebuffer, wclen, interactive); 33 | 34 | sfree(widebuffer); 35 | } 36 | 37 | void luni_send(void *handle, wchar_t * widebuf, int len, int interactive) 38 | { 39 | Ldisc ldisc = (Ldisc)handle; 40 | int ratio = (in_utf(ldisc->term))?3:1; 41 | char *linebuffer; 42 | int linesize; 43 | int i; 44 | char *p; 45 | 46 | linesize = len * ratio * 2; 47 | linebuffer = snewn(linesize, char); 48 | 49 | if (in_utf(ldisc->term)) { 50 | /* UTF is a simple algorithm */ 51 | for (p = linebuffer, i = 0; i < len; i++) { 52 | unsigned long ch = widebuf[i]; 53 | 54 | if (IS_SURROGATE(ch)) { 55 | #ifdef PLATFORM_IS_UTF16 56 | if (i+1 < len) { 57 | unsigned long ch2 = widebuf[i+1]; 58 | if (IS_SURROGATE_PAIR(ch, ch2)) { 59 | ch = FROM_SURROGATES(ch, ch2); 60 | i++; 61 | } 62 | } else 63 | #endif 64 | { 65 | /* Unrecognised UTF-16 sequence */ 66 | ch = '.'; 67 | } 68 | } 69 | 70 | if (ch < 0x80) { 71 | *p++ = (char) (ch); 72 | } else if (ch < 0x800) { 73 | *p++ = (char) (0xC0 | (ch >> 6)); 74 | *p++ = (char) (0x80 | (ch & 0x3F)); 75 | } else if (ch < 0x10000) { 76 | *p++ = (char) (0xE0 | (ch >> 12)); 77 | *p++ = (char) (0x80 | ((ch >> 6) & 0x3F)); 78 | *p++ = (char) (0x80 | (ch & 0x3F)); 79 | } else { 80 | *p++ = (char) (0xF0 | (ch >> 18)); 81 | *p++ = (char) (0x80 | ((ch >> 12) & 0x3F)); 82 | *p++ = (char) (0x80 | ((ch >> 6) & 0x3F)); 83 | *p++ = (char) (0x80 | (ch & 0x3F)); 84 | } 85 | } 86 | } else { 87 | int rv; 88 | rv = wc_to_mb(ldisc->term->ucsdata->line_codepage, 0, widebuf, len, 89 | linebuffer, linesize, NULL, NULL, ldisc->term->ucsdata); 90 | if (rv >= 0) 91 | p = linebuffer + rv; 92 | else 93 | p = linebuffer; 94 | } 95 | if (p > linebuffer) 96 | ldisc_send(ldisc, linebuffer, p - linebuffer, interactive); 97 | 98 | sfree(linebuffer); 99 | } 100 | -------------------------------------------------------------------------------- /macosx/README.OSX: -------------------------------------------------------------------------------- 1 | This directory contains a Mac OS X port of PuTTY/pterm, running as a 2 | native Aqua GUI application. 3 | 4 | THIS PORT IS CURRENTLY UNFINISHED AND EXPERIMENTAL. It is _not_ 5 | considered to be of release quality, even if you've found it (and 6 | are reading this) in a PuTTY release source archive. You are welcome 7 | to try using it, but don't be surprised at unexpected behaviour. I'm 8 | not kidding. 9 | 10 | In particular, I have not yet decided where OS X PuTTY should store 11 | its configuration data. Options include storing it in ~/.putty to be 12 | compatible with Unix PuTTY, storing it wherever is compatible with 13 | Mac Classic PuTTY, storing it in a natively OS X location, or 14 | sorting out the `config-locations' wishlist item and doing all 15 | three. Therefore, if you start using this port and create a whole 16 | load of saved sessions, you should not be surprised if a future 17 | version of the port decides to look somewhere completely different 18 | for the data and therefore loses them all. If that happens, don't 19 | say you weren't warned! 20 | 21 | Other ways in which the port is currently unfinished include: 22 | 23 | Bit rot 24 | ------- 25 | 26 | - the conversion of the old fixed-size 'Config' structure to the 27 | new dynamic 'Conf' was never applied to this directory 28 | 29 | - probably other things are out of date too; it would need some 30 | work to make it compile again 31 | 32 | Missing terminal window features 33 | -------------------------------- 34 | 35 | - terminal display is horribly slow 36 | 37 | - fonts aren't configurable 38 | 39 | - several features are unimplemented in the terminal display: 40 | underlining, non-solid-block cursors, double-width and 41 | double-height line attributes, bold as font rather than as 42 | colour, wide (CJK) characters, combining characters. 43 | 44 | - there's no scrollbar 45 | 46 | - terminal window resizing isn't implemented yet 47 | 48 | - proper window placement (cascading down and right from the 49 | starting position, plus remembering previous window positions per 50 | the Apple HIG) is not implemented 51 | 52 | Missing alert box features 53 | -------------------------- 54 | 55 | - warn-on-close isn't implemented 56 | 57 | Missing input features 58 | ---------------------- 59 | 60 | - use of Alt+numberpad to enter arbitrary numeric character codes 61 | is not yet supported 62 | 63 | - there's no Meta key yet. (I'd like to at least have the 64 | possibility of using Command rather than Option as the Meta key, 65 | since the latter is necessary to send some characters, including 66 | the rather important # on Apple UK keyboards; but trapping 67 | Command- and sending it to the window rather than the 68 | application menu requires me to make a positive effort of some 69 | sort and I haven't got round to it yet. For those Mac users who 70 | consider their Command key sacrosanct, don't worry, this option 71 | _will_ be configurable and _will_ be off by default.) 72 | 73 | - there's no specials menu 74 | 75 | - mouse activity isn't supported (neither cut-and-paste nor xterm 76 | mouse tracking) 77 | 78 | Missing terminal emulation features 79 | ----------------------------------- 80 | 81 | - currently no support for server-side window management requests 82 | (i.e. escape sequences to minimise or maximise the window, 83 | request or change its position and size, change its title etc) 84 | 85 | - window title is currently fixed 86 | 87 | Other missing features 88 | ---------------------- 89 | 90 | - no Event Log 91 | 92 | - no mid-session Change Settings 93 | -------------------------------------------------------------------------------- /macosx/info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIconFile 6 | PuTTY.icns 7 | 8 | 9 | -------------------------------------------------------------------------------- /macosx/osx.h: -------------------------------------------------------------------------------- 1 | #ifndef PUTTY_OSX_H 2 | #define PUTTY_OSX_H 3 | 4 | /* 5 | * Cocoa defines `FontSpec' itself, so we must change its name. 6 | * (Arrgh.) 7 | */ 8 | #define FontSpec FontSpec_OSX_Proof 9 | 10 | /* 11 | * Define the various compatibility symbols to make uxpty.c compile 12 | * correctly on OS X. 13 | */ 14 | #define BSD_PTYS 15 | #define OMIT_UTMP 16 | #define HAVE_NO_SETRESUID 17 | #define NOT_X_WINDOWS 18 | 19 | /* 20 | * OS X is largely just Unix, so we can include most of this 21 | * unchanged. 22 | */ 23 | #include "unix.h" 24 | 25 | /* 26 | * Functions exported by osxsel.m. (Both of these functions are 27 | * expected to be called in the _main_ thread: the select subthread 28 | * is an implementation detail of osxsel.m and ideally should not 29 | * be visible at all outside it.) 30 | */ 31 | void osxsel_init(void); /* call this to kick things off */ 32 | void osxsel_process_results(void); /* call this on receipt of a netevent */ 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /macosx/osxclass.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Header file for the Objective-C parts of Mac OS X PuTTY. This 3 | * file contains the class definitions, which would cause compile 4 | * failures in the pure C modules if they appeared in osx.h. 5 | */ 6 | 7 | #ifndef PUTTY_OSXCLASS_H 8 | #define PUTTY_OSXCLASS_H 9 | 10 | #include "putty.h" 11 | 12 | /* 13 | * The application controller class, defined in osxmain.m. 14 | */ 15 | @interface AppController : NSObject 16 | { 17 | NSTimer *timer; 18 | } 19 | - (void)newSessionConfig:(id)sender; 20 | - (void)newTerminal:(id)sender; 21 | - (void)newSessionWithConfig:(id)cfg; 22 | - (void)setTimer:(long)next; 23 | @end 24 | extern AppController *controller; 25 | 26 | /* 27 | * The SessionWindow class, defined in osxwin.m. 28 | */ 29 | 30 | struct alert_queue { 31 | struct alert_queue *next; 32 | NSAlert *alert; 33 | void (*callback)(void *, int); 34 | void *ctx; 35 | }; 36 | 37 | @class SessionWindow; 38 | @class TerminalView; 39 | 40 | @interface SessionWindow : NSWindow 41 | { 42 | Terminal *term; 43 | TerminalView *termview; 44 | struct unicode_data ucsdata; 45 | void *logctx; 46 | Config cfg; 47 | void *ldisc; 48 | Backend *back; 49 | void *backhandle; 50 | int exited; 51 | /* 52 | * The following two members relate to the currently active 53 | * alert sheet, if any. They are NULL if there isn't one. 54 | */ 55 | void (*alert_callback)(void *, int); 56 | void *alert_ctx; 57 | /* This queues future alerts that need to be shown. */ 58 | struct alert_queue *alert_qhead, *alert_qtail; 59 | } 60 | - (id)initWithConfig:(Config)cfg; 61 | - (void)drawStartFinish:(BOOL)start; 62 | - (void)setColour:(int)n r:(float)r g:(float)g b:(float)b; 63 | - (Config *)cfg; 64 | - (void)doText:(wchar_t *)text len:(int)len x:(int)x y:(int)y 65 | attr:(unsigned long)attr lattr:(int)lattr; 66 | - (int)fromBackend:(const char *)data len:(int)len isStderr:(int)is_stderr; 67 | - (int)fromBackendUntrusted:(const char *)data len:(int)len; 68 | - (void)startAlert:(NSAlert *)alert 69 | withCallback:(void (*)(void *, int))callback andCtx:(void *)ctx; 70 | - (void)endSession:(int)clean; 71 | - (void)notifyRemoteExit; 72 | - (Terminal *)term; 73 | @end 74 | 75 | /* 76 | * The ConfigWindow class, defined in osxdlg.m. 77 | */ 78 | 79 | @class ConfigWindow; 80 | 81 | @interface ConfigWindow : NSWindow 82 | { 83 | NSOutlineView *treeview; 84 | struct controlbox *ctrlbox; 85 | void *dv; 86 | Config cfg; 87 | } 88 | - (id)initWithConfig:(Config)cfg; 89 | @end 90 | 91 | /* 92 | * Functions exported by osxctrls.m. (They have to go in this 93 | * header file and not osx.h, because some of them have Cocoa class 94 | * types in their prototypes.) 95 | */ 96 | #define HSPACING 12 /* needed in osxdlg.m and osxctrls.m */ 97 | #define VSPACING 8 98 | 99 | void *fe_dlg_init(void *data, NSWindow *window, NSObject *target, SEL action); 100 | void fe_dlg_free(void *dv); 101 | void create_ctrls(void *dv, NSView *parent, struct controlset *s, 102 | int *minw, int *minh); 103 | int place_ctrls(void *dv, struct controlset *s, int leftx, int topy, 104 | int width); /* returns height used */ 105 | void select_panel(void *dv, struct controlbox *b, const char *name); 106 | 107 | #endif /* PUTTY_OSXCLASS_H */ 108 | -------------------------------------------------------------------------------- /macosx/putty.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FireEgl/FuTTY/c536b357184be8a9faff2c87fa17a5f2b707092d/macosx/putty.icns -------------------------------------------------------------------------------- /mkauto.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # This script makes the autoconf mechanism for the Unix port work. 3 | # It's separate from mkfiles.pl because it won't work (and isn't needed) 4 | # on a non-Unix system. 5 | 6 | # It's nice to be able to run this from inside the unix subdir as 7 | # well as from outside. 8 | test -f unix.h && cd .. 9 | 10 | # Run autoconf on our real configure.in. 11 | autoreconf -i && rm -rf autom4te.cache 12 | -------------------------------------------------------------------------------- /mksrcarc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | perl mkfiles.pl 6 | # These are text files. 7 | text=`{ find . -name CVS -prune -o \ 8 | -name .cvsignore -prune -o \ 9 | -name .svn -prune -o \ 10 | -name LATEST.VER -prune -o \ 11 | -name CHECKLST.txt -prune -o \ 12 | -name mksrcarc.sh -prune -o \ 13 | -name '*.dsp' -prune -o \ 14 | -name '*.dsw' -prune -o \ 15 | -type f -print | sed 's/^\.\///'; } | \ 16 | grep -ivE 'testdata/.*\.txt|MODULE|putty.iss|website.url' | grep -vF .ico | grep -vF .icns` 17 | # These are files which I'm _sure_ should be treated as text, but 18 | # which zip might complain about, so we direct its moans to 19 | # /dev/null! Apparently its heuristics are doubtful of UTF-8 text 20 | # files. 21 | bintext=testdata/*.txt 22 | # These are actual binary files which we don't want transforming. 23 | bin=`{ ls -1 windows/*.ico windows/putty.iss windows/website.url macosx/*.icns; \ 24 | find . -name '*.dsp' -print -o -name '*.dsw' -print; }` 25 | 26 | verbosely() { 27 | echo "$@" 28 | "$@" 29 | } 30 | 31 | verbosely zip -l putty-src.zip $text 32 | verbosely zip -l putty-src.zip $bintext 33 | verbosely zip putty-src.zip $bin 34 | -------------------------------------------------------------------------------- /mkunxarc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Build a Unix source distribution from the PuTTY CVS area. 4 | # 5 | # Expects the following arguments: 6 | # - the version number to write into configure.ac 7 | # - the suffix to put on the Unix source tarball 8 | # - the options to put on the 'make' command line for the docs 9 | 10 | autoconfver="$1" 11 | arcsuffix="$2" 12 | docver="$3" 13 | 14 | perl mkfiles.pl 15 | (cd doc && make -s ${docver:+"$docver"}) 16 | 17 | relver=`cat LATEST.VER` 18 | arcname="putty$arcsuffix" 19 | mkdir uxarc 20 | mkdir uxarc/$arcname 21 | find . -name uxarc -prune -o \ 22 | -name CVS -prune -o \ 23 | -name .svn -prune -o \ 24 | -name . -o \ 25 | -type d -exec mkdir uxarc/$arcname/{} \; 26 | find . -name uxarc -prune -o \ 27 | -name CVS -prune -o \ 28 | -name .cvsignore -prune -o \ 29 | -name .svn -prune -o \ 30 | -name configure.ac -prune -o \ 31 | -name '*.zip' -prune -o \ 32 | -name '*.tar.gz' -prune -o \ 33 | -type f -exec ln -s $PWD/{} uxarc/$arcname/{} \; 34 | sed "s/^AC_INIT(putty,.*/AC_INIT(putty, $autoconfver)/" configure.ac > uxarc/$arcname/configure.ac 35 | (cd uxarc/$arcname && sh mkauto.sh) 2>errors || { cat errors >&2; exit 1; } 36 | 37 | tar -C uxarc -chzof $arcname.tar.gz $arcname 38 | rm -rf uxarc 39 | -------------------------------------------------------------------------------- /nocproxy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Routines to refuse to do cryptographic interaction with proxies 3 | * in PuTTY. This is a stub implementation of the same interfaces 4 | * provided by cproxy.c, for use in PuTTYtel. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #define DEFINE_PLUG_METHOD_MACROS 12 | #include "putty.h" 13 | #include "network.h" 14 | #include "proxy.h" 15 | 16 | void proxy_socks5_offerencryptedauth(char * command, int * len) 17 | { 18 | /* For telnet, don't add any new encrypted authentication routines */ 19 | } 20 | 21 | int proxy_socks5_handlechap (Proxy_Socket p) 22 | { 23 | 24 | plug_closing(p->plug, "Proxy error: Trying to handle a SOCKS5 CHAP request" 25 | " in telnet-only build", 26 | PROXY_ERROR_GENERAL, 0); 27 | return 1; 28 | } 29 | 30 | int proxy_socks5_selectchap(Proxy_Socket p) 31 | { 32 | plug_closing(p->plug, "Proxy error: Trying to handle a SOCKS5 CHAP request" 33 | " in telnet-only build", 34 | PROXY_ERROR_GENERAL, 0); 35 | return 1; 36 | } 37 | -------------------------------------------------------------------------------- /nogss.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Stub definitions of the GSSAPI library list, for Unix pterm and 3 | * any other application that needs the symbols defined but has no 4 | * use for them. 5 | */ 6 | 7 | #include "putty.h" 8 | 9 | const int ngsslibs = 0; 10 | const char *const gsslibnames[1] = { "dummy" }; 11 | const struct keyvalwhere gsslibkeywords[1] = { { "dummy", 0, -1, -1 } }; 12 | -------------------------------------------------------------------------------- /noprint.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Stub implementation of the printing interface for PuTTY, for the 3 | * benefit of non-printing terminal applications. 4 | */ 5 | 6 | #include 7 | #include 8 | #include "putty.h" 9 | 10 | struct printer_job_tag { 11 | int dummy; 12 | }; 13 | 14 | printer_job *printer_start_job(char *printer) 15 | { 16 | return NULL; 17 | } 18 | 19 | void printer_job_data(printer_job *pj, void *data, int len) 20 | { 21 | } 22 | 23 | void printer_finish_job(printer_job *pj) 24 | { 25 | } 26 | 27 | printer_enum *printer_start_enum(int *nprinters_ptr) 28 | { 29 | *nprinters_ptr = 0; 30 | return NULL; 31 | } 32 | char *printer_get_name(printer_enum *pe, int i) 33 | { 34 | return NULL; 35 | } 36 | void printer_finish_enum(printer_enum *pe) 37 | { 38 | } 39 | -------------------------------------------------------------------------------- /noshare.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Stub implementation of SSH connection-sharing IPC, for any 3 | * platform which can't support it at all. 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "tree234.h" 11 | #include "putty.h" 12 | #include "ssh.h" 13 | #include "network.h" 14 | 15 | int platform_ssh_share(const char *name, Conf *conf, 16 | Plug downplug, Plug upplug, Socket *sock, 17 | char **logtext, char **ds_err, char **us_err, 18 | int can_upstream, int can_downstream) 19 | { 20 | return SHARE_NONE; 21 | } 22 | 23 | void platform_ssh_share_cleanup(const char *name) 24 | { 25 | } 26 | -------------------------------------------------------------------------------- /noterm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Stubs of functions in terminal.c, for use in programs that don't 3 | * have a terminal. 4 | */ 5 | 6 | #include "putty.h" 7 | #include "terminal.h" 8 | 9 | void term_nopaste(Terminal *term) 10 | { 11 | } 12 | -------------------------------------------------------------------------------- /notiming.c: -------------------------------------------------------------------------------- 1 | /* 2 | * notiming.c: stub version of timing API. 3 | * 4 | * Used in any tool which needs a subsystem linked against the 5 | * timing API but doesn't want to actually provide timing. For 6 | * example, key generation tools need the random number generator, 7 | * but they don't want the hassle of calling noise_regular() at 8 | * regular intervals - and they don't _need_ it either, since they 9 | * have their own rigorous and different means of noise collection. 10 | */ 11 | 12 | #include "putty.h" 13 | 14 | unsigned long schedule_timer(int ticks, timer_fn_t fn, void *ctx) 15 | { 16 | return 0; 17 | } 18 | 19 | void expire_timer_context(void *ctx) 20 | { 21 | } 22 | -------------------------------------------------------------------------------- /pinger.c: -------------------------------------------------------------------------------- 1 | /* 2 | * pinger.c: centralised module that deals with sending TS_PING 3 | * keepalives, to avoid replicating this code in multiple backends. 4 | */ 5 | 6 | #include "putty.h" 7 | 8 | struct pinger_tag { 9 | int interval; 10 | int pending; 11 | unsigned long next; 12 | Backend *back; 13 | void *backhandle; 14 | }; 15 | 16 | static void pinger_schedule(Pinger pinger); 17 | 18 | static void pinger_timer(void *ctx, unsigned long now) 19 | { 20 | Pinger pinger = (Pinger)ctx; 21 | 22 | if (pinger->pending && now == pinger->next) { 23 | pinger->back->special(pinger->backhandle, TS_PING); 24 | pinger->pending = FALSE; 25 | pinger_schedule(pinger); 26 | } 27 | } 28 | 29 | static void pinger_schedule(Pinger pinger) 30 | { 31 | unsigned long next; 32 | 33 | if (!pinger->interval) { 34 | pinger->pending = FALSE; /* cancel any pending ping */ 35 | return; 36 | } 37 | 38 | next = schedule_timer(pinger->interval * TICKSPERSEC, 39 | pinger_timer, pinger); 40 | if (!pinger->pending || next < pinger->next) { 41 | pinger->next = next; 42 | pinger->pending = TRUE; 43 | } 44 | } 45 | 46 | Pinger pinger_new(Conf *conf, Backend *back, void *backhandle) 47 | { 48 | Pinger pinger = snew(struct pinger_tag); 49 | 50 | pinger->interval = conf_get_int(conf, CONF_ping_interval); 51 | pinger->pending = FALSE; 52 | pinger->back = back; 53 | pinger->backhandle = backhandle; 54 | pinger_schedule(pinger); 55 | 56 | return pinger; 57 | } 58 | 59 | void pinger_reconfig(Pinger pinger, Conf *oldconf, Conf *newconf) 60 | { 61 | int newinterval = conf_get_int(newconf, CONF_ping_interval); 62 | if (conf_get_int(oldconf, CONF_ping_interval) != newinterval) { 63 | pinger->interval = newinterval; 64 | pinger_schedule(pinger); 65 | } 66 | } 67 | 68 | void pinger_free(Pinger pinger) 69 | { 70 | expire_timer_context(pinger); 71 | sfree(pinger); 72 | } 73 | -------------------------------------------------------------------------------- /pproxy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * pproxy.c: dummy implementation of platform_new_connection(), to 3 | * be supplanted on any platform which has its own local proxy 4 | * method. 5 | */ 6 | 7 | #include "putty.h" 8 | #include "network.h" 9 | #include "proxy.h" 10 | 11 | Socket platform_new_connection(SockAddr addr, char *hostname, 12 | int port, int privport, 13 | int oobinline, int nodelay, int keepalive, 14 | Plug plug, Conf *conf) 15 | { 16 | return NULL; 17 | } 18 | -------------------------------------------------------------------------------- /proxy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Network proxy abstraction in PuTTY 3 | * 4 | * A proxy layer, if necessary, wedges itself between the 5 | * network code and the higher level backend. 6 | * 7 | * Supported proxies: HTTP CONNECT, generic telnet, SOCKS 4 & 5 8 | */ 9 | 10 | #ifndef PUTTY_PROXY_H 11 | #define PUTTY_PROXY_H 12 | 13 | #define PROXY_ERROR_GENERAL 8000 14 | #define PROXY_ERROR_UNEXPECTED 8001 15 | 16 | typedef struct Socket_proxy_tag * Proxy_Socket; 17 | 18 | struct Socket_proxy_tag { 19 | const struct socket_function_table *fn; 20 | /* the above variable absolutely *must* be the first in this structure */ 21 | 22 | char * error; 23 | 24 | Socket sub_socket; 25 | Plug plug; 26 | SockAddr remote_addr; 27 | int remote_port; 28 | 29 | bufchain pending_output_data; 30 | bufchain pending_oob_output_data; 31 | int pending_flush; 32 | bufchain pending_input_data; 33 | int pending_eof; 34 | 35 | #define PROXY_STATE_NEW -1 36 | #define PROXY_STATE_ACTIVE 0 37 | 38 | int state; /* proxy states greater than 0 are implementation 39 | * dependent, but represent various stages/states 40 | * of the initialization/setup/negotiation with the 41 | * proxy server. 42 | */ 43 | int freeze; /* should we freeze the underlying socket when 44 | * we are done with the proxy negotiation? this 45 | * simply caches the value of sk_set_frozen calls. 46 | */ 47 | 48 | #define PROXY_CHANGE_NEW -1 49 | #define PROXY_CHANGE_CLOSING 0 50 | #define PROXY_CHANGE_SENT 1 51 | #define PROXY_CHANGE_RECEIVE 2 52 | #define PROXY_CHANGE_ACCEPTING 3 53 | 54 | /* something has changed (a call from the sub socket 55 | * layer into our Proxy Plug layer, or we were just 56 | * created, etc), so the proxy layer needs to handle 57 | * this change (the type of which is the second argument) 58 | * and further the proxy negotiation process. 59 | */ 60 | 61 | int (*negotiate) (Proxy_Socket /* this */, int /* change type */); 62 | 63 | /* current arguments of plug handlers 64 | * (for use by proxy's negotiate function) 65 | */ 66 | 67 | /* closing */ 68 | const char *closing_error_msg; 69 | int closing_error_code; 70 | int closing_calling_back; 71 | 72 | /* receive */ 73 | int receive_urgent; 74 | char *receive_data; 75 | int receive_len; 76 | 77 | /* sent */ 78 | int sent_bufsize; 79 | 80 | /* accepting */ 81 | accept_fn_t accepting_constructor; 82 | accept_ctx_t accepting_ctx; 83 | 84 | /* configuration, used to look up proxy settings */ 85 | Conf *conf; 86 | 87 | /* CHAP transient data */ 88 | int chap_num_attributes; 89 | int chap_num_attributes_processed; 90 | int chap_current_attribute; 91 | int chap_current_datalen; 92 | }; 93 | 94 | typedef struct Plug_proxy_tag * Proxy_Plug; 95 | 96 | struct Plug_proxy_tag { 97 | const struct plug_function_table *fn; 98 | /* the above variable absolutely *must* be the first in this structure */ 99 | 100 | Proxy_Socket proxy_socket; 101 | 102 | }; 103 | 104 | extern void proxy_activate (Proxy_Socket); 105 | 106 | extern int proxy_http_negotiate (Proxy_Socket, int); 107 | extern int proxy_telnet_negotiate (Proxy_Socket, int); 108 | extern int proxy_socks4_negotiate (Proxy_Socket, int); 109 | extern int proxy_socks5_negotiate (Proxy_Socket, int); 110 | 111 | /* 112 | * This may be reused by local-command proxies on individual 113 | * platforms. 114 | */ 115 | char *format_telnet_command(SockAddr addr, int port, Conf *conf); 116 | 117 | /* 118 | * These are implemented in cproxy.c or nocproxy.c, depending on 119 | * whether encrypted proxy authentication is available. 120 | */ 121 | extern void proxy_socks5_offerencryptedauth(char *command, int *len); 122 | extern int proxy_socks5_handlechap (Proxy_Socket p); 123 | extern int proxy_socks5_selectchap(Proxy_Socket p); 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /puttymem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PuTTY memory-handling header. 3 | */ 4 | 5 | #ifndef PUTTY_PUTTYMEM_H 6 | #define PUTTY_PUTTYMEM_H 7 | 8 | #include /* for size_t */ 9 | #include /* for memcpy() */ 10 | 11 | 12 | /* #define MALLOC_LOG do this if you suspect putty of leaking memory */ 13 | #ifdef MALLOC_LOG 14 | #define smalloc(z) (mlog(__FILE__,__LINE__), safemalloc(z,1)) 15 | #define snmalloc(z,s) (mlog(__FILE__,__LINE__), safemalloc(z,s)) 16 | #define srealloc(y,z) (mlog(__FILE__,__LINE__), saferealloc(y,z,1)) 17 | #define snrealloc(y,z,s) (mlog(__FILE__,__LINE__), saferealloc(y,z,s)) 18 | #define sfree(z) (mlog(__FILE__,__LINE__), safefree(z)) 19 | void mlog(char *, int); 20 | #else 21 | #define smalloc(z) safemalloc(z,1) 22 | #define snmalloc safemalloc 23 | #define srealloc(y,z) saferealloc(y,z,1) 24 | #define snrealloc saferealloc 25 | #define sfree safefree 26 | #endif 27 | 28 | void *safemalloc(size_t, size_t); 29 | void *saferealloc(void *, size_t, size_t); 30 | void safefree(void *); 31 | 32 | /* 33 | * Direct use of smalloc within the code should be avoided where 34 | * possible, in favour of these type-casting macros which ensure 35 | * you don't mistakenly allocate enough space for one sort of 36 | * structure and assign it to a different sort of pointer. 37 | * 38 | * The nasty trick in sresize with sizeof arranges for the compiler, 39 | * in passing, to type-check the expression ((type *)0 == (ptr)), i.e. 40 | * to type-check that the input pointer is a pointer to the correct 41 | * type. The construction sizeof(stuff) ? (b) : (b) looks like a 42 | * violation of the first principle of safe macros, but in fact it's 43 | * OK - although it _expands_ the macro parameter more than once, it 44 | * only _evaluates_ it once, so it's still side-effect safe. 45 | */ 46 | #define snew(type) ((type *)snmalloc(1, sizeof(type))) 47 | #define snewn(n, type) ((type *)snmalloc((n), sizeof(type))) 48 | #define sresize(ptr, n, type) \ 49 | ((type *)snrealloc(sizeof((type *)0 == (ptr)) ? (ptr) : (ptr), \ 50 | (n), sizeof(type))) 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /puttyps.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Find the platform-specific header for this platform. 3 | */ 4 | 5 | #ifndef PUTTY_PUTTYPS_H 6 | #define PUTTY_PUTTYPS_H 7 | 8 | #ifdef _WINDOWS 9 | 10 | #include "winstuff.h" 11 | 12 | #elif defined(MACOSX) 13 | 14 | #include "osx.h" 15 | 16 | #else 17 | 18 | #include "unix.h" 19 | 20 | #endif 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Developer Studio generated include file. 3 | // Used by win_res.rc 4 | // 5 | 6 | // Next default values for new objects 7 | // 8 | #ifdef APSTUDIO_INVOKED 9 | #ifndef APSTUDIO_READONLY_SYMBOLS 10 | #define _APS_NEXT_RESOURCE_VALUE 101 11 | #define _APS_NEXT_COMMAND_VALUE 40001 12 | #define _APS_NEXT_CONTROL_VALUE 1000 13 | #define _APS_NEXT_SYMED_VALUE 101 14 | #endif 15 | #endif 16 | -------------------------------------------------------------------------------- /sign.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Generate GPG signatures on a PuTTY release/snapshot directory as 4 | # delivered by Buildscr. 5 | 6 | # Usage: sh sign.sh 7 | # e.g. sh sign.sh putty Snapshots (probably in the build.out directory) 8 | # or sh sign.sh 0.60 Releases 9 | 10 | set -e 11 | 12 | sign() { 13 | # Check for the prior existence of the signature, so we can 14 | # re-run this script if it encounters an error part way 15 | # through. 16 | echo "----- Signing $2 with '$keyname'" 17 | test -f "$3" || \ 18 | gpg --load-extension=idea "$1" -u "$keyname" -o "$3" "$2" 19 | } 20 | 21 | cd "$1" 22 | for t in DSA RSA; do 23 | keyname="$2 ($t)" 24 | echo "===== Signing with '$keyname'" 25 | for i in putty*src.zip putty*.tar.gz x86/*.exe x86/*.zip; do 26 | sign --detach-sign "$i" "$i.$t" 27 | done 28 | for i in md5sums sha1sums sha256sums sha512sums; do 29 | sign --clearsign $i ${i}.$t 30 | done 31 | done 32 | -------------------------------------------------------------------------------- /ssharcf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Arcfour (RC4) implementation for PuTTY. 3 | * 4 | * Coded from Schneier. 5 | */ 6 | 7 | #include 8 | #include "ssh.h" 9 | 10 | typedef struct { 11 | unsigned char i, j, s[256]; 12 | } ArcfourContext; 13 | 14 | static void arcfour_block(void *handle, unsigned char *blk, int len) 15 | { 16 | ArcfourContext *ctx = (ArcfourContext *)handle; 17 | unsigned k; 18 | unsigned char tmp, i, j, *s; 19 | 20 | s = ctx->s; 21 | i = ctx->i; j = ctx->j; 22 | for (k = 0; (int)k < len; k++) { 23 | i = (i + 1) & 0xff; 24 | j = (j + s[i]) & 0xff; 25 | tmp = s[i]; s[i] = s[j]; s[j] = tmp; 26 | blk[k] ^= s[(s[i]+s[j]) & 0xff]; 27 | } 28 | ctx->i = i; ctx->j = j; 29 | } 30 | 31 | static void arcfour_setkey(ArcfourContext *ctx, unsigned char const *key, 32 | unsigned keybytes) 33 | { 34 | unsigned char tmp, k[256], *s; 35 | unsigned i, j; 36 | 37 | s = ctx->s; 38 | assert(keybytes <= 256); 39 | ctx->i = ctx->j = 0; 40 | for (i = 0; i < 256; i++) { 41 | s[i] = i; 42 | k[i] = key[i % keybytes]; 43 | } 44 | j = 0; 45 | for (i = 0; i < 256; i++) { 46 | j = (j + s[i] + k[i]) & 0xff; 47 | tmp = s[i]; s[i] = s[j]; s[j] = tmp; 48 | } 49 | } 50 | 51 | /* -- Interface with PuTTY -- */ 52 | 53 | /* 54 | * We don't implement Arcfour in SSH-1 because it's utterly insecure in 55 | * several ways. See CERT Vulnerability Notes VU#25309, VU#665372, 56 | * and VU#565052. 57 | * 58 | * We don't implement the "arcfour" algorithm in SSH-2 because it doesn't 59 | * stir the cipher state before emitting keystream, and hence is likely 60 | * to leak data about the key. 61 | */ 62 | 63 | static void *arcfour_make_context(void) 64 | { 65 | return snew(ArcfourContext); 66 | } 67 | 68 | static void arcfour_free_context(void *handle) 69 | { 70 | sfree(handle); 71 | } 72 | 73 | static void arcfour_stir(ArcfourContext *ctx) 74 | { 75 | unsigned char *junk = snewn(1536, unsigned char); 76 | memset(junk, 0, 1536); 77 | arcfour_block(ctx, junk, 1536); 78 | smemclr(junk, 1536); 79 | sfree(junk); 80 | } 81 | 82 | static void arcfour128_key(void *handle, unsigned char *key) 83 | { 84 | ArcfourContext *ctx = (ArcfourContext *)handle; 85 | arcfour_setkey(ctx, key, 16); 86 | arcfour_stir(ctx); 87 | } 88 | 89 | static void arcfour256_key(void *handle, unsigned char *key) 90 | { 91 | ArcfourContext *ctx = (ArcfourContext *)handle; 92 | arcfour_setkey(ctx, key, 32); 93 | arcfour_stir(ctx); 94 | } 95 | 96 | static void arcfour_iv(void *handle, unsigned char *key) 97 | { 98 | 99 | } 100 | 101 | const struct ssh2_cipher ssh_arcfour128_ssh2 = { 102 | arcfour_make_context, arcfour_free_context, arcfour_iv, arcfour128_key, 103 | arcfour_block, arcfour_block, 104 | "arcfour128", 105 | 1, 128, 0, "Arcfour-128" 106 | }; 107 | 108 | const struct ssh2_cipher ssh_arcfour256_ssh2 = { 109 | arcfour_make_context, arcfour_free_context, arcfour_iv, arcfour256_key, 110 | arcfour_block, arcfour_block, 111 | "arcfour256", 112 | 1, 256, 0, "Arcfour-256" 113 | }; 114 | 115 | static const struct ssh2_cipher *const arcfour_list[] = { 116 | &ssh_arcfour256_ssh2, 117 | &ssh_arcfour128_ssh2, 118 | }; 119 | 120 | const struct ssh2_ciphers ssh2_arcfour = { 121 | sizeof(arcfour_list) / sizeof(*arcfour_list), 122 | arcfour_list 123 | }; 124 | -------------------------------------------------------------------------------- /sshgssc.h: -------------------------------------------------------------------------------- 1 | #ifndef PUTTY_SSHGSSC_H 2 | #define PUTTY_SSHGSSC_H 3 | #include "putty.h" 4 | #ifndef NO_GSSAPI 5 | 6 | #include "pgssapi.h" 7 | #include "sshgss.h" 8 | 9 | typedef struct gssapi_ssh_gss_ctx { 10 | OM_uint32 maj_stat; 11 | OM_uint32 min_stat; 12 | gss_ctx_id_t ctx; 13 | } gssapi_ssh_gss_ctx; 14 | 15 | void ssh_gssapi_bind_fns(struct ssh_gss_library *lib); 16 | 17 | #else 18 | 19 | int ssh_gssapi_init(void); 20 | 21 | #endif /*NO_GSSAPI*/ 22 | 23 | #endif /*PUTTY_SSHGSSC_H*/ 24 | -------------------------------------------------------------------------------- /sshnogss.c: -------------------------------------------------------------------------------- 1 | #include "putty.h" 2 | #ifndef NO_GSSAPI 3 | 4 | /* For platforms not supporting GSSAPI */ 5 | 6 | struct ssh_gss_liblist *ssh_gss_setup(Conf *conf) 7 | { 8 | struct ssh_gss_liblist *list = snew(struct ssh_gss_liblist *); 9 | list->libraries = NULL; 10 | list->nlibraries = 0; 11 | return list; 12 | } 13 | 14 | void ssh_gss_cleanup(struct ssh_gss_liblist *list) 15 | { 16 | sfree(list); 17 | } 18 | 19 | #endif /* NO_GSSAPI */ 20 | -------------------------------------------------------------------------------- /sshrsag.c: -------------------------------------------------------------------------------- 1 | /* 2 | * RSA key generation. 3 | */ 4 | 5 | #include 6 | 7 | #include "ssh.h" 8 | 9 | #define RSA_EXPONENT 37 /* we like this prime */ 10 | 11 | int rsa_generate(struct RSAKey *key, int bits, progfn_t pfn, 12 | void *pfnparam) 13 | { 14 | Bignum pm1, qm1, phi_n; 15 | unsigned pfirst, qfirst; 16 | 17 | /* 18 | * Set up the phase limits for the progress report. We do this 19 | * by passing minus the phase number. 20 | * 21 | * For prime generation: our initial filter finds things 22 | * coprime to everything below 2^16. Computing the product of 23 | * (p-1)/p for all prime p below 2^16 gives about 20.33; so 24 | * among B-bit integers, one in every 20.33 will get through 25 | * the initial filter to be a candidate prime. 26 | * 27 | * Meanwhile, we are searching for primes in the region of 2^B; 28 | * since pi(x) ~ x/log(x), when x is in the region of 2^B, the 29 | * prime density will be d/dx pi(x) ~ 1/log(B), i.e. about 30 | * 1/0.6931B. So the chance of any given candidate being prime 31 | * is 20.33/0.6931B, which is roughly 29.34 divided by B. 32 | * 33 | * So now we have this probability P, we're looking at an 34 | * exponential distribution with parameter P: we will manage in 35 | * one attempt with probability P, in two with probability 36 | * P(1-P), in three with probability P(1-P)^2, etc. The 37 | * probability that we have still not managed to find a prime 38 | * after N attempts is (1-P)^N. 39 | * 40 | * We therefore inform the progress indicator of the number B 41 | * (29.34/B), so that it knows how much to increment by each 42 | * time. We do this in 16-bit fixed point, so 29.34 becomes 43 | * 0x1D.57C4. 44 | */ 45 | pfn(pfnparam, PROGFN_PHASE_EXTENT, 1, 0x10000); 46 | pfn(pfnparam, PROGFN_EXP_PHASE, 1, -0x1D57C4 / (bits / 2)); 47 | pfn(pfnparam, PROGFN_PHASE_EXTENT, 2, 0x10000); 48 | pfn(pfnparam, PROGFN_EXP_PHASE, 2, -0x1D57C4 / (bits - bits / 2)); 49 | pfn(pfnparam, PROGFN_PHASE_EXTENT, 3, 0x4000); 50 | pfn(pfnparam, PROGFN_LIN_PHASE, 3, 5); 51 | pfn(pfnparam, PROGFN_READY, 0, 0); 52 | 53 | /* 54 | * We don't generate e; we just use a standard one always. 55 | */ 56 | key->exponent = bignum_from_long(RSA_EXPONENT); 57 | 58 | /* 59 | * Generate p and q: primes with combined length `bits', not 60 | * congruent to 1 modulo e. (Strictly speaking, we wanted (p-1) 61 | * and e to be coprime, and (q-1) and e to be coprime, but in 62 | * general that's slightly more fiddly to arrange. By choosing 63 | * a prime e, we can simplify the criterion.) 64 | */ 65 | invent_firstbits(&pfirst, &qfirst); 66 | key->p = primegen(bits / 2, RSA_EXPONENT, 1, NULL, 67 | 1, pfn, pfnparam, pfirst); 68 | key->q = primegen(bits - bits / 2, RSA_EXPONENT, 1, NULL, 69 | 2, pfn, pfnparam, qfirst); 70 | 71 | /* 72 | * Ensure p > q, by swapping them if not. 73 | */ 74 | if (bignum_cmp(key->p, key->q) < 0) { 75 | Bignum t = key->p; 76 | key->p = key->q; 77 | key->q = t; 78 | } 79 | 80 | /* 81 | * Now we have p, q and e. All we need to do now is work out 82 | * the other helpful quantities: n=pq, d=e^-1 mod (p-1)(q-1), 83 | * and (q^-1 mod p). 84 | */ 85 | pfn(pfnparam, PROGFN_PROGRESS, 3, 1); 86 | key->modulus = bigmul(key->p, key->q); 87 | pfn(pfnparam, PROGFN_PROGRESS, 3, 2); 88 | pm1 = copybn(key->p); 89 | decbn(pm1); 90 | qm1 = copybn(key->q); 91 | decbn(qm1); 92 | phi_n = bigmul(pm1, qm1); 93 | pfn(pfnparam, PROGFN_PROGRESS, 3, 3); 94 | freebn(pm1); 95 | freebn(qm1); 96 | key->private_exponent = modinv(key->exponent, phi_n); 97 | assert(key->private_exponent); 98 | pfn(pfnparam, PROGFN_PROGRESS, 3, 4); 99 | key->iqmp = modinv(key->q, key->p); 100 | assert(key->iqmp); 101 | pfn(pfnparam, PROGFN_PROGRESS, 3, 5); 102 | 103 | /* 104 | * Clean up temporary numbers. 105 | */ 106 | freebn(phi_n); 107 | 108 | return 1; 109 | } 110 | -------------------------------------------------------------------------------- /testdata/lattrs.txt: -------------------------------------------------------------------------------- 1 | Test of line attributes: 2 | 3 | #3Double-height top 4 | #4Double-height bottom 5 | #5Normal text (#5) 6 | #6Double-width only 7 | -------------------------------------------------------------------------------- /testdata/scocols.txt: -------------------------------------------------------------------------------- 1 | Test of (destructive) SCO colour rendering. 2 | SCO fg: [=0F0[=7F [=1F1[=7F [=2F2[=7F [=3F3[=7F [=4F4[=7F [=5F5[=7F [=6F6[=7F [=7F7[=7F [=8F8[=7F [=9F9[=7F [=10F10[=7F [=11F11[=7F [=12F12[=7F [=13F13[=7F [=14F14[=7F [=15F15[=7F 3 | SCO bg: [=0G0[=0G [=1G1[=0G [=2G2[=0G [=3G3[=0G [=4G4[=0G [=5G5[=0G [=6G6[=0G [=7G7[=0G [=8G8[=0G [=9G9[=0G [=10G10[=0G [=11G11[=0G [=12G12[=0G [=13G13[=0G [=14G14[=0G [=15G15[=0G 4 | -------------------------------------------------------------------------------- /testdata/utf8.txt: -------------------------------------------------------------------------------- 1 | Test of UTF-8 output in a terminal emulator 2 | ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ 3 | 4 | Some basic Unicode: 5 | ∮ E⋅da = Q, n → ∞, ∑ f(i) = ∏ g(i), ∀x∈ℝ: ⌈x⌉ = −⌊−x⌋, α ∧ ¬β = ¬(¬α ∨ β), 6 | ℕ ⊆ ℕ₀ ⊂ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ, ⊥ < a ≠ b ≡ c ≤ d ≪ ⊤ ⇒ (A ⇔ B), 7 | 8 | Combining characters: 9 | STARGΛ̊TE SG-1, a = v̇ = r̈, a⃑ ⊥ b⃑ 10 | [----------------------------|------------------------] 11 | ๏ แผ่นดินฮั่นเสื่อมโทรมแสนสังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่ 12 | สิบสองกษัตริย์ก่อนหน้าแลถัดไป สององค์ไซร้โง่เขลาเบาปัญญา 13 | 14 | Wide characters with difficult wrapping: 15 | Here we go then: コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ 16 | 17 | Arabic and bidirectional text: 18 | (من مجمع الزوائد ومنبع الفوائد للهيثمي ، ج 1 ، ص 74-84) 19 | عن جرير رضي الله عنه قال قال رسول الله صلى الله عليه 20 | وسلم: بني الاسلام على خمس شهادة ان لا اله الا الله واقام 21 | Mixed LTR and RTL text: جرير رضي back to LTR. 22 | 23 | East Asian Ambiguous characters: ¼½¾¼½¾¼½¾¼½¾¼½¾¼½¾¼½¾¼½¾¼½¾¼½¾ 24 | -------------------------------------------------------------------------------- /testdata/vt100.txt: -------------------------------------------------------------------------------- 1 | VT100 line drawing characters, actually using the VT100 escapes 2 | (B)0ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 3 | 4 | lqqqqqqqqqqpoopqrssrqqqqqqqqqqwqqqqqqqqqqpoopqrssrqqqqqqqqqqk 5 | x x x 6 | x ooh, swirly! x top right corner x 7 | x x x 8 | tqqqqqqqqqqpoopqrssrqqqqqqqqqqnqqqqqqqqqqpoopqrssrqqqqqqqqqqu 9 | x x x 10 | x stuff down here x is quite inane x 11 | x x x 12 | mqqqqqqqqqqpoopqrssrqqqqqqqqqqvqqqqqqqqqqpoopqrssrqqqqqqqqqqj 13 | -------------------------------------------------------------------------------- /time.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Portable implementation of ltime() for any ISO-C platform where 3 | * time_t behaves. (In practice, we've found that platforms such as 4 | * Windows and Mac have needed their own specialised implementations.) 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | struct tm ltime(void) 11 | { 12 | time_t t; 13 | time(&t); 14 | assert (t != ((time_t)-1)); 15 | return *localtime(&t); 16 | } 17 | -------------------------------------------------------------------------------- /unix/.gitignore: -------------------------------------------------------------------------------- 1 | config.* 2 | configure 3 | install-sh 4 | uxconfig.* 5 | .deps 6 | *.cache 7 | empty.h 8 | missing 9 | stamp-h1 10 | depcomp 11 | aclocal.m4 12 | ar-lib 13 | compile 14 | -------------------------------------------------------------------------------- /unix/configure: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | $(echo "$0" | sed '$s!configure$!../configure!') "$@" 4 | -------------------------------------------------------------------------------- /unix/gtkcols.h: -------------------------------------------------------------------------------- 1 | /* 2 | * gtkcols.h - header file for a columns-based widget container 3 | * capable of supporting the PuTTY portable dialog box layout 4 | * mechanism. 5 | */ 6 | 7 | #ifndef COLUMNS_H 8 | #define COLUMNS_H 9 | 10 | #include 11 | #include 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif /* __cplusplus */ 16 | 17 | #define TYPE_COLUMNS (columns_get_type()) 18 | #define COLUMNS(obj) (GTK_CHECK_CAST((obj), TYPE_COLUMNS, Columns)) 19 | #define COLUMNS_CLASS(klass) \ 20 | (GTK_CHECK_CLASS_CAST((klass), TYPE_COLUMNS, ColumnsClass)) 21 | #define IS_COLUMNS(obj) (GTK_CHECK_TYPE((obj), TYPE_COLUMNS)) 22 | #define IS_COLUMNS_CLASS(klass) (GTK_CHECK_CLASS_TYPE((klass), TYPE_COLUMNS)) 23 | 24 | typedef struct Columns_tag Columns; 25 | typedef struct ColumnsClass_tag ColumnsClass; 26 | typedef struct ColumnsChild_tag ColumnsChild; 27 | 28 | struct Columns_tag { 29 | GtkContainer container; 30 | /* private after here */ 31 | GList *children; /* this holds ColumnsChild structures */ 32 | GList *taborder; /* this just holds GtkWidgets */ 33 | gint spacing; 34 | }; 35 | 36 | struct ColumnsClass_tag { 37 | GtkContainerClass parent_class; 38 | }; 39 | 40 | struct ColumnsChild_tag { 41 | /* If `widget' is non-NULL, this entry represents an actual widget. */ 42 | GtkWidget *widget; 43 | gint colstart, colspan; 44 | gboolean force_left; /* for recalcitrant GtkLabels */ 45 | /* Otherwise, this entry represents a change in the column setup. */ 46 | gint ncols; 47 | gint *percentages; 48 | }; 49 | 50 | GtkType columns_get_type(void); 51 | GtkWidget *columns_new(gint spacing); 52 | void columns_set_cols(Columns *cols, gint ncols, const gint *percentages); 53 | void columns_add(Columns *cols, GtkWidget *child, 54 | gint colstart, gint colspan); 55 | void columns_taborder_last(Columns *cols, GtkWidget *child); 56 | void columns_force_left_align(Columns *cols, GtkWidget *child); 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif /* __cplusplus */ 61 | 62 | #endif /* COLUMNS_H */ 63 | -------------------------------------------------------------------------------- /unix/gtkfont.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Header file for gtkfont.c. Has to be separate from unix.h 3 | * because it depends on GTK data types, hence can't be included 4 | * from cross-platform code (which doesn't go near GTK). 5 | */ 6 | 7 | #ifndef PUTTY_GTKFONT_H 8 | #define PUTTY_GTKFONT_H 9 | 10 | /* 11 | * Exports from gtkfont.c. 12 | */ 13 | struct unifont_vtable; /* contents internal to gtkfont.c */ 14 | typedef struct unifont { 15 | const struct unifont_vtable *vt; 16 | /* 17 | * `Non-static data members' of the `class', accessible to 18 | * external code. 19 | */ 20 | 21 | /* 22 | * public_charset is the charset used when the user asks for 23 | * `Use font encoding'. 24 | */ 25 | int public_charset; 26 | 27 | /* 28 | * Font dimensions needed by clients. 29 | */ 30 | int width, height, ascent, descent; 31 | 32 | /* 33 | * Indicates whether this font is capable of handling all glyphs 34 | * (Pango fonts can do this because Pango automatically supplies 35 | * missing glyphs from other fonts), or whether it would like a 36 | * fallback font to cope with missing glyphs. 37 | */ 38 | int want_fallback; 39 | } unifont; 40 | 41 | unifont *unifont_create(GtkWidget *widget, const char *name, 42 | int wide, int bold, 43 | int shadowoffset, int shadowalways); 44 | void unifont_destroy(unifont *font); 45 | void unifont_draw_text(GdkDrawable *target, GdkGC *gc, unifont *font, 46 | int x, int y, const wchar_t *string, int len, 47 | int wide, int bold, int cellwidth); 48 | 49 | /* 50 | * This function behaves exactly like the low-level unifont_create, 51 | * except that as well as the requested font it also allocates (if 52 | * necessary) a fallback font for filling in replacement glyphs. 53 | * 54 | * Return value is usable with unifont_destroy and unifont_draw_text 55 | * as if it were an ordinary unifont. 56 | */ 57 | unifont *multifont_create(GtkWidget *widget, const char *name, 58 | int wide, int bold, 59 | int shadowoffset, int shadowalways); 60 | 61 | /* 62 | * Unified font selector dialog. I can't be bothered to do a 63 | * proper GTK subclassing today, so this will just be an ordinary 64 | * data structure with some useful members. 65 | * 66 | * (Of course, these aren't the only members; this structure is 67 | * contained within a bigger one which holds data visible only to 68 | * the implementation.) 69 | */ 70 | typedef struct unifontsel { 71 | void *user_data; /* settable by the user */ 72 | GtkWindow *window; 73 | GtkWidget *ok_button, *cancel_button; 74 | } unifontsel; 75 | 76 | unifontsel *unifontsel_new(const char *wintitle); 77 | void unifontsel_destroy(unifontsel *fontsel); 78 | void unifontsel_set_name(unifontsel *fontsel, const char *fontname); 79 | char *unifontsel_get_name(unifontsel *fontsel); 80 | 81 | #endif /* PUTTY_GTKFONT_H */ 82 | -------------------------------------------------------------------------------- /unix/urlhack_unix.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "urlhack.h" 6 | 7 | enum { max = 4000 }; 8 | void urlhack_launch_url(const char* app, const wchar_t *url) 9 | { 10 | char buf[max]; 11 | const char *browser = NULL; 12 | 13 | if (app) 14 | browser = app; 15 | if (NULL == browser || 0 == strlen(browser)) 16 | browser = "xdg-open"; 17 | 18 | strncat(buf, browser, max - 1); 19 | strcat(buf, " "); 20 | wcstombs(buf + strlen(buf), url, max - strlen(buf) - 2); 21 | if (!system(buf)) 22 | printf("couldn't run browser: %s", buf); 23 | } 24 | 25 | int urlhack_is_ctrl_pressed() 26 | { 27 | // TODO 28 | return 1; 29 | } 30 | 31 | 32 | void rtfm(const char *error) 33 | { 34 | // TODO 35 | } 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /unix/ux_x11.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ux_x11.c: fetch local auth data for X forwarding. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "putty.h" 12 | #include "ssh.h" 13 | #include "network.h" 14 | 15 | void platform_get_x11_auth(struct X11Display *disp, Conf *conf) 16 | { 17 | char *xauthfile; 18 | int needs_free; 19 | 20 | /* 21 | * Find the .Xauthority file. 22 | */ 23 | needs_free = FALSE; 24 | xauthfile = getenv("XAUTHORITY"); 25 | if (!xauthfile) { 26 | xauthfile = getenv("HOME"); 27 | if (xauthfile) { 28 | xauthfile = dupcat(xauthfile, "/.Xauthority", NULL); 29 | needs_free = TRUE; 30 | } 31 | } 32 | 33 | if (xauthfile) { 34 | x11_get_auth_from_authfile(disp, xauthfile); 35 | if (needs_free) 36 | sfree(xauthfile); 37 | } 38 | } 39 | 40 | const int platform_uses_x11_unix_by_default = TRUE; 41 | -------------------------------------------------------------------------------- /unix/uxcfg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * uxcfg.c - the Unix-specific parts of the PuTTY configuration 3 | * box. 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include "putty.h" 10 | #include "dialog.h" 11 | #include "storage.h" 12 | 13 | void unix_setup_config_box(struct controlbox *b, int midsession, int protocol) 14 | { 15 | struct controlset *s; 16 | union control *c; 17 | 18 | /* 19 | * The Conf structure contains two Unix-specific elements which 20 | * are not configured in here: stamp_utmp and login_shell. This 21 | * is because pterm does not put up a configuration box right at 22 | * the start, which is the only time when these elements would 23 | * be useful to configure. 24 | */ 25 | 26 | /* 27 | * On Unix, we don't have a drop-down list for the printer 28 | * control. 29 | */ 30 | s = ctrl_getset(b, "Terminal", "printing", "Remote-controlled printing"); 31 | assert(s->ncontrols == 1 && s->ctrls[0]->generic.type == CTRL_EDITBOX); 32 | s->ctrls[0]->editbox.has_list = 0; 33 | 34 | /* 35 | * Unix supports a local-command proxy. This also means we must 36 | * adjust the text on the `Telnet command' control. 37 | */ 38 | if (!midsession) { 39 | int i; 40 | s = ctrl_getset(b, "Connection/Proxy", "basics", NULL); 41 | for (i = 0; i < s->ncontrols; i++) { 42 | c = s->ctrls[i]; 43 | if (c->generic.type == CTRL_RADIO && 44 | c->generic.context.i == CONF_proxy_type) { 45 | assert(c->generic.handler == conf_radiobutton_handler); 46 | c->radio.nbuttons++; 47 | c->radio.buttons = 48 | sresize(c->radio.buttons, c->radio.nbuttons, char *); 49 | c->radio.buttons[c->radio.nbuttons-1] = 50 | dupstr("Local"); 51 | c->radio.buttondata = 52 | sresize(c->radio.buttondata, c->radio.nbuttons, intorptr); 53 | c->radio.buttondata[c->radio.nbuttons-1] = I(PROXY_CMD); 54 | break; 55 | } 56 | } 57 | 58 | for (i = 0; i < s->ncontrols; i++) { 59 | c = s->ctrls[i]; 60 | if (c->generic.type == CTRL_EDITBOX && 61 | c->generic.context.i == CONF_proxy_telnet_command) { 62 | assert(c->generic.handler == conf_editbox_handler); 63 | sfree(c->generic.label); 64 | c->generic.label = dupstr("Telnet command, or local" 65 | " proxy command"); 66 | break; 67 | } 68 | } 69 | } 70 | 71 | /* 72 | * Serial back end is available on Unix. However, we have to 73 | * mask out a couple of the configuration options: mark and 74 | * space parity are not conveniently supported, and neither is 75 | * DSR/DTR flow control. 76 | */ 77 | if (!midsession || (protocol == PROT_SERIAL)) 78 | ser_setup_config_box(b, midsession, 0x07, 0x07); 79 | } 80 | -------------------------------------------------------------------------------- /unix/uxgen.c: -------------------------------------------------------------------------------- 1 | /* 2 | * uxgen.c: Unix implementation of get_heavy_noise() from cmdgen.c. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "putty.h" 10 | 11 | char *get_random_data(int len) 12 | { 13 | char *buf = snewn(len, char); 14 | int fd; 15 | int ngot, ret; 16 | 17 | fd = open("/dev/random", O_RDONLY); 18 | if (fd < 0) { 19 | sfree(buf); 20 | perror("puttygen: unable to open /dev/random"); 21 | return NULL; 22 | } 23 | 24 | ngot = 0; 25 | while (ngot < len) { 26 | ret = read(fd, buf+ngot, len-ngot); 27 | if (ret < 0) { 28 | close(fd); 29 | sfree(buf); 30 | perror("puttygen: unable to read /dev/random"); 31 | return NULL; 32 | } 33 | ngot += ret; 34 | } 35 | 36 | close(fd); 37 | 38 | return buf; 39 | } 40 | -------------------------------------------------------------------------------- /unix/uxnoise.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Noise generation for PuTTY's cryptographic random number 3 | * generator. 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "putty.h" 16 | #include "ssh.h" 17 | #include "storage.h" 18 | 19 | static int read_dev_urandom(char *buf, int len) 20 | { 21 | int fd; 22 | int ngot, ret; 23 | 24 | fd = open("/dev/urandom", O_RDONLY); 25 | if (fd < 0) 26 | return 0; 27 | 28 | ngot = 0; 29 | while (ngot < len) { 30 | ret = read(fd, buf+ngot, len-ngot); 31 | if (ret < 0) { 32 | close(fd); 33 | return 0; 34 | } 35 | ngot += ret; 36 | } 37 | 38 | close(fd); 39 | 40 | return 1; 41 | } 42 | 43 | /* 44 | * This function is called once, at PuTTY startup. It will do some 45 | * slightly silly things such as fetching an entire process listing 46 | * and scanning /tmp, load the saved random seed from disk, and 47 | * also read 32 bytes out of /dev/urandom. 48 | */ 49 | 50 | void noise_get_heavy(void (*func) (void *, int)) 51 | { 52 | char buf[512]; 53 | FILE *fp; 54 | int ret; 55 | int got_dev_urandom = 0; 56 | 57 | if (read_dev_urandom(buf, 32)) { 58 | got_dev_urandom = 1; 59 | func(buf, 32); 60 | } 61 | 62 | fp = popen("ps -axu 2>/dev/null", "r"); 63 | if (fp) { 64 | while ( (ret = fread(buf, 1, sizeof(buf), fp)) > 0) 65 | func(buf, ret); 66 | pclose(fp); 67 | } else if (!got_dev_urandom) { 68 | fprintf(stderr, "popen: %s\n" 69 | "Unable to access fallback entropy source\n", strerror(errno)); 70 | exit(1); 71 | } 72 | 73 | fp = popen("ls -al /tmp 2>/dev/null", "r"); 74 | if (fp) { 75 | while ( (ret = fread(buf, 1, sizeof(buf), fp)) > 0) 76 | func(buf, ret); 77 | pclose(fp); 78 | } else if (!got_dev_urandom) { 79 | fprintf(stderr, "popen: %s\n" 80 | "Unable to access fallback entropy source\n", strerror(errno)); 81 | exit(1); 82 | } 83 | 84 | read_random_seed(func); 85 | random_save_seed(); 86 | } 87 | 88 | void random_save_seed(void) 89 | { 90 | int len; 91 | void *data; 92 | 93 | if (random_active) { 94 | random_get_savedata(&data, &len); 95 | write_random_seed(data, len); 96 | sfree(data); 97 | } 98 | } 99 | 100 | /* 101 | * This function is called every time the random pool needs 102 | * stirring, and will acquire the system time. 103 | */ 104 | void noise_get_light(void (*func) (void *, int)) 105 | { 106 | struct timeval tv; 107 | gettimeofday(&tv, NULL); 108 | func(&tv, sizeof(tv)); 109 | } 110 | 111 | /* 112 | * This function is called on a timer, and grabs as much changeable 113 | * system data as it can quickly get its hands on. 114 | */ 115 | void noise_regular(void) 116 | { 117 | int fd; 118 | int ret; 119 | char buf[512]; 120 | struct rusage rusage; 121 | 122 | if ((fd = open("/proc/meminfo", O_RDONLY)) >= 0) { 123 | while ( (ret = read(fd, buf, sizeof(buf))) > 0) 124 | random_add_noise(buf, ret); 125 | close(fd); 126 | } 127 | if ((fd = open("/proc/stat", O_RDONLY)) >= 0) { 128 | while ( (ret = read(fd, buf, sizeof(buf))) > 0) 129 | random_add_noise(buf, ret); 130 | close(fd); 131 | } 132 | getrusage(RUSAGE_SELF, &rusage); 133 | random_add_noise(&rusage, sizeof(rusage)); 134 | } 135 | 136 | /* 137 | * This function is called on every keypress or mouse move, and 138 | * will add the current time to the noise pool. It gets the scan 139 | * code or mouse position passed in, and adds that too. 140 | */ 141 | void noise_ultralight(unsigned long data) 142 | { 143 | struct timeval tv; 144 | gettimeofday(&tv, NULL); 145 | random_add_noise(&tv, sizeof(tv)); 146 | random_add_noise(&data, sizeof(data)); 147 | } 148 | -------------------------------------------------------------------------------- /unix/uxpeer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Unix: wrapper for getsockopt(SO_PEERCRED), conditionalised on 3 | * appropriate autoconfery. 4 | */ 5 | 6 | #ifdef HAVE_CONFIG_H 7 | # include "uxconfig.h" /* leading space prevents mkfiles.pl trying to follow */ 8 | #endif 9 | 10 | #ifdef HAVE_SO_PEERCRED 11 | #define _GNU_SOURCE 12 | #include 13 | #endif 14 | 15 | #include 16 | 17 | #include "putty.h" 18 | 19 | int so_peercred(int fd, int *pid, int *uid, int *gid) 20 | { 21 | #ifdef HAVE_SO_PEERCRED 22 | struct ucred cr; 23 | socklen_t crlen = sizeof(cr); 24 | if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &crlen) == 0) { 25 | *pid = cr.pid; 26 | *uid = cr.uid; 27 | *gid = cr.gid; 28 | return TRUE; 29 | } 30 | #endif 31 | return FALSE; 32 | } 33 | -------------------------------------------------------------------------------- /unix/uxprint.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Printing interface for PuTTY. 3 | */ 4 | 5 | #include 6 | #include 7 | #include "putty.h" 8 | 9 | struct printer_job_tag { 10 | FILE *fp; 11 | }; 12 | 13 | printer_job *printer_start_job(char *printer) 14 | { 15 | printer_job *ret = snew(printer_job); 16 | /* 17 | * On Unix, we treat the printer string as the name of a 18 | * command to pipe to - typically lpr, of course. 19 | */ 20 | ret->fp = popen(printer, "w"); 21 | if (!ret->fp) { 22 | sfree(ret); 23 | ret = NULL; 24 | } 25 | return ret; 26 | } 27 | 28 | void printer_job_data(printer_job *pj, void *data, int len) 29 | { 30 | if (!pj) 31 | return; 32 | 33 | if (fwrite(data, 1, len, pj->fp) < len) 34 | /* ignore */; 35 | } 36 | 37 | void printer_finish_job(printer_job *pj) 38 | { 39 | if (!pj) 40 | return; 41 | 42 | pclose(pj->fp); 43 | sfree(pj); 44 | } 45 | 46 | /* 47 | * There's no sensible way to enumerate printers under Unix, since 48 | * practically any valid Unix command is a valid printer :-) So 49 | * these are useless stub functions, and uxcfg.c will disable the 50 | * drop-down list in the printer configurer. 51 | */ 52 | printer_enum *printer_start_enum(int *nprinters_ptr) { 53 | *nprinters_ptr = 0; 54 | return NULL; 55 | } 56 | char *printer_get_name(printer_enum *pe, int i) { return NULL; 57 | } 58 | void printer_finish_enum(printer_enum *pe) { } 59 | -------------------------------------------------------------------------------- /unix/uxpterm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * pterm main program. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #include "putty.h" 9 | 10 | const char *const appname = "pterm"; 11 | const int use_event_log = 0; /* pterm doesn't need it */ 12 | const int new_session = 0, saved_sessions = 0; /* or these */ 13 | const int use_pty_argv = TRUE; 14 | 15 | Backend *select_backend(Conf *conf) 16 | { 17 | return &pty_backend; 18 | } 19 | 20 | int cfgbox(Conf *conf) 21 | { 22 | /* 23 | * This is a no-op in pterm, except that we'll ensure the 24 | * protocol is set to -1 to inhibit the useless Connection 25 | * panel in the config box. 26 | */ 27 | conf_set_int(conf, CONF_protocol, -1); 28 | return 1; 29 | } 30 | 31 | void cleanup_exit(int code) 32 | { 33 | exit(code); 34 | } 35 | 36 | int process_nonoption_arg(char *arg, Conf *conf, int *allow_launch) 37 | { 38 | return 0; /* pterm doesn't have any. */ 39 | } 40 | 41 | char *make_default_wintitle(char *hostname) 42 | { 43 | return dupstr("pterm"); 44 | } 45 | 46 | int main(int argc, char **argv) 47 | { 48 | extern int pt_main(int argc, char **argv); 49 | extern void pty_pre_init(void); /* declared in pty.c */ 50 | int ret; 51 | 52 | cmdline_tooltype = TOOLTYPE_NONNETWORK; 53 | default_protocol = -1; 54 | 55 | pty_pre_init(); 56 | 57 | ret = pt_main(argc, argv); 58 | cleanup_exit(ret); 59 | return ret; /* not reached, but placates optimisers */ 60 | } 61 | -------------------------------------------------------------------------------- /unix/uxputty.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Unix PuTTY main program. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "putty.h" 13 | #include "storage.h" 14 | 15 | /* 16 | * Stubs to avoid uxpty.c needing to be linked in. 17 | */ 18 | const int use_pty_argv = FALSE; 19 | char **pty_argv; /* never used */ 20 | 21 | /* 22 | * Clean up and exit. 23 | */ 24 | void cleanup_exit(int code) 25 | { 26 | /* 27 | * Clean up. 28 | */ 29 | sk_cleanup(); 30 | random_save_seed(); 31 | exit(code); 32 | } 33 | 34 | Backend *select_backend(Conf *conf) 35 | { 36 | Backend *back = backend_from_proto(conf_get_int(conf, CONF_protocol)); 37 | assert(back != NULL); 38 | return back; 39 | } 40 | 41 | int cfgbox(Conf *conf) 42 | { 43 | char *title = dupcat(appname, " Configuration", NULL); 44 | int ret = do_config_box(title, conf, 0, 0); 45 | sfree(title); 46 | return ret; 47 | } 48 | 49 | static int got_host = 0; 50 | 51 | const int use_event_log = 1, new_session = 1, saved_sessions = 1; 52 | 53 | int process_nonoption_arg(char *arg, Conf *conf, int *allow_launch) 54 | { 55 | char *p, *q = arg; 56 | 57 | if (got_host) { 58 | /* 59 | * If we already have a host name, treat this argument as a 60 | * port number. NB we have to treat this as a saved -P 61 | * argument, so that it will be deferred until it's a good 62 | * moment to run it. 63 | */ 64 | int ret = cmdline_process_param("-P", arg, 1, conf); 65 | assert(ret == 2); 66 | } else if (!strncmp(q, "telnet:", 7)) { 67 | /* 68 | * If the hostname starts with "telnet:", 69 | * set the protocol to Telnet and process 70 | * the string as a Telnet URL. 71 | */ 72 | char c; 73 | 74 | q += 7; 75 | if (q[0] == '/' && q[1] == '/') 76 | q += 2; 77 | conf_set_int(conf, CONF_protocol, PROT_TELNET); 78 | p = q; 79 | p += host_strcspn(p, ":/"); 80 | c = *p; 81 | if (*p) 82 | *p++ = '\0'; 83 | if (c == ':') 84 | conf_set_int(conf, CONF_port, atoi(p)); 85 | else 86 | conf_set_int(conf, CONF_port, -1); 87 | conf_set_str(conf, CONF_host, q); 88 | got_host = 1; 89 | } else { 90 | /* 91 | * Otherwise, treat this argument as a host name. 92 | */ 93 | p = arg; 94 | while (*p && !isspace((unsigned char)*p)) 95 | p++; 96 | if (*p) 97 | *p++ = '\0'; 98 | conf_set_str(conf, CONF_host, q); 99 | got_host = 1; 100 | } 101 | if (got_host) 102 | *allow_launch = TRUE; 103 | return 1; 104 | } 105 | 106 | char *make_default_wintitle(char *hostname) 107 | { 108 | return dupcat(hostname, " - ", appname, NULL); 109 | } 110 | 111 | /* 112 | * X11-forwarding-related things suitable for Gtk app. 113 | */ 114 | 115 | char *platform_get_x_display(void) { 116 | const char *display; 117 | /* Try to take account of --display and what have you. */ 118 | if (!(display = gdk_get_display())) 119 | /* fall back to traditional method */ 120 | display = getenv("DISPLAY"); 121 | return dupstr(display); 122 | } 123 | 124 | const int share_can_be_downstream = TRUE; 125 | const int share_can_be_upstream = TRUE; 126 | 127 | int main(int argc, char **argv) 128 | { 129 | extern int pt_main(int argc, char **argv); 130 | int ret; 131 | 132 | sk_init(); 133 | flags = FLAG_VERBOSE | FLAG_INTERACTIVE; 134 | default_protocol = be_default_protocol; 135 | /* Find the appropriate default port. */ 136 | { 137 | Backend *b = backend_from_proto(default_protocol); 138 | default_port = 0; /* illegal */ 139 | if (b) 140 | default_port = b->default_port; 141 | } 142 | ret = pt_main(argc, argv); 143 | cleanup_exit(ret); 144 | return ret; /* not reached, but placates optimisers */ 145 | } 146 | -------------------------------------------------------------------------------- /unix/uxsel.c: -------------------------------------------------------------------------------- 1 | /* 2 | * uxsel.c 3 | * 4 | * This module is a sort of all-purpose interchange for file 5 | * descriptors. At one end it talks to uxnet.c and pty.c and 6 | * anything else which might have one or more fds that need 7 | * select()-type things doing to them during an extended program 8 | * run; at the other end it talks to pterm.c or uxplink.c or 9 | * anything else which might have its own means of actually doing 10 | * those select()-type things. 11 | */ 12 | 13 | #include 14 | 15 | #include "putty.h" 16 | #include "tree234.h" 17 | 18 | struct fd { 19 | int fd; 20 | int rwx; /* 4=except 2=write 1=read */ 21 | uxsel_callback_fn callback; 22 | int id; /* for uxsel_input_remove */ 23 | }; 24 | 25 | static tree234 *fds; 26 | 27 | static int uxsel_fd_cmp(void *av, void *bv) 28 | { 29 | struct fd *a = (struct fd *)av; 30 | struct fd *b = (struct fd *)bv; 31 | if (a->fd < b->fd) 32 | return -1; 33 | if (a->fd > b->fd) 34 | return +1; 35 | return 0; 36 | } 37 | static int uxsel_fd_findcmp(void *av, void *bv) 38 | { 39 | int *a = (int *)av; 40 | struct fd *b = (struct fd *)bv; 41 | if (*a < b->fd) 42 | return -1; 43 | if (*a > b->fd) 44 | return +1; 45 | return 0; 46 | } 47 | 48 | void uxsel_init(void) 49 | { 50 | fds = newtree234(uxsel_fd_cmp); 51 | } 52 | 53 | /* 54 | * Here is the interface to fd-supplying modules. They supply an 55 | * fd, a set of read/write/execute states, and a callback function 56 | * for when the fd satisfies one of those states. Repeated calls to 57 | * uxsel_set on the same fd are perfectly legal and serve to change 58 | * the rwx state (typically you only want to select an fd for 59 | * writing when you actually have pending data you want to write to 60 | * it!). 61 | */ 62 | 63 | void uxsel_set(int fd, int rwx, uxsel_callback_fn callback) 64 | { 65 | struct fd *newfd; 66 | 67 | uxsel_del(fd); 68 | 69 | if (rwx) { 70 | newfd = snew(struct fd); 71 | newfd->fd = fd; 72 | newfd->rwx = rwx; 73 | newfd->callback = callback; 74 | newfd->id = uxsel_input_add(fd, rwx); 75 | add234(fds, newfd); 76 | } 77 | } 78 | 79 | void uxsel_del(int fd) 80 | { 81 | struct fd *oldfd = find234(fds, &fd, uxsel_fd_findcmp); 82 | if (oldfd) { 83 | uxsel_input_remove(oldfd->id); 84 | del234(fds, oldfd); 85 | sfree(oldfd); 86 | } 87 | } 88 | 89 | /* 90 | * And here is the interface to select-functionality-supplying 91 | * modules. 92 | */ 93 | 94 | int next_fd(int *state, int *rwx) 95 | { 96 | struct fd *fd; 97 | fd = index234(fds, (*state)++); 98 | if (fd) { 99 | *rwx = fd->rwx; 100 | return fd->fd; 101 | } else 102 | return -1; 103 | } 104 | 105 | int first_fd(int *state, int *rwx) 106 | { 107 | *state = 0; 108 | return next_fd(state, rwx); 109 | } 110 | 111 | int select_result(int fd, int event) 112 | { 113 | struct fd *fdstruct = find234(fds, &fd, uxsel_fd_findcmp); 114 | /* 115 | * Apparently this can sometimes be NULL. Can't see how, but I 116 | * assume it means I need to ignore the event since it's on an 117 | * fd I've stopped being interested in. Sigh. 118 | */ 119 | if (fdstruct) 120 | return fdstruct->callback(fd, event); 121 | else 122 | return 1; 123 | } 124 | -------------------------------------------------------------------------------- /unix/uxsignal.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 6 | * Calling signal() is non-portable, as it varies in meaning 7 | * between platforms and depending on feature macros, and has 8 | * stupid semantics at least some of the time. 9 | * 10 | * This function provides the same interface as the libc function, 11 | * but provides consistent semantics. It assumes POSIX semantics 12 | * for sigaction() (so you might need to do some more work if you 13 | * port to something ancient like SunOS 4) 14 | */ 15 | void (*putty_signal(int sig, void (*func)(int)))(int) { 16 | struct sigaction sa; 17 | struct sigaction old; 18 | 19 | sa.sa_handler = func; 20 | if(sigemptyset(&sa.sa_mask) < 0) 21 | return SIG_ERR; 22 | sa.sa_flags = SA_RESTART; 23 | if(sigaction(sig, &sa, &old) < 0) 24 | return SIG_ERR; 25 | return old.sa_handler; 26 | } 27 | 28 | void block_signal(int sig, int block_it) 29 | { 30 | sigset_t ss; 31 | 32 | sigemptyset(&ss); 33 | sigaddset(&ss, sig); 34 | if(sigprocmask(block_it ? SIG_BLOCK : SIG_UNBLOCK, &ss, 0) < 0) { 35 | perror("sigprocmask"); 36 | exit(1); 37 | } 38 | } 39 | 40 | /* 41 | Local Variables: 42 | c-basic-offset:4 43 | comment-column:40 44 | End: 45 | */ 46 | -------------------------------------------------------------------------------- /version.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PuTTY version numbering 3 | */ 4 | 5 | /* 6 | * The difficult part of deciding what goes in these version strings 7 | * is done in Buildscr, and then written into version.h. All we have 8 | * to do here is to drop it into variables of the right names. 9 | */ 10 | 11 | #include "version.h" 12 | 13 | char ver[] = TEXTVER; 14 | char sshver[] = SSHVER; 15 | 16 | /* 17 | * SSH local version string MUST be under 40 characters. Here's a 18 | * compile time assertion to verify this. 19 | */ 20 | enum { vorpal_sword = 1 / (sizeof(sshver) <= 40) }; 21 | -------------------------------------------------------------------------------- /version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This header file provides the various versioning-related #defines 3 | * for a particular PuTTY build. 4 | * 5 | * When my automated build system does a full build, Buildscr 6 | * completely overwrites this file with information derived from the 7 | * circumstances and type of that build. The information _here_ is 8 | * default stuff used for local development runs of 'make'. 9 | */ 10 | 11 | #define TEXTVER "Unidentified build" 12 | #define SSHVER "PuTTY-Unidentified-Local-Build" 13 | #define BINARY_VERSION 0,0,0,0 14 | -------------------------------------------------------------------------------- /windows/README.txt: -------------------------------------------------------------------------------- 1 | PuTTY README 2 | ============ 3 | 4 | This is the README file for the PuTTY installer distribution. If 5 | you're reading this, you've probably just run our installer and 6 | installed PuTTY on your system. 7 | 8 | What should I do next? 9 | ---------------------- 10 | 11 | If you want to use PuTTY to connect to other computers, or use PSFTP 12 | to transfer files, you should just be able to run them from the 13 | Start menu. 14 | 15 | If you want to use the command-line-only file transfer utility PSCP, 16 | you will probably want to put the PuTTY installation directory on 17 | your PATH. On Windows 7 and similar versions, you can do this at 18 | Control Panel > System and Security > System > Advanced system 19 | settings > Environment Variables. 20 | 21 | Some versions of Windows will refuse to run HTML Help files (.CHM) 22 | if they are installed on a network drive. If you have installed 23 | PuTTY on a network drive, you might want to check that the help file 24 | works properly. If not, see http://support.microsoft.com/kb/896054 25 | for information on how to solve this problem. 26 | 27 | What do I do if it doesn't work? 28 | -------------------------------- 29 | 30 | The PuTTY home web site is 31 | 32 | http://www.chiark.greenend.org.uk/~sgtatham/putty/ 33 | 34 | Here you will find our list of known bugs and pending feature 35 | requests. If your problem is not listed in there, or in the FAQ, or 36 | in the manuals, read the Feedback page to find out how to report 37 | bugs to us. PLEASE read the Feedback page carefully: it is there to 38 | save you time as well as us. Do not send us one-line bug reports 39 | telling us `it doesn't work'. 40 | -------------------------------------------------------------------------------- /windows/build-debug.bat: -------------------------------------------------------------------------------- 1 | for /f "usebackq delims=" %%i in (`git describe`) do set desc=%%i 2 | for /f "tokens=2,3 delims=tv-" %%i in ("%desc%") do set trayversion=%%i & set traypatch=%%j 3 | if "%traypatch%" == "" set traypatch=9001 4 | nmake /F Makefile.vc DEBUG=1 ^ 5 | "VER=/DSNAPSHOT= /DSVN_REV=%desc% /DSVN_REV1=%trayversion% /DSVN_REV2=%traypatch%" ^ 6 | putty.exe ^ 7 | %1 %2 %3 %4 %5 %6 %7 %8 %9 ^ 8 | 2>&1 -------------------------------------------------------------------------------- /windows/build-release.bat: -------------------------------------------------------------------------------- 1 | set upstreammajor= 2 | set upstreamminor= 3 | set trayversion= 4 | for /f "tokens=1,2 delims=p." %%i in ("%1") do set upstreammajor=%%i 5 | for /f "tokens=2,3 delims=p.-" %%i in ("%1") do set upstreamminor=%%i 6 | for /f "tokens=2,3 delims=-t" %%i in ("%1") do set trayversion=%%i 7 | if %trayversion%.==. echo Usage: %0 p0.61-t004 & goto end 8 | 9 | ; remove leading zeros, fixing octal confusion 10 | set /a trayversion=10000%trayversion% %% 10000 11 | 12 | echo #define TEXTVER "PuTTYTray %1" > ../version.h 13 | echo #define SSHVER "PuTTYTray-%1" >> ../version.h 14 | echo #define BINARY_VERSION %upstreammajor%,%upstreamminor%,0,%trayversion% >> ../version.h 15 | 16 | nmake /F Makefile.vc putty.exe 17 | 18 | signtool sign /fd SHA256 /a /t http://timestamp.verisign.com/scripts/timstamp.dll ^ 19 | putty.exe 20 | :end 21 | -------------------------------------------------------------------------------- /windows/clean.bat: -------------------------------------------------------------------------------- 1 | nmake /F Makefile.vc clean -------------------------------------------------------------------------------- /windows/cthelper/BUILDING: -------------------------------------------------------------------------------- 1 | BUILDING 2 | 3 | The build process has been tested only under Cygwin, of course. The patch 4 | file is executable and runs the following script: 5 | 6 | PUTTY_VERSION=0.60 7 | set -e -u -x 8 | PUTTY=putty-$PUTTY_VERSION 9 | 10 | ## Extract PuTTY 11 | if [ ! -d $PUTTY ]; then 12 | ## Download the source for PuTTY 13 | if [ ! -f $PUTTY.tar.gz ]; then 14 | wget http://the.earth.li/~sgtatham/putty/$PUTTY_VERSION/$PUTTY.tar.gz 15 | fi 16 | tar xzf $PUTTY.tar.gz 17 | fi 18 | 19 | ## Apply the PuTTYcyg patch 20 | cd $PUTTY 21 | patch -p1 22 | 23 | ## Create Makefile.cyg 24 | perl mkfiles.pl 25 | 26 | ## Build putty.exe 27 | make -C windows -f Makefile.cyg putty.exe 28 | 29 | ## Build cthelper.exe 30 | make -C windows/cthelper 31 | 32 | size windows/putty.exe windows/cthelper/cthelper.exe 33 | -------------------------------------------------------------------------------- /windows/cthelper/Makefile: -------------------------------------------------------------------------------- 1 | TARGET_ARCH = -mcygwin 2 | LINK = $(CC) 3 | CFLAGS = $(DBUG_CFLAGS) $(DEFINES) $(INCLUDE) $(PLATFORM) 4 | DEFINES = $(DBUG_DEFINES) 5 | INCLUDE = $(DBUG_INCLUDE) 6 | LDFLAGS = -s $(DBUG_LDFLAGS) 7 | q = @echo $@; 8 | 9 | ifdef DEBUG 10 | DBUG = /usr/local 11 | #DBUG = /home/dbug 12 | #DBUG = . 13 | DBUG_CFLAGS = -g 14 | DBUG_DEFINES = -DDEBUG -DDEBUG_CHILD 15 | DBUG_INCLUDE = -I$(DBUG)/include 16 | DBUG_LDFLAGS = -L$(DBUG)/lib 17 | DBUG_OBJ = dump.o 18 | LDLIBS = -ldbug 19 | else 20 | DBUG_DEFINES = -DDBUG_OFF 21 | endif 22 | 23 | ## SFU (INTERIX) needs these also 24 | ifdef INTERIX 25 | APUE_OBJ = ptyfork.o ptyopen.o error.o 26 | endif 27 | 28 | SRC = cthelper.c buffer.c buffer.h dump.c debug.h 29 | OBJ = cthelper.o buffer.o message.o $(APUE_OBJ) $(DBUG_OBJ) 30 | 31 | default: all 32 | all: cthelper.exe 33 | 34 | cthelper.exe: $(OBJ) 35 | $(q) $(LINK) $(LDFLAGS) -o $@ $(OBJ) $(LDLIBS) 36 | cthelper.o: cthelper.c cthelper.h ptyfork.h buffer.h debug.h 37 | buffer.o: buffer.c buffer.h debug.h 38 | message.o: message.c message.h debug.h 39 | .c.o:; $(q) $(CC) $(CFLAGS) -o $@ -c $*.c 40 | 41 | checkin: Makefile $(SRC) 42 | ci -l $^ 43 | 44 | TAGS: $(SRC) 45 | ctags $^ 46 | clean: 47 | rm -f *.o *.exe *~ *.stackdump *core tags 48 | 49 | -------------------------------------------------------------------------------- /windows/cthelper/TODO: -------------------------------------------------------------------------------- 1 | * cthelper 2 | 3 | [done] A way to propagate fatal error messages back to PuTTYcyg to display in a message box 4 | 5 | BUG: Duplicate session brings up dialog on cygterm terminals using the user's default shell. 6 | 7 | BUG: When running an arbitrary command, PuTTYcyg closes one character after EOF. 8 | 9 | Misfeature: In Cygwin ps output, the cthelper process does not show with which TTY it is associated. 10 | 11 | Flow control stop (^S) should be more instantaneous 12 | 13 | * PuTTY cygterm backend 14 | 15 | hide the Port editbox 16 | 17 | [done] allow setting a default command of "-" or allow empty command to launch the user's shell 18 | 19 | * PuTTY (not related to cygterm backend) 20 | 21 | [done] add Ctrl-/ map to C-_ 22 | 23 | [done] add Shift-Enter, Ctrl-Enter map to LINEFEED 24 | 25 | [done] add Ctrl-Backspace map same as Shift-Backspace (alternate 0x08 or 0x7F) 26 | 27 | [done] PuTTY wish alt-metabit 28 | 29 | add Alt modifier to mouse location reporting (low-priority) 30 | 31 | add ssh-agent support to PuTTY (?) -or- add pageant support to openssh (Cygwin) 32 | 33 | add cursor styles vertical-half-block and horizontal-half-block 34 | 35 | PuTTY wish key-mapping 36 | 37 | PuTTY wish portable-keyboard 38 | 39 | -------------------------------------------------------------------------------- /windows/cthelper/buffer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "buffer.h" 8 | #include "debug.h" 9 | 10 | Buffer 11 | buffer_init(size_t size) 12 | { 13 | Buffer b; 14 | 15 | DBUG_ENTER("buffer_init"); 16 | assert((b = malloc(sizeof(struct buffer_tag) + size))); 17 | b->len = 0; 18 | b->avail = size; 19 | DBUG_RETURN(b); 20 | } 21 | 22 | void 23 | buffer_free(Buffer *pb) 24 | { 25 | DBUG_ENTER("buffer_free"); 26 | assert(pb); 27 | if (*pb) free(*pb); 28 | *pb = 0; 29 | DBUG_VOID_RETURN; 30 | } 31 | 32 | ssize_t 33 | buffer_read(Buffer b, int d) 34 | { 35 | ssize_t n, total; 36 | DBUG_ENTER("buffer_read"); 37 | total = 0; 38 | n = -1; 39 | DBUG_PRINT("buffer", ("reading %d: %p:%u", d, &b->data[b->len], b->avail)); 40 | if (b->avail > 0 && (n = read(d, &b->data[b->len], b->avail)) > 0) { 41 | DBUG_PRINT("io", (" read %4d", n)); 42 | b->len += n; 43 | b->avail -= n; 44 | total += n; 45 | } 46 | DBUG_PRINT("buffer", ("total %4d", total)); 47 | DBUG_RETURN(total ? total : n); 48 | } 49 | 50 | ssize_t 51 | buffer_write(Buffer b, int d) 52 | { 53 | ssize_t n, total; 54 | DBUG_ENTER("buffer_write"); 55 | total = 0; 56 | n = -1; 57 | DBUG_PRINT("buffer", ("writing %d: %p:%u", d, b->data, b->len)); 58 | if (b->len > 0 && (n = write(d, b->data, b->len)) > 0) { 59 | DBUG_PRINT("io", ("wrote %4d", n)); 60 | buffer_consumed(b, n); 61 | total += n; 62 | } 63 | DBUG_PRINT("buffer", ("total %4d", total)); 64 | DBUG_RETURN(total ? total : n); 65 | } 66 | 67 | size_t 68 | buffer_consumed(Buffer b, size_t n) 69 | { 70 | DBUG_ENTER("buffer_consumed"); 71 | assert(0 < n && n <= b->len); 72 | memmove(b->data, &b->data[n], b->len - n); 73 | b->len -= n; 74 | b->avail += n; 75 | DBUG_RETURN(n); 76 | } 77 | -------------------------------------------------------------------------------- /windows/cthelper/buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef BUFFER_H 2 | #define BUFFER_H 3 | 4 | #include 5 | #include 6 | 7 | typedef struct buffer_tag *Buffer; 8 | struct buffer_tag { 9 | size_t avail, len; 10 | unsigned char data[1]; 11 | }; 12 | 13 | /* Initialize a Buffer */ 14 | Buffer buffer_init(size_t size); 15 | 16 | /* Free a buffer; sets *pb to NULL */ 17 | void buffer_free(Buffer *pb); 18 | 19 | /* Initialize a Buffer with alloca() */ 20 | #define BUFFER_ALLOCA(b,s) do{\ 21 | b = alloca(sizeof(b)+(s)); b->avail = s; b->len = 0;\ 22 | }while(0) 23 | 24 | /* Returns true if buffer is full */ 25 | #define buffer_isfull(b) ((b)->avail == 0) 26 | 27 | /* Returns true if buffer is empty */ 28 | #define buffer_isempty(b) ((b)->len == 0) 29 | 30 | /* Reads up to buffer_avail(b) bytes from descriptor `des' */ 31 | ssize_t buffer_read(Buffer b, int des); 32 | 33 | /* Writes as many bytes in the buffer as possible to descriptor `des' */ 34 | ssize_t buffer_write(Buffer b, int des); 35 | 36 | /* Appends data from data to end of buffer returning number of bytes 37 | * appended (which may be less than `len') */ 38 | size_t buffer_append(Buffer b, const char *data, size_t len); 39 | 40 | /* Clears len bytes from start of buffer, returning number of bytes removed */ 41 | size_t buffer_consumed(Buffer b, size_t len); 42 | 43 | #endif /* BUFFER_H */ 44 | -------------------------------------------------------------------------------- /windows/cthelper/cthelper.h: -------------------------------------------------------------------------------- 1 | enum cthelper_exitcode { 2 | CthelperSuccess = 0, 3 | CthelperInvalidUsage, 4 | CthelperInvalidPort, 5 | CthelperConnectFailed, 6 | CthelperPtyforkFailure, 7 | CthelperExecFailure, 8 | }; 9 | -------------------------------------------------------------------------------- /windows/cthelper/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef DEBUG_H 2 | #define DEBUG_H 3 | 4 | #include "dbug.h" 5 | #include "mm.h" 6 | 7 | #ifndef __attribute__ 8 | #define __attribute__(x) 9 | #endif 10 | 11 | #if !defined(DBUG_OFF) && !defined(_lint) 12 | 13 | /* allow GCC to check format strings against their arguments */ 14 | extern void _dbug_doprnt_(const char *format, ...) 15 | __attribute__((format(printf, 1, 2))); 16 | 17 | extern void debug_memdump(const void *buf, int len, int L); 18 | 19 | #else 20 | 21 | #define debug_memdump(buf,len,L) 22 | 23 | #endif 24 | 25 | #endif /* DEBUG_H */ 26 | /* ex:set sw=4: */ 27 | -------------------------------------------------------------------------------- /windows/cthelper/dump.c: -------------------------------------------------------------------------------- 1 | /* Code stolen from putty/misc.c */ 2 | 3 | #include 4 | #include "dbug.h" 5 | 6 | void 7 | debug_memdump(const void *buf, int len, int L) 8 | { 9 | int i; 10 | unsigned const char *p = buf; 11 | char foo[17]; 12 | if (L) { 13 | int delta; 14 | fprintf(DBUG_FILE,"\t%d (0x%x) bytes:\n", len, len); 15 | delta = 15 & (int) p; 16 | p -= delta; 17 | len += delta; 18 | } 19 | for (; 0 < len; p += 16, len -= 16) { 20 | fputs(" ", DBUG_FILE); 21 | if (L) 22 | fprintf(DBUG_FILE,"%p: ", p); 23 | strcpy(foo, "................"); /* sixteen dots */ 24 | for (i = 0; i < 16 && i < len; ++i) { 25 | if (&p[i] < (unsigned char *) buf) { 26 | fputs(" ", DBUG_FILE); /* 3 spaces */ 27 | foo[i] = ' '; 28 | } 29 | else { 30 | fprintf(DBUG_FILE,"%c%02x", 31 | &p[i] != (unsigned char *) buf 32 | && i % 4 ? '.' : ' ', p[i]); 33 | if (p[i] >= ' ' && p[i] <= '~') 34 | foo[i] = (char) p[i]; 35 | } 36 | } 37 | foo[i] = '\0'; 38 | fprintf(DBUG_FILE,"%*s%s\n", (16 - i) * 3 + 2, "", foo); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /windows/cthelper/error.c: -------------------------------------------------------------------------------- 1 | #include /* for definition of errno */ 2 | #include /* ANSI C header file */ 3 | #include "ourhdr.h" 4 | 5 | static void err_doit(int, const char *, va_list); 6 | 7 | char *pname = NULL; /* caller can set this from argv[0] */ 8 | 9 | /* Nonfatal error related to a system call. 10 | * Print a message and return. */ 11 | 12 | void 13 | err_ret(const char *fmt, ...) 14 | { 15 | va_list ap; 16 | 17 | va_start(ap, fmt); 18 | err_doit(1, fmt, ap); 19 | va_end(ap); 20 | return; 21 | } 22 | 23 | /* Fatal error related to a system call. 24 | * Print a message and terminate. */ 25 | 26 | void 27 | err_sys(const char *fmt, ...) 28 | { 29 | va_list ap; 30 | 31 | va_start(ap, fmt); 32 | err_doit(1, fmt, ap); 33 | va_end(ap); 34 | exit(1); 35 | } 36 | 37 | /* Fatal error related to a system call. 38 | * Print a message, dump core, and terminate. */ 39 | 40 | void 41 | err_dump(const char *fmt, ...) 42 | { 43 | va_list ap; 44 | 45 | va_start(ap, fmt); 46 | err_doit(1, fmt, ap); 47 | va_end(ap); 48 | abort(); /* dump core and terminate */ 49 | exit(1); /* shouldn't get here */ 50 | } 51 | 52 | /* Nonfatal error unrelated to a system call. 53 | * Print a message and return. */ 54 | 55 | void 56 | err_msg(const char *fmt, ...) 57 | { 58 | va_list ap; 59 | 60 | va_start(ap, fmt); 61 | err_doit(0, fmt, ap); 62 | va_end(ap); 63 | return; 64 | } 65 | 66 | /* Fatal error unrelated to a system call. 67 | * Print a message and terminate. */ 68 | 69 | void 70 | err_quit(const char *fmt, ...) 71 | { 72 | va_list ap; 73 | 74 | va_start(ap, fmt); 75 | err_doit(0, fmt, ap); 76 | va_end(ap); 77 | exit(1); 78 | } 79 | 80 | /* Print a message and return to caller. 81 | * Caller specifies "errnoflag". */ 82 | 83 | static void 84 | err_doit(int errnoflag, const char *fmt, va_list ap) 85 | { 86 | int errno_save; 87 | char buf[MAXLINE]; 88 | 89 | errno_save = errno; /* value caller might want printed */ 90 | vsprintf(buf, fmt, ap); 91 | if (errnoflag) 92 | sprintf(buf+strlen(buf), ": %s", strerror(errno_save)); 93 | strcat(buf, "\n"); 94 | fflush(stdout); /* in case stdout and stderr are the same */ 95 | fputs(buf, stderr); 96 | fflush(NULL); /* flushes all stdio output streams */ 97 | return; 98 | } 99 | -------------------------------------------------------------------------------- /windows/cthelper/message.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "message.h" 4 | #include "debug.h" 5 | 6 | int 7 | message_get(Message *m, const unsigned char *data, size_t len) 8 | { 9 | int size; 10 | 11 | DBUG_ENTER("message_get"); 12 | 13 | if (len < MESSAGE_MIN) 14 | /* partial message */ 15 | DBUG_RETURN(0); 16 | 17 | /* we at least have the message header */ 18 | size = data[0]; 19 | 20 | if (MESSAGE_MIN > size || size > MESSAGE_MAX) 21 | /* bad message */ 22 | DBUG_RETURN(-1); 23 | 24 | if (size > len) 25 | /* partial message */ 26 | DBUG_RETURN(0); 27 | 28 | memcpy(m, data, size); 29 | 30 | DBUG_RETURN(1); 31 | } 32 | -------------------------------------------------------------------------------- /windows/cthelper/message.h: -------------------------------------------------------------------------------- 1 | #ifndef MESSAGE_H 2 | #define MESSAGE_H 3 | 4 | #if __STDC__VERSION >= 199901L 5 | #include 6 | #elif defined(__INTERIX) 7 | #include 8 | #else 9 | typedef unsigned char uint8_t; 10 | typedef unsigned short uint16_t; 11 | #endif 12 | 13 | typedef struct message_tag Message; 14 | struct message_tag { 15 | uint8_t size; 16 | uint8_t type; 17 | union { 18 | struct { 19 | uint16_t width, height; 20 | } resize; 21 | } msg; 22 | }; 23 | 24 | /* message types */ 25 | #define MSG_RESIZE (21) 26 | 27 | #define MESSAGE_MIN (2) 28 | #define MESSAGE_MAX (sizeof(struct message_tag)) 29 | 30 | /* Fills in a Message structure from `data'. Does not attempt to validate 31 | * the message type, but returns 0 if a partial message is received. 32 | * Returns -1 if the size is impossible (bigger than largest possible 33 | * message or smaller than smallest possible message). 34 | * Returns 1 if the message structure is filled in properly. 35 | */ 36 | int message_get(Message *m, const unsigned char *data, size_t len); 37 | 38 | #endif /* MESSAGE_H */ 39 | -------------------------------------------------------------------------------- /windows/cthelper/mm.h: -------------------------------------------------------------------------------- 1 | #ifndef _mm_h_ 2 | #define _mm_H_ 3 | 4 | #include 5 | 6 | #ifndef DBUG_OFF 7 | void *dbug_malloc (ssize_t len, const char *, int); 8 | char *dbug_strdup (const char *s, const char *, int); 9 | void *dbug_calloc (ssize_t nmemb, ssize_t len, const char *, int); 10 | void *dbug_realloc (void *ptr, ssize_t len); 11 | void dbug_free (void *ptr); 12 | void dbug_dump_mm (void); 13 | #endif 14 | 15 | #ifndef DBUG_OFF 16 | #undef strdup 17 | #define malloc(x) dbug_malloc(x,__FILE__,__LINE__) 18 | #define realloc(x,y) dbug_realloc(x,y) 19 | #define free(x) dbug_free(x) 20 | #define strdup(x) dbug_strdup(x,__FILE__,__LINE__) 21 | #define calloc(x,y) dbug_calloc(x,y,__FILE__,__LINE__) 22 | /*#else 23 | #define dbug_malloc(x) malloc(x) 24 | #define dbug_strdup(x) strdup(x) 25 | #define dbug_calloc(x,y) calloc(x,y) 26 | #define dbug_free(x) free(x)*/ 27 | #endif /* DBUG_OFF */ 28 | #endif /* _mm_h_ */ 29 | -------------------------------------------------------------------------------- /windows/cthelper/ptyfork.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #ifndef TIOCGWINSZ 4 | #include /* 44BSD requires this too */ 5 | #endif 6 | #include "ourhdr.h" 7 | 8 | pid_t 9 | pty_fork(int *ptrfdm, char *slave_name, 10 | const struct termios *slave_termios, 11 | const struct winsize *slave_winsize) 12 | { 13 | int fdm, fds; 14 | pid_t pid; 15 | char pts_name[20]; 16 | 17 | if ( (fdm = ptym_open(pts_name)) < 0) 18 | err_sys("can't open master pty: %s", pts_name); 19 | 20 | if (slave_name != NULL) 21 | strcpy(slave_name, pts_name); /* return name of slave */ 22 | 23 | if ( (pid = fork()) < 0) 24 | return(-1); 25 | 26 | else if (pid == 0) { /* child */ 27 | if (setsid() < 0) 28 | err_sys("setsid error"); 29 | 30 | /* SVR4 acquires controlling terminal on open() */ 31 | if ( (fds = ptys_open(fdm, pts_name)) < 0) 32 | err_sys("can't open slave pty"); 33 | close(fdm); /* all done with master in child */ 34 | 35 | #if defined(TIOCSCTTY) && !defined(CIBAUD) 36 | /* 44BSD way to acquire controlling terminal */ 37 | /* !CIBAUD to avoid doing this under SunOS */ 38 | if (ioctl(fds, TIOCSCTTY, (char *) 0) < 0) 39 | err_sys("TIOCSCTTY error"); 40 | #endif 41 | /* set slave's termios and window size */ 42 | if (slave_termios != NULL) { 43 | if (tcsetattr(fds, TCSANOW, slave_termios) < 0) 44 | err_sys("tcsetattr error on slave pty"); 45 | } 46 | if (slave_winsize != NULL) { 47 | if (ioctl(fds, TIOCSWINSZ, slave_winsize) < 0) 48 | err_sys("TIOCSWINSZ error on slave pty"); 49 | } 50 | /* slave becomes stdin/stdout/stderr of child */ 51 | if (dup2(fds, STDIN_FILENO) != STDIN_FILENO) 52 | err_sys("dup2 error to stdin"); 53 | if (dup2(fds, STDOUT_FILENO) != STDOUT_FILENO) 54 | err_sys("dup2 error to stdout"); 55 | if (dup2(fds, STDERR_FILENO) != STDERR_FILENO) 56 | err_sys("dup2 error to stderr"); 57 | if (fds > STDERR_FILENO) 58 | close(fds); 59 | return(0); /* child returns 0 just like fork() */ 60 | 61 | } else { /* parent */ 62 | *ptrfdm = fdm; /* return fd of master */ 63 | return(pid); /* parent returns pid of child */ 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /windows/cthelper/ptyfork.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | pid_t pty_fork(int *ptrfdm, char *slave_name, 4 | const struct termios *slave_termios, 5 | const struct winsize *slave_winsize); 6 | -------------------------------------------------------------------------------- /windows/cthelper/ptyopen.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "ourhdr.h" 6 | 7 | extern char *ptsname(int); /* prototype not in any system header */ 8 | 9 | int 10 | ptym_open(char *pts_name) 11 | { 12 | char *ptr; 13 | int fdm; 14 | 15 | strcpy(pts_name, "/dev/ptmx"); /* in case open fails */ 16 | if ( (fdm = open(pts_name, O_RDWR)) < 0) 17 | return(-1); 18 | 19 | if (grantpt(fdm) < 0) { /* grant access to slave */ 20 | close(fdm); 21 | return(-2); 22 | } 23 | if (unlockpt(fdm) < 0) { /* clear slave's lock flag */ 24 | close(fdm); 25 | return(-3); 26 | } 27 | if ( (ptr = ptsname(fdm)) == NULL) { /* get slave's name */ 28 | close(fdm); 29 | return(-4); 30 | } 31 | 32 | strcpy(pts_name, ptr); /* return name of slave */ 33 | return(fdm); /* return fd of master */ 34 | } 35 | int 36 | ptys_open(int fdm, char *pts_name) 37 | { 38 | int fds; 39 | 40 | /* following should allocate controlling terminal */ 41 | if ( (fds = open(pts_name, O_RDWR)) < 0) { 42 | close(fdm); 43 | return(-5); 44 | } 45 | 46 | return(fds); 47 | } 48 | -------------------------------------------------------------------------------- /windows/cygcfg.c: -------------------------------------------------------------------------------- 1 | #include "putty.h" 2 | #include "dialog.h" 3 | 4 | extern void config_protocolbuttons_handler(union control *, void *, void *, int); 5 | 6 | static int is64Bits() 7 | { 8 | return (NULL != GetProcAddress(GetModuleHandle("kernel32"), "IsWow64Process")) ? 1 : 0; 9 | } 10 | 11 | void cygterm_setup_config_box(struct controlbox *b, int midsession) 12 | { 13 | union control *c; 14 | int i; 15 | struct controlset *s; 16 | s = ctrl_getset(b, "Session", "hostport", 17 | "Specify the destination you want to connect to"); 18 | for (i = 0; i < s->ncontrols; i++) { 19 | c = s->ctrls[i]; 20 | if (c->generic.type == CTRL_RADIO && 21 | c->generic.handler == config_protocolbuttons_handler) { 22 | c->radio.nbuttons++; 23 | /* c->radio.ncolumns++; */ 24 | c->radio.buttons = 25 | sresize(c->radio.buttons, c->radio.nbuttons, char *); 26 | c->radio.buttons[c->radio.nbuttons-1] = dupstr("Cygterm"); 27 | c->radio.buttondata = 28 | sresize(c->radio.buttondata, c->radio.nbuttons, intorptr); 29 | c->radio.buttondata[c->radio.nbuttons-1] = I(PROT_CYGTERM); 30 | if (c->radio.shortcuts) { 31 | c->radio.shortcuts = 32 | sresize(c->radio.shortcuts, c->radio.nbuttons, char); 33 | c->radio.shortcuts[c->radio.nbuttons-1] = NO_SHORTCUT; 34 | } 35 | } 36 | } 37 | if (!midsession) { 38 | ctrl_settitle(b, "Connection/Cygterm", 39 | "Options controlling Cygterm sessions"); 40 | s = ctrl_getset(b, "Connection/Cygterm", "cygterm", 41 | "Configure Cygwin paths"); 42 | ctrl_checkbox(s, "Autodetect Cygwin installation", 'd', 43 | HELPCTX(no_help), 44 | conf_checkbox_handler, 45 | I(CONF_cygautopath)); 46 | if( is64Bits() ) 47 | { 48 | ctrl_checkbox(s, "Use Cygwin64", 'u', 49 | HELPCTX(no_help), 50 | conf_checkbox_handler, 51 | I(CONF_cygterm64)); 52 | } 53 | } 54 | } 55 | 56 | /* ex:set ts=8 sw=4: */ 57 | -------------------------------------------------------------------------------- /windows/fatty.c: -------------------------------------------------------------------------------- 1 | #include "putty.h" 2 | 3 | int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) { 4 | char us[MAX_PATH]; 5 | 6 | while (*cmdline && isspace(*cmdline)) 7 | ++cmdline; 8 | 9 | # define ARG_RUN(arg, method) \ 10 | if (!strncmp(cmdline, arg, strlen(arg))) { \ 11 | return method(inst, prev, cmdline+strlen(arg), show); \ 12 | } 13 | 14 | ARG_RUN("--as-gen", puttygen_main); 15 | ARG_RUN("--as-agent", pageant_main); 16 | ARG_RUN("--as-putty", putty_main); 17 | # undef ARG_RUN 18 | 19 | if (GetModuleFileName(NULL, us, MAX_PATH)) { 20 | char *fn = strrchr(us, '\\'); 21 | if (!fn) 22 | fn = us; 23 | else 24 | ++fn; 25 | 26 | if (!strncmp(fn, "puttygen", strlen("puttygen"))) { 27 | return puttygen_main(inst, prev, cmdline, show); 28 | } 29 | if (!strncmp(fn, "pageant", strlen("pageant"))) { 30 | return pageant_main(inst, prev, cmdline, show); 31 | } 32 | } 33 | 34 | return putty_main(inst, prev, cmdline, show); 35 | } 36 | -------------------------------------------------------------------------------- /windows/pageant.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FireEgl/FuTTY/c536b357184be8a9faff2c87fa17a5f2b707092d/windows/pageant.ico -------------------------------------------------------------------------------- /windows/pageant.mft: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | PuTTY SSH authentication agent 12 | 13 | 14 | 16 | 22 | 23 | 24 | 25 | 26 | 28 | true 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /windows/pageant.rc: -------------------------------------------------------------------------------- 1 | /* 2 | * Windows resources for Pageant. 3 | */ 4 | 5 | #include "rcstuff.h" 6 | 7 | 900 ICON "pageant.ico" 8 | 9 | 910 DIALOG DISCARDABLE 0, 0, 140, 60 10 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 11 | CAPTION "Pageant: Enter Passphrase" 12 | FONT 8, "MS Shell Dlg" 13 | BEGIN 14 | CTEXT "Enter passphrase for key", 100, 10, 6, 120, 8 15 | CTEXT "", 101, 10, 16, 120, 8 16 | EDITTEXT 102, 10, 26, 120, 12, ES_PASSWORD | ES_AUTOHSCROLL 17 | DEFPUSHBUTTON "O&K", IDOK, 20, 42, 40, 14 18 | PUSHBUTTON "&Cancel", IDCANCEL, 80, 42, 40, 14 19 | END 20 | 21 | 911 DIALOG DISCARDABLE 0, 0, 330, 200 22 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 23 | CAPTION "Pageant Key List" 24 | FONT 8, "MS Shell Dlg" 25 | BEGIN 26 | LISTBOX 100, 10, 10, 310, 155, 27 | LBS_EXTENDEDSEL | LBS_HASSTRINGS | LBS_USETABSTOPS | WS_VSCROLL | WS_TABSTOP 28 | PUSHBUTTON "&Add Key", 101, 27, 162, 60, 14 29 | PUSHBUTTON "Add ~/.ssh/&id_rsa", 107, 125, 162, 80, 14 30 | PUSHBUTTON "&Remove Key", 102, 235, 162, 60, 14 31 | PUSHBUTTON "Copy OpenSSH public keys", 108, 105, 182, 120, 14 32 | PUSHBUTTON "&Help", 103, 10, 182, 50, 14 33 | DEFPUSHBUTTON "&Close", IDOK, 270, 182, 50, 14 34 | END 35 | 36 | /* Accelerators used: cl */ 37 | 913 DIALOG DISCARDABLE 140, 40, 136, 70 38 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 39 | CAPTION "About Pageant" 40 | FONT 8, "MS Shell Dlg" 41 | BEGIN 42 | DEFPUSHBUTTON "&Close", IDOK, 82, 52, 48, 14 43 | PUSHBUTTON "View &Licence", 101, 6, 52, 70, 14 44 | CTEXT "Pageant", 102, 10, 6, 120, 8 45 | CTEXT "", 100, 10, 16, 120, 16 46 | CTEXT "\251 1997-2015 Simon Tatham. All rights reserved.", 47 | 103, 10, 34, 120, 16 48 | END 49 | 50 | /* No accelerators used */ 51 | 914 DIALOG DISCARDABLE 50, 50, 226, 271 52 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 53 | CAPTION "PuTTY Licence" 54 | FONT 8, "MS Shell Dlg" 55 | BEGIN 56 | DEFPUSHBUTTON "OK", IDOK, 98, 251, 44, 14 57 | 58 | LTEXT "Copyright \251 1997-2015 Simon Tatham", 1000, 10, 10, 206, 8 59 | 60 | LTEXT "Portions copyright Robert de Bath, Joris van Rantwijk, Delian", 1001, 10, 26, 206, 8 61 | LTEXT "Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas", 1002, 10, 34, 206, 8 62 | LTEXT "Barry, Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa,", 1003, 10, 42, 206, 8 63 | LTEXT "Markus Kuhn, Colin Watson, Christopher Staite, and CORE SDI", 1004, 10, 50, 206, 8 64 | LTEXT "S.A.", 1005, 10, 58, 206, 8 65 | 66 | LTEXT "Permission is hereby granted, free of charge, to any person", 1006, 10, 74, 206, 8 67 | LTEXT "obtaining a copy of this software and associated documentation", 1007, 10, 82, 206, 8 68 | LTEXT "files (the ""Software""), to deal in the Software without restriction,", 1008, 10, 90, 206, 8 69 | LTEXT "including without limitation the rights to use, copy, modify, merge,", 1009, 10, 98, 206, 8 70 | LTEXT "publish, distribute, sublicense, and/or sell copies of the Software,", 1010, 10, 106, 206, 8 71 | LTEXT "and to permit persons to whom the Software is furnished to do so,", 1011, 10, 114, 206, 8 72 | LTEXT "subject to the following conditions:", 1012, 10, 122, 206, 8 73 | 74 | LTEXT "The above copyright notice and this permission notice shall be", 1013, 10, 138, 206, 8 75 | LTEXT "included in all copies or substantial portions of the Software.", 1014, 10, 146, 206, 8 76 | 77 | LTEXT "THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT", 1015, 10, 162, 206, 8 78 | LTEXT "WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,", 1016, 10, 170, 206, 8 79 | LTEXT "INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF", 1017, 10, 178, 206, 8 80 | LTEXT "MERCHANTABILITY, FITNESS FOR A PARTICULAR", 1018, 10, 186, 206, 8 81 | LTEXT "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE", 1019, 10, 194, 206, 8 82 | LTEXT "COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES", 1020, 10, 202, 206, 8 83 | LTEXT "OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,", 1021, 10, 210, 206, 8 84 | LTEXT "TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN", 1022, 10, 218, 206, 8 85 | LTEXT "CONNECTION WITH THE SOFTWARE OR THE USE OR", 1023, 10, 226, 206, 8 86 | LTEXT "OTHER DEALINGS IN THE SOFTWARE.", 1024, 10, 234, 206, 8 87 | 88 | END 89 | -------------------------------------------------------------------------------- /windows/pageant64.mft: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | PuTTY SSH authentication agent 12 | 13 | 14 | 16 | 22 | 23 | 24 | 25 | 26 | 28 | true 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /windows/pickicondialog.c: -------------------------------------------------------------------------------- 1 | #include 2 | typedef WINSHELLAPI BOOL(WINAPI *fnPickIconDlg) (HWND hWndParent, LPTSTR pszFilename, LPDWORD pdwBufferSize, LPDWORD pdwIndex); 3 | 4 | BOOL SelectIconA(HWND hWndParent, LPSTR lpszFilename, DWORD dwBufferSize, DWORD *pdwIndex) { 5 | BOOL result = FALSE; 6 | OSVERSIONINFO versioninfo; 7 | HMODULE hShell32 = LoadLibrary("shell32.dll"); 8 | versioninfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 9 | GetVersionEx(&versioninfo); 10 | 11 | if (hShell32) { 12 | fnPickIconDlg PickIconDlg = (fnPickIconDlg) GetProcAddress(hShell32, (LPCSTR) 62); 13 | if (PickIconDlg) { 14 | if (versioninfo.dwPlatformId == VER_PLATFORM_WIN32_NT) { 15 | LPWSTR pszWideName = (LPWSTR) malloc(dwBufferSize); 16 | MultiByteToWideChar(CP_ACP, 0, lpszFilename, -1, pszWideName, dwBufferSize); 17 | result = PickIconDlg(hWndParent, (LPTSTR) pszWideName, &dwBufferSize, pdwIndex); 18 | WideCharToMultiByte(CP_ACP, 0, pszWideName, -1, lpszFilename, dwBufferSize, NULL, NULL); 19 | free(pszWideName); 20 | } else { 21 | result = PickIconDlg(hWndParent, (LPTSTR) lpszFilename, &dwBufferSize, pdwIndex); 22 | } 23 | } 24 | FreeLibrary(hShell32); 25 | } 26 | 27 | return result; 28 | } 29 | 30 | BOOL SelectIconW(HWND hWndParent, LPWSTR lpszFilename, DWORD dwBufferSize, DWORD *pdwIndex) { 31 | BOOL result = FALSE; 32 | OSVERSIONINFO versioninfo; 33 | HMODULE hShell32 = LoadLibrary("shell32.dll"); 34 | versioninfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 35 | GetVersionEx(&versioninfo); 36 | 37 | if (hShell32) { 38 | fnPickIconDlg PickIconDlg = (fnPickIconDlg) GetProcAddress(hShell32, (LPCSTR) 62); 39 | if (PickIconDlg) { 40 | if (versioninfo.dwPlatformId != VER_PLATFORM_WIN32_NT) { 41 | LPSTR pszMBName = (LPSTR) malloc(dwBufferSize); 42 | WideCharToMultiByte(CP_ACP, 0, lpszFilename, -1, pszMBName, dwBufferSize, NULL, NULL); 43 | result = PickIconDlg(hWndParent, (LPTSTR) pszMBName, &dwBufferSize, pdwIndex); 44 | MultiByteToWideChar(CP_ACP, 0, pszMBName, -1, lpszFilename, dwBufferSize); 45 | free(pszMBName); 46 | } else { 47 | result = PickIconDlg(hWndParent, (LPTSTR) lpszFilename, &dwBufferSize, pdwIndex); 48 | } 49 | } 50 | FreeLibrary(hShell32); 51 | } 52 | 53 | return result; 54 | } 55 | -------------------------------------------------------------------------------- /windows/pickicondialog.h: -------------------------------------------------------------------------------- 1 | #ifndef _SELECTICON_H_ 2 | #define _SELECTICON_H_ 3 | 4 | BOOL SelectIconW(HWND hWndParent, LPWSTR lpszFilename, DWORD dwBufferSize, DWORD *pdwIndex); 5 | BOOL SelectIconA(HWND hWndParent, LPSTR lpszFilename, DWORD dwBufferSize, DWORD *pdwIndex); 6 | 7 | #ifdef _UNICODE 8 | #define SelectIcon SelectIconA 9 | // Was SelectIconW, but it doesn't work when you use it. 10 | #else 11 | #define SelectIcon SelectIconA 12 | #endif 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /windows/plink.rc: -------------------------------------------------------------------------------- 1 | #include "rcstuff.h" 2 | 3 | #define APPNAME "Plink" 4 | #define APPDESC "Command-line SSH, Telnet, and Rlogin client" 5 | 6 | 200 ICON "putty.ico" 7 | 8 | #include "version.rc2" 9 | -------------------------------------------------------------------------------- /windows/pscp.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FireEgl/FuTTY/c536b357184be8a9faff2c87fa17a5f2b707092d/windows/pscp.ico -------------------------------------------------------------------------------- /windows/pscp.rc: -------------------------------------------------------------------------------- 1 | #include "rcstuff.h" 2 | 3 | #define APPNAME "PSCP" 4 | #define APPDESC "Command-line SCP/SFTP client" 5 | 6 | 200 ICON "pscp.ico" 7 | 8 | #include "version.rc2" 9 | -------------------------------------------------------------------------------- /windows/psftp.rc: -------------------------------------------------------------------------------- 1 | #include "rcstuff.h" 2 | 3 | #define APPNAME "PSFTP" 4 | #define APPDESC "Command-line interactive SFTP client" 5 | 6 | 200 ICON "pscp.ico" 7 | 8 | #include "version.rc2" 9 | -------------------------------------------------------------------------------- /windows/putty.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FireEgl/FuTTY/c536b357184be8a9faff2c87fa17a5f2b707092d/windows/putty.ico -------------------------------------------------------------------------------- /windows/putty.mft: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | A network client and terminal emulator 12 | 13 | 14 | 16 | 22 | 23 | 24 | 25 | 26 | 28 | true 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /windows/putty.rc: -------------------------------------------------------------------------------- 1 | #include "rcstuff.h" 2 | 3 | #define APPNAME "FuTTY" 4 | #define APPDESC "SSH, Telnet, Rlogin, Cygterm, and Adb client." 5 | 6 | #include "win_res.rc2" 7 | #include "puttygen.rc" 8 | #include "pageant.rc" 9 | 10 | #ifndef NO_MANIFESTS 11 | #ifndef _WIN64 12 | 1 RT_MANIFEST "putty.mft" 13 | #else 14 | 1 RT_MANIFEST "putty64.mft" 15 | #endif 16 | #endif /* NO_MANIFESTS */ 17 | -------------------------------------------------------------------------------- /windows/putty64.mft: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | A network client and terminal emulator 12 | 13 | 14 | 16 | 22 | 23 | 24 | 25 | 26 | 28 | true 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /windows/puttycfg.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FireEgl/FuTTY/c536b357184be8a9faff2c87fa17a5f2b707092d/windows/puttycfg.ico -------------------------------------------------------------------------------- /windows/puttycyg.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FireEgl/FuTTY/c536b357184be8a9faff2c87fa17a5f2b707092d/windows/puttycyg.ico -------------------------------------------------------------------------------- /windows/puttygen.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FireEgl/FuTTY/c536b357184be8a9faff2c87fa17a5f2b707092d/windows/puttygen.ico -------------------------------------------------------------------------------- /windows/puttygen.mft: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | SSH key generator for PuTTY 12 | 13 | 14 | 16 | 22 | 23 | 24 | 25 | 26 | 28 | true 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /windows/puttygen.rc: -------------------------------------------------------------------------------- 1 | /* 2 | * Windows resources for PuTTYgen. 3 | */ 4 | 5 | #include "rcstuff.h" 6 | 7 | 800 ICON "puttygen.ico" 8 | 9 | 801 DIALOG DISCARDABLE 0, 0, 318, 270 10 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 11 | CAPTION "PuTTY Key Generator" 12 | FONT 8, "MS Shell Dlg" 13 | BEGIN 14 | END 15 | 16 | 810 DIALOG DISCARDABLE 0, 0, 140, 60 17 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 18 | CAPTION "PuTTYgen: Enter Passphrase" 19 | FONT 8, "MS Shell Dlg" 20 | BEGIN 21 | CTEXT "Enter passphrase for key", 100, 10, 6, 120, 8 22 | CTEXT "", 101, 10, 16, 120, 8 23 | EDITTEXT 102, 10, 26, 120, 12, ES_PASSWORD | ES_AUTOHSCROLL 24 | DEFPUSHBUTTON "O&K", IDOK, 20, 42, 40, 14 25 | PUSHBUTTON "&Cancel", IDCANCEL, 80, 42, 40, 14 26 | END 27 | 28 | /* Accelerators used: cl */ 29 | 813 DIALOG DISCARDABLE 140, 40, 136, 70 30 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 31 | CAPTION "About PuTTYgen" 32 | FONT 8, "MS Shell Dlg" 33 | BEGIN 34 | DEFPUSHBUTTON "&Close", IDOK, 82, 52, 48, 14 35 | PUSHBUTTON "View &Licence", 101, 6, 52, 70, 14 36 | CTEXT "PuTTYgen", 102, 10, 6, 120, 8 37 | CTEXT "", 100, 10, 16, 120, 16 38 | CTEXT "\251 1997-2015 Simon Tatham. All rights reserved.", 39 | 103, 10, 34, 120, 16 40 | END 41 | 42 | /* No accelerators used */ 43 | 814 DIALOG DISCARDABLE 50, 50, 226, 271 44 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 45 | CAPTION "PuTTY Licence" 46 | FONT 8, "MS Shell Dlg" 47 | BEGIN 48 | DEFPUSHBUTTON "OK", IDOK, 98, 251, 44, 14 49 | 50 | LTEXT "Copyright \251 1997-2015 Simon Tatham", 1000, 10, 10, 206, 8 51 | 52 | LTEXT "Portions copyright Robert de Bath, Joris van Rantwijk, Delian", 1001, 10, 26, 206, 8 53 | LTEXT "Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas", 1002, 10, 34, 206, 8 54 | LTEXT "Barry, Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa,", 1003, 10, 42, 206, 8 55 | LTEXT "Markus Kuhn, Colin Watson, Christopher Staite, and CORE SDI", 1004, 10, 50, 206, 8 56 | LTEXT "S.A.", 1005, 10, 58, 206, 8 57 | 58 | LTEXT "Permission is hereby granted, free of charge, to any person", 1006, 10, 74, 206, 8 59 | LTEXT "obtaining a copy of this software and associated documentation", 1007, 10, 82, 206, 8 60 | LTEXT "files (the ""Software""), to deal in the Software without restriction,", 1008, 10, 90, 206, 8 61 | LTEXT "including without limitation the rights to use, copy, modify, merge,", 1009, 10, 98, 206, 8 62 | LTEXT "publish, distribute, sublicense, and/or sell copies of the Software,", 1010, 10, 106, 206, 8 63 | LTEXT "and to permit persons to whom the Software is furnished to do so,", 1011, 10, 114, 206, 8 64 | LTEXT "subject to the following conditions:", 1012, 10, 122, 206, 8 65 | 66 | LTEXT "The above copyright notice and this permission notice shall be", 1013, 10, 138, 206, 8 67 | LTEXT "included in all copies or substantial portions of the Software.", 1014, 10, 146, 206, 8 68 | 69 | LTEXT "THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT", 1015, 10, 162, 206, 8 70 | LTEXT "WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,", 1016, 10, 170, 206, 8 71 | LTEXT "INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF", 1017, 10, 178, 206, 8 72 | LTEXT "MERCHANTABILITY, FITNESS FOR A PARTICULAR", 1018, 10, 186, 206, 8 73 | LTEXT "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE", 1019, 10, 194, 206, 8 74 | LTEXT "COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES", 1020, 10, 202, 206, 8 75 | LTEXT "OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,", 1021, 10, 210, 206, 8 76 | LTEXT "TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN", 1022, 10, 218, 206, 8 77 | LTEXT "CONNECTION WITH THE SOFTWARE OR THE USE OR", 1023, 10, 226, 206, 8 78 | LTEXT "OTHER DEALINGS IN THE SOFTWARE.", 1024, 10, 234, 206, 8 79 | 80 | END 81 | -------------------------------------------------------------------------------- /windows/puttygen64.mft: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | SSH key generator for PuTTY 12 | 13 | 14 | 16 | 22 | 23 | 24 | 25 | 26 | 28 | true 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /windows/puttyins.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FireEgl/FuTTY/c536b357184be8a9faff2c87fa17a5f2b707092d/windows/puttyins.ico -------------------------------------------------------------------------------- /windows/puttytel.rc: -------------------------------------------------------------------------------- 1 | #include "rcstuff.h" 2 | 3 | #define APPNAME "FuTTYtel" 4 | #define APPDESC "Telnet, Rlogin, Cygterm, and Adb client" 5 | 6 | #include "win_res.rc2" 7 | 8 | #ifndef NO_MANIFESTS 9 | /* FIXME */ 10 | 1 RT_MANIFEST "putty.mft" 11 | #endif /* NO_MANIFESTS */ 12 | -------------------------------------------------------------------------------- /windows/rcstuff.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Miscellaneous stuff to include in all .rc files. 3 | */ 4 | 5 | #ifndef PUTTY_RCSTUFF_H 6 | #define PUTTY_RCSTUFF_H 7 | 8 | #ifdef __LCC__ 9 | #include 10 | #else 11 | 12 | /* Some compilers, like Borland, don't have winresrc.h */ 13 | #ifndef NO_WINRESRC_H 14 | #ifndef MSVC4 15 | #include 16 | #else 17 | #include 18 | #endif 19 | #endif 20 | 21 | #endif /* end #ifdef __LCC__ */ 22 | 23 | /* Some systems don't define this, so I do it myself if necessary */ 24 | #ifndef TCS_MULTILINE 25 | #define TCS_MULTILINE 0x0200 26 | #endif 27 | 28 | /* Likewise */ 29 | #ifndef RT_MANIFEST 30 | #define RT_MANIFEST 24 31 | #endif 32 | 33 | /* LCC is the offender here. */ 34 | #ifndef VS_FF_DEBUG 35 | #define VS_FF_DEBUG 1 36 | #endif 37 | #ifndef VS_FF_PRERELEASE 38 | #define VS_FF_PRERELEASE 2 39 | #endif 40 | #ifndef VS_FF_PRIVATEBUILD 41 | #define VS_FF_PRIVATEBUILD 8 42 | #endif 43 | #ifndef VOS__WINDOWS32 44 | #define VOS__WINDOWS32 4 45 | #endif 46 | #ifndef VFT_APP 47 | #define VFT_APP 1 48 | #endif 49 | 50 | #endif /* PUTTY_RCSTUFF_H */ 51 | -------------------------------------------------------------------------------- /windows/re_lib/regexp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Definitions etc. for regexp(3) routines. 3 | * 4 | * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof], 5 | * not the System V one. 6 | */ 7 | #define NSUBEXP 16 8 | typedef struct regexp { 9 | char *startp[NSUBEXP]; 10 | char *endp[NSUBEXP]; 11 | char regstart; /* Internal use only. */ 12 | char reganch; /* Internal use only. */ 13 | char *regmust; /* Internal use only. */ 14 | size_t regmlen; /* Internal use only. */ 15 | char program[1]; /* Unwarranted chumminess with compiler. */ 16 | } regexp; 17 | 18 | regexp *regcomp( char* re); 19 | int regexec( regexp* r, char* str); 20 | void regsub( regexp* r, char* str, char* substr); 21 | void regerror( const char* s); /* for internal use only */ 22 | void set_regerror_func( void (*func)( const char*)); 23 | -------------------------------------------------------------------------------- /windows/re_lib/regmagic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The first byte of the regexp internal "program" is actually this magic 3 | * number; the start node begins in the second byte. 4 | */ 5 | #define MAGIC 0234 6 | -------------------------------------------------------------------------------- /windows/urlhack.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _URLHACK_H 3 | #define _URLHACK_H 4 | 5 | #include "re_lib/regexp.h" 6 | #include 7 | 8 | typedef struct { int x0, y0, x1, y1; } text_region; 9 | 10 | extern const char* urlhack_default_regex; 11 | extern const char* urlhack_liberal_regex; 12 | extern int urlhack_mouse_old_x, urlhack_mouse_old_y, urlhack_current_region; 13 | 14 | void urlhack_reset(); 15 | void urlhack_go_find_me_some_hyperlinks(int screen_width); 16 | void urlhack_putchar(char ch); 17 | text_region urlhack_get_link_region(unsigned int index); 18 | 19 | int urlhack_is_in_link_region(int x, int y); 20 | int urlhack_is_in_this_link_region(text_region r, int x, int y); 21 | text_region urlhack_get_link_bounds(int x, int y); 22 | void urlhack_add_link_region(int x0, int y0, int x1, int y1); 23 | void urlhack_launch_url(const char* app, const wchar_t *url); 24 | int urlhack_is_ctrl_pressed(); 25 | void urlhack_set_regular_expression(int mode, const char* expression); 26 | void rtfm(const char *error); 27 | 28 | void urlhack_init(); 29 | void urlhack_cleanup(); 30 | 31 | #endif // _URLHACK_H 32 | -------------------------------------------------------------------------------- /windows/urlhack_win.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "misc.h" 4 | #include "urlhack.h" 5 | 6 | enum { MAX_STR = 4096 }; 7 | 8 | static int starts_with(const wchar_t *thing, const wchar_t *prefix) { 9 | return 0 == wcsncmp(thing, prefix, wcslen(prefix)); 10 | } 11 | 12 | void urlhack_launch_url(const char* app, const wchar_t *url) 13 | { 14 | wchar_t *u; 15 | if (app) { 16 | wchar_t app_w[MAX_STR]; 17 | size_t newlen; 18 | mbstowcs_s(&newlen, app_w, MAX_STR, app, MAX_STR); 19 | ShellExecuteW(NULL, NULL, app_w, url, NULL, SW_SHOW); 20 | return; 21 | } 22 | 23 | if ((long)ShellExecuteW(NULL, NULL, url, NULL, NULL, SW_SHOWNORMAL) > 32) { 24 | return; 25 | } 26 | 27 | // if the OS couldn't launch it, munge it towards a plausible url, then launch that instead: 28 | u = snewn(wcslen(url) + 10, wchar_t); 29 | wcscpy(u, url); 30 | 31 | if (!starts_with(url, L"http://") && !starts_with(url, L"https://") && 32 | !starts_with(url, L"ftp://") && !starts_with(url, L"ftps://")) { 33 | if (wcsstr(url, L"ftp.")) { 34 | wcscpy(u, L"ftp://"); 35 | wcscat(u, url); 36 | } else { 37 | wcscpy(u, L"http://"); 38 | wcscat(u, url); 39 | } 40 | } 41 | 42 | if (!!wcscmp(url, u)) { 43 | ShellExecuteW(NULL, NULL, u, NULL, NULL, SW_SHOWNORMAL); 44 | } 45 | 46 | free(u); 47 | } 48 | 49 | int urlhack_is_ctrl_pressed() 50 | { 51 | return HIWORD(GetAsyncKeyState(VK_CONTROL)); 52 | } 53 | 54 | 55 | void rtfm(const char *error) 56 | { 57 | char std_msg[] = "The following error occured when compiling the regular expression\n" \ 58 | "for the hyperlink support. Hyperlink detection is disabled during\n" \ 59 | "this session (restart PuTTY Tray to try again).\n\n"; 60 | 61 | char *full_msg = dupprintf("%s%s", std_msg, error); 62 | 63 | MessageBox(0, full_msg, "PuTTY Tray Error", MB_OK); 64 | free(full_msg); 65 | } 66 | -------------------------------------------------------------------------------- /windows/version.rc2: -------------------------------------------------------------------------------- 1 | /* 2 | * Standard Windows version information. 3 | * (For inclusion in other .rc files with appropriate macro definitions.) 4 | * FIXME: This file is called '.rc2' rather than '.rc' to avoid MSVC trying 5 | * to compile it on its own when using the project files. Nicer solutions 6 | * welcome. 7 | */ 8 | 9 | #include "version.h" 10 | 11 | /* 12 | * The actual VERSIONINFO resource. 13 | */ 14 | VS_VERSION_INFO VERSIONINFO 15 | /* (None of this "fixed" info appears to be trivially user-visible on 16 | * Win98SE. The binary version does show up on Win2K.) */ 17 | FILEVERSION BINARY_VERSION 18 | PRODUCTVERSION BINARY_VERSION /* version of whole suite */ 19 | FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE | VS_FF_PRIVATEBUILD 20 | FILEFLAGS 0x0L 21 | #if defined DEBUG 22 | | VS_FF_DEBUG 23 | #endif 24 | #if defined SNAPSHOT || defined PRERELEASE 25 | | VS_FF_PRERELEASE 26 | #elif !defined RELEASE 27 | | VS_FF_PRIVATEBUILD 28 | #endif 29 | FILEOS VOS__WINDOWS32 30 | FILETYPE VFT_APP 31 | FILESUBTYPE 0x0L /* n/a for VFT_APP */ 32 | BEGIN 33 | /* (On Win98SE and Win2K, we can see most of this on the Version tab 34 | * in the file properties in Explorer.) */ 35 | BLOCK "StringFileInfo" 36 | BEGIN 37 | /* "lang-charset" LLLLCCCC = (UK English, Unicode) */ 38 | BLOCK "080904B0" 39 | BEGIN 40 | VALUE "CompanyName", "Simon Tatham" /* required :/ */ 41 | VALUE "ProductName", "PuTTY suite" 42 | VALUE "FileDescription", APPDESC 43 | VALUE "InternalName", APPNAME 44 | VALUE "OriginalFilename", APPNAME 45 | VALUE "FileVersion", TEXTVER 46 | VALUE "ProductVersion", TEXTVER 47 | VALUE "LegalCopyright", "Copyright \251 1997-2015 Simon Tatham." 48 | #if (!defined SNAPSHOT) && (!defined RELEASE) && (!defined PRERELEASE) 49 | /* Only if VS_FF_PRIVATEBUILD. */ 50 | VALUE "PrivateBuild", TEXTVER /* NBI */ 51 | #endif 52 | END 53 | END 54 | BLOCK "VarFileInfo" 55 | BEGIN 56 | /* Once again -- same meanings -- apparently necessary */ 57 | VALUE "Translation", 0x809, 1200 58 | END 59 | END 60 | -------------------------------------------------------------------------------- /windows/website.url: -------------------------------------------------------------------------------- 1 | [InternetShortcut] 2 | URL=http://www.chiark.greenend.org.uk/~sgtatham/putty/ 3 | -------------------------------------------------------------------------------- /windows/win_res.h: -------------------------------------------------------------------------------- 1 | /* 2 | * win_res.h - constants shared between win_res.rc2 and the C code. 3 | */ 4 | 5 | #ifndef PUTTY_WIN_RES_H 6 | #define PUTTY_WIN_RES_H 7 | 8 | #define IDI_MAINICON 200 9 | #define IDI_CFGICON 201 10 | 11 | #define IDD_MAINBOX 102 12 | #define IDD_LOGBOX 110 13 | #define IDD_ABOUTBOX 111 14 | #define IDD_RECONF 112 15 | #define IDD_LICENCEBOX 113 16 | 17 | #define IDN_LIST 1001 18 | #define IDN_COPY 1002 19 | 20 | #define IDA_ICON 1001 21 | #define IDA_TEXT1 1002 22 | #define IDA_VERSION 1003 23 | #define IDA_TEXT2 1004 24 | #define IDA_LICENCE 1005 25 | #define IDA_WEB 1006 26 | 27 | #define IDC_TAB 1001 28 | #define IDC_TABSTATIC1 1002 29 | #define IDC_TABSTATIC2 1003 30 | #define IDC_TABLIST 1004 31 | #define IDC_HELPBTN 1005 32 | #define IDC_ABOUT 1006 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /windows/windefs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * windefs.c: default settings that are specific to Windows. 3 | */ 4 | 5 | #include "putty.h" 6 | 7 | #include 8 | 9 | FontSpec *platform_default_fontspec(const char *name) 10 | { 11 | if (!strcmp(name, "Font")) { 12 | OSVERSIONINFO versioninfo; 13 | versioninfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 14 | GetVersionEx(&versioninfo); 15 | 16 | if (versioninfo.dwMajorVersion >= 6) 17 | return fontspec_new("Consolas", 0, 10, ANSI_CHARSET); 18 | return fontspec_new("Courier New", 0, 10, ANSI_CHARSET); 19 | } else 20 | return fontspec_new("", 0, 0, 0); 21 | } 22 | 23 | Filename *platform_default_filename(const char *name) 24 | { 25 | if (!strcmp(name, "LogFileName")) 26 | return filename_from_str("putty.log"); 27 | else 28 | return filename_from_str(""); 29 | } 30 | 31 | char *platform_default_s(const char *name) 32 | { 33 | if (!strcmp(name, "SerialLine")) 34 | return dupstr("COM1"); 35 | return NULL; 36 | } 37 | 38 | int platform_default_i(const char *name, int def) 39 | { 40 | if (!strcmp(name, "FontQuality")) 41 | { 42 | OSVERSIONINFO versioninfo; 43 | versioninfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 44 | GetVersionEx(&versioninfo); 45 | if (versioninfo.dwMajorVersion >= 6) 46 | return FQ_CLEARTYPE; 47 | } 48 | return def; 49 | } 50 | -------------------------------------------------------------------------------- /windows/winhelp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * winhelp.c: centralised functions to launch Windows help files, 3 | * and to decide whether to use .HLP or .CHM help in any given 4 | * situation. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "putty.h" 13 | 14 | #ifndef NO_HTMLHELP 15 | #include 16 | #endif /* NO_HTMLHELP */ 17 | 18 | static int requested_help; 19 | static char *help_path; 20 | static int help_has_contents; 21 | #ifndef NO_HTMLHELP 22 | DECL_WINDOWS_FUNCTION(static, HWND, HtmlHelpA, (HWND, LPCSTR, UINT, DWORD)); 23 | static char *chm_path; 24 | #endif /* NO_HTMLHELP */ 25 | 26 | void init_help(void) 27 | { 28 | char b[2048], *p, *q, *r; 29 | FILE *fp; 30 | 31 | GetModuleFileName(NULL, b, sizeof(b) - 1); 32 | r = b; 33 | p = strrchr(b, '\\'); 34 | if (p && p >= r) r = p+1; 35 | q = strrchr(b, ':'); 36 | if (q && q >= r) r = q+1; 37 | strcpy(r, PUTTY_HELP_FILE); 38 | if ( (fp = fopen(b, "r")) != NULL) { 39 | help_path = dupstr(b); 40 | fclose(fp); 41 | } else 42 | help_path = NULL; 43 | strcpy(r, PUTTY_HELP_CONTENTS); 44 | if ( (fp = fopen(b, "r")) != NULL) { 45 | help_has_contents = TRUE; 46 | fclose(fp); 47 | } else 48 | help_has_contents = FALSE; 49 | 50 | #ifndef NO_HTMLHELP 51 | strcpy(r, PUTTY_CHM_FILE); 52 | if ( (fp = fopen(b, "r")) != NULL) { 53 | chm_path = dupstr(b); 54 | fclose(fp); 55 | } else 56 | chm_path = NULL; 57 | if (chm_path) { 58 | HINSTANCE dllHH = load_system32_dll("hhctrl.ocx"); 59 | GET_WINDOWS_FUNCTION(dllHH, HtmlHelpA); 60 | if (!p_HtmlHelpA) { 61 | chm_path = NULL; 62 | if (dllHH) 63 | FreeLibrary(dllHH); 64 | } 65 | } 66 | #endif /* NO_HTMLHELP */ 67 | } 68 | 69 | void shutdown_help(void) 70 | { 71 | /* Nothing to do currently. 72 | * (If we were running HTML Help single-threaded, this is where we'd 73 | * call HH_UNINITIALIZE.) */ 74 | } 75 | 76 | int has_help(void) 77 | { 78 | /* 79 | * FIXME: it would be nice here to disregard help_path on 80 | * platforms that didn't have WINHLP32. But that's probably 81 | * unrealistic, since even Vista will have it if the user 82 | * specifically downloads it. 83 | */ 84 | return (help_path != NULL 85 | #ifndef NO_HTMLHELP 86 | || chm_path 87 | #endif /* NO_HTMLHELP */ 88 | ); 89 | } 90 | 91 | void launch_help(HWND hwnd, const char *topic) 92 | { 93 | if (topic) { 94 | int colonpos = strcspn(topic, ":"); 95 | 96 | #ifndef NO_HTMLHELP 97 | if (chm_path) { 98 | char *fname; 99 | assert(topic[colonpos] != '\0'); 100 | fname = dupprintf("%s::/%s.html>main", chm_path, 101 | topic + colonpos + 1); 102 | p_HtmlHelpA(hwnd, fname, HH_DISPLAY_TOPIC, 0); 103 | sfree(fname); 104 | } else 105 | #endif /* NO_HTMLHELP */ 106 | if (help_path) { 107 | char *cmd = dupprintf("JI(`',`%.*s')", colonpos, topic); 108 | WinHelp(hwnd, help_path, HELP_COMMAND, (DWORD)cmd); 109 | sfree(cmd); 110 | } 111 | } else { 112 | #ifndef NO_HTMLHELP 113 | if (chm_path) { 114 | p_HtmlHelpA(hwnd, chm_path, HH_DISPLAY_TOPIC, 0); 115 | } else 116 | #endif /* NO_HTMLHELP */ 117 | if (help_path) { 118 | WinHelp(hwnd, help_path, 119 | help_has_contents ? HELP_FINDER : HELP_CONTENTS, 0); 120 | } 121 | } 122 | requested_help = TRUE; 123 | } 124 | 125 | void quit_help(HWND hwnd) 126 | { 127 | if (requested_help) { 128 | #ifndef NO_HTMLHELP 129 | if (chm_path) { 130 | p_HtmlHelpA(NULL, NULL, HH_CLOSE_ALL, 0); 131 | } else 132 | #endif /* NO_HTMLHELP */ 133 | if (help_path) { 134 | WinHelp(hwnd, help_path, HELP_QUIT, 0); 135 | } 136 | requested_help = FALSE; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /windows/winnojmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * winnojmp.c: stub jump list functions for Windows executables that 3 | * don't update the jump list. 4 | */ 5 | 6 | void add_session_to_jumplist(const char * const sessionname) {} 7 | void remove_session_from_jumplist(const char * const sessionname) {} 8 | void clear_jumplist(void) {} 9 | -------------------------------------------------------------------------------- /windows/winnpc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Windows support module which deals with being a named-pipe client. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #define DEFINE_PLUG_METHOD_MACROS 9 | #include "tree234.h" 10 | #include "putty.h" 11 | #include "network.h" 12 | #include "proxy.h" 13 | #include "ssh.h" 14 | 15 | #if !defined NO_SECURITY 16 | 17 | #include "winsecur.h" 18 | 19 | Socket make_handle_socket(HANDLE send_H, HANDLE recv_H, Plug plug, 20 | int overlapped); 21 | 22 | Socket new_named_pipe_client(const char *pipename, Plug plug) 23 | { 24 | HANDLE pipehandle; 25 | PSID usersid, pipeowner; 26 | PSECURITY_DESCRIPTOR psd; 27 | char *err; 28 | Socket ret; 29 | 30 | assert(strncmp(pipename, "\\\\.\\pipe\\", 9) == 0); 31 | assert(strchr(pipename + 9, '\\') == NULL); 32 | 33 | while (1) { 34 | pipehandle = CreateFile(pipename, GENERIC_READ | GENERIC_WRITE, 35 | 0, NULL, OPEN_EXISTING, 36 | FILE_FLAG_OVERLAPPED, NULL); 37 | 38 | if (pipehandle != INVALID_HANDLE_VALUE) 39 | break; 40 | 41 | if (GetLastError() != ERROR_PIPE_BUSY) { 42 | err = dupprintf("Unable to open named pipe '%s': %s", 43 | pipename, win_strerror(GetLastError())); 44 | ret = new_error_socket(err, plug); 45 | sfree(err); 46 | return ret; 47 | } 48 | 49 | /* 50 | * If we got ERROR_PIPE_BUSY, wait for the server to 51 | * create a new pipe instance. (Since the server is 52 | * expected to be winnps.c, which will do that immediately 53 | * after a previous connection is accepted, that shouldn't 54 | * take excessively long.) 55 | */ 56 | if (!WaitNamedPipe(pipename, NMPWAIT_USE_DEFAULT_WAIT)) { 57 | err = dupprintf("Error waiting for named pipe '%s': %s", 58 | pipename, win_strerror(GetLastError())); 59 | ret = new_error_socket(err, plug); 60 | sfree(err); 61 | return ret; 62 | } 63 | } 64 | 65 | if ((usersid = get_user_sid()) == NULL) { 66 | CloseHandle(pipehandle); 67 | err = dupprintf("Unable to get user SID"); 68 | ret = new_error_socket(err, plug); 69 | sfree(err); 70 | return ret; 71 | } 72 | 73 | if (p_GetSecurityInfo(pipehandle, SE_KERNEL_OBJECT, 74 | OWNER_SECURITY_INFORMATION, 75 | &pipeowner, NULL, NULL, NULL, 76 | &psd) != ERROR_SUCCESS) { 77 | err = dupprintf("Unable to get named pipe security information: %s", 78 | win_strerror(GetLastError())); 79 | ret = new_error_socket(err, plug); 80 | sfree(err); 81 | CloseHandle(pipehandle); 82 | sfree(usersid); 83 | return ret; 84 | } 85 | 86 | if (!EqualSid(pipeowner, usersid)) { 87 | err = dupprintf("Owner of named pipe '%s' is not us", pipename); 88 | ret = new_error_socket(err, plug); 89 | sfree(err); 90 | CloseHandle(pipehandle); 91 | LocalFree(psd); 92 | sfree(usersid); 93 | return ret; 94 | } 95 | 96 | LocalFree(psd); 97 | sfree(usersid); 98 | 99 | return make_handle_socket(pipehandle, pipehandle, plug, TRUE); 100 | } 101 | 102 | #endif /* !defined NO_SECURITY */ 103 | -------------------------------------------------------------------------------- /windows/winsecur.h: -------------------------------------------------------------------------------- 1 | /* 2 | * winsecur.h: some miscellaneous security-related helper functions, 3 | * defined in winsecur.c, that use the advapi32 library. Also 4 | * centralises the machinery for dynamically loading that library. 5 | */ 6 | 7 | #if !defined NO_SECURITY 8 | 9 | #include 10 | 11 | #ifndef WINSECUR_GLOBAL 12 | #define WINSECUR_GLOBAL extern 13 | #endif 14 | 15 | /* 16 | * Functions loaded from advapi32.dll. 17 | */ 18 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, OpenProcessToken, 19 | (HANDLE, DWORD, PHANDLE)); 20 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, GetTokenInformation, 21 | (HANDLE, TOKEN_INFORMATION_CLASS, 22 | LPVOID, DWORD, PDWORD)); 23 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, InitializeSecurityDescriptor, 24 | (PSECURITY_DESCRIPTOR, DWORD)); 25 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, SetSecurityDescriptorOwner, 26 | (PSECURITY_DESCRIPTOR, PSID, BOOL)); 27 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, DWORD, GetSecurityInfo, 28 | (HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION, 29 | PSID *, PSID *, PACL *, PACL *, 30 | PSECURITY_DESCRIPTOR *)); 31 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, DWORD, SetEntriesInAclA, 32 | (ULONG, PEXPLICIT_ACCESS, PACL, PACL *)); 33 | int got_advapi(void); 34 | 35 | /* 36 | * Functions loaded from crypt32.dll. 37 | */ 38 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, CryptProtectMemory, 39 | (LPVOID, DWORD, DWORD)); 40 | int got_crypt(void); 41 | 42 | /* 43 | * Find the SID describing the current user. The return value (if not 44 | * NULL for some error-related reason) is smalloced. 45 | */ 46 | PSID get_user_sid(void); 47 | 48 | /* 49 | * Construct a PSECURITY_DESCRIPTOR of the type used for named pipe 50 | * servers, i.e. allowing access only to the current user id and also 51 | * only local (i.e. not over SMB) connections. 52 | * 53 | * If this function returns TRUE, then 'psd' and 'acl' will have been 54 | * filled in with memory allocated using LocalAlloc (and hence must be 55 | * freed later using LocalFree). If it returns FALSE, then instead 56 | * 'error' has been filled with a dynamically allocated error message. 57 | */ 58 | int make_private_security_descriptor(DWORD permissions, 59 | PSECURITY_DESCRIPTOR *psd, 60 | PACL *acl, 61 | char **error); 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /windows/wintime.c: -------------------------------------------------------------------------------- 1 | /* 2 | * wintime.c - Avoid trouble with time() returning (time_t)-1 on Windows. 3 | */ 4 | 5 | #include "putty.h" 6 | #include 7 | 8 | struct tm ltime(void) 9 | { 10 | SYSTEMTIME st; 11 | struct tm tm; 12 | 13 | GetLocalTime(&st); 14 | tm.tm_sec=st.wSecond; 15 | tm.tm_min=st.wMinute; 16 | tm.tm_hour=st.wHour; 17 | tm.tm_mday=st.wDay; 18 | tm.tm_mon=st.wMonth-1; 19 | tm.tm_year=(st.wYear>=1900?st.wYear-1900:0); 20 | tm.tm_wday=st.wDayOfWeek; 21 | tm.tm_yday=-1; /* GetLocalTime doesn't tell us */ 22 | tm.tm_isdst=0; /* GetLocalTime doesn't tell us */ 23 | return tm; 24 | } 25 | -------------------------------------------------------------------------------- /windows/winx11.c: -------------------------------------------------------------------------------- 1 | /* 2 | * winx11.c: fetch local auth data for X forwarding. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "putty.h" 10 | #include "ssh.h" 11 | 12 | void platform_get_x11_auth(struct X11Display *disp, Conf *conf) 13 | { 14 | char *xauthpath = conf_get_filename(conf, CONF_xauthfile)->path; 15 | if (xauthpath[0]) 16 | x11_get_auth_from_authfile(disp, xauthpath); 17 | } 18 | 19 | const int platform_uses_x11_unix_by_default = FALSE; 20 | --------------------------------------------------------------------------------