X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/cbe2d68fd7c7c7bac692b3a2d200a5d2429ab201..679539d7ab96f188640d159ea0b004275db67356:/psftp.c diff --git a/psftp.c b/psftp.c index 75161519..28c3dd97 100644 --- a/psftp.c +++ b/psftp.c @@ -2,8 +2,6 @@ * psftp.c: front end for PSFTP. */ -#include - #include #include #include @@ -12,6 +10,7 @@ #define PUTTY_DO_GLOBALS #include "putty.h" +#include "psftp.h" #include "storage.h" #include "ssh.h" #include "sftp.h" @@ -26,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. @@ -48,6 +48,8 @@ static Config cfg; char *canonify(char *name) { char *fullname, *canonname; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; if (name[0] == '/') { fullname = dupstr(name); @@ -60,7 +62,10 @@ char *canonify(char *name) fullname = dupcat(pwd, slash, name, NULL); } - canonname = fxp_realpath(fullname); + sftp_register(req = fxp_realpath_send(fullname)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + canonname = fxp_realpath_recv(pktin, rreq); if (canonname) { sfree(fullname); @@ -115,10 +120,13 @@ char *canonify(char *name) */ fullname[i] = '\0'; /* separate the string */ if (i == 0) { - canonname = fxp_realpath("/"); + sftp_register(req = fxp_realpath_send("/")); } else { - canonname = fxp_realpath(fullname); + sftp_register(req = fxp_realpath_send(fullname)); } + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + canonname = fxp_realpath_recv(pktin, rreq); if (!canonname) return fullname; /* even that failed; give up */ @@ -202,6 +210,8 @@ int sftp_cmd_ls(struct sftp_command *cmd) struct fxp_name **ournames; int nnames, namesize; char *dir, *cdir; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; int i; if (back == NULL) { @@ -222,7 +232,11 @@ int sftp_cmd_ls(struct sftp_command *cmd) printf("Listing directory %s\n", cdir); - dirh = fxp_opendir(cdir); + sftp_register(req = fxp_opendir_send(cdir)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + dirh = fxp_opendir_recv(pktin, rreq); + if (dirh == NULL) { printf("Unable to open %s: %s\n", dir, fxp_error()); } else { @@ -231,7 +245,11 @@ int sftp_cmd_ls(struct sftp_command *cmd) while (1) { - names = fxp_readdir(dirh); + sftp_register(req = fxp_readdir_send(dirh)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + names = fxp_readdir_recv(pktin, rreq); + if (names == NULL) { if (fxp_error_type() == SSH_FX_EOF) break; @@ -253,7 +271,10 @@ int sftp_cmd_ls(struct sftp_command *cmd) fxp_free_names(names); } - fxp_close(dirh); + sftp_register(req = fxp_close_send(dirh)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + fxp_close_recv(pktin, rreq); /* * Now we have our filenames. Sort them by actual file @@ -283,6 +304,8 @@ int sftp_cmd_ls(struct sftp_command *cmd) int sftp_cmd_cd(struct sftp_command *cmd) { struct fxp_handle *dirh; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; char *dir; if (back == NULL) { @@ -300,14 +323,21 @@ int sftp_cmd_cd(struct sftp_command *cmd) return 0; } - dirh = fxp_opendir(dir); + sftp_register(req = fxp_opendir_send(dir)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + dirh = fxp_opendir_recv(pktin, rreq); + if (!dirh) { printf("Directory %s: %s\n", dir, fxp_error()); sfree(dir); return 0; } - fxp_close(dirh); + sftp_register(req = fxp_close_send(dirh)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + fxp_close_recv(pktin, rreq); sfree(pwd); pwd = dir; @@ -339,6 +369,9 @@ int sftp_cmd_pwd(struct sftp_command *cmd) int sftp_general_get(struct sftp_command *cmd, int restart) { struct fxp_handle *fh; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; + struct fxp_xfer *xfer; char *fname, *outfname; uint64 offset; FILE *fp; @@ -362,7 +395,11 @@ int sftp_general_get(struct sftp_command *cmd, int restart) outfname = (cmd->nwords == 2 ? stripslashes(cmd->words[1], 0) : cmd->words[2]); - fh = fxp_open(fname, SSH_FXF_READ); + sftp_register(req = fxp_open_send(fname, SSH_FXF_READ)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + fh = fxp_open_recv(pktin, rreq); + if (!fh) { printf("%s: %s\n", fname, fxp_error()); sfree(fname); @@ -377,7 +414,12 @@ int sftp_general_get(struct sftp_command *cmd, int restart) if (!fp) { printf("local: unable to open %s\n", outfname); - fxp_close(fh); + + sftp_register(req = fxp_close_send(fh)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + fxp_close_recv(pktin, rreq); + sfree(fname); return 0; } @@ -399,39 +441,52 @@ int sftp_general_get(struct sftp_command *cmd, int restart) * thus put up a progress bar. */ ret = 1; - while (1) { - char buffer[4096]; - int len; + xfer = xfer_download_init(fh, offset); + while (!xfer_done(xfer)) { + void *vbuf; + int ret, len; int wpos, wlen; - len = fxp_read(fh, buffer, offset, sizeof(buffer)); - if ((len == -1 && fxp_error_type() == SSH_FX_EOF) || len == 0) - break; - if (len == -1) { - printf("error while reading: %s\n", fxp_error()); - ret = 0; - break; + xfer_download_queue(xfer); + pktin = sftp_recv(); + ret = xfer_download_gotpkt(xfer, pktin); + + if (ret < 0) { + printf("error while reading: %s\n", fxp_error()); + ret = 0; } - wpos = 0; - while (wpos < len) { - wlen = fwrite(buffer, 1, len - wpos, fp); - if (wlen <= 0) { - printf("error while writing local file\n"); + while (xfer_download_data(xfer, &vbuf, &len)) { + unsigned char *buf = (unsigned char *)vbuf; + + wpos = 0; + while (wpos < len) { + wlen = fwrite(buf + wpos, 1, len - wpos, fp); + if (wlen <= 0) { + printf("error while writing local file\n"); + ret = 0; + xfer_set_error(xfer); + } + wpos += wlen; + } + if (wpos < len) { /* we had an error */ ret = 0; - break; + xfer_set_error(xfer); } - wpos += wlen; - } - if (wpos < len) { /* we had an error */ - ret = 0; - break; + + sfree(vbuf); } - offset = uint64_add32(offset, len); } + xfer_cleanup(xfer); + fclose(fp); - fxp_close(fh); + + sftp_register(req = fxp_close_send(fh)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + fxp_close_recv(pktin, rreq); + sfree(fname); return ret; @@ -454,10 +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"); @@ -485,12 +543,15 @@ int sftp_general_put(struct sftp_command *cmd, int restart) return 0; } if (restart) { - fh = fxp_open(outfname, - SSH_FXF_WRITE); + sftp_register(req = fxp_open_send(outfname, SSH_FXF_WRITE)); } else { - fh = fxp_open(outfname, - SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_TRUNC); + sftp_register(req = fxp_open_send(outfname, SSH_FXF_WRITE | + SSH_FXF_CREAT | SSH_FXF_TRUNC)); } + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + fh = fxp_open_recv(pktin, rreq); + if (!fh) { printf("%s: %s\n", outfname, fxp_error()); sfree(outfname); @@ -500,7 +561,14 @@ int sftp_general_put(struct sftp_command *cmd, int restart) if (restart) { char decbuf[30]; struct fxp_attrs attrs; - if (!fxp_fstat(fh, &attrs)) { + int ret; + + sftp_register(req = fxp_fstat_send(fh)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + ret = fxp_fstat_recv(pktin, rreq, &attrs); + + if (!ret) { printf("read size of %s: %s\n", outfname, fxp_error()); sfree(outfname); return 0; @@ -531,27 +599,41 @@ 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; - - 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; + int len, ret; + + 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); + } } - if (!fxp_write(fh, buffer, offset, len)) { - 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); } - fxp_close(fh); + xfer_cleanup(xfer); + + sftp_register(req = fxp_close_send(fh)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + fxp_close_recv(pktin, rreq); + fclose(fp); sfree(outfname); @@ -569,6 +651,8 @@ int sftp_cmd_reput(struct sftp_command *cmd) int sftp_cmd_mkdir(struct sftp_command *cmd) { char *dir; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; int result; if (back == NULL) { @@ -587,7 +671,11 @@ int sftp_cmd_mkdir(struct sftp_command *cmd) return 0; } - result = fxp_mkdir(dir); + sftp_register(req = fxp_mkdir_send(dir)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + result = fxp_mkdir_recv(pktin, rreq); + if (!result) { printf("mkdir %s: %s\n", dir, fxp_error()); sfree(dir); @@ -601,6 +689,8 @@ int sftp_cmd_mkdir(struct sftp_command *cmd) int sftp_cmd_rmdir(struct sftp_command *cmd) { char *dir; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; int result; if (back == NULL) { @@ -619,7 +709,11 @@ int sftp_cmd_rmdir(struct sftp_command *cmd) return 0; } - result = fxp_rmdir(dir); + sftp_register(req = fxp_rmdir_send(dir)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + result = fxp_rmdir_recv(pktin, rreq); + if (!result) { printf("rmdir %s: %s\n", dir, fxp_error()); sfree(dir); @@ -633,6 +727,8 @@ int sftp_cmd_rmdir(struct sftp_command *cmd) int sftp_cmd_rm(struct sftp_command *cmd) { char *fname; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; int result; if (back == NULL) { @@ -651,7 +747,11 @@ int sftp_cmd_rm(struct sftp_command *cmd) return 0; } - result = fxp_remove(fname); + sftp_register(req = fxp_remove_send(fname)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + result = fxp_remove_recv(pktin, rreq); + if (!result) { printf("rm %s: %s\n", fname, fxp_error()); sfree(fname); @@ -665,6 +765,8 @@ int sftp_cmd_rm(struct sftp_command *cmd) int sftp_cmd_mv(struct sftp_command *cmd) { char *srcfname, *dstfname; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; int result; if (back == NULL) { @@ -688,7 +790,11 @@ int sftp_cmd_mv(struct sftp_command *cmd) return 0; } - result = fxp_rename(srcfname, dstfname); + sftp_register(req = fxp_rename_send(srcfname, dstfname)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + result = fxp_rename_recv(pktin, rreq); + if (!result) { char const *error = fxp_error(); struct fxp_attrs attrs; @@ -699,7 +805,11 @@ int sftp_cmd_mv(struct sftp_command *cmd) * _is_ a directory, we re-attempt the move by appending * the basename of srcfname to dstfname. */ - result = fxp_stat(dstfname, &attrs); + sftp_register(req = fxp_stat_send(dstfname)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + result = fxp_stat_recv(pktin, rreq, &attrs); + if (result && (attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) && (attrs.permissions & 0040000)) { @@ -714,7 +824,12 @@ int sftp_cmd_mv(struct sftp_command *cmd) if (newcanon) { sfree(dstfname); dstfname = newcanon; - result = fxp_rename(srcfname, dstfname); + + sftp_register(req = fxp_rename_send(srcfname, dstfname)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + result = fxp_rename_recv(pktin, rreq); + error = result ? NULL : fxp_error(); } } @@ -738,6 +853,8 @@ int sftp_cmd_chmod(struct sftp_command *cmd) int result; struct fxp_attrs attrs; unsigned attrs_clr, attrs_xor, oldperms, newperms; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; if (back == NULL) { printf("psftp: not connected to a host; use \"open host.name\"\n"); @@ -788,20 +905,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; @@ -816,7 +933,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; @@ -824,7 +941,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++; @@ -832,7 +949,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; @@ -860,7 +977,11 @@ int sftp_cmd_chmod(struct sftp_command *cmd) return 0; } - result = fxp_stat(fname, &attrs); + sftp_register(req = fxp_stat_send(fname)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + result = fxp_stat_recv(pktin, rreq, &attrs); + if (!result || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) { printf("get attrs for %s: %s\n", fname, result ? "file permissions not provided" : fxp_error()); @@ -874,7 +995,10 @@ int sftp_cmd_chmod(struct sftp_command *cmd) attrs.permissions ^= attrs_xor; newperms = attrs.permissions & 07777; - result = fxp_setstat(fname, attrs); + sftp_register(req = fxp_setstat_send(fname, attrs)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + result = fxp_setstat_recv(pktin, rreq); if (!result) { printf("set attrs for %s: %s\n", fname, fxp_error()); @@ -910,34 +1034,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); @@ -947,13 +1058,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); @@ -994,9 +1100,10 @@ static struct sftp_cmd_lookup { * in ASCII order. */ { - "!", TRUE, "run a local Windows command", + "!", TRUE, "run a local 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 }, { @@ -1298,8 +1405,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 { /* @@ -1342,10 +1449,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. */ @@ -1366,6 +1474,9 @@ struct sftp_command *sftp_getcmd(FILE *fp, int mode, int modeflags) static int do_sftp_init(void) { + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; + /* * Do protocol initialisation. */ @@ -1378,7 +1489,11 @@ static int do_sftp_init(void) /* * Find out where our home directory is. */ - homedir = fxp_realpath("."); + sftp_register(req = fxp_realpath_send(".")); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + homedir = fxp_realpath_recv(pktin, rreq); + if (!homedir) { fprintf(stderr, "Warning: failed to resolve home directory: %s\n", @@ -1391,6 +1506,23 @@ static int do_sftp_init(void) return 0; } +void do_sftp_cleanup() +{ + char ch; + 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; @@ -1409,7 +1541,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 { @@ -1500,20 +1640,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. */ @@ -1541,14 +1667,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; } @@ -1558,7 +1683,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; @@ -1608,13 +1733,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; @@ -1626,42 +1746,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) @@ -1692,6 +1776,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; @@ -1842,9 +1927,16 @@ 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); + if (realhost != NULL) + sfree(realhost); return 0; } @@ -1862,7 +1954,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; @@ -1872,10 +1964,13 @@ int 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; - init_winsock(); sk_init(); userhost = user = NULL; @@ -1927,13 +2022,16 @@ int 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); @@ -1943,8 +2041,13 @@ int main(int argc, char *argv[]) back->special(backhandle, TS_EOF); sftp_recvdata(&ch, 1); } - WSACleanup(); random_save_seed(); + cmdline_cleanup(); + console_provide_logctx(NULL); + do_sftp_cleanup(); + backhandle = NULL; + back = NULL; + sk_cleanup(); return 0; }