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 int fallback_cmd_is_sftp = 0;
static int using_sftp = 0;
static Backend *back;
if (ssh_sftp_loop_iteration() < 0)
return; /* doom */
}
- using_sftp = !ssh_fallback_cmd(backhandle);
+
+ /* Work out which backend we ended up using. */
+ if (!ssh_fallback_cmd(backhandle))
+ using_sftp = main_cmd_is_sftp;
+ else
+ using_sftp = fallback_cmd_is_sftp;
+
if (verbose) {
if (using_sftp)
tell_user(stderr, "Using SFTP");
if (host == NULL || host[0] == '\0')
bump("Empty host name");
- /* Try to load settings for this host */
- do_defaults(host, &cfg);
- if (cfg.host[0] == '\0') {
- /* No settings for this host; use defaults */
- do_defaults(NULL, &cfg);
+ /*
+ * If we haven't loaded session details already (e.g., from -load),
+ * try looking for a session called "host".
+ */
+ if (!loaded_session) {
+ /* Try to load settings for `host' into a temporary config */
+ Config cfg2;
+ cfg2.host[0] = '\0';
+ do_defaults(host, &cfg2);
+ if (cfg2.host[0] != '\0') {
+ /* Settings present and include hostname */
+ /* Re-load data into the real config. */
+ do_defaults(host, &cfg);
+ } else {
+ /* Session doesn't exist or mention a hostname. */
+ /* Use `host' as a bare hostname. */
+ strncpy(cfg.host, host, sizeof(cfg.host) - 1);
+ cfg.host[sizeof(cfg.host) - 1] = '\0';
+ }
+ } else {
+ /* Patch in hostname `host' to session details. */
strncpy(cfg.host, host, sizeof(cfg.host) - 1);
cfg.host[sizeof(cfg.host) - 1] = '\0';
}
/* See if host is of the form user@host */
if (cfg.host[0] != '\0') {
- char *atsign = strchr(cfg.host, '@');
+ char *atsign = strrchr(cfg.host, '@');
/* Make sure we're not overflowing the user field */
if (atsign) {
if (atsign - cfg.host < sizeof cfg.username) {
cfg.portfwd[0] = cfg.portfwd[1] = '\0';
/*
+ * Set up main and possibly fallback command depending on
+ * options specified by user.
* Attempt to start the SFTP subsystem as a first choice,
* falling back to the provided scp command if that fails.
*/
- strcpy(cfg.remote_cmd, "sftp");
- cfg.ssh_subsys = TRUE;
- cfg.remote_cmd_ptr2 = cmd;
- cfg.ssh_subsys2 = FALSE;
+ cfg.remote_cmd_ptr2 = NULL;
+ if (try_sftp) {
+ /* First choice is SFTP subsystem. */
+ main_cmd_is_sftp = 1;
+ strcpy(cfg.remote_cmd, "sftp");
+ cfg.ssh_subsys = TRUE;
+ if (try_scp) {
+ /* Fallback is to use the provided scp command. */
+ fallback_cmd_is_sftp = 0;
+ cfg.remote_cmd_ptr2 = cmd;
+ cfg.ssh_subsys2 = FALSE;
+ } else {
+ /* Since we're not going to try SCP, we may as well try
+ * harder to find an SFTP server, since in the current
+ * implementation we have a spare slot. */
+ fallback_cmd_is_sftp = 1;
+ /* see psftp.c for full explanation of this kludge */
+ cfg.remote_cmd_ptr2 =
+ "test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server\n"
+ "test -x /usr/local/lib/sftp-server && exec /usr/local/lib/sftp-server\n"
+ "exec sftp-server";
+ cfg.ssh_subsys2 = FALSE;
+ }
+ } else {
+ /* Don't try SFTP at all; just try the scp command. */
+ main_cmd_is_sftp = 0;
+ cfg.remote_cmd_ptr = cmd;
+ cfg.ssh_subsys = FALSE;
+ }
cfg.nopty = TRUE;
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)
bump("ssh_init: %s", err);
logctx = log_init(NULL, &cfg);
{
float ratebs;
unsigned long eta;
- char etastr[10];
+ char *etastr;
int pct;
int len;
int elap;
eta = size - done;
else
eta = (unsigned long) ((size - done) / ratebs);
- sprintf(etastr, "%02ld:%02ld:%02ld",
- eta / 3600, (eta % 3600) / 60, eta % 60);
+ etastr = dupprintf("%02ld:%02ld:%02ld",
+ eta / 3600, (eta % 3600) / 60, eta % 60);
pct = (int) (100 * (done * 1.0 / size));
fflush(stdout);
}
+
+ free(etastr);
}
/*
received = 0;
while (received < act.size) {
char transbuf[4096];
- int blksize, read;
+ unsigned long blksize;
+ int read;
blksize = 4096;
- if (blksize > (int)(act.size - received))
+ if (blksize > (act.size - received))
blksize = act.size - received;
- read = scp_recv_filedata(transbuf, blksize);
+ read = scp_recv_filedata(transbuf, (int)blksize);
if (read <= 0)
bump("Lost connection");
if (wrerror)
printf(" -i key private key file for authentication\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
/*
* -gui is an internal option, used by GUI front ends to get
cleanup_exit(1);
}
+void version(void)
+{
+ printf("pscp: %s\n", ver);
+ cleanup_exit(1);
+}
+
void cmdline_error(char *p, ...)
{
va_list ap;
ssh_get_line = &console_get_line;
sk_init();
+ /* Load Default Settings before doing anything else. */
+ do_defaults(NULL, &cfg);
+ loaded_session = FALSE;
+
for (i = 1; i < argc; i++) {
int ret;
if (argv[i][0] != '-')
statistics = 0;
} 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], "-gui") == 0 && i + 1 < argc) {
gui_enable(argv[++i]);
gui_mode = 1;
console_batch_mode = 1;
} else if (strcmp(argv[i], "-unsafe") == 0) {
scp_unsafe_mode = 1;
+ } else if (strcmp(argv[i], "-sftp") == 0) {
+ try_scp = 0; try_sftp = 1;
+ } else if (strcmp(argv[i], "-scp") == 0) {
+ try_scp = 1; try_sftp = 0;
} else if (strcmp(argv[i], "--") == 0) {
i++;
break;