]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - pscp.c
first pass
[PuTTY.git] / pscp.c
diff --git a/pscp.c b/pscp.c
index 50ab90b5e1922d9c5075b5b4b71a0ab3d4bbd6eb..454ec084c5cf5d161d713ed2f643e5dc4429bee2 100644 (file)
--- a/pscp.c
+++ b/pscp.c
@@ -48,9 +48,9 @@ static void *backhandle;
 static Conf *conf;
 int sent_eof = FALSE;
 
-static void source(char *src);
-static void rsource(char *src);
-static void sink(char *targ, char *src);
+static void source(const char *src);
+static void rsource(const char *src);
+static void sink(const char *targ, const char *src);
 
 const char *const appname = "PSCP";
 
@@ -62,12 +62,12 @@ const char *const appname = "PSCP";
 
 void ldisc_echoedit_update(void *handle) { }
 
-static void tell_char(FILE * stream, char c)
+static void tell_char(FILE *stream, char c)
 {
     fputc(c, stream);
 }
 
-static void tell_str(FILE * stream, char *str)
+static void tell_str(FILE *stream, const char *str)
 {
     unsigned int i;
 
@@ -75,7 +75,7 @@ static void tell_str(FILE * stream, char *str)
        tell_char(stream, str[i]);
 }
 
