X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/2184a5d91ffbcf2de2f730c83dda2d9443035f50..3ca5c28cafade2c9e0ada4d5b30c1d9b1be32f4c:/psftp.c diff --git a/psftp.c b/psftp.c index 250a5fcc..feefbbc0 100644 --- a/psftp.c +++ b/psftp.c @@ -24,6 +24,9 @@ * send buffer. */ +static int psftp_connect(char *userhost, char *user, int portnumber); +static void do_sftp_init(void); + /* ---------------------------------------------------------------------- * sftp client state. */ @@ -165,13 +168,13 @@ struct sftp_command { int sftp_cmd_null(struct sftp_command *cmd) { - return 0; + return 1; /* success */ } int sftp_cmd_unknown(struct sftp_command *cmd) { printf("psftp: unknown command \"%s\"\n", cmd->words[0]); - return 0; + return 0; /* failure */ } int sftp_cmd_quit(struct sftp_command *cmd) @@ -198,6 +201,11 @@ int sftp_cmd_ls(struct sftp_command *cmd) char *dir, *cdir; int i; + if (back == NULL) { + printf("psftp: not connected to a host; use \"open host.name\"\n"); + return 0; + } + if (cmd->nwords < 2) dir = "."; else @@ -261,7 +269,7 @@ int sftp_cmd_ls(struct sftp_command *cmd) sfree(cdir); - return 0; + return 1; } /* @@ -273,6 +281,11 @@ int sftp_cmd_cd(struct sftp_command *cmd) struct fxp_handle *dirh; char *dir; + if (back == NULL) { + printf("psftp: not connected to a host; use \"open host.name\"\n"); + return 0; + } + if (cmd->nwords < 2) dir = dupstr(homedir); else @@ -296,7 +309,7 @@ int sftp_cmd_cd(struct sftp_command *cmd) pwd = dir; printf("Remote directory is now %s\n", pwd); - return 0; + return 1; } /* @@ -304,8 +317,13 @@ int sftp_cmd_cd(struct sftp_command *cmd) */ int sftp_cmd_pwd(struct sftp_command *cmd) { + if (back == NULL) { + printf("psftp: not connected to a host; use \"open host.name\"\n"); + return 0; + } + printf("Remote directory is %s\n", pwd); - return 0; + return 1; } /* @@ -320,6 +338,12 @@ int sftp_general_get(struct sftp_command *cmd, int restart) char *fname, *outfname; uint64 offset; FILE *fp; + int ret; + + if (back == NULL) { + printf("psftp: not connected to a host; use \"open host.name\"\n"); + return 0; + } if (cmd->nwords < 2) { printf("get: expects a filename\n"); @@ -370,6 +394,7 @@ int sftp_general_get(struct sftp_command *cmd, int restart) * FIXME: we can use FXP_FSTAT here to get the file size, and * thus put up a progress bar. */ + ret = 1; while (1) { char buffer[4096]; int len; @@ -380,6 +405,7 @@ int sftp_general_get(struct sftp_command *cmd, int restart) break; if (len == -1) { printf("error while reading: %s\n", fxp_error()); + ret = 0; break; } @@ -388,12 +414,15 @@ int sftp_general_get(struct sftp_command *cmd, int restart) wlen = fwrite(buffer, 1, len - wpos, fp); if (wlen <= 0) { printf("error while writing local file\n"); + ret = 0; break; } wpos += wlen; } - if (wpos < len) /* we had an error */ + if (wpos < len) { /* we had an error */ + ret = 0; break; + } offset = uint64_add32(offset, len); } @@ -401,7 +430,7 @@ int sftp_general_get(struct sftp_command *cmd, int restart) fxp_close(fh); sfree(fname); - return 0; + return ret; } int sftp_cmd_get(struct sftp_command *cmd) { @@ -424,6 +453,12 @@ int sftp_general_put(struct sftp_command *cmd, int restart) char *fname, *origoutfname, *outfname; uint64 offset; FILE *fp; + int ret; + + if (back == NULL) { + printf("psftp: not connected to a host; use \"open host.name\"\n"); + return 0; + } if (cmd->nwords < 2) { printf("put: expects a filename\n"); @@ -491,6 +526,7 @@ int sftp_general_put(struct sftp_command *cmd, int restart) * FIXME: we can use FXP_FSTAT here to get the file size, and * thus put up a progress bar. */ + ret = 1; while (1) { char buffer[4096]; int len; @@ -498,12 +534,14 @@ int sftp_general_put(struct sftp_command *cmd, int restart) 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; } if (!fxp_write(fh, buffer, offset, len)) { printf("error while writing: %s\n", fxp_error()); + ret = 0; break; } offset = uint64_add32(offset, len); @@ -513,7 +551,7 @@ int sftp_general_put(struct sftp_command *cmd, int restart) fclose(fp); sfree(outfname); - return 0; + return ret; } int sftp_cmd_put(struct sftp_command *cmd) { @@ -529,6 +567,10 @@ int sftp_cmd_mkdir(struct sftp_command *cmd) char *dir; int result; + if (back == NULL) { + printf("psftp: not connected to a host; use \"open host.name\"\n"); + return 0; + } if (cmd->nwords < 2) { printf("mkdir: expects a directory\n"); @@ -549,7 +591,7 @@ int sftp_cmd_mkdir(struct sftp_command *cmd) } sfree(dir); - return 0; + return 1; } int sftp_cmd_rmdir(struct sftp_command *cmd) @@ -557,6 +599,10 @@ int sftp_cmd_rmdir(struct sftp_command *cmd) char *dir; int result; + if (back == NULL) { + printf("psftp: not connected to a host; use \"open host.name\"\n"); + return 0; + } if (cmd->nwords < 2) { printf("rmdir: expects a directory\n"); @@ -577,7 +623,7 @@ int sftp_cmd_rmdir(struct sftp_command *cmd) } sfree(dir); - return 0; + return 1; } int sftp_cmd_rm(struct sftp_command *cmd) @@ -585,6 +631,11 @@ int sftp_cmd_rm(struct sftp_command *cmd) char *fname; int result; + if (back == NULL) { + printf("psftp: not connected to a host; use \"open host.name\"\n"); + return 0; + } + if (cmd->nwords < 2) { printf("rm: expects a filename\n"); return 0; @@ -604,8 +655,7 @@ int sftp_cmd_rm(struct sftp_command *cmd) } sfree(fname); - return 0; - + return 1; } int sftp_cmd_mv(struct sftp_command *cmd) @@ -613,6 +663,11 @@ int sftp_cmd_mv(struct sftp_command *cmd) char *srcfname, *dstfname; int result; + if (back == NULL) { + printf("psftp: not connected to a host; use \"open host.name\"\n"); + return 0; + } + if (cmd->nwords < 3) { printf("mv: expects two filenames\n"); return 0; @@ -670,7 +725,7 @@ int sftp_cmd_mv(struct sftp_command *cmd) sfree(srcfname); sfree(dstfname); - return 0; + return 1; } int sftp_cmd_chmod(struct sftp_command *cmd) @@ -680,6 +735,11 @@ int sftp_cmd_chmod(struct sftp_command *cmd) struct fxp_attrs attrs; unsigned attrs_clr, attrs_xor, oldperms, newperms; + if (back == NULL) { + printf("psftp: not connected to a host; use \"open host.name\"\n"); + return 0; + } + if (cmd->nwords < 3) { printf("chmod: expects a mode specifier and a filename\n"); return 0; @@ -821,7 +881,27 @@ int sftp_cmd_chmod(struct sftp_command *cmd) printf("%s: %04o -> %04o\n", fname, oldperms, newperms); sfree(fname); - return 0; + return 1; +} + +static int sftp_cmd_open(struct sftp_command *cmd) +{ + if (back != NULL) { + printf("psftp: already connected\n"); + return 0; + } + + if (cmd->nwords < 2) { + printf("open: expects a host name\n"); + return 0; + } + + if (psftp_connect(cmd->words[1], NULL, 0)) { + back = NULL; /* connection is already closed */ + return -1; /* this is fatal */ + } + do_sftp_init(); + return 1; } static int sftp_cmd_help(struct sftp_command *cmd); @@ -954,6 +1034,14 @@ static struct sftp_cmd_lookup { sftp_cmd_put }, { + "open", "connect to a host", + " [@]\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", + sftp_cmd_open + }, + { "pwd", "print your remote working directory", "\n" " Print the current remote working directory for your SFTP session.\n", @@ -1059,7 +1147,7 @@ static int sftp_cmd_help(struct sftp_command *cmd) } } } - return 0; + return 1; } /* ---------------------------------------------------------------------- @@ -1073,9 +1161,9 @@ struct sftp_command *sftp_getcmd(FILE *fp, int mode, int modeflags) char *p, *q, *r; int quoting; - if ((mode == 0) || (modeflags & 1)) { - printf("psftp> "); - } + if ((mode == 0) || (modeflags & 1)) { + printf("psftp> "); + } fflush(stdout); cmd = smalloc(sizeof(struct sftp_command)); @@ -1092,13 +1180,11 @@ struct sftp_command *sftp_getcmd(FILE *fp, int mode, int modeflags) linesize += 512; line = srealloc(line, linesize); ret = fgets(line + linelen, linesize - linelen, fp); - if (modeflags & 1) { - printf("%s", ret); - } if (!ret || (linelen == 0 && line[0] == '\0')) { cmd->obey = sftp_cmd_quit; - printf("quit\n"); + if ((mode == 0) || (modeflags & 1)) + printf("quit\n"); return cmd; /* eof */ } len = linelen + strlen(line + linelen); @@ -1109,6 +1195,9 @@ struct sftp_command *sftp_getcmd(FILE *fp, int mode, int modeflags) break; } } + if (modeflags & 1) { + printf("%s\n", line); + } /* * Parse the command line into words. The syntax is: @@ -1173,10 +1262,8 @@ struct sftp_command *sftp_getcmd(FILE *fp, int mode, int modeflags) return cmd; } -void do_sftp(int mode, int modeflags, char *batchfile) +static void do_sftp_init(void) { - FILE *fp; - /* * Do protocol initialisation. */ @@ -1199,6 +1286,12 @@ void do_sftp(int mode, int modeflags, char *batchfile) printf("Remote working directory is %s\n", homedir); } pwd = dupstr(homedir); +} + +void do_sftp(int mode, int modeflags, char *batchfile) +{ + FILE *fp; + int ret; /* * Batch mode? @@ -1209,12 +1302,12 @@ void do_sftp(int mode, int modeflags, char *batchfile) * Now we're ready to do Real Stuff. */ while (1) { - struct sftp_command *cmd; - cmd = sftp_getcmd(stdin, 0, 0); - if (!cmd) - break; - if (cmd->obey(cmd) < 0) - break; + struct sftp_command *cmd; + cmd = sftp_getcmd(stdin, 0, 0); + if (!cmd) + break; + if (cmd->obey(cmd) < 0) + break; } } else { fp = fopen(batchfile, "r"); @@ -1227,9 +1320,10 @@ void do_sftp(int mode, int modeflags, char *batchfile) cmd = sftp_getcmd(fp, mode, modeflags); if (!cmd) break; - if (cmd->obey(cmd) < 0) + ret = cmd->obey(cmd); + if (ret < 0) break; - if (fxp_error() != NULL) { + if (ret == 0) { if (!(modeflags & 2)) break; } @@ -1392,7 +1486,7 @@ void fatalbox(char *fmt, ...) vsprintf(str + strlen(str), fmt, ap); va_end(ap); strcat(str, "\n"); - fprintf(stderr, str); + fputs(stderr, str); exit(1); } @@ -1405,7 +1499,7 @@ void connection_fatal(char *fmt, ...) vsprintf(str + strlen(str), fmt, ap); va_end(ap); strcat(str, "\n"); - fprintf(stderr, str); + fputs(stderr, str); exit(1); } @@ -1648,62 +1742,12 @@ static void usage(void) } /* - * Main program. Parse arguments etc. + * Connect to a host. */ -int main(int argc, char *argv[]) +static int psftp_connect(char *userhost, char *user, int portnumber) { - int i; - int portnumber = 0; - char *user, *host, *userhost, *realhost; + char *host, *realhost; char *err; - int mode = 0; - int modeflags = 0; - char *batchfile = NULL; - - flags = FLAG_STDERR | FLAG_INTERACTIVE; - ssh_get_line = &get_line; - init_winsock(); - sk_init(); - - userhost = user = NULL; - - for (i = 1; i < argc; i++) { - if (argv[i][0] != '-') { - if (userhost) - usage(); - else - userhost = dupstr(argv[i]); - } else if (strcmp(argv[i], "-v") == 0) { - verbose = 1, flags |= FLAG_VERBOSE; - } else if (strcmp(argv[i], "-h") == 0 || - strcmp(argv[i], "-?") == 0) { - usage(); - } else if (strcmp(argv[i], "-l") == 0 && i + 1 < argc) { - user = argv[++i]; - } else if (strcmp(argv[i], "-P") == 0 && i + 1 < argc) { - portnumber = atoi(argv[++i]); - } else if (strcmp(argv[i], "-pw") == 0 && i + 1 < argc) { - password = argv[++i]; - } else if (strcmp(argv[i], "-b") == 0 && i + 1 < argc) { - mode = 1; - batchfile = argv[++i]; - } else if (strcmp(argv[i], "-bc") == 0 && i + 1 < argc) { - modeflags = modeflags | 1; - } else if (strcmp(argv[i], "-be") == 0 && i + 1 < argc) { - modeflags = modeflags | 2; - } else if (strcmp(argv[i], "--") == 0) { - i++; - break; - } else { - usage(); - } - } - argc -= i; - argv += i; - back = NULL; - - if (argc > 0 || !userhost) - usage(); /* Separate host and username */ host = userhost; @@ -1822,12 +1866,81 @@ int main(int argc, char *argv[]) err = back->init(cfg.host, cfg.port, &realhost, 0); if (err != NULL) { - fprintf(stderr, "ssh_init: %s", err); + fprintf(stderr, "ssh_init: %s\n", err); return 1; } ssh_sftp_init(); if (verbose && realhost != NULL) printf("Connected to %s\n", realhost); + return 0; +} + +/* + * Main program. Parse arguments etc. + */ +int main(int argc, char *argv[]) +{ + int i; + int portnumber = 0; + char *userhost, *user; + int mode = 0; + int modeflags = 0; + char *batchfile = NULL; + + flags = FLAG_STDERR | FLAG_INTERACTIVE; + ssh_get_line = &get_line; + init_winsock(); + sk_init(); + + userhost = user = NULL; + + for (i = 1; i < argc; i++) { + if (argv[i][0] != '-') { + if (userhost) + usage(); + else + userhost = dupstr(argv[i]); + } else if (strcmp(argv[i], "-v") == 0) { + verbose = 1, flags |= FLAG_VERBOSE; + } else if (strcmp(argv[i], "-h") == 0 || + strcmp(argv[i], "-?") == 0) { + usage(); + } else if (strcmp(argv[i], "-l") == 0 && i + 1 < argc) { + user = argv[++i]; + } else if (strcmp(argv[i], "-P") == 0 && i + 1 < argc) { + portnumber = atoi(argv[++i]); + } else if (strcmp(argv[i], "-pw") == 0 && i + 1 < argc) { + password = argv[++i]; + } else if (strcmp(argv[i], "-b") == 0 && i + 1 < argc) { + mode = 1; + batchfile = argv[++i]; + } else if (strcmp(argv[i], "-bc") == 0) { + modeflags = modeflags | 1; + } else if (strcmp(argv[i], "-be") == 0) { + modeflags = modeflags | 2; + } else if (strcmp(argv[i], "--") == 0) { + i++; + break; + } else { + usage(); + } + } + argc -= i; + argv += i; + back = NULL; + + /* + * If a user@host string has already been provided, connect to + * it now. + */ + if (userhost) { + if (psftp_connect(userhost, user, portnumber)) + return 1; + do_sftp_init(); + } else { + printf("psftp: no hostname specified; use \"open host.name\"" + " to connect\n"); + } do_sftp(mode, modeflags, batchfile);