* canonification fails, at least fall back to returning a _valid_
* pathname (though it may be ugly, eg /home/simon/../foobar).
*/
-char *canonify(char *name)
+char *canonify(const char *name)
{
char *fullname, *canonname;
struct sftp_packet *pktin;
if (name[0] == '/') {
fullname = dupstr(name);
} else {
- char *slash;
+ const char *slash;
if (pwd[strlen(pwd) - 1] == '/')
slash = "";
else
/*
* Return a pointer to the portion of str that comes after the last
* slash (or backslash or colon, if `local' is TRUE).
+ *
+ * This function has the annoying strstr() property of taking a const
+ * char * and returning a char *. You should treat it as if it was a
+ * pair of overloaded functions, one mapping mutable->mutable and the
+ * other const->const :-(
*/
-static char *stripslashes(char *str, int local)
+static char *stripslashes(const char *str, int local)
{
char *p;
if (p) str = p+1;
}
- return str;
+ return (char *)str;
}
/*
if (fxp_error_type() == SSH_FX_EOF)
break;
printf("%s: reading directory: %s\n", fname, fxp_error());
+
+ req = fxp_close_send(dirhandle);
+ pktin = sftp_wait_for_reply(req);
+ fxp_close_recv(pktin, req);
+
sfree(ournames);
return 0;
}
* readdirs on the same remote directory return a
* different order.
*/
- qsort(ournames, nnames, sizeof(*ournames), sftp_name_compare);
+ if (nnames > 0)
+ qsort(ournames, nnames, sizeof(*ournames), sftp_name_compare);
/*
* If we're in restart mode, find the last filename on
printf("error while reading: %s\n", fxp_error());
shown_err = TRUE;
}
+ if (ret == INT_MIN) /* pktin not even freed */
+ sfree(pktin);
ret = 0;
}
* same directory, just in case two readdirs on the same
* local directory return a different order.
*/
- qsort(ournames, nnames, sizeof(*ournames), bare_name_compare);
+ if (nnames > 0)
+ qsort(ournames, nnames, sizeof(*ournames), bare_name_compare);
/*
* If we're in restart mode, find the last filename on this
if (restart) {
char decbuf[30];
struct fxp_attrs attrs;
- int ret;
req = fxp_fstat_send(fh);
pktin = sftp_wait_for_reply(req);
ret = fxp_fstat_recv(pktin, req, &attrs);
if (!ret) {
- close_rfile(file);
printf("read size of %s: %s\n", outfname, fxp_error());
- return 0;
+ goto cleanup;
}
if (!(attrs.flags & SSH_FILEXFER_ATTR_SIZE)) {
- close_rfile(file);
printf("read size of %s: size was not given\n", outfname);
- return 0;
+ ret = 0;
+ goto cleanup;
}
offset = attrs.size;
uint64_decimal(offset, decbuf);
if (!xfer_done(xfer)) {
pktin = sftp_recv();
ret = xfer_upload_gotpkt(xfer, pktin);
- if (ret <= 0 && !err) {
- printf("error while writing: %s\n", fxp_error());
- err = 1;
+ if (ret <= 0) {
+ if (ret == INT_MIN) /* pktin not even freed */
+ sfree(pktin);
+ if (!err) {
+ printf("error while writing: %s\n", fxp_error());
+ err = 1;
+ }
}
}
}
xfer_cleanup(xfer);
+ cleanup:
req = fxp_close_send(fh);
pktin = sftp_wait_for_reply(req);
fxp_close_recv(pktin, req);
printf("%s: canonify: %s\n", newname, fxp_error());
ret = 0;
}
+ sfree(newname);
matched = TRUE;
ret &= func(ctx, cname);
sfree(cname);
struct fxp_names *names;
struct fxp_name **ournames;
int nnames, namesize;
- char *dir, *cdir, *unwcdir, *wildcard;
+ const char *dir;
+ char *cdir, *unwcdir, *wildcard;
struct sftp_packet *pktin;
struct sftp_request *req;
int i;
char *tmpdir;
int len, check;
+ sfree(unwcdir);
wildcard = stripslashes(dir, 0);
unwcdir = dupstr(dir);
len = wildcard - dir;
* Now we have our filenames. Sort them by actual file
* name, and then output the longname parts.
*/
- qsort(ournames, nnames, sizeof(*ournames), sftp_name_compare);
+ if (nnames > 0)
+ qsort(ournames, nnames, sizeof(*ournames), sftp_name_compare);
/*
* And print them.
fname = canonify(origwfname);
if (!fname) {
+ sftp_finish_wildcard_matching(swcm);
printf("%s: canonify: %s\n", origwfname, fxp_error());
+ sfree(origwfname);
sfree(unwcfname);
return 0;
}
static int sftp_cmd_help(struct sftp_command *cmd);
static struct sftp_cmd_lookup {
- char *name;
+ const char *name;
/*
* For help purposes, there are two kinds of command:
*
* contains the help that should double up for this command.
*/
int listed; /* do we list this in primary help? */
- char *shorthelp;
- char *longhelp;
+ const char *shorthelp;
+ const char *longhelp;
int (*obey) (struct sftp_command *);
} sftp_lookup[] = {
/*
}
};
-const struct sftp_cmd_lookup *lookup_command(char *name)
+const struct sftp_cmd_lookup *lookup_command(const char *name)
{
int i, j, k, cmp;
cmd->obey = sftp_cmd_quit;
if ((mode == 0) || (modeflags & 1))
printf("quit\n");
+ sfree(line);
return cmd; /* eof */
}
}
}
-void do_sftp(int mode, int modeflags, char *batchfile)
+int do_sftp(int mode, int modeflags, char *batchfile)
{
FILE *fp;
int ret;
fp = fopen(batchfile, "r");
if (!fp) {
printf("Fatal: unable to open %s\n", batchfile);
- return;
+ return 1;
}
+ ret = 0;
while (1) {
struct sftp_command *cmd;
cmd = sftp_getcmd(fp, mode, modeflags);
}
}
fclose(fp);
-
+ /*
+ * In batch mode, and if exit on command failure is enabled,
+ * any command failure causes the whole of PSFTP to fail.
+ */
+ if (ret == 0 && !(modeflags & 2)) return 2;
}
+ return 0;
}
/* ----------------------------------------------------------------------
/*
* Print an error message and perform a fatal exit.
*/
-void fatalbox(char *fmt, ...)
+void fatalbox(const char *fmt, ...)
{
char *str, *str2;
va_list ap;
cleanup_exit(1);
}
-void modalfatalbox(char *fmt, ...)
+void modalfatalbox(const char *fmt, ...)
{
char *str, *str2;
va_list ap;
cleanup_exit(1);
}
-void connection_fatal(void *frontend, char *fmt, ...)
+void nonfatal(const char *fmt, ...)
+{
+ char *str, *str2;
+ va_list ap;
+ va_start(ap, fmt);
+ str = dupvprintf(fmt, ap);
+ str2 = dupcat("Error: ", str, "\n", NULL);
+ sfree(str);
+ va_end(ap);
+ fputs(str2, stderr);
+ sfree(str2);
+}
+void connection_fatal(void *frontend, const char *fmt, ...)
{
char *str, *str2;
va_list ap;
cleanup_exit(1);
}
-void ldisc_send(void *handle, char *buf, int len, int interactive)
-{
- /*
- * This is only here because of the calls to ldisc_send(NULL,
- * 0) in ssh.c. Nothing in PSFTP actually needs to use the
- * ldisc as an ldisc. So if we get called with any real data, I
- * want to know about it.
- */
- assert(len == 0);
-}
+void ldisc_echoedit_update(void *handle) { }
/*
* In psftp, all agent requests should be synchronous, so this is a
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(" -i key private key file for user authentication\n");
printf(" -noagent disable use of Pageant\n");
printf(" -agent enable use of Pageant\n");
+ printf(" -hostkey aa:bb:cc:...\n");
+ printf(" manually specify a host key (may be repeated)\n");
printf(" -batch disable all interactive prompts\n");
cleanup_exit(1);
}
/* Use `host' as a bare hostname. */
conf_set_str(conf, CONF_host, host);
}
+ conf_free(conf2);
} else {
/* Patch in hostname `host' to session details. */
conf_set_str(conf, CONF_host, host);
return 0;
}
-void cmdline_error(char *p, ...)
+void cmdline_error(const char *p, ...)
{
va_list ap;
fprintf(stderr, "psftp: ");
exit(1);
}
+const int share_can_be_downstream = TRUE;
+const int share_can_be_upstream = FALSE;
+
/*
* Main program. Parse arguments etc.
*/
int psftp_main(int argc, char *argv[])
{
- int i;
+ int i, ret;
int portnumber = 0;
char *userhost, *user;
int mode = 0;
" to connect\n");
}
- do_sftp(mode, modeflags, batchfile);
+ ret = do_sftp(mode, modeflags, batchfile);
if (back != NULL && back->connected(backhandle)) {
char ch;
console_provide_logctx(NULL);
sk_cleanup();
- return 0;
+ return ret;
}