Next phase of general SFTP reworking: psftp.c is now a platform-
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 24 Aug 2003 12:47:46 +0000 (12:47 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 24 Aug 2003 12:47:46 +0000 (12:47 +0000)
independent source file. All Windowsisms have been moved out to
winsftp.c.

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

Recipe
psftp.c
psftp.h [new file with mode: 0644]
winsftp.c [new file with mode: 0644]

diff --git a/Recipe b/Recipe
index 51d2ede..7e7295b 100644 (file)
--- a/Recipe
+++ b/Recipe
@@ -140,7 +140,7 @@ puttytel : [G] GUITERM NONSSH be_nossh WINMISC win_res.res LIBS1
 plink    : [C] plink console NONSSH WINSSH be_all logging WINMISC
          + plink.res LIBS2
 pscp     : [C] scp console WINSSH be_none SFTP wildcard WINMISC scp.res LIBS1
-psftp    : [C] psftp console WINSSH be_none SFTP WINMISC scp.res LIBS1
+psftp    : [C] psftp winsftp console WINSSH be_none SFTP WINMISC scp.res LIBS1
 
 pageant  : [G] pageant sshrsa sshpubk sshdes sshbn sshmd5 version tree234
          + misc sshaes sshsha pageantc sshdss sshsh512 winutils winmisc
@@ -159,6 +159,8 @@ puttytel : [X] UXTERM uxmisc misc ldisc settings pty uxsel be_nossh uxstore
 
 plink    : [U] uxplink uxcons NONSSH UXSSH be_all logging UXMISC signal ux_x11
 
+# psftp    : [U] psftp uxsftp console UXSSH be_none SFTP UXMISC
+
 PuTTY    : [M] terminal wcwidth ldiscucs logging be_all mac macdlg macevlog
          + macterm macucs mac_res.rsrc testback NONSSH MACSSH MACMISC CHARSET
          + stricmp vsnprint dialog config macctrls
diff --git a/psftp.c b/psftp.c
index 484d153..a032c70 100644 (file)
--- a/psftp.c
+++ b/psftp.c
@@ -2,8 +2,6 @@
  * psftp.c: front end for PSFTP.
  */
 
-#include <windows.h>
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
@@ -12,6 +10,7 @@
 
 #define PUTTY_DO_GLOBALS
 #include "putty.h"
+#include "psftp.h"
 #include "storage.h"
 #include "ssh.h"
 #include "sftp.h"
@@ -1024,34 +1023,21 @@ static int sftp_cmd_open(struct sftp_command *cmd)
 
 static int sftp_cmd_lcd(struct sftp_command *cmd)
 {
-    char *currdir;
-    int len;
+    char *currdir, *errmsg;
 
     if (cmd->nwords < 2) {
        printf("lcd: expects a local directory name\n");
        return 0;
     }
 
-    if (!SetCurrentDirectory(cmd->words[1])) {
-       LPVOID message;
-       int i;
-       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-                     FORMAT_MESSAGE_FROM_SYSTEM |
-                     FORMAT_MESSAGE_IGNORE_INSERTS,
-                     NULL, GetLastError(),
-                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-                     (LPTSTR)&message, 0, NULL);
-       i = strcspn((char *)message, "\n");
-       printf("lcd: unable to change directory: %.*s\n", i, (LPCTSTR)message);
-       LocalFree(message);
+    errmsg = psftp_lcd(cmd->words[1]);
+    if (errmsg) {
+       printf("lcd: unable to change directory: %s\n", errmsg);
+       sfree(errmsg);
        return 0;
     }
 
-    currdir = snewn(256, char);
-    len = GetCurrentDirectory(256, currdir);
-    if (len > 256)
-       currdir = sresize(currdir, len, char);
-    GetCurrentDirectory(len, currdir);
+    currdir = psftp_getcwd();
     printf("New local directory is %s\n", currdir);
     sfree(currdir);
 
@@ -1061,13 +1047,8 @@ static int sftp_cmd_lcd(struct sftp_command *cmd)
 static int sftp_cmd_lpwd(struct sftp_command *cmd)
 {
     char *currdir;
-    int len;
 
-    currdir = snewn(256, char);
-    len = GetCurrentDirectory(256, currdir);
-    if (len > 256)
-       currdir = sresize(currdir, len, char);
-    GetCurrentDirectory(len, currdir);
+    currdir = psftp_getcwd();
     printf("Current local directory is %s\n", currdir);
     sfree(currdir);
 
@@ -1108,9 +1089,10 @@ static struct sftp_cmd_lookup {
      * in ASCII order.
      */
     {
-       "!", TRUE, "run a local Windows command",
+       "!", TRUE, "run a local command",
            "<command>\n"
-           "  Runs a local Windows command. For example, \"!del myfile\".\n",
+           /* FIXME: this example is crap for non-Windows. */
+           "  Runs a local command. For example, \"!del myfile\".\n",
            sftp_cmd_pling
     },
     {
@@ -1621,20 +1603,6 @@ void ldisc_send(void *handle, char *buf, int len, int interactive)
 }
 
 /*
- * Be told what socket we're supposed to be using.
- */
-static SOCKET sftp_ssh_socket;
-char *do_select(SOCKET skt, int startup)
-{
-    if (startup)
-       sftp_ssh_socket = skt;
-    else
-       sftp_ssh_socket = INVALID_SOCKET;
-    return NULL;
-}
-extern int select_result(WPARAM, LPARAM);
-
-/*
  * In psftp, all agent requests should be synchronous, so this is a
  * never-called stub.
  */
@@ -1729,13 +1697,8 @@ int sftp_recvdata(char *buf, int len)
     }
 
     while (outlen > 0) {
-       fd_set readfds;
-
-       FD_ZERO(&readfds);
-       FD_SET(sftp_ssh_socket, &readfds);
-       if (select(1, &readfds, NULL, NULL, NULL) < 0)
+       if (ssh_sftp_loop_iteration() < 0)
            return 0;                  /* doom */
-       select_result((WPARAM) sftp_ssh_socket, (LPARAM) FD_READ);
     }
 
     return 1;
@@ -1747,42 +1710,6 @@ int sftp_senddata(char *buf, int len)
 }
 
 /*
- * Loop through the ssh connection and authentication process.
- */
-static void ssh_sftp_init(void)
-{
-    if (sftp_ssh_socket == INVALID_SOCKET)
-       return;
-    while (!back->sendok(backhandle)) {
-       fd_set readfds;
-       FD_ZERO(&readfds);
-       FD_SET(sftp_ssh_socket, &readfds);
-       if (select(1, &readfds, NULL, NULL, NULL) < 0)
-           return;                    /* doom */
-       select_result((WPARAM) sftp_ssh_socket, (LPARAM) FD_READ);
-    }
-}
-
-/*
- *  Initialize the Win$ock driver.
- */
-static void init_winsock(void)
-{
-    WORD winsock_ver;
-    WSADATA wsadata;
-
-    winsock_ver = MAKEWORD(1, 1);
-    if (WSAStartup(winsock_ver, &wsadata)) {
-       fprintf(stderr, "Unable to initialise WinSock");
-       cleanup_exit(1);
-    }
-    if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1) {
-       fprintf(stderr, "WinSock version is incompatible with 1.1");
-       cleanup_exit(1);
-    }
-}
-
-/*
  *  Short description of parameters.
  */
 static void usage(void)
@@ -1963,7 +1890,12 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
     logctx = log_init(NULL, &cfg);
     back->provide_logctx(backhandle, logctx);
     console_provide_logctx(logctx);
-    ssh_sftp_init();
+    while (!back->sendok(backhandle)) {
+       if (ssh_sftp_loop_iteration() < 0) {
+           fprintf(stderr, "ssh_init: error during SSH connection setup\n");
+           return 1;
+       }
+    }
     if (verbose && realhost != NULL)
        printf("Connected to %s\n", realhost);
     return 0;
@@ -1983,7 +1915,7 @@ void cmdline_error(char *p, ...)
 /*
  * Main program. Parse arguments etc.
  */
-int main(int argc, char *argv[])
+int psftp_main(int argc, char *argv[])
 {
     int i;
     int portnumber = 0;
@@ -1996,7 +1928,6 @@ int main(int argc, char *argv[])
     flags = FLAG_STDERR | FLAG_INTERACTIVE | FLAG_SYNCAGENT;
     cmdline_tooltype = TOOLTYPE_FILETRANSFER;
     ssh_get_line = &console_get_line;
-    init_winsock();
     sk_init();
 
     userhost = user = NULL;
@@ -2064,7 +1995,6 @@ int main(int argc, char *argv[])
        back->special(backhandle, TS_EOF);
        sftp_recvdata(&ch, 1);
     }
-    WSACleanup();
     random_save_seed();
 
     return 0;
diff --git a/psftp.h b/psftp.h
new file mode 100644 (file)
index 0000000..092d10a
--- /dev/null
+++ b/psftp.h
@@ -0,0 +1,28 @@
+/*\r
+ * psftp.h: interface between psftp.c and each platform-specific\r
+ * SFTP module.\r
+ */\r
+\r
+#ifndef PUTTY_PSFTP_H\r
+#define PUTTY_PSFTP_H\r
+\r
+/*\r
+ * psftp_getcwd returns the local current directory. The returned\r
+ * string must be freed by the caller.\r
+ */\r
+char *psftp_getcwd(void);\r
+\r
+/*\r
+ * psftp_lcd changes the local current directory. The return value\r
+ * is NULL on success, or else an error message which must be freed\r
+ * by the caller.\r
+ */\r
+char *psftp_lcd(char *newdir);\r
+\r
+/*\r
+ * One iteration of the PSFTP event loop: wait for network data and\r
+ * process it, once.\r
+ */\r
+int ssh_sftp_loop_iteration(void);\r
+\r
+#endif /* PUTTY_PSFTP_H */\r
diff --git a/winsftp.c b/winsftp.c
new file mode 100644 (file)
index 0000000..677bf02
--- /dev/null
+++ b/winsftp.c
@@ -0,0 +1,113 @@
+/*
+ * winsftp.c: the Windows-specific parts of PSFTP.
+ */
+
+#include <windows.h>
+
+#include "putty.h"
+#include "psftp.h"
+
+/*
+ * Be told what socket we're supposed to be using.
+ */
+static SOCKET sftp_ssh_socket;
+char *do_select(SOCKET skt, int startup)
+{
+    if (startup)
+       sftp_ssh_socket = skt;
+    else
+       sftp_ssh_socket = INVALID_SOCKET;
+    return NULL;
+}
+extern int select_result(WPARAM, LPARAM);
+
+/*
+ * Initialize the WinSock driver.
+ */
+static void init_winsock(void)
+{
+    WORD winsock_ver;
+    WSADATA wsadata;
+
+    winsock_ver = MAKEWORD(1, 1);
+    if (WSAStartup(winsock_ver, &wsadata)) {
+       fprintf(stderr, "Unable to initialise WinSock");
+       cleanup_exit(1);
+    }
+    if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1) {
+       fprintf(stderr, "WinSock version is incompatible with 1.1");
+       cleanup_exit(1);
+    }
+}
+
+/*
+ * Set local current directory. Returns NULL on success, or else an
+ * error message which must be freed after printing.
+ */
+char *psftp_lcd(char *dir)
+{
+    char *ret = NULL;
+
+    if (!SetCurrentDirectory(dir)) {
+       LPVOID message;
+       int i;
+       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                     FORMAT_MESSAGE_FROM_SYSTEM |
+                     FORMAT_MESSAGE_IGNORE_INSERTS,
+                     NULL, GetLastError(),
+                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                     (LPTSTR)&message, 0, NULL);
+       i = strcspn((char *)message, "\n");
+       ret = dupprintf("%.*s", i, (LPCTSTR)message);
+       LocalFree(message);
+    }
+
+    return ret;
+}
+
+/*
+ * Get local current directory. Returns a string which must be
+ * freed.
+ */
+char *psftp_getcwd(void)
+{
+    char *ret = snewn(256, char);
+    int len = GetCurrentDirectory(256, ret);
+    if (len > 256)
+       ret = sresize(ret, len, char);
+    GetCurrentDirectory(len, ret);
+    return ret;
+}
+
+/*
+ * Wait for some network data and process it.
+ */
+int ssh_sftp_loop_iteration(void)
+{
+    fd_set readfds;
+
+    if (sftp_ssh_socket == INVALID_SOCKET)
+       return -1;                     /* doom */
+
+    FD_ZERO(&readfds);
+    FD_SET(sftp_ssh_socket, &readfds);
+    if (select(1, &readfds, NULL, NULL, NULL) < 0)
+       return -1;                     /* doom */
+
+    select_result((WPARAM) sftp_ssh_socket, (LPARAM) FD_READ);
+    return 0;
+}
+
+/*
+ * Main program. Parse arguments etc.
+ */
+int main(int argc, char *argv[])
+{
+    int ret;
+
+    init_winsock();
+    ret = psftp_main(argc, argv);
+    WSACleanup();
+
+    return ret;
+}