Ensure our network layer is properly cleaned up before PuTTY exits.
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Wed, 6 Mar 2002 20:13:22 +0000 (20:13 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Wed, 6 Mar 2002 20:13:22 +0000 (20:13 +0000)
Specifically, we explicitly closesocket() all open sockets, which
appears to be necessary since otherwise Windows sends RST rather
than FIN. I'm _sure_ that's a Windows bug, but there we go.

git-svn-id: svn://svn.tartarus.org/sgt/putty@1574 cda61777-01e9-0310-a592-d414129be87e

15 files changed:
console.c
misc.c
network.h
noise.c
pageant.c
plink.c
psftp.c
putty.h
puttygen.c
scp.c
ssh.c
sshrand.c
windlg.c
window.c
winnet.c

index 2a7efdc..557c144 100644 (file)
--- a/console.c
+++ b/console.c
 
 int console_batch_mode = FALSE;
 
+/*
+ * Clean up and exit.
+ */
+void cleanup_exit(int code)
+{
+    /*
+     * Clean up.
+     */
+    sk_cleanup();
+    WSACleanup();
+
+    if (cfg.protocol == PROT_SSH) {
+       random_save_seed();
+#ifdef MSCRYPTOAPI
+       crypto_wrapup();
+#endif
+    }
+
+    exit(code);
+}
+
 void verify_ssh_host_key(char *host, int port, char *keytype,
                         char *keystr, char *fingerprint)
 {
@@ -86,7 +107,7 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
     if (ret == 2) {                   /* key was different */
        if (console_batch_mode) {
            fprintf(stderr, wrongmsg_batch, fingerprint);
-           exit(1);
+           cleanup_exit(1);
        }
        fprintf(stderr, wrongmsg, fingerprint);
        fflush(stderr);
@@ -94,7 +115,7 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
     if (ret == 1) {                   /* key was absent */
        if (console_batch_mode) {
            fprintf(stderr, absentmsg_batch, fingerprint);
-           exit(1);
+           cleanup_exit(1);
        }
        fprintf(stderr, absentmsg, fingerprint);
        fflush(stderr);
@@ -112,7 +133,7 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
            store_host_key(host, port, keytype, keystr);
     } else {
        fprintf(stderr, abandoned);
-       exit(0);
+       cleanup_exit(0);
     }
 }
 
@@ -143,7 +164,7 @@ void askcipher(char *ciphername, int cs)
                (cs == 0) ? "" :
                (cs == 1) ? "client-to-server " : "server-to-client ",
                ciphername);
-       exit(1);
+       cleanup_exit(1);
     }
 
     fprintf(stderr, msg,
@@ -163,7 +184,7 @@ void askcipher(char *ciphername, int cs)
        return;
     } else {
        fprintf(stderr, abandoned);
-       exit(0);
+       cleanup_exit(0);
     }
 }
 
@@ -266,7 +287,7 @@ int console_get_line(const char *prompt, char *str,
        hout = GetStdHandle(STD_OUTPUT_HANDLE);
        if (hin == INVALID_HANDLE_VALUE || hout == INVALID_HANDLE_VALUE) {
            fprintf(stderr, "Cannot get standard input/output handles\n");
-           exit(1);
+           cleanup_exit(1);
        }
 
        GetConsoleMode(hin, &savemode);
diff --git a/misc.c b/misc.c
index a2d741e..ee1abf7 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -415,7 +415,7 @@ void *safemalloc(size_t size)
 #endif
        MessageBox(NULL, str, "PuTTY Fatal Error",
                   MB_SYSTEMMODAL | MB_ICONERROR | MB_OK);
-       exit(1);
+       cleanup_exit(1);
     }
 #ifdef MALLOC_LOG
     if (fp)
@@ -452,7 +452,7 @@ void *saferealloc(void *ptr, size_t size)
 #endif
        MessageBox(NULL, str, "PuTTY Fatal Error",
                   MB_SYSTEMMODAL | MB_ICONERROR | MB_OK);
