Major destabilisation, phase 2. This time it's the backends' turn:
[u/mdw/putty] / psftp.c
diff --git a/psftp.c b/psftp.c
index 302e1a7..a278260 100644 (file)
--- a/psftp.c
+++ b/psftp.c
@@ -25,7 +25,7 @@
  */
 
 static int psftp_connect(char *userhost, char *user, int portnumber);
-static void do_sftp_init(void);
+static int do_sftp_init(void);
 
 /* ----------------------------------------------------------------------
  * sftp client state.
@@ -188,15 +188,15 @@ int sftp_cmd_quit(struct sftp_command *cmd)
  */
 static int sftp_ls_compare(const void *av, const void *bv)
 {
-    const struct fxp_name *a = (const struct fxp_name *) av;
-    const struct fxp_name *b = (const struct fxp_name *) bv;
-    return strcmp(a->filename, b->filename);
+    const struct fxp_name *const *a = (const struct fxp_name *const *) av;
+    const struct fxp_name *const *b = (const struct fxp_name *const *) bv;
+    return strcmp((*a)->filename, (*b)->filename);
 }
 int sftp_cmd_ls(struct sftp_command *cmd)
 {
     struct fxp_handle *dirh;
     struct fxp_names *names;
-    struct fxp_name *ournames;
+    struct fxp_name **ournames;
     int nnames, namesize;
     char *dir, *cdir;
     int i;
@@ -247,9 +247,8 @@ int sftp_cmd_ls(struct sftp_command *cmd)
            }
 
            for (i = 0; i < names->nnames; i++)
-               ournames[nnames++] = names->names[i];
+               ournames[nnames++] = fxp_dup_name(&names->names[i]);
 
-           names->nnames = 0;         /* prevent free_names */
            fxp_free_names(names);
        }
        fxp_close(dirh);
@@ -263,8 +262,11 @@ int sftp_cmd_ls(struct sftp_command *cmd)
        /*
         * And print them.
         */
-       for (i = 0; i < nnames; i++)
-           printf("%s\n", ournames[i].longname);
+       for (i = 0; i < nnames; i++) {
+           printf("%s\n", ournames[i]->longname);
+           fxp_free_name(ournames[i]);
+       }
+       sfree(ournames);
     }
 
     sfree(cdir);
@@ -1361,7 +1363,7 @@ struct sftp_command *sftp_getcmd(FILE *fp, int mode, int modeflags)
     return cmd;
 }
 
-static void do_sftp_init(void)
+static int do_sftp_init(void)
 {
     /*
      * Do protocol initialisation. 
@@ -1369,7 +1371,7 @@ static void do_sftp_init(void)
     if (!fxp_init()) {
        fprintf(stderr,
                "Fatal: unable to initialise SFTP: %s\n", fxp_error());
-       return;
+       return 1;                      /* failure */
     }
 
     /*
@@ -1385,6 +1387,7 @@ static void do_sftp_init(void)
        printf("Remote working directory is %s\n", homedir);
     }
     pwd = dupstr(homedir);
+    return 0;
 }
 
 void do_sftp(int mode, int modeflags, char *batchfile)
@@ -1452,7 +1455,20 @@ void fatalbox(char *fmt, ...)
     strcat(str, "\n");
     fputs(str, stderr);
 
-    exit(1);
+    cleanup_exit(1);
+}
+void modalfatalbox(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");
+    fputs(str, stderr);
+
+    cleanup_exit(1);
 }
 void connection_fatal(char *fmt, ...)
 {
@@ -1465,7 +1481,7 @@ void connection_fatal(char *fmt, ...)
     strcat(str, "\n");
     fputs(str, stderr);
 
-    exit(1);
+    cleanup_exit(1);
 }
 
 void ldisc_send(char *buf, int len, int interactive)
@@ -1506,11 +1522,13 @@ static unsigned char *outptr;          /* where to put the data */
 static unsigned outlen;                       /* how much data required */
 static unsigned char *pending = NULL;  /* any spare data */
 static unsigned pendlen = 0, pendsize = 0;     /* length and phys. size of buffer */
-int from_backend(int is_stderr, char *data, int datalen)
+int from_backend(void *frontend, int is_stderr, 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.
@@ -1592,7 +1610,7 @@ int sftp_recvdata(char *buf, int len)
 }
 int sftp_senddata(char *buf, int len)
 {
-    back->send((unsigned char *) buf, len);
+    back->send(backhandle, (unsigned char *) buf, len);
     return 1;
 }
 
