X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/c606c42da46efa232c1f29791877f07d98da262e..33f07e9636e80bb17f25f97145ca2e0eb262db30:/psftp.c diff --git a/psftp.c b/psftp.c index 9e697d50..10056bd5 100644 --- a/psftp.c +++ b/psftp.c @@ -1,5 +1,5 @@ /* - * psftp.c: front end for PSFTP. + * psftp.c: (platform-independent) front end for PSFTP. */ #include @@ -25,6 +25,7 @@ static int psftp_connect(char *userhost, char *user, int portnumber); static int do_sftp_init(void); +void do_sftp_cleanup(); /* ---------------------------------------------------------------------- * sftp client state. @@ -441,7 +442,7 @@ int sftp_general_get(struct sftp_command *cmd, int restart) */ ret = 1; xfer = xfer_download_init(fh, offset); - while (!xfer_download_done(xfer)) { + while (!xfer_done(xfer)) { void *vbuf; int ret, len; int wpos, wlen; @@ -472,6 +473,8 @@ int sftp_general_get(struct sftp_command *cmd, int restart) ret = 0; xfer_set_error(xfer); } + + sfree(vbuf); } } @@ -506,12 +509,13 @@ int sftp_cmd_reget(struct sftp_command *cmd) int sftp_general_put(struct sftp_command *cmd, int restart) { struct fxp_handle *fh; + struct fxp_xfer *xfer; char *fname, *origoutfname, *outfname; struct sftp_packet *pktin; struct sftp_request *req, *rreq; uint64 offset; FILE *fp; - int ret; + int ret, err, eof; if (back == NULL) { printf("psftp: not connected to a host; use \"open host.name\"\n"); @@ -595,32 +599,36 @@ int sftp_general_put(struct sftp_command *cmd, int restart) * thus put up a progress bar. */ ret = 1; - while (1) { + xfer = xfer_upload_init(fh, offset); + err = eof = 0; + while ((!err && !eof) || !xfer_done(xfer)) { char buffer[4096]; int len, ret; - len = fread(buffer, 1, sizeof(buffer), fp); - if (len == -1) { - printf("error while reading local file\n"); - ret = 0; - break; - } else if (len == 0) { - break; + while (xfer_upload_ready(xfer) && !err && !eof) { + len = fread(buffer, 1, sizeof(buffer), fp); + if (len == -1) { + printf("error while reading local file\n"); + err = 1; + } else if (len == 0) { + eof = 1; + } else { + xfer_upload_data(xfer, buffer, len); + } } - sftp_register(req = fxp_write_send(fh, buffer, offset, len)); - rreq = sftp_find_request(pktin = sftp_recv()); - assert(rreq == req); - ret = fxp_write_recv(pktin, rreq); - - if (!ret) { - printf("error while writing: %s\n", fxp_error()); - ret = 0; - break; + if (!xfer_done(xfer)) { + pktin = sftp_recv(); + ret = xfer_upload_gotpkt(xfer, pktin); + if (!ret) { + printf("error while writing: %s\n", fxp_error()); + err = 1; + } } - offset = uint64_add32(offset, len); } + xfer_cleanup(xfer); + sftp_register(req = fxp_close_send(fh)); rreq = sftp_find_request(pktin = sftp_recv()); assert(rreq == req); @@ -1006,6 +1014,8 @@ int sftp_cmd_chmod(struct sftp_command *cmd) static int sftp_cmd_open(struct sftp_command *cmd) { + int portnumber; + if (back != NULL) { printf("psftp: already connected\n"); return 0; @@ -1016,7 +1026,16 @@ static int sftp_cmd_open(struct sftp_command *cmd) return 0; } - if (psftp_connect(cmd->words[1], NULL, 0)) { + if (cmd->nwords > 2) { + portnumber = atoi(cmd->words[2]); + if (portnumber == 0) { + printf("open: invalid port number\n"); + return 0; + } + } else + portnumber = 0; + + if (psftp_connect(cmd->words[1], NULL, portnumber)) { back = NULL; /* connection is already closed */ return -1; /* this is fatal */ } @@ -1208,7 +1227,7 @@ static struct sftp_cmd_lookup { }, { "open", TRUE, "connect to a host", - " [@]\n" + " [@] []\n" " Establishes an SFTP connection to a given host. Only usable\n" " when you did not already specify a host name on the command\n" " line.\n", @@ -1397,8 +1416,8 @@ struct sftp_command *sftp_getcmd(FILE *fp, int mode, int modeflags) */ cmd->nwords = cmd->wordssize = 2; cmd->words = sresize(cmd->words, cmd->wordssize, char *); - cmd->words[0] = "!"; - cmd->words[1] = p+1; + cmd->words[0] = dupstr("!"); + cmd->words[1] = dupstr(p+1); } else { /* @@ -1441,10 +1460,11 @@ struct sftp_command *sftp_getcmd(FILE *fp, int mode, int modeflags) cmd->wordssize = cmd->nwords + 16; cmd->words = sresize(cmd->words, cmd->wordssize, char *); } - cmd->words[cmd->nwords++] = q; + cmd->words[cmd->nwords++] = dupstr(q); } } + sfree(line); /* * Now parse the first word and assign a function. */ @@ -1497,6 +1517,25 @@ static int do_sftp_init(void) return 0; } +void do_sftp_cleanup() +{ + char ch; + if (back) { + back->special(backhandle, TS_EOF); + sftp_recvdata(&ch, 1); + back->free(backhandle); + sftp_cleanup_request(); + } + if (pwd) { + sfree(pwd); + pwd = NULL; + } + if (homedir) { + sfree(homedir); + homedir = NULL; + } +} + void do_sftp(int mode, int modeflags, char *batchfile) { FILE *fp; @@ -1515,7 +1554,15 @@ void do_sftp(int mode, int modeflags, char *batchfile) cmd = sftp_getcmd(stdin, 0, 0); if (!cmd) break; - if (cmd->obey(cmd) < 0) + ret = cmd->obey(cmd); + if (cmd->words) { + int i; + for(i = 0; i < cmd->nwords; i++) + sfree(cmd->words[i]); + sfree(cmd->words); + } + sfree(cmd); + if (ret < 0) break; } } else { @@ -1633,14 +1680,13 @@ int from_backend(void *frontend, int is_stderr, const char *data, int datalen) unsigned char *p = (unsigned char *) data; unsigned len = (unsigned) datalen; - assert(len > 0); - /* * stderr data is just spouted to local stderr and otherwise * ignored. */ if (is_stderr) { - fwrite(data, 1, len, stderr); + if (len > 0) + fwrite(data, 1, len, stderr); return 0; } @@ -1650,7 +1696,7 @@ int from_backend(void *frontend, int is_stderr, const char *data, int datalen) if (!outptr) return 0; - if (outlen > 0) { + if ((outlen > 0) && (len > 0)) { unsigned used = outlen; if (used > len) used = len; @@ -1708,7 +1754,7 @@ int sftp_recvdata(char *buf, int len) } int sftp_senddata(char *buf, int len) { - back->send(backhandle, (unsigned char *) buf, len); + back->send(backhandle, buf, len); return 1; } @@ -1719,7 +1765,7 @@ static void usage(void) { printf("PuTTY Secure File Transfer (SFTP) client\n"); printf("%s\n", ver); - printf("Usage: psftp [options] user@host\n"); + printf("Usage: psftp [options] [user@]host\n"); printf("Options:\n"); printf(" -b file use specified batchfile\n"); printf(" -bc output batchfile commands\n"); @@ -1733,9 +1779,16 @@ static void usage(void) printf(" -C enable compression\n"); printf(" -i key private key file for authentication\n"); printf(" -batch disable all interactive prompts\n"); + printf(" -V print version information\n"); cleanup_exit(1); } +static void version(void) +{ + printf("psftp: %s\n", ver); + cleanup_exit(1); +} + /* * Connect to a host. */ @@ -1886,7 +1939,8 @@ static int psftp_connect(char *userhost, char *user, int portnumber) back = &ssh_backend; - err = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port, &realhost,0); + err = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port, &realhost, + 0, cfg.tcp_keepalives); if (err != NULL) { fprintf(stderr, "ssh_init: %s\n", err); return 1; @@ -1902,6 +1956,8 @@ static int psftp_connect(char *userhost, char *user, int portnumber) } if (verbose && realhost != NULL) printf("Connected to %s\n", realhost); + if (realhost != NULL) + sfree(realhost); return 0; } @@ -1962,6 +2018,8 @@ int psftp_main(int argc, char *argv[]) } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-?") == 0) { usage(); + } else if (strcmp(argv[i], "-V") == 0) { + version(); } else if (strcmp(argv[i], "-batch") == 0) { console_batch_mode = 1; } else if (strcmp(argv[i], "-b") == 0 && i + 1 < argc) { @@ -1987,13 +2045,16 @@ int psftp_main(int argc, char *argv[]) * it now. */ if (userhost) { - if (psftp_connect(userhost, user, portnumber)) + int ret; + ret = psftp_connect(userhost, user, portnumber); + sfree(userhost); + if (ret) return 1; if (do_sftp_init()) return 1; } else { printf("psftp: no hostname specified; use \"open host.name\"" - " to connect\n"); + " to connect\n"); } do_sftp(mode, modeflags, batchfile); @@ -2004,6 +2065,12 @@ int psftp_main(int argc, char *argv[]) sftp_recvdata(&ch, 1); } random_save_seed(); + cmdline_cleanup(); + console_provide_logctx(NULL); + do_sftp_cleanup(); + backhandle = NULL; + back = NULL; + sk_cleanup(); return 0; }