And just to prove that psftp.c really is now platform-independent
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 24 Aug 2003 13:22:17 +0000 (13:22 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 24 Aug 2003 13:22:17 +0000 (13:22 +0000)
... here's a Unix port of PSFTP. Woo. (Oddly PSCP looks to be
somewhat harder; there's more Windows code interleaved than there
was in PSFTP.)

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

Recipe
psftp.c
psftp.h
sftp.c
unix/.cvsignore
unix/unix.h
unix/uxcons.c
unix/uxplink.c
unix/uxsftp.c [new file with mode: 0644]

diff --git a/Recipe b/Recipe
index 7e7295b..4422441 100644 (file)
--- a/Recipe
+++ b/Recipe
@@ -159,7 +159,7 @@ 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
+psftp    : [U] psftp uxsftp uxcons 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
diff --git a/psftp.c b/psftp.c
index a032c70..5389659 100644 (file)
--- a/psftp.c
+++ b/psftp.c
@@ -894,20 +894,20 @@ int sftp_cmd_chmod(struct sftp_command *cmd)
                  default:
                    printf("chmod: file mode '%.*s' contains unrecognised"
                           " user/group/other specifier '%c'\n",
-                          strcspn(modebegin, ","), modebegin, *mode);
+                          (int)strcspn(modebegin, ","), modebegin, *mode);
                    return 0;
                }
                mode++;
            }
            if (!*mode || *mode == ',') {
                printf("chmod: file mode '%.*s' is incomplete\n",
-                      strcspn(modebegin, ","), modebegin);
+                      (int)strcspn(modebegin, ","), modebegin);
                return 0;
            }
            action = *mode++;
            if (!*mode || *mode == ',') {
                printf("chmod: file mode '%.*s' is incomplete\n",
-                      strcspn(modebegin, ","), modebegin);
+                      (int)strcspn(modebegin, ","), modebegin);
                return 0;
            }
            perms = 0;
@@ -922,7 +922,7 @@ int sftp_cmd_chmod(struct sftp_command *cmd)
                        (subset & 06777) != 02070) {
                        printf("chmod: file mode '%.*s': set[ug]id bit should"
                               " be used with exactly one of u or g only\n",
-                              strcspn(modebegin, ","), modebegin);
+                              (int)strcspn(modebegin, ","), modebegin);
                        return 0;
                    }
                    perms |= 06000;
@@ -930,7 +930,7 @@ int sftp_cmd_chmod(struct sftp_command *cmd)
                  default:
                    printf("chmod: file mode '%.*s' contains unrecognised"
                           " permission specifier '%c'\n",
-                          strcspn(modebegin, ","), modebegin, *mode);
+                          (int)strcspn(modebegin, ","), modebegin, *mode);
                    return 0;
                }
                mode++;
@@ -938,7 +938,7 @@ int sftp_cmd_chmod(struct sftp_command *cmd)
            if (!(subset & 06777) && (perms &~ subset)) {
                printf("chmod: file mode '%.*s' contains no user/group/other"
                       " specifier and permissions other than 't' \n",
-                      strcspn(modebegin, ","), modebegin);
+                      (int)strcspn(modebegin, ","), modebegin);
                return 0;
            }
            perms &= subset;