@@ -1603,7 +1621,7 @@ static void ssh_sftp_init(void)
 {
     if (sftp_ssh_socket == INVALID_SOCKET)
        return;
-    while (!back->sendok()) {
+    while (!back->sendok(backhandle)) {
        fd_set readfds;
        FD_ZERO(&readfds);
        FD_SET(sftp_ssh_socket, &readfds);
@@ -1624,11 +1642,11 @@ static void init_winsock(void)
     winsock_ver = MAKEWORD(1, 1);
     if (WSAStartup(winsock_ver, &wsadata)) {
        fprintf(stderr, "Unable to initialise WinSock");
-       exit(1);
+       cleanup_exit(1);
     }
     if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1) {
        fprintf(stderr, "WinSock version is incompatible with 1.1");
-       exit(1);
+       cleanup_exit(1);
     }
 }
 
@@ -1645,9 +1663,15 @@ static void usage(void)
     printf("  -bc       output batchfile commands\n");
     printf("  -be       don't stop batchfile processing if errors\n");
     printf("  -v        show verbose messages\n");
+    printf("  -load sessname  Load settings from saved session\n");
+    printf("  -l user   connect with specified username\n");
     printf("  -P port   connect to specified port\n");
     printf("  -pw passw login with specified password\n");
-    exit(1);
+    printf("  -1 -2     force use of particular SSH protocol version\n");
+    printf("  -C        enable compression\n");
+    printf("  -i key    private key file for authentication\n");
+    printf("  -batch    disable all interactive prompts\n");
+    cleanup_exit(1);
 }
 
 /*
@@ -1679,10 +1703,23 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
        do_defaults(NULL, &cfg);
        strncpy(cfg.host, host, sizeof(cfg.host) - 1);
        cfg.host[sizeof(cfg.host) - 1] = '\0';
-       cfg.port = 22;
     }
 
     /*
+     * 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.
      */
     {
@@ -1708,6 +1745,21 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
      */
     cfg.host[strcspn(cfg.host, ":")] = '\0';
 
+    /*
+     * Remove any remaining whitespace from the hostname.
+     */
+    {
+       int p1 = 0, p2 = 0;
+       while (cfg.host[p2] != '\0') {
+           if (cfg.host[p2] != ' ' && cfg.host[p2] != '\t') {
+               cfg.host[p1] = cfg.host[p2];
+               p1++;
+           }
+           p2++;
+       }
+       cfg.host[p1] = '\0';
+    }
+
     /* Set username */
     if (user != NULL && user[0] != '\0') {
        strncpy(cfg.username, user, sizeof(cfg.username) - 1);
@@ -1717,7 +1769,7 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
        printf("login as: ");
        if (!fgets(cfg.username, sizeof(cfg.username), stdin)) {
            fprintf(stderr, "psftp: aborting\n");
-           exit(1);
+           cleanup_exit(1);
        } else {
            int len = strlen(cfg.username);
            if (cfg.username[len - 1] == '\n')
@@ -1725,9 +1777,6 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
        }
     }
 
-    if (cfg.protocol != PROT_SSH)
-       cfg.port = 22;
-
     if (portnumber)
        cfg.port = portnumber;
 
@@ -1773,7 +1822,7 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
 
     back = &ssh_backend;
 
-    err = back->init(cfg.host, cfg.port, &realhost, 0);
+    err = back->init(NULL, &backhandle, cfg.host, cfg.port, &realhost, 0);
     if (err != NULL) {
        fprintf(stderr, "ssh_init: %s\n", err);
        return 1;
@@ -1784,6 +1833,17 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
     return 0;
 }
 
+void cmdline_error(char *p, ...)
+{
+    va_list ap;
+    fprintf(stderr, "pscp: ");
+    va_start(ap, p);
+    vfprintf(stderr, p, ap);
+    va_end(ap);
+    fputc('\n', stderr);
+    exit(1);
+}
+
 /*
  * Main program. Parse arguments etc.
  */
@@ -1797,6 +1857,7 @@ int main(int argc, char *argv[])
     char *batchfile = NULL;
 
     flags = FLAG_STDERR | FLAG_INTERACTIVE;
+    cmdline_tooltype = TOOLTYPE_FILETRANSFER;
     ssh_get_line = &console_get_line;
     init_winsock();
     sk_init();
@@ -1804,29 +1865,33 @@ int main(int argc, char *argv[])
     userhost = user = NULL;
 
     for (i = 1; i < argc; i++) {
+       int ret;
        if (argv[i][0] != '-') {
-           if (userhost)
-               usage();
-           else
-               userhost = dupstr(argv[i]);
-       } else if (strcmp(argv[i], "-v") == 0) {
-           verbose = 1, flags |= FLAG_VERBOSE;
+            if (userhost)
+                usage();
+            else
+                userhost = dupstr(argv[i]);
+           continue;
+       }
+       ret = cmdline_process_param(argv[i], i+1<argc?argv[i+1]:NULL, 1);
+       if (ret == -2) {
+           cmdline_error("option \"%s\" requires an argument", argv[i]);
+       } else if (ret == 2) {
+           i++;               /* skip next argument */
+       } else if (ret == 1) {
+           /* We have our own verbosity in addition to `flags'. */
+           if (flags & FLAG_VERBOSE)
+               verbose = 1;
        } 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) {
-           console_password = argv[++i];
+       } else if (strcmp(argv[i], "-batch") == 0) {
+           console_batch_mode = 1;
        } 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], "-batch") == 0) {
-           console_batch_mode = TRUE;
        } else if (strcmp(argv[i], "-be") == 0) {
            modeflags = modeflags | 2;
        } else if (strcmp(argv[i], "--") == 0) {
@@ -1847,7 +1912,8 @@ int main(int argc, char *argv[])
     if (userhost) {
        if (psftp_connect(userhost, user, portnumber))
            return 1;
-       do_sftp_init();
+       if (do_sftp_init())
+           return 1;
     } else {
        printf("psftp: no hostname specified; use \"open host.name\""
            " to connect\n");
@@ -1855,9 +1921,9 @@ int main(int argc, char *argv[])
 
     do_sftp(mode, modeflags, batchfile);
 
-    if (back != NULL && back->socket() != NULL) {
+    if (back != NULL && back->socket(backhandle) != NULL) {
        char ch;
-       back->special(TS_EOF);
+       back->special(backhandle, TS_EOF);
        sftp_recvdata(&ch, 1);
     }
     WSACleanup();