static Conf *conf;
int sent_eof = FALSE;
-static void source(char *src);
-static void rsource(char *src);
-static void sink(char *targ, char *src);
+static void source(const char *src);
+static void rsource(const char *src);
+static void sink(const char *targ, const char *src);
const char *const appname = "PSCP";
*/
#define MAX_SCP_BUFSIZE 16384
-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 PSCP 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) { }
-static void tell_char(FILE * stream, char c)
+static void tell_char(FILE *stream, char c)
{
fputc(c, stream);
}
-static void tell_str(FILE * stream, char *str)
+static void tell_str(FILE *stream, const char *str)
{
unsigned int i;
tell_char(stream, str[i]);
}
-static void tell_user(FILE * stream, char *fmt, ...)
+static void tell_user(FILE *stream, const char *fmt, ...)
{
char *str, *str2;
va_list ap;
/*
* 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 nonfatal(char *fmt, ...)
+void nonfatal(const char *fmt, ...)
{
char *str, *str2;
va_list ap;
sfree(str2);
errs++;
}
-void connection_fatal(void *frontend, char *fmt, ...)
+void connection_fatal(void *frontend, const char *fmt, ...)
{
char *str, *str2;
va_list ap;
/*
* Print an error message and exit after closing the SSH link.
*/
-static void bump(char *fmt, ...)
+static void bump(const char *fmt, ...)
{
char *str, *str2;
va_list ap;
/* 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);
back = &ssh_backend;
+ logctx = log_init(NULL, conf);
+ console_provide_logctx(logctx);
+
+ platform_psftp_pre_conn_setup();
+
err = back->init(NULL, &backhandle, conf,
conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port),
conf_get_int(conf, CONF_tcp_keepalives));
if (err != NULL)
bump("ssh_init: %s", err);
- logctx = log_init(NULL, conf);
back->provide_logctx(backhandle, logctx);
- console_provide_logctx(logctx);
ssh_scp_init();
if (verbose && realhost != NULL && errs == 0)
tell_user(stderr, "Connected to %s", realhost);
/*
* Update statistic information about current file.
*/
-static void print_stats(char *name, uint64 size, uint64 done,
+static void print_stats(const char *name, uint64 size, uint64 done,
time_t start, time_t now)
{
float ratebs;
return (NULL);
}
-/*
- * Return a pointer to the portion of str that comes after the last
- * slash (or backslash or colon, if `local' is TRUE).
- */
-static char *stripslashes(char *str, int local)
-{
- char *p;
-
- if (local) {
- p = strchr(str, ':');
- if (p) str = p+1;
- }
-
- p = strrchr(str, '/');
- if (p) str = p+1;
-
- if (local) {
- p = strrchr(str, '\\');
- if (p) str = p+1;
- }
-
- return str;
-}
-
/*
* Determine whether a string is entirely composed of dots.
*/
back->send(backhandle, buf, len);
return 1;
}
+int sftp_sendbuffer(void)
+{
+ return back->sendbuffer(backhandle);
+}
/* ----------------------------------------------------------------------
* sftp-based replacement for the hacky `pscp -ls'.
const struct fxp_name *b = (const struct fxp_name *) bv;
return strcmp(a->filename, b->filename);
}
-void scp_sftp_listdir(char *dirname)
+void scp_sftp_listdir(const char *dirname)
{
struct fxp_handle *dirh;
struct fxp_names *names;
dirh = fxp_opendir_recv(pktin, req);
if (dirh == NULL) {
- printf("Unable to open %s: %s\n", dirname, fxp_error());
+ tell_user(stderr, "Unable to open %s: %s\n", dirname, fxp_error());
+ errs++;
} else {
nnames = namesize = 0;
ournames = NULL;
static struct fxp_xfer *scp_sftp_xfer;
static uint64 scp_sftp_fileoffset;
-int scp_source_setup(char *target, int shouldbedir)
+int scp_source_setup(const char *target, int shouldbedir)
{
if (using_sftp) {
/*
}
}
-int scp_send_filename(char *name, uint64 size, int permissions)
+int scp_send_filename(const char *name, uint64 size, int permissions)
{
if (using_sftp) {
char *fullname;
scp_sftp_remotepath = data;
}
-int scp_send_dirname(char *name, int modes)
+int scp_send_dirname(const char *name, int modes)
{
if (using_sftp) {
char *fullname;
* right at the start, whereas scp_sink_init is called to
* initialise every level of recursion in the protocol.
*/
-int scp_sink_setup(char *source, int preserve, int recursive)
+int scp_sink_setup(const char *source, int preserve, int recursive)
{
if (using_sftp) {
char *newsource;
{
char sizestr[40];
- if (sscanf(act->buf, "%lo %s %n", &act->permissions,
+ if (sscanf(act->buf, "%lo %39s %n", &act->permissions,
sizestr, &i) != 2)
bump("Protocol error: Illegal file descriptor format");
act->size = uint64_from_decimal(sizestr);
}
if (xfer_download_data(scp_sftp_xfer, &vbuf, &actuallen)) {
+ if (actuallen <= 0) {
+ tell_user(stderr, "pscp: end of file while reading");
+ errs++;
+ sfree(vbuf);
+ return -1;
+ }
/*
* This assertion relies on the fact that the natural
* block size used in the xfer manager is at most that
/*
* Execute the source part of the SCP protocol.
*/
-static void source(char *src)
+static void source(const char *src)
{
uint64 size;
unsigned long mtime, atime;
long permissions;
- char *last;
+ const char *last;
RFile *f;
int attr;
uint64 i;
/*
* Avoid . and .. directories.
*/
- char *p;
+ const char *p;
p = strrchr(src, '/');
if (!p)
p = strrchr(src, '\\');
stat_starttime = time(NULL);
stat_lasttime = 0;
+#define PSCP_SEND_BLOCK 4096
for (i = uint64_make(0,0);
uint64_compare(i,size) < 0;
- i = uint64_add32(i,4096)) {
- char transbuf[4096];
- int j, k = 4096;
+ i = uint64_add32(i,PSCP_SEND_BLOCK)) {
+ char transbuf[PSCP_SEND_BLOCK];
+ int j, k = PSCP_SEND_BLOCK;
if (uint64_compare(uint64_add32(i, k),size) > 0) /* i + k > size */
k = (uint64_subtract(size, i)).lo; /* k = size - i; */
/*
* Recursively send the contents of a directory.
*/
-static void rsource(char *src)
+static void rsource(const char *src)
{
- char *last;
+ const char *last;
char *save_target;
DirHandle *dir;
/*
* Execute the sink part of the SCP protocol.
*/
-static void sink(char *targ, char *src)
+static void sink(const char *targ, const char *src)
{
char *destfname;
int targisdir = 0;
read = scp_recv_filedata(transbuf, (int)blksize.lo);
if (read <= 0)
bump("Lost connection");
- if (wrerror)
+ if (wrerror) {
+ received = uint64_add32(received, read);
continue;
+ }
if (write_to_file(f, transbuf, read) != (int)read) {
wrerror = 1;
/* FIXME: in sftp we can actually abort the transfer */
printf("\r%-25.25s | %50s\n",
stat_name,
"Write error.. waiting for end of file");
+ received = uint64_add32(received, read);
continue;
}
if (statistics) {
*/
static void toremote(int argc, char *argv[])
{
- char *src, *targ, *host, *user;
+ char *src, *wtarg, *host, *user;
+ const char *targ;
char *cmd;
int i, wc_type;
uploading = 1;
- targ = argv[argc - 1];
+ wtarg = argv[argc - 1];
/* Separate host from filename */
- host = targ;
- targ = colon(targ);
- if (targ == NULL)
- bump("targ == NULL in toremote()");
- *targ++ = '\0';
- if (*targ == '\0')
- targ = ".";
+ host = wtarg;
+ wtarg = colon(wtarg);
+ if (wtarg == NULL)
+ bump("wtarg == NULL in toremote()");
+ *wtarg++ = '\0';
/* Substitute "." for empty target */
+ if (*wtarg == '\0')
+ targ = ".";
+ else
+ targ = wtarg;
/* Separate host and username */
user = host;
*/
static void tolocal(int argc, char *argv[])
{
- char *src, *targ, *host, *user;
+ char *wsrc, *host, *user;
+ const char *src, *targ;
char *cmd;
uploading = 0;
if (argc != 2)
bump("More than one remote source not supported");
- src = argv[0];
+ wsrc = argv[0];
targ = argv[1];
/* Separate host from filename */
- host = src;
- src = colon(src);
- if (src == NULL)
+ host = wsrc;
+ wsrc = colon(wsrc);
+ if (wsrc == NULL)
bump("Local to local copy not supported");
- *src++ = '\0';
- if (*src == '\0')
- src = ".";
+ *wsrc++ = '\0';
/* Substitute "." for empty filename */
+ if (*wsrc == '\0')
+ src = ".";
+ else
+ src = wsrc;
/* Separate username and hostname */
user = host;
*/
static void get_dir_list(int argc, char *argv[])
{
- char *src, *host, *user;
- char *cmd, *p, *q;
+ char *wsrc, *host, *user;
+ const char *src;
+ char *cmd, *p;
+ const char *q;
char c;
- src = argv[0];
+ wsrc = argv[0];
/* Separate host from filename */
- host = src;
- src = colon(src);
- if (src == NULL)
+ host = wsrc;
+ wsrc = colon(wsrc);
+ if (wsrc == NULL)
bump("Local file listing not supported");
- *src++ = '\0';
- if (*src == '\0')
- src = ".";
+ *wsrc++ = '\0';
/* Substitute "." for empty filename */
+ if (*wsrc == '\0')
+ src = ".";
+ else
+ src = wsrc;
/* Separate username and hostname */
user = host;
printf(" -hostkey aa:bb:cc:...\n");
printf(" manually specify a host key (may be repeated)\n");
printf(" -batch disable all interactive prompts\n");
+ printf(" -proxycmd command\n");
+ printf(" use 'command' as local proxy\n");
printf(" -unsafe allow server-side wildcards (DANGEROUS)\n");
printf(" -sftp force use of SFTP protocol\n");
printf(" -scp force use of SCP protocol\n");
void version(void)
{
- printf("pscp: %s\n", ver);
- cleanup_exit(1);
+ char *buildinfo_text = buildinfo("\n");
+ printf("pscp: %s\n%s\n", ver, buildinfo_text);
+ sfree(buildinfo_text);
+ exit(0);
}
-void cmdline_error(char *p, ...)
+void cmdline_error(const char *p, ...)
{
va_list ap;
fprintf(stderr, "pscp: ");