-       exit(1);
+       cleanup_exit(1);
     }
 #ifdef MALLOC_LOG
     if (fp)
index 3ec9eb7..2cab438 100644 (file)
--- a/network.h
+++ b/network.h
@@ -62,6 +62,7 @@ struct plug_function_table {
 
 
 void sk_init(void);                   /* called once at program startup */
+void sk_cleanup(void);                /* called just before program exit */
 
 SockAddr sk_namelookup(char *host, char **canonicalname);
 void sk_getaddr(SockAddr addr, char *buf, int buflen);
diff --git a/noise.c b/noise.c
index 856974b..a094d25 100644 (file)
--- a/noise.c
+++ b/noise.c
@@ -53,8 +53,10 @@ void random_save_seed(void)
     int len;
     void *data;
 
-    random_get_savedata(&data, &len);
-    write_random_seed(data, len);
+    if (random_active) {
+       random_get_savedata(&data, &len);
+       write_random_seed(data, len);
+    }
 }
 
 /*
index 12e03a8..c4eef55 100644 (file)
--- a/pageant.c
+++ b/pageant.c
@@ -1658,6 +1658,8 @@ void spawn_cmd(char *cmdline, char * args, int show)
     }
 }
 
+void cleanup_exit(int code) { exit(code); }
+
 int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
 {
     WNDCLASS wndclass;
diff --git a/plink.c b/plink.c
index b2c07ac..a76570e 100644 (file)
--- a/plink.c
+++ b/plink.c
@@ -27,7 +27,7 @@ void fatalbox(char *p, ...)
     va_end(ap);
     fputc('\n', stderr);
     WSACleanup();
-    exit(1);
+    cleanup_exit(1);
 }
 void connection_fatal(char *p, ...)
 {
@@ -38,7 +38,7 @@ void connection_fatal(char *p, ...)
     va_end(ap);
     fputc('\n', stderr);
     WSACleanup();
-    exit(1);
+    cleanup_exit(1);
 }
 
 static char *password = NULL;
@@ -607,7 +607,7 @@ int main(int argc, char **argv)
     if (!CreateThread(NULL, 0, stdout_write_thread,
                      &odata, 0, &out_threadid)) {
        fprintf(stderr, "Unable to create output thread\n");
-       exit(1);
+       cleanup_exit(1);
     }
     edata.event = stderrevent;
     edata.eventback = CreateEvent(NULL, FALSE, FALSE, NULL);
@@ -616,7 +616,7 @@ int main(int argc, char **argv)
     if (!CreateThread(NULL, 0, stdout_write_thread,
                      &edata, 0, &err_threadid)) {
        fprintf(stderr, "Unable to create error output thread\n");
-       exit(1);
+       cleanup_exit(1);
     }
 
     while (1) {
@@ -644,7 +644,7 @@ int main(int argc, char **argv)
            if (!CreateThread(NULL, 0, stdin_read_thread,
                              &idata, 0, &in_threadid)) {
                fprintf(stderr, "Unable to create input thread\n");
-               exit(1);
+               cleanup_exit(1);
            }
            sending = TRUE;
        }
@@ -725,7 +725,7 @@ int main(int argc, char **argv)
            odata.busy = 0;
            if (!odata.writeret) {
                fprintf(stderr, "Unable to write to standard output\n");
-               exit(0);
+               cleanup_exit(0);
            }
            bufchain_consume(&stdout_data, odata.lenwritten);
            if (bufchain_size(&stdout_data) > 0)
@@ -738,7 +738,7 @@ int main(int argc, char **argv)
            edata.busy = 0;
            if (!edata.writeret) {
                fprintf(stderr, "Unable to write to standard output\n");
-               exit(0);
+               cleanup_exit(0);
            }
            bufchain_consume(&stderr_data, edata.lenwritten);
            if (bufchain_size(&stderr_data) > 0)
diff --git a/psftp.c b/psftp.c
index 094e68b..6dae40a 100644 (file)
--- a/psftp.c
+++ b/psftp.c
@@ -1453,7 +1453,7 @@ void fatalbox(char *fmt, ...)
     strcat(str, "\n");
     fputs(str, stderr);
 
-    exit(1);
+    cleanup_exit(1);
 }
 void connection_fatal(char *fmt, ...)
 {
@@ -1466,7 +1466,7 @@ void connection_fatal(char *fmt, ...)
     strcat(str, "\n");
     fputs(str, stderr);
 
-    exit(1);
+    cleanup_exit(1);
 }
 
 void ldisc_send(char *buf, int len, int interactive)
@@ -1627,11 +1627,11 @@ static void init_winsock(void)
     winsock_ver = MAKEWORD(1, 1);
     if (WSAStartup(winsock_ver, &wsadata)) {
        fprintf(stderr, "Unable to initialise WinSock");
-       exit(1);
+       cleanup_exit(1);
     }
     if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1) {
        fprintf(stderr, "WinSock version is incompatible with 1.1");
-       exit(1);
+       cleanup_exit(1);
     }
 }
 
@@ -1650,7 +1650,7 @@ static void usage(void)
     printf("  -v        show verbose messages\n");
     printf("  -P port   connect to specified port\n");
     printf("  -pw passw login with specified password\n");
-    exit(1);
+    cleanup_exit(1);
 }
 
 /*
@@ -1720,7 +1720,7 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
        printf("login as: ");
        if (!fgets(cfg.username, sizeof(cfg.username), stdin)) {
            fprintf(stderr, "psftp: aborting\n");
-           exit(1);
+           cleanup_exit(1);
        } else {
            int len = strlen(cfg.username);
            if (cfg.username[len - 1] == '\n')
diff --git a/putty.h b/putty.h
index baa55ff..04804c2 100644 (file)
--- a/putty.h
+++ b/putty.h
@@ -427,6 +427,8 @@ void get_window_pos(int *x, int *y);
 void get_window_pixels(int *x, int *y);
 char *get_window_title(int icon);
 
+void cleanup_exit(int);
+
 /*
  * Exports from noise.c.
  */
