#include "ssh.h"
#include "sftp.h"
#include "storage.h"
+#include "int64.h"
static int list = 0;
static int verbose = 0;
static int prev_stats_len = 0;
static int scp_unsafe_mode = 0;
static int errs = 0;
-static int gui_mode = 0;
static int try_scp = 1;
static int try_sftp = 1;
static int main_cmd_is_sftp = 0;
static void tell_char(FILE * stream, char c)
{
- if (!gui_mode)
- fputc(c, stream);
- else
- gui_send_char(stream == stderr, c);
+ fputc(c, stream);
}
static void tell_str(FILE * stream, char *str)
sfree(str2);
errs++;
- if (gui_mode)
- gui_send_errcount(list, errs);
-
cleanup_exit(1);
}
void modalfatalbox(char *fmt, ...)
sfree(str2);
errs++;
- if (gui_mode)
- gui_send_errcount(list, errs);
-
cleanup_exit(1);
}
void connection_fatal(void *frontend, char *fmt, ...)
sfree(str2);
errs++;
- if (gui_mode)
- gui_send_errcount(list, errs);
-
cleanup_exit(1);
}
if (pendsize < pendlen + len) {
pendsize = pendlen + len + 4096;
pending = sresize(pending, pendsize, unsigned char);
- if (!pending)
- fatalbox("Out of memory");
}
memcpy(pending + pendlen, p, len);
pendlen += len;
return 0;
}
+int from_backend_untrusted(void *frontend_handle, const char *data, int len)
+{
+ /*
+ * No "untrusted" output should get here (the way the code is
+ * currently, it's all diverted by FLAG_STDERR).
+ */
+ assert(!"Unexpected call to from_backend_untrusted()");
+ return 0; /* not reached */
+}
static int ssh_scp_recv(unsigned char *buf, int len)
{
outptr = buf;
}
while (outlen > 0) {
- if (ssh_sftp_loop_iteration() < 0)
+ if (back->exitcode(backhandle) >= 0 || ssh_sftp_loop_iteration() < 0)
return 0; /* doom */
}
ssh_scp_recv((unsigned char *) &ch, 1);
}
- if (gui_mode)
- gui_send_errcount(list, errs);
-
cleanup_exit(1);
}
bump("Empty host name");
/*
+ * Remove fiddly bits of address: remove a colon suffix, and
+ * the square brackets around an IPv6 literal address.
+ */
+ if (host[0] == '[') {
+ host++;
+ host[strcspn(host, "]")] = '\0';
+ } else {
+ host[strcspn(host, ":")] = '\0';
+ }
+
+ /*
* If we haven't loaded session details already (e.g., from -load),
* try looking for a session called "host".
*/
}
/*
- * Trim a colon suffix off the hostname if it's there.
- */
- cfg.host[strcspn(cfg.host, ":")] = '\0';
-
- /*
* Remove any remaining whitespace from the hostname.
*/
{
/*
* Update statistic information about current file.
*/
-static void print_stats(char *name, unsigned long size, unsigned long done,
+static void print_stats(char *name, uint64 size, uint64 done,
time_t start, time_t now)
{
float ratebs;
int pct;
int len;
int elap;
+ double donedbl;
+ double sizedbl;
elap = (unsigned long) difftime(now, start);
if (now > start)
- ratebs = (float) done / elap;
+ ratebs = (float) (uint64_to_double(done) / elap);
else
- ratebs = (float) done;
+ ratebs = (float) uint64_to_double(done);
if (ratebs < 1.0)
- eta = size - done;
- else
- eta = (unsigned long) ((size - done) / ratebs);
+ eta = (unsigned long) (uint64_to_double(uint64_subtract(size, done)));
+ else {
+ eta = (unsigned long)
+ ((uint64_to_double(uint64_subtract(size, done)) / ratebs));
+ }
+
etastr = dupprintf("%02ld:%02ld:%02ld",
eta / 3600, (eta % 3600) / 60, eta % 60);
- pct = (int) (100 * (done * 1.0 / size));
+ donedbl = uint64_to_double(done);
+ sizedbl = uint64_to_double(size);
+ pct = (int) (100 * (donedbl * 1.0 / sizedbl));
- if (gui_mode) {
- gui_update_stats(name, size, pct, elap, done, eta,
- (unsigned long) ratebs);
- } else {
- len = printf("\r%-25.25s | %10ld kB | %5.1f kB/s | ETA: %8s | %3d%%",
- name, done / 1024, ratebs / 1024.0, etastr, pct);
+ {
+ char donekb[40];
+ /* divide by 1024 to provide kB */
+ uint64_decimal(uint64_shift_right(done, 10), donekb);
+ len = printf("\r%-25.25s | %s kB | %5.1f kB/s | ETA: %8s | %3d%%",
+ name,
+ donekb, ratebs / 1024.0, etastr, pct);
if (len < prev_stats_len)
printf("%*s", prev_stats_len - len, "");
prev_stats_len = len;
- if (done == size)
+ if (uint64_compare(done, size) == 0)
printf("\n");
fflush(stdout);
/* We ignore a leading colon, since the hostname cannot be
empty. We also ignore a colon as second character because
of filenames like f:myfile.txt. */
- if (str[0] == '\0' || str[0] == ':' || str[1] == ':')
+ if (str[0] == '\0' || str[0] == ':' ||
+ (str[0] != '[' && str[1] == ':'))
return (NULL);
- while (*str != '\0' && *str != ':' && *str != '/' && *str != '\\')
+ while (*str != '\0' && *str != ':' && *str != '/' && *str != '\\') {
+ if (*str == '[') {
+ /* Skip over IPv6 literal addresses
+ * (eg: 'jeroen@[2001:db8::1]:myfile.txt') */
+ char *ipv6_end = strchr(str, ']');
+ if (ipv6_end) {
+ str = ipv6_end;
+ }
+ }
str++;
+ }
if (*str == ':')
return (str);
else
static struct fxp_xfer *scp_sftp_xfer;
static uint64 scp_sftp_fileoffset;
-void scp_source_setup(char *target, int shouldbedir)
+int scp_source_setup(char *target, int shouldbedir)
{
if (using_sftp) {
/*
if (!fxp_init()) {
tell_user(stderr, "unable to initialise SFTP: %s", fxp_error());
errs++;
- return;
+ return 1;
}
sftp_register(req = fxp_stat_send(target));
} else {
(void) response();
}
+ return 0;
}
int scp_send_errmsg(char *str)
}
}
-int scp_send_filename(char *name, unsigned long size, int modes)
+int scp_send_filename(char *name, uint64 size, int modes)
{
if (using_sftp) {
char *fullname;
return 0;
} else {
char buf[40];
- sprintf(buf, "C%04o %lu ", modes, size);
+ char sizestr[40];
+ uint64_decimal(size, sizestr);
+ sprintf(buf, "C%04o %s ", modes, sizestr);
back->send(backhandle, buf, strlen(buf));
back->send(backhandle, name, strlen(name));
back->send(backhandle, "\n", 1);
char *buf; /* will need freeing after use */
char *name; /* filename or dirname (not ENDDIR) */
int mode; /* access mode (not ENDDIR) */
- unsigned long size; /* file size (not ENDDIR) */
+ uint64 size; /* file size (not ENDDIR) */
int settime; /* 1 if atime and mtime are filled */
unsigned long atime, mtime; /* access times for the file */
};
act->action = SCP_SINK_DIR;
act->buf = dupstr(stripslashes(fname, 0));
act->name = act->buf;
- act->size = 0; /* duhh, it's a directory */
+ act->size = uint64_make(0,0); /* duhh, it's a directory */
act->mode = 07777 & attrs.permissions;
if (scp_sftp_preserve &&
(attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME)) {
act->buf = dupstr(stripslashes(fname, 0));
act->name = act->buf;
if (attrs.flags & SSH_FILEXFER_ATTR_SIZE) {
- if (uint64_compare(attrs.size,
- uint64_make(0, ULONG_MAX)) > 0) {
- act->size = ULONG_MAX; /* *boggle* */
- } else
- act->size = attrs.size.lo;
+ act->size = attrs.size;
} else
- act->size = ULONG_MAX; /* no idea */
+ act->size = uint64_make(ULONG_MAX,ULONG_MAX); /* no idea */
act->mode = 07777 & attrs.permissions;
if (scp_sftp_preserve &&
(attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME)) {
* If we get here, we must have seen SCP_SINK_FILE or
* SCP_SINK_DIR.
*/
- if (sscanf(act->buf, "%o %lu %n", &act->mode, &act->size, &i) != 2)
- bump("Protocol error: Illegal file descriptor format");
- act->name = act->buf + i;
- return 0;
+ {
+ char sizestr[40];
+
+ if (sscanf(act->buf, "%o %s %n", &act->mode, sizestr, &i) != 2)
+ bump("Protocol error: Illegal file descriptor format");
+ act->size = uint64_from_decimal(sizestr);
+ act->name = act->buf + i;
+ return 0;
+ }
}
}
*/
static void source(char *src)
{
- unsigned long size;
+ uint64 size;
unsigned long mtime, atime;
char *last;
RFile *f;
int attr;
- unsigned long i;
- unsigned long stat_bytes;
+ uint64 i;
+ uint64 stat_bytes;
time_t stat_starttime, stat_lasttime;
attr = file_type(src);
return;
}
- if (verbose)
- tell_user(stderr, "Sending file %s, size=%lu", last, size);
+ if (verbose) {
+ char sizestr[40];
+ uint64_decimal(size, sizestr);
+ tell_user(stderr, "Sending file %s, size=%s", last, sizestr);
+ }
if (scp_send_filename(last, size, 0644))
return;
- stat_bytes = 0;
+ stat_bytes = uint64_make(0,0);
stat_starttime = time(NULL);
stat_lasttime = 0;
- for (i = 0; i < size; i += 4096) {
+ for (i = uint64_make(0,0);
+ uint64_compare(i,size) < 0;
+ i = uint64_add32(i,4096)) {
char transbuf[4096];
int j, k = 4096;
- if (i + k > size)
- k = size - i;
+ if (uint64_compare(uint64_add32(i, k),size) > 0) /* i + k > size */
+ k = (uint64_subtract(size, i)).lo; /* k = size - i; */
if ((j = read_from_file(f, transbuf, k)) != k) {
if (statistics)
printf("\n");
bump("%s: Network error occurred", src);
if (statistics) {
- stat_bytes += k;
- if (time(NULL) != stat_lasttime || i + k == size) {
+ stat_bytes = uint64_add32(stat_bytes, k);
+ if (time(NULL) != stat_lasttime ||
+ (uint64_compare(uint64_add32(i, k), size) == 0)) {
stat_lasttime = time(NULL);
print_stats(last, size, stat_bytes,
stat_starttime, stat_lasttime);
int exists;
int attr;
WFile *f;
- unsigned long received;
+ uint64 received;
int wrerror = 0;
- unsigned long stat_bytes;
+ uint64 stat_bytes;
time_t stat_starttime, stat_lasttime;
char *stat_name;
tell_user(stderr, " when we requested a file "
"called '%s'.", stripsrc);
tell_user(stderr, " If this is a wildcard, "
- "consider upgrading to SSH 2 or using");
+ "consider upgrading to SSH-2 or using");
tell_user(stderr, " the '-unsafe' option. Renaming"
" of this file has been disallowed.");
/* Override the name the server provided with our own. */
if (scp_accept_filexfer())
return;
- stat_bytes = 0;
+ stat_bytes = uint64_make(0, 0);
stat_starttime = time(NULL);
stat_lasttime = 0;
stat_name = stripslashes(destfname, 1);
- received = 0;
- while (received < act.size) {
- char transbuf[4096];
- unsigned long blksize;
+ received = uint64_make(0, 0);
+ while (uint64_compare(received,act.size) < 0) {
+ char transbuf[32768];
+ uint64 blksize;
int read;
- blksize = 4096;
- if (blksize > (act.size - received))
- blksize = act.size - received;
- read = scp_recv_filedata(transbuf, (int)blksize);
+ blksize = uint64_make(0, 32768);
+ if (uint64_compare(blksize,uint64_subtract(act.size,received)) > 0)
+ blksize = uint64_subtract(act.size,received);
+ read = scp_recv_filedata(transbuf, (int)blksize.lo);
if (read <= 0)
bump("Lost connection");
if (wrerror)
continue;
}
if (statistics) {
- stat_bytes += read;
+ stat_bytes = uint64_add32(stat_bytes,read);
if (time(NULL) > stat_lasttime ||
- received + read == act.size) {
+ uint64_compare(uint64_add32(received, read), act.size) == 0) {
stat_lasttime = time(NULL);
print_stats(stat_name, act.size, stat_bytes,
stat_starttime, stat_lasttime);
}
}
- received += read;
+ received = uint64_add32(received, read);
}
if (act.settime) {
set_file_times(f, act.mtime, act.atime);
*targ++ = '\0';
if (*targ == '\0')
targ = ".";
- /* Substitute "." for emtpy target */
+ /* Substitute "." for empty target */
/* Separate host and username */
user = host;
do_cmd(host, user, cmd);
sfree(cmd);
- scp_source_setup(targ, targetshouldbedirectory);
+ if (scp_source_setup(targ, targetshouldbedirectory))
+ return;
for (i = 0; i < argc - 1; i++) {
src = argv[i];
(" pscp [options] source [source...] [user@]host:target\n");
printf(" pscp [options] -ls [user@]host:filespec\n");
printf("Options:\n");
+ printf(" -V print version information and exit\n");
+ printf(" -pgpfp print PGP key fingerprints and exit\n");
printf(" -p preserve file attributes\n");
printf(" -q quiet, don't show statistics\n");
printf(" -r copy directories recursively\n");
printf(" -l user connect with specified username\n");
printf(" -pw passw login with specified password\n");
printf(" -1 -2 force use of particular SSH protocol version\n");
+ printf(" -4 -6 force use of IPv4 or IPv6\n");
printf(" -C enable compression\n");
printf(" -i key private key file for authentication\n");
+ printf(" -noagent disable use of Pageant\n");
+ printf(" -agent enable use of Pageant\n");
printf(" -batch disable all interactive prompts\n");
printf(" -unsafe allow server-side wildcards (DANGEROUS)\n");
- printf(" -V print version information\n");
printf(" -sftp force use of SFTP protocol\n");
printf(" -scp force use of SCP protocol\n");
#if 0
#endif
;
cmdline_tooltype = TOOLTYPE_FILETRANSFER;
- ssh_get_line = &console_get_line;
sk_init();
/* Load Default Settings before doing anything else. */
/* We have our own verbosity in addition to `flags'. */
if (flags & FLAG_VERBOSE)
verbose = 1;
+ } else if (strcmp(argv[i], "-pgpfp") == 0) {
+ pgp_fingerprints();
+ return 1;
} else if (strcmp(argv[i], "-r") == 0) {
recursive = 1;
} else if (strcmp(argv[i], "-p") == 0) {
usage();
} else if (strcmp(argv[i], "-V") == 0) {
version();
- } else if (strcmp(argv[i], "-gui") == 0 && i + 1 < argc) {
- gui_enable(argv[++i]);
- gui_mode = 1;
- console_batch_mode = TRUE;
} else if (strcmp(argv[i], "-ls") == 0) {
list = 1;
} else if (strcmp(argv[i], "-batch") == 0) {
}
random_save_seed();
- if (gui_mode)
- gui_send_errcount(list, errs);
-
cmdline_cleanup();
console_provide_logctx(NULL);
back->free(backhandle);