Implement the `close' command, which terminates an SFTP session but
[sgt/putty] / psftp.c
diff --git a/psftp.c b/psftp.c
index bd1f9cb..b1cfe16 100644 (file)
--- a/psftp.c
+++ b/psftp.c
@@ -767,6 +767,23 @@ int sftp_cmd_quit(struct sftp_command *cmd)
     return -1;
 }
 
+int sftp_cmd_close(struct sftp_command *cmd)
+{
+    if (back == NULL) {
+       printf("psftp: not connected to a host; use \"open host.name\"\n");
+       return 0;
+    }
+
+    if (back != NULL && back->socket(backhandle) != NULL) {
+       char ch;
+       back->special(backhandle, TS_EOF);
+       sftp_recvdata(&ch, 1);
+    }
+    do_sftp_cleanup();
+
+    return 0;
+}
+
 /*
  * List a directory. If no arguments are given, list pwd; otherwise
  * list the directory given in words[1].
@@ -777,7 +794,7 @@ int sftp_cmd_ls(struct sftp_command *cmd)
     struct fxp_names *names;
     struct fxp_name **ournames;
     int nnames, namesize;
-    char *dir, *cdir;
+    char *dir, *cdir, *unwcdir, *wildcard;
     struct sftp_packet *pktin;
     struct sftp_request *req, *rreq;
     int i;
@@ -792,9 +809,35 @@ int sftp_cmd_ls(struct sftp_command *cmd)
     else
        dir = cmd->words[1];
 
+    unwcdir = snewn(1 + strlen(dir), char);
+    if (wc_unescape(unwcdir, dir)) {
+       dir = unwcdir;
+       wildcard = NULL;
+    } else {
+       char *tmpdir;
+       int len, check;
+
+       wildcard = stripslashes(dir, 0);
+       unwcdir = dupstr(dir);
+       len = wildcard - dir;
+       unwcdir[len] = '\0';
+       if (len > 0 && unwcdir[len-1] == '/')
+           unwcdir[len-1] = '\0';
+       tmpdir = snewn(1 + len, char);
+       check = wc_unescape(tmpdir, unwcdir);
+       sfree(tmpdir);
+       if (!check) {
+           printf("Multiple-level wildcards are not supported\n");
+           sfree(unwcdir);
+           return 0;
+       }
+       dir = unwcdir;
+    }
+
     cdir = canonify(dir);
     if (!cdir) {
        printf("%s: %s\n", dir, fxp_error());
+       sfree(unwcdir);
        return 0;
     }
 
@@ -835,7 +878,8 @@ int sftp_cmd_ls(struct sftp_command *cmd)
            }
 
            for (i = 0; i < names->nnames; i++)
-               ournames[nnames++] = fxp_dup_name(&names->names[i]);
+               if (!wildcard || wc_match(wildcard, names->names[i].filename))
+                   ournames[nnames++] = fxp_dup_name(&names->names[i]);
 
            fxp_free_names(names);
        }
@@ -861,6 +905,7 @@ int sftp_cmd_ls(struct sftp_command *cmd)
     }
 
     sfree(cdir);
+    sfree(unwcdir);
 
     return 1;
 }
@@ -987,7 +1032,7 @@ int sftp_general_get(struct sftp_command *cmd, int restart, int multiple)
            if (!multiple && i < cmd->nwords)
                outfname = cmd->words[i++];
            else
-               outfname = stripslashes(origfname, 1);
+               outfname = stripslashes(origfname, 0);
 
            ret = sftp_get_file(fname, outfname, recurse, restart, NULL);
 
@@ -1604,6 +1649,14 @@ static struct sftp_cmd_lookup {
            sftp_cmd_chmod
     },
     {
+       "close", TRUE, "finish your SFTP session but do not quit PSFTP",
+           "\n"
+           "  Terminates your SFTP session, but does not quit the PSFTP\n"
+           "  program. You can then use \"open\" to start another SFTP\n"
+           "  session, to the same server or to a different one.\n",
+           sftp_cmd_close
+    },
+    {
        "del", TRUE, "delete a file",
            " <filename>\n"
            "  Delete a file.\n",
@@ -1838,7 +1891,7 @@ struct sftp_command *sftp_getcmd(FILE *fp, int mode, int modeflags)
            printf("psftp> ");
        line = fgetline(fp);
     } else {
-       line = ssh_sftp_get_cmdline("psftp> ");
+       line = ssh_sftp_get_cmdline("psftp> ", back == NULL);
     }
 
     if (!line || !*line) {
@@ -1976,6 +2029,8 @@ void do_sftp_cleanup()
        sftp_recvdata(&ch, 1);
        back->free(backhandle);
        sftp_cleanup_request();
+       back = NULL;
+       backhandle = NULL;
     }
     if (pwd) {
        sfree(pwd);
@@ -2549,12 +2604,10 @@ int psftp_main(int argc, char *argv[])
        back->special(backhandle, TS_EOF);
        sftp_recvdata(&ch, 1);
     }
+    do_sftp_cleanup();
     random_save_seed();
     cmdline_cleanup();
     console_provide_logctx(NULL);
-    do_sftp_cleanup();
-    backhandle = NULL;
-    back = NULL;
     sk_cleanup();
 
     return 0;