@@ -536,6 +538,7 @@ void random_add_noise(void *noise, int length);
 void random_init(void);
 int random_byte(void);
 void random_get_savedata(void **data, int *len);
+extern int random_active;
 
 /*
  * Exports from misc.c.
index 330176c..6116e0f 100644 (file)
@@ -1142,6 +1142,8 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
     return 0;
 }
 
+void cleanup_exit(int code) { exit(code); }
+
 int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
 {
     InitCommonControls();
diff --git a/scp.c b/scp.c
index 34f6ffb..bde4cda 100644 (file)
--- a/scp.c
+++ b/scp.c
@@ -210,7 +210,7 @@ void fatalbox(char *fmt, ...)
                0 /*lParam */ ))SleepEx(1000, TRUE);
     }
 
-    exit(1);
+    cleanup_exit(1);
 }
 void connection_fatal(char *fmt, ...)
 {
@@ -233,7 +233,7 @@ void connection_fatal(char *fmt, ...)
                0 /*lParam */ ))SleepEx(1000, TRUE);
     }
 
-    exit(1);
+    cleanup_exit(1);
 }
 
 /*
@@ -404,7 +404,7 @@ static void bump(char *fmt, ...)
                0 /*lParam */ ))SleepEx(1000, TRUE);
     }
 