@@ -1740,6 +1740,7 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
 {
     char *host, *realhost;
     const char *err;
+    void *logctx;
 
     /* Separate host and username */
     host = userhost;
@@ -1925,7 +1926,11 @@ int psftp_main(int argc, char *argv[])
     char *batchfile = NULL;
     int errors = 0;
 
-    flags = FLAG_STDERR | FLAG_INTERACTIVE | FLAG_SYNCAGENT;
+    flags = FLAG_STDERR | FLAG_INTERACTIVE
+#ifdef FLAG_SYNCAGENT
+       | FLAG_SYNCAGENT
+#endif
+       ;
     cmdline_tooltype = TOOLTYPE_FILETRANSFER;
     ssh_get_line = &console_get_line;
     sk_init();
diff --git a/psftp.h b/psftp.h
index 092d10a..30fbd88 100644 (file)
--- a/psftp.h
+++ b/psftp.h
@@ -25,4 +25,10 @@ char *psftp_lcd(char *newdir);
  */\r
 int ssh_sftp_loop_iteration(void);\r
 \r
+/*\r
+ * The main program in psftp.c. Called from main() in the platform-\r
+ * specific code, after doing any platform-specific initialisation.\r
+ */\r
+int psftp_main(int argc, char *argv[]);\r
+\r
 #endif /* PUTTY_PSFTP_H */\r
diff --git a/sftp.c b/sftp.c
index e19c985..b9dc44b 100644 (file)
--- a/sftp.c
+++ b/sftp.c
@@ -67,10 +67,12 @@ static struct sftp_packet *sftp_pkt_init(int pkt_type)
     sftp_pkt_addbyte(pkt, (unsigned char) pkt_type);
     return pkt;
 }
+/*
 static void sftp_pkt_addbool(struct sftp_packet *pkt, unsigned char value)
 {
     sftp_pkt_adddata(pkt, &value, 1);
 }
+*/
 static void sftp_pkt_adduint32(struct sftp_packet *pkt,
                               unsigned long value)
 {
@@ -282,7 +284,6 @@ static tree234 *sftp_requests;
 
 static struct sftp_request *sftp_alloc_request(void)
 {
-    const unsigned CHANNEL_NUMBER_OFFSET = 256;
     unsigned low, high, mid;
     int tsize;
     struct sftp_request *r;
@@ -296,7 +297,7 @@ static struct sftp_request *sftp_alloc_request(void)
      * B-tree to find the largest ID which is in a contiguous
      * sequence from the beginning. (Precisely everything in that
      * sequence must have ID equal to its tree index plus
-     * SEQUENCE_NUMBER_OFFSET.)
+     * REQUEST_ID_OFFSET.)
      */
     tsize = count234(sftp_requests);
 
index 781d9db..24c9bd8 100644 (file)
@@ -1,4 +1,4 @@
 Makefile.gtk Makefile
 local
-plink pterm putty puttytel
+plink pterm putty puttytel psftp
 *.log
index dbb28d6..f12f576 100644 (file)
@@ -51,8 +51,6 @@ unsigned long getticks(void);        /* based on gettimeofday(2) */
 #define WCHAR wchar_t
 #define BYTE unsigned char
 
-GLOBAL void *logctx;
-
 /* Things pty.c needs from pterm.c */
 char *get_x_display(void *frontend);
 int font_dimension(void *frontend, int which);/* 0 for width, 1 for height */
@@ -128,4 +126,13 @@ int init_ucs(struct unicode_data *ucsdata,
  */
 int sk_getxdmdata(void *sock, unsigned long *ip, int *port);
 
+/*
+ * General helpful Unix stuff: more helpful version of the FD_SET
+ * macro, which also handles maxfd.
+ */
+#define FD_SET_MAX(fd, max, set) do { \
+    FD_SET(fd, &set); \
+    if (max < fd + 1) max = fd + 1; \
+} while (0)
+
 #endif
index 881b6bf..5e3949b 100644 (file)
@@ -16,6 +16,8 @@
 
 int console_batch_mode = FALSE;
 
+static void *console_logctx = NULL;
+
 /*
  * Clean up and exit.
  */
@@ -258,9 +260,15 @@ void old_keyfile_warning(void)
     fputs(message, stderr);
 }
 
+void console_provide_logctx(void *logctx)
+{
+    console_logctx = logctx;
+}
+
 void logevent(void *frontend, const char *string)
 {
-    log_eventlog(logctx, string);
+    if (console_logctx)
+       log_eventlog(console_logctx, string);
 }
 
 int console_get_line(const char *prompt, char *str,
index 5d3efb2..e8b616e 100644 (file)
 #include <pwd.h>
 #include <sys/ioctl.h>
 
-/* More helpful version of the FD_SET macro, to also handle maxfd. */
-#define FD_SET_MAX(fd, max, set) do { \
-    FD_SET(fd, &set); \
-    if (max < fd + 1) max = fd + 1; \
-} while (0)
-
 #define PUTTY_DO_GLOBALS              /* actually _define_ globals */
 #include "putty.h"
 #include "storage.h"