-static void tell_user(FILE * stream, char *fmt, ...)
+static void tell_user(FILE *stream, const char *fmt, ...)
 {
     char *str, *str2;
     va_list ap;
@@ -91,7 +91,7 @@ static void tell_user(FILE * stream, char *fmt, ...)
 /*
  *  Print an error message and perform a fatal exit.
  */
-void fatalbox(char *fmt, ...)
+void fatalbox(const char *fmt, ...)
 {
     char *str, *str2;
     va_list ap;
@@ -106,7 +106,7 @@ void fatalbox(char *fmt, ...)
 
     cleanup_exit(1);
 }
-void modalfatalbox(char *fmt, ...)
+void modalfatalbox(const char *fmt, ...)
 {
     char *str, *str2;
     va_list ap;
@@ -121,7 +121,7 @@ void modalfatalbox(char *fmt, ...)
 
     cleanup_exit(1);
 }
-void nonfatal(char *fmt, ...)
+void nonfatal(const char *fmt, ...)
 {
     char *str, *str2;
     va_list ap;
@@ -134,7 +134,7 @@ void nonfatal(char *fmt, ...)
     sfree(str2);
     errs++;
 }
-void connection_fatal(void *frontend, char *fmt, ...)
+void connection_fatal(void *frontend, const char *fmt, ...)
 {
     char *str, *str2;
     va_list ap;
@@ -302,7 +302,7 @@ static void ssh_scp_init(void)
 /*
  *  Print an error message and exit after closing the SSH link.
  */
-static void bump(char *fmt, ...)
+static void bump(const char *fmt, ...)
 {
     char *str, *str2;
     va_list ap;
@@ -383,6 +383,7 @@ static void do_cmd(char *host, char *user, char *cmd)
            /* Use `host' as a bare hostname. */
            conf_set_str(conf, CONF_host, host);
        }
+        conf_free(conf2);
     } else {
        /* Patch in hostname `host' to session details. */
        conf_set_str(conf, CONF_host, host);
@@ -514,6 +515,11 @@ static void do_cmd(char *host, char *user, char *cmd)
 
     back = &ssh_backend;
 
+    logctx = log_init(NULL, conf);
+    console_provide_logctx(logctx);
+
+    platform_psftp_pre_conn_setup();
+
     err = back->init(NULL, &backhandle, conf,
                     conf_get_str(conf, CONF_host),
                     conf_get_int(conf, CONF_port),
@@ -521,9 +527,7 @@ static void do_cmd(char *host, char *user, char *cmd)
                     conf_get_int(conf, CONF_tcp_keepalives));
     if (err != NULL)
        bump("ssh_init: %s", err);
-    logctx = log_init(NULL, conf);
     back->provide_logctx(backhandle, logctx);
-    console_provide_logctx(logctx);
     ssh_scp_init();
     if (verbose && realhost != NULL && errs == 0)
        tell_user(stderr, "Connected to %s", realhost);
@@ -533,7 +537,7 @@ static void do_cmd(char *host, char *user, char *cmd)
 /*
  *  Update statistic information about current file.
  */
-static void print_stats(char *name, uint64 size, uint64 done,
+static void print_stats(const char *name, uint64 size, uint64 done,
                        time_t start, time_t now)
 {
     float ratebs;
@@ -605,30 +609,6 @@ static char *colon(char *str)
        return (NULL);
 }
 
-/*
- * Return a pointer to the portion of str that comes after the last
- * slash (or backslash or colon, if `local' is TRUE).
- */
-static char *stripslashes(char *str, int local)
-{
-    char *p;
-
-    if (local) {
-        p = strchr(str, ':');
-        if (p) str = p+1;
-    }
-
-    p = strrchr(str, '/');
-    if (p) str = p+1;
-
-    if (local) {
-       p = strrchr(str, '\\');
-       if (p) str = p+1;
-    }
-
-    return str;
-}
-
 /*
  * Determine whether a string is entirely composed of dots.
  */
@@ -682,6 +662,10 @@ int sftp_senddata(char *buf, int len)
     back->send(backhandle, buf, len);
     return 1;
 }
+int sftp_sendbuffer(void)
+{
+    return back->sendbuffer(backhandle);
+}
 
 /* ----------------------------------------------------------------------
  * sftp-based replacement for the hacky `pscp -ls'.
@@ -692,7 +676,7 @@ static int sftp_ls_compare(const void *av, const void *bv)
     const struct fxp_name *b = (const struct fxp_name *) bv;
     return strcmp(a->filename, b->filename);
 }
-void scp_sftp_listdir(char *dirname)
+void scp_sftp_listdir(const char *dirname)
 {
     struct fxp_handle *dirh;
     struct fxp_names *names;
@@ -715,7 +699,8 @@ void scp_sftp_listdir(char *dirname)
     dirh = fxp_opendir_recv(pktin, req);
 
     if (dirh == NULL) {
-       printf("Unable to open %s: %s\n", dirname, fxp_error());
+               tell_user(stderr, "Unable to open %s: %s\n", dirname, fxp_error());
+               errs++;
     } else {
        nnames = namesize = 0;
        ournames = NULL;
@@ -791,7 +776,7 @@ static struct fxp_handle *scp_sftp_filehandle;
 static struct fxp_xfer *scp_sftp_xfer;
 static uint64 scp_sftp_fileoffset;
 
-int scp_source_setup(char *target, int shouldbedir)
+int scp_source_setup(const char *target, int shouldbedir)
 {
     if (using_sftp) {
        /*
@@ -857,7 +842,7 @@ int scp_send_filetimes(unsigned long mtime, unsigned long atime)
     }
 }
 
-int scp_send_filename(char *name, uint64 size, int permissions)
+int scp_send_filename(const char *name, uint64 size, int permissions)
 {
     if (using_sftp) {
        char *fullname;
@@ -1012,7 +997,7 @@ void scp_restore_remotepath(char *data)
        scp_sftp_remotepath = data;
 }
 
-int scp_send_dirname(char *name, int modes)
+int scp_send_dirname(const char *name, int modes)
 {
     if (using_sftp) {
        char *fullname;
@@ -1087,7 +1072,7 @@ int scp_send_enddir(void)
  * right at the start, whereas scp_sink_init is called to
  * initialise every level of recursion in the protocol.
  */
-int scp_sink_setup(char *source, int preserve, int recursive)
+int scp_sink_setup(const char *source, int preserve, int recursive)
 {
     if (using_sftp) {
        char *newsource;
@@ -1519,7 +1504,7 @@ int scp_get_sink_action(struct scp_sink_action *act)
        {
            char sizestr[40];
        
-           if (sscanf(act->buf, "%lo %s %n", &act->permissions,
+            if (sscanf(act->buf, "%lo %39s %n", &act->permissions,
                        sizestr, &i) != 2)
                bump("Protocol error: Illegal file descriptor format");
            act->size = uint64_from_decimal(sizestr);
@@ -1575,6 +1560,12 @@ int scp_recv_filedata(char *data, int len)
        }
 
        if (xfer_download_data(scp_sftp_xfer, &vbuf, &actuallen)) {
+            if (actuallen <= 0) {
+                tell_user(stderr, "pscp: end of file while reading");
+                errs++;
+                sfree(vbuf);
+                return -1;
+            }
            /*
             * This assertion relies on the fact that the natural
             * block size used in the xfer manager is at most that
@@ -1657,12 +1648,12 @@ static void run_err(const char *fmt, ...)
 /*
  *  Execute the source part of the SCP protocol.
  */
-static void source(char *src)
+static void source(const char *src)
 {
     uint64 size;
     unsigned long mtime, atime;
     long permissions;
-    char *last;
+    const char *last;
     RFile *f;
     int attr;
     uint64 i;
@@ -1682,7 +1673,7 @@ static void source(char *src)
            /*
             * Avoid . and .. directories.
             */
-           char *p;
+           const char *p;
            p = strrchr(src, '/');
            if (!p)
                p = strrchr(src, '\\');
@@ -1735,11 +1726,12 @@ static void source(char *src)
     stat_starttime = time(NULL);
     stat_lasttime = 0;
 
+#define PSCP_SEND_BLOCK 4096
     for (i = uint64_make(0,0);
         uint64_compare(i,size) < 0;
-        i = uint64_add32(i,4096)) {
-       char transbuf[4096];
-       int j, k = 4096;
+        i = uint64_add32(i,PSCP_SEND_BLOCK)) {
+       char transbuf[PSCP_SEND_BLOCK];
+       int j, k = PSCP_SEND_BLOCK;
 
        if (uint64_compare(uint64_add32(i, k),size) > 0) /* i + k > size */ 
            k = (uint64_subtract(size, i)).lo;  /* k = size - i; */
@@ -1770,9 +1762,9 @@ static void source(char *src)
 /*
  *  Recursively send the contents of a directory.
  */
-static void rsource(char *src)
+static void rsource(const char *src)
 {
-    char *last;
+    const char *last;
     char *save_target;
     DirHandle *dir;
 
@@ -1814,7 +1806,7 @@ static void rsource(char *src)
 /*
  * Execute the sink part of the SCP protocol.
  */
-static void sink(char *targ, char *src)
+static void sink(const char *targ, const char *src)
 {
     char *destfname;
     int targisdir = 0;
@@ -1977,8 +1969,10 @@ static void sink(char *targ, char *src)
            read = scp_recv_filedata(transbuf, (int)blksize.lo);
            if (read <= 0)
                bump("Lost connection");
-           if (wrerror)
+           if (wrerror) {
+                received = uint64_add32(received, read);
                continue;
+            }
            if (write_to_file(f, transbuf, read) != (int)read) {
                wrerror = 1;
                /* FIXME: in sftp we can actually abort the transfer */
@@ -1986,6 +1980,7 @@ static void sink(char *targ, char *src)
                    printf("\r%-25.25s | %50s\n",
                           stat_name,
                           "Write error.. waiting for end of file");
+                received = uint64_add32(received, read);
                continue;
            }
            if (statistics) {
@@ -2020,23 +2015,26 @@ static void sink(char *targ, char *src)
  */
 static void toremote(int argc, char *argv[])
 {
-    char *src, *targ, *host, *user;
+    char *src, *wtarg, *host, *user;
+    const char *targ;
     char *cmd;
     int i, wc_type;
 
     uploading = 1;
 
-    targ = argv[argc - 1];
+    wtarg = argv[argc - 1];
 
     /* Separate host from filename */
-    host = targ;
-    targ = colon(targ);
-    if (targ == NULL)
-       bump("targ == NULL in toremote()");
-    *targ++ = '\0';
-    if (*targ == '\0')
-       targ = ".";
+    host = wtarg;
+    wtarg = colon(wtarg);
+    if (wtarg == NULL)
+       bump("wtarg == NULL in toremote()");
+    *wtarg++ = '\0';
     /* Substitute "." for empty target */
+    if (*wtarg == '\0')
+       targ = ".";
+    else
+        targ = wtarg;
 
     /* Separate host and username */
     user = host;
@@ -2112,7 +2110,8 @@ static void toremote(int argc, char *argv[])
  */
 static void tolocal(int argc, char *argv[])
 {
-    char *src, *targ, *host, *user;
+    char *wsrc, *host, *user;
+    const char *src, *targ;
     char *cmd;
 
     uploading = 0;
@@ -2120,18 +2119,20 @@ static void tolocal(int argc, char *argv[])
     if (argc != 2)
        bump("More than one remote source not supported");
 
-    src = argv[0];
+    wsrc = argv[0];
     targ = argv[1];
 
     /* Separate host from filename */
-    host = src;
-    src = colon(src);
-    if (src == NULL)
+    host = wsrc;
+    wsrc = colon(wsrc);
+    if (wsrc == NULL)
        bump("Local to local copy not supported");
-    *src++ = '\0';
-    if (*src == '\0')
-       src = ".";
+    *wsrc++ = '\0';
     /* Substitute "." for empty filename */
+    if (*wsrc == '\0')
+       src = ".";
+    else
+        src = wsrc;
 
     /* Separate username and hostname */
     user = host;
@@ -2164,21 +2165,25 @@ static void tolocal(int argc, char *argv[])
  */
 static void get_dir_list(int argc, char *argv[])
 {
-    char *src, *host, *user;
-    char *cmd, *p, *q;
+    char *wsrc, *host, *user;
+    const char *src;
+    char *cmd, *p;
+    const char *q;
     char c;
 
-    src = argv[0];
+    wsrc = argv[0];
 
     /* Separate host from filename */
-    host = src;
-    src = colon(src);
-    if (src == NULL)
+    host = wsrc;
+    wsrc = colon(wsrc);
+    if (wsrc == NULL)
        bump("Local file listing not supported");
-    *src++ = '\0';
-    if (*src == '\0')
-       src = ".";
+    *wsrc++ = '\0';
     /* Substitute "." for empty filename */
+    if (*wsrc == '\0')
+       src = ".";
+    else
+        src = wsrc;
 
     /* Separate username and hostname */
     user = host;
@@ -2250,9 +2255,14 @@ static void usage(void)
     printf("  -hostkey aa:bb:cc:...\n");
     printf("            manually specify a host key (may be repeated)\n");
     printf("  -batch    disable all interactive prompts\n");
+    printf("  -proxycmd command\n");
+    printf("            use 'command' as local proxy\n");
     printf("  -unsafe   allow server-side wildcards (DANGEROUS)\n");
     printf("  -sftp     force use of SFTP protocol\n");
     printf("  -scp      force use of SCP protocol\n");
+    printf("  -sshlog file\n");
+    printf("  -sshrawlog file\n");
+    printf("            log protocol details to a file\n");
 #if 0
     /*
      * -gui is an internal option, used by GUI front ends to get
@@ -2269,11 +2279,13 @@ static void usage(void)
 
 void version(void)
 {
-    printf("pscp: %s\n", ver);
-    cleanup_exit(1);
+    char *buildinfo_text = buildinfo("\n");
+    printf("pscp: %s\n%s\n", ver, buildinfo_text);
+    sfree(buildinfo_text);
+    exit(0);
 }
 
-void cmdline_error(char *p, ...)
+void cmdline_error(const char *p, ...)
 {
     va_list ap;
     fprintf(stderr, "pscp: ");