-    exit(1);
+    cleanup_exit(1);
 }
 
 /*
@@ -2055,7 +2055,7 @@ static void usage(void)
     printf
        ("  -gui hWnd GUI mode with the windows handle for receiving messages\n");
 #endif
-    exit(1);
+    cleanup_exit(1);
 }
 
 /*
diff --git a/ssh.c b/ssh.c
index 4fb0822..d03de08 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -2168,8 +2168,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
                            break;
                          case 3:
                          case 4:
-                           random_save_seed();
-                           exit(0);
+                           cleanup_exit(0);
                            break;
                          default:
                            if (((c >= ' ' && c <= '~') ||
@@ -2474,8 +2473,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
                        break;
                      case 3:
                      case 4:
-                       random_save_seed();
-                       exit(0);
+                       cleanup_exit(0);
                        break;
                      default:
                        if (pos < sizeof(password)-1)
@@ -3973,8 +3971,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
                            break;
                          case 3:
                          case 4:
-                           random_save_seed();
-                           exit(0);
+                           cleanup_exit(0);
                            break;
                          default:
                            if (((c >= ' ' && c <= '~') ||
@@ -4452,8 +4449,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
                                break;
                              case 3:
                              case 4:
-                               random_save_seed();
-                               exit(0);
+                               cleanup_exit(0);
                                break;
                              default:
                                if (pos < sizeof(password)-1)
index 3014da4..7c401af 100644 (file)
--- a/sshrand.c
+++ b/sshrand.c
@@ -39,7 +39,7 @@ struct RandPool {
 };
 
 static struct RandPool pool;
-static int random_active = 0;
+int random_active = 0;
 
 void random_stir(void)
 {
index 7ee5c97..20d7fc2 100644 (file)
--- a/windlg.c
+++ b/windlg.c
@@ -3365,7 +3365,7 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
        if (mbret == IDYES)
            store_host_key(host, port, keytype, keystr);
        if (mbret == IDCANCEL)
-           exit(0);
+           cleanup_exit(0);
     }
     if (ret == 1) {                   /* key was absent */
        int mbret;
@@ -3375,7 +3375,7 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
        if (mbret == IDYES)
            store_host_key(host, port, keytype, keystr);
        if (mbret == IDCANCEL)
-           exit(0);
+           cleanup_exit(0);
     }
 }
 
@@ -3406,7 +3406,7 @@ void askcipher(char *ciphername, int cs)
     if (mbret == IDYES)
        return;
     else
-       exit(0);
+       cleanup_exit(0);
 }
 
 /*
index 4bcc269..a779dbc 100644 (file)
--- a/window.c
+++ b/window.c
@@ -159,6 +159,8 @@ static char *window_name, *icon_name;
 
 static int compose_state = 0;
 
+static int wsa_started = 0;
+
 static OSVERSIONINFO osVersion;
 
 static UINT wm_mousewheel = WM_MOUSEWHEEL;
@@ -192,6 +194,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        WSACleanup();
        return 1;
     }
+    wsa_started = 1;
     /* WISHLIST: maybe allow config tweaking even if winsock not present? */
     sk_init();
 
@@ -753,6 +756,14 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        }
     }
 
+    cleanup_exit(msg.wParam);
+}
+
+/*
+ * Clean up and exit.
+ */
+void cleanup_exit(int code)
+{
     /*
      * Clean up.
      */
@@ -760,7 +771,9 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
     sfree(logpal);
     if (pal)
        DeleteObject(pal);
-    WSACleanup();
+    sk_cleanup();
+    if (wsa_started)
+       WSACleanup();
 
     if (cfg.protocol == PROT_SSH) {
        random_save_seed();
@@ -769,7 +782,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
 #endif
     }
 
-    return msg.wParam;
+    exit(code);
 }
 
 /*
@@ -4123,7 +4136,7 @@ void fatalbox(char *fmt, ...)
     vsprintf(stuff, fmt, ap);
     va_end(ap);
     MessageBox(hwnd, stuff, "PuTTY Fatal Error", MB_ICONERROR | MB_OK);
-    exit(1);
+    cleanup_exit(1);
 }
 
 /*
index 1663148..0dac18e 100644 (file)
--- a/winnet.c
+++ b/winnet.c
@@ -124,6 +124,18 @@ void sk_init(void)
     sktree = newtree234(cmpfortree);
 }
 
+void sk_cleanup(void)
+{
+    Actual_Socket s;
+    int i;
+
+    if (sktree) {
+       for (i = 0; (s = index234(sktree, i)) != NULL; i++) {
+           closesocket(s->s);
+       }
+    }
+}
+
 char *winsock_error_string(int error)
 {
     switch (error) {