@@ -287,7 +281,7 @@ int main(int argc, char **argv)
     int connopen;
     int exitcode;
     int errors;
-    void *ldisc;
+    void *ldisc, *logctx;
 
     ssh_get_line = console_get_line;
 
@@ -573,6 +567,7 @@ int main(int argc, char **argv)
      * Start up the connection.
      */
     logctx = log_init(NULL, &cfg);
+    console_provide_logctx(logctx);
     {
        const char *error;
        char *realhost;
diff --git a/unix/uxsftp.c b/unix/uxsftp.c
new file mode 100644 (file)
index 0000000..e9c9f6e
--- /dev/null
@@ -0,0 +1,224 @@
+/*\r
+ * uxsftp.c: the Unix-specific parts of PSFTP.\r
+ */\r
+\r
+#include <sys/time.h>\r
+#include <sys/types.h>\r
+#include <unistd.h>\r
+#include <errno.h>\r
+#include <pwd.h>\r
+\r
+#include "putty.h"\r
+#include "psftp.h"\r
+\r
+/*\r
+ * In PSFTP our selects are synchronous, so these functions are\r
+ * empty stubs.\r
+ */\r
+int uxsel_input_add(int fd, int rwx) { return 0; }\r
+void uxsel_input_remove(int id) { }\r
+\r
+char *x_get_default(const char *key)\r
+{\r
+    return NULL;                      /* this is a stub */\r
+}\r
+\r
+void platform_get_x11_auth(char *display, int *protocol,\r
+                           unsigned char *data, int *datalen)\r
+{\r
+    /* Do nothing, therefore no auth. */\r
+}\r
+\r
+/*\r
+ * Default settings that are specific to PSFTP.\r
+ */\r
+char *platform_default_s(const char *name)\r
+{\r
+    if (!strcmp(name, "UserName")) {\r
+       /*\r
+        * Remote login username will default to the local username.\r
+        */\r
+       struct passwd *p;\r
+       uid_t uid = getuid();\r
+       char *user, *ret = NULL;\r
+\r
+       /*\r
+        * First, find who we think we are using getlogin. If this\r
+        * agrees with our uid, we'll go along with it. This should\r
+        * allow sharing of uids between several login names whilst\r
+        * coping correctly with people who have su'ed.\r
+        */\r
+       user = getlogin();\r
+       setpwent();\r
+       if (user)\r
+           p = getpwnam(user);\r
+       else\r
+           p = NULL;\r
+       if (p && p->pw_uid == uid) {\r
+           /*\r
+            * The result of getlogin() really does correspond to\r
+            * our uid. Fine.\r
+            */\r
+           ret = user;\r
+       } else {\r
+           /*\r
+            * If that didn't work, for whatever reason, we'll do\r
+            * the simpler version: look up our uid in the password\r
+            * file and map it straight to a name.\r
+            */\r
+           p = getpwuid(uid);\r
+           ret = p->pw_name;\r
+       }\r
+       endpwent();\r
+\r
+       return ret;\r
+    }\r
+    return NULL;\r
+}\r
+\r
+int platform_default_i(const char *name, int def)\r
+{\r
+    return def;\r
+}\r
+\r
+FontSpec platform_default_fontspec(const char *name)\r
+{\r
+    FontSpec ret;\r
+    *ret.name = '\0';\r
+    return ret;\r
+}\r
+\r
+Filename platform_default_filename(const char *name)\r
+{\r
+    Filename ret;\r
+    if (!strcmp(name, "LogFileName"))\r
+       strcpy(ret.path, "putty.log");\r
+    else\r
+       *ret.path = '\0';\r
+    return ret;\r
+}\r
+\r
+/*\r
+ * Set local current directory. Returns NULL on success, or else an\r
+ * error message which must be freed after printing.\r
+ */\r
+char *psftp_lcd(char *dir)\r
+{\r
+    if (chdir(dir) < 0)\r
+       return dupprintf("%s: chdir: %s", dir, strerror(errno));\r
+    else\r
+       return NULL;\r
+}\r
+\r
+/*\r
+ * Get local current directory. Returns a string which must be\r
+ * freed.\r
+ */\r
+char *psftp_getcwd(void)\r
+{\r
+    char *buffer, *ret;\r
+    int size = 256;\r
+\r
+    buffer = snewn(size, char);\r
+    while (1) {\r
+       ret = getcwd(buffer, size);\r
+       if (ret != NULL)\r
+           return ret;\r
+       if (errno != ERANGE) {\r
+           sfree(buffer);\r
+           return dupprintf("[cwd unavailable: %s]", strerror(errno));\r
+       }\r
+       /*\r
+        * Otherwise, ERANGE was returned, meaning the buffer\r
+        * wasn't big enough.\r
+        */\r
+       size = size * 3 / 2;\r
+       buffer = sresize(buffer, size, char);\r
+    }\r
+}\r
+\r
+/*\r
+ * Wait for some network data and process it.\r
+ */\r
+int ssh_sftp_loop_iteration(void)\r
+{\r
+    fd_set rset, wset, xset;\r
+    int i, fdcount, fdsize, *fdlist;\r
+    int fd, fdstate, rwx, ret, maxfd;\r
+\r
+    fdlist = NULL;\r
+    fdcount = fdsize = 0;\r
+\r
+    /* Count the currently active fds. */\r
+    i = 0;\r
+    for (fd = first_fd(&fdstate, &rwx); fd >= 0;\r
+        fd = next_fd(&fdstate, &rwx)) i++;\r
+\r
+    if (i < 1)\r
+       return -1;                     /* doom */\r
+\r
+    /* Expand the fdlist buffer if necessary. */\r
+    if (i > fdsize) {\r
+       fdsize = i + 16;\r
+       fdlist = sresize(fdlist, fdsize, int);\r
+    }\r
+\r
+    FD_ZERO(&rset);\r
+    FD_ZERO(&wset);\r
+    FD_ZERO(&xset);\r
+    maxfd = 0;\r
+\r
+    /*\r
+     * Add all currently open fds to the select sets, and store\r
+     * them in fdlist as well.\r
+     */\r
+    fdcount = 0;\r
+    for (fd = first_fd(&fdstate, &rwx); fd >= 0;\r
+        fd = next_fd(&fdstate, &rwx)) {\r
+       fdlist[fdcount++] = fd;\r
+       if (rwx & 1)\r
+           FD_SET_MAX(fd, maxfd, rset);\r
+       if (rwx & 2)\r
+           FD_SET_MAX(fd, maxfd, wset);\r
+       if (rwx & 4)\r
+           FD_SET_MAX(fd, maxfd, xset);\r
+    }\r
+\r
+    do {\r
+       ret = select(maxfd, &rset, &wset, &xset, NULL);\r
+    } while (ret < 0 && errno == EINTR);\r
+\r
+    if (ret < 0) {\r
+       perror("select");\r
+       exit(1);\r
+    }\r
+\r
+    for (i = 0; i < fdcount; i++) {\r
+       fd = fdlist[i];\r
+       /*\r
+        * We must process exceptional notifications before\r
+        * ordinary readability ones, or we may go straight\r
+        * past the urgent marker.\r
+        */\r
+       if (FD_ISSET(fd, &xset))\r
+           select_result(fd, 4);\r
+       if (FD_ISSET(fd, &rset))\r
+           select_result(fd, 1);\r
+       if (FD_ISSET(fd, &wset))\r
+           select_result(fd, 2);\r
+    }\r
+\r
+    sfree(fdlist);\r
+\r
+    return 0;\r
+}\r
+\r
+/*\r
+ * Main program: do platform-specific initialisation and then call\r
+ * psftp_main().\r
+ */\r
+int main(int argc, char *argv[])\r
+{\r
+    uxsel_init();\r
+    return psftp_main(argc, argv);\r
+}\r