+/*
+ * Print an error message and exit after closing the SSH link.
+ */
+static void bump(char *fmt, ...)
+{
+ char str[0x100]; /* Make the size big enough */
+ va_list ap;
+ va_start(ap, fmt);
+ strcpy(str, "Fatal: ");
+ vsprintf(str + strlen(str), fmt, ap);
+ va_end(ap);
+ strcat(str, "\n");
+ tell_str(stderr, str);
+ errs++;
+
+ if (back != NULL && back->socket() != NULL) {
+ char ch;
+ back->special(TS_EOF);
+ ssh_scp_recv(&ch, 1);
+ }
+
+ if (gui_mode) {
+ unsigned int msg_id = WM_RET_ERR_CNT;
+ if (list)
+ msg_id = WM_LS_RET_ERR_CNT;
+ while (!PostMessage
+ ((HWND) atoi(gui_hwnd), msg_id, (WPARAM) errs,
+ 0 /*lParam */ ))SleepEx(1000, TRUE);
+ }
+
+ cleanup_exit(1);
+}
+
+/*
+ * Open an SSH connection to user@host and execute cmd.
+ */
+static void do_cmd(char *host, char *user, char *cmd)
+{
+ char *err, *realhost;
+ DWORD namelen;
+
+ 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);
+ strncpy(cfg.host, host, sizeof(cfg.host) - 1);
+ cfg.host[sizeof(cfg.host) - 1] = '\0';
+ }
+
+ /*
+ * Force use of SSH. (If they got the protocol wrong we assume the
+ * port is useless too.)
+ */
+ if (cfg.protocol != PROT_SSH) {
+ cfg.protocol = PROT_SSH;
+ cfg.port = 22;
+ }
+
+ /*
+ * Enact command-line overrides.
+ */
+ cmdline_run_saved();
+
+ /*
+ * Trim leading whitespace off the hostname if it's there.
+ */
+ {
+ int space = strspn(cfg.host, " \t");
+ memmove(cfg.host, cfg.host+space, 1+strlen(cfg.host)-space);
+ }
+
+ /* See if host is of the form user@host */
+ if (cfg.host[0] != '\0') {
+ char *atsign = strchr(cfg.host, '@');
+ /* Make sure we're not overflowing the user field */
+ if (atsign) {
+ if (atsign - cfg.host < sizeof cfg.username) {
+ strncpy(cfg.username, cfg.host, atsign - cfg.host);
+ cfg.username[atsign - cfg.host] = '\0';
+ }
+ memmove(cfg.host, atsign + 1, 1 + strlen(atsign + 1));
+ }
+ }
+
+ /*
+ * Trim a colon suffix off the hostname if it's there.
+ */
+ cfg.host[strcspn(cfg.host, ":")] = '\0';
+
+ /* Set username */
+ if (user != NULL && user[0] != '\0') {
+ strncpy(cfg.username, user, sizeof(cfg.username) - 1);
+ cfg.username[sizeof(cfg.username) - 1] = '\0';
+ } else if (cfg.username[0] == '\0') {
+ namelen = 0;
+ if (GetUserName(user, &namelen) == FALSE)
+ bump("Empty user name");
+ user = smalloc(namelen * sizeof(char));
+ GetUserName(user, &namelen);
+ if (verbose)
+ tell_user(stderr, "Guessing user name: %s", user);
+ strncpy(cfg.username, user, sizeof(cfg.username) - 1);
+ cfg.username[sizeof(cfg.username) - 1] = '\0';
+ free(user);
+ }
+
+ /*
+ * Disable scary things which shouldn't be enabled for simple
+ * things like SCP and SFTP: agent forwarding, port forwarding,
+ * X forwarding.
+ */
+ cfg.x11_forward = 0;
+ cfg.agentfwd = 0;
+ cfg.portfwd[0] = cfg.portfwd[1] = '\0';
+
+ /*
+ * 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.nopty = TRUE;
+
+ back = &ssh_backend;
+
+ err = back->init(cfg.host, cfg.port, &realhost, 0);
+ if (err != NULL)
+ bump("ssh_init: %s", err);
+ ssh_scp_init();
+ if (verbose && realhost != NULL)
+ tell_user(stderr, "Connected to %s\n", realhost);
+ sfree(realhost);
+}