X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/c51a56e2f86b1ab9c803453186e5e21697554c06..297d398b09441e5cbfee439d4bbc772a2807d848:/scp.c?ds=sidebyside diff --git a/scp.c b/scp.c index d0f70ae5..8f70a53f 100644 --- a/scp.c +++ b/scp.c @@ -1,6 +1,6 @@ /* * scp.c - Scp (Secure Copy) client for PuTTY. - * Joris van Rantwijk, Aug 1999. + * Joris van Rantwijk, Aug 1999, Nov 1999. * * This is mainly based on ssh-1.2.26/scp.c by Timo Rinne & Tatu Ylonen. * They, in turn, used stuff from BSD rcp. @@ -27,6 +27,8 @@ static int recursive = 0; static int preserve = 0; static int targetshouldbedirectory = 0; static int statistics = 1; +static int portnumber = 0; +static char *password = NULL; static int errs = 0; static int connection_open = 0; @@ -70,8 +72,14 @@ static void bump(char *fmt, ...) void ssh_get_password(char *prompt, char *str, int maxlen) { HANDLE hin, hout; - DWORD savemode; - int i; + DWORD savemode, i; + + if (password) { + strncpy(str, password, maxlen); + str[maxlen-1] = '\0'; + password = NULL; + return; + } hin = GetStdHandle(STD_INPUT_HANDLE); hout = GetStdHandle(STD_OUTPUT_HANDLE); @@ -87,7 +95,7 @@ void ssh_get_password(char *prompt, char *str, int maxlen) SetConsoleMode(hin, savemode); - if (i > maxlen) i = maxlen-1; else i = i - 2; + if ((int)i > maxlen) i = maxlen-1; else i = i - 2; str[i] = '\0'; WriteFile(hout, "\r\n", 2, &i, NULL); @@ -116,7 +124,6 @@ static void do_cmd(char *host, char *user, char *cmd) if (user != NULL && user[0] != '\0') { strncpy(cfg.username, user, sizeof(cfg.username)-1); cfg.username[sizeof(cfg.username)-1] = '\0'; - cfg.port = 22; } else if (cfg.username[0] == '\0') { bump("Empty user name"); } @@ -124,6 +131,9 @@ static void do_cmd(char *host, char *user, char *cmd) if (cfg.protocol != PROT_SSH) cfg.port = 22; + if (portnumber) + cfg.port = portnumber; + err = ssh_init(cfg.host, cfg.port, cmd, &realhost); if (err != NULL) bump("ssh_init: %s", err); @@ -153,7 +163,7 @@ static void print_stats(char *name, unsigned long size, unsigned long done, eta = size - done; else eta = (unsigned long) ((size - done) / ratebs); - sprintf(etastr, "%02d:%02d:%02d", + sprintf(etastr, "%02ld:%02ld:%02ld", eta / 3600, (eta % 3600) / 60, eta % 60); pct = (int) (100.0 * (float) done / size); @@ -168,7 +178,7 @@ static void print_stats(char *name, unsigned long size, unsigned long done, /* * Find a colon in str and return a pointer to the colon. - * This is used to seperate hostname from filename. + * This is used to separate hostname from filename. */ static char * colon(char *str) { @@ -260,16 +270,31 @@ static void source(char *src) time_t stat_starttime, stat_lasttime; attr = GetFileAttributes(src); - if (attr == -1) { + if (attr == (DWORD)-1) { run_err("%s: No such file or directory", src); return; } if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { - if (recursive) - rsource(src); - else + if (recursive) { + /* + * Avoid . and .. directories. + */ + char *p; + p = strrchr(src, '/'); + if (!p) + p = strrchr(src, '\\'); + if (!p) + p = src; + else + p++; + if (!strcmp(p, ".") || !strcmp(p, "..")) + /* skip . and .. */; + else + rsource(src); + } else { run_err("%s: not a regular file", src); + } return; } @@ -285,7 +310,7 @@ static void source(char *src) f = CreateFile(src, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); if (f == INVALID_HANDLE_VALUE) { - run_err("%s: Cannot open file"); + run_err("%s: Cannot open file", src); return; } @@ -400,7 +425,7 @@ static void sink(char *targ) char namebuf[2048]; char ch; int targisdir = 0; - int settime = 0; + int settime; int exists; DWORD attr; HANDLE f; @@ -413,7 +438,7 @@ static void sink(char *targ) char *stat_name; attr = GetFileAttributes(targ); - if (attr != -1 && (attr & FILE_ATTRIBUTE_DIRECTORY) != 0) + if (attr != (DWORD)-1 && (attr & FILE_ATTRIBUTE_DIRECTORY) != 0) targisdir = 1; if (targetshouldbedirectory && !targisdir) @@ -446,7 +471,7 @@ static void sink(char *targ) ssh_send("", 1); return; case 'T': - if (sscanf(buf, "T%d %*d %d %*d", + if (sscanf(buf, "T%ld %*d %ld %*d", &mtime, &atime) == 2) { settime = 1; ssh_send("", 1); @@ -460,7 +485,7 @@ static void sink(char *targ) bump("Protocol error: Expected control record"); } - if (sscanf(buf+1, "%u %u %[^\n]", &mode, &size, namebuf) != 3) + if (sscanf(buf+1, "%u %lu %[^\n]", &mode, &size, namebuf) != 3) bump("Protocol error: Illegal file descriptor format"); if (targisdir) { char t[2048]; @@ -473,7 +498,7 @@ static void sink(char *targ) strcpy(namebuf, targ); } attr = GetFileAttributes(namebuf); - exists = (attr != -1); + exists = (attr != (DWORD)-1); if (buf[0] == 'D') { if (exists && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0) { @@ -515,7 +540,7 @@ static void sink(char *targ) for (i = 0; i < size; i += 4096) { char transbuf[4096]; - int j, k = 4096; + DWORD j, k = 4096; if (i + k > size) k = size - i; if (ssh_recv(transbuf, k) == 0) bump("Lost connection"); @@ -567,7 +592,7 @@ static void toremote(int argc, char *argv[]) targ = argv[argc-1]; - /* Seperate host from filename */ + /* Separate host from filename */ host = targ; targ = colon(targ); if (targ == NULL) @@ -577,7 +602,7 @@ static void toremote(int argc, char *argv[]) targ = "."; /* Substitute "." for emtpy target */ - /* Seperate host and username */ + /* Separate host and username */ user = host; host = strrchr(host, '@'); if (host == NULL) { @@ -669,7 +694,7 @@ static void tolocal(int argc, char *argv[]) src = argv[0]; targ = argv[1]; - /* Seperate host from filename */ + /* Separate host from filename */ host = src; src = colon(src); if (src == NULL) @@ -679,7 +704,7 @@ static void tolocal(int argc, char *argv[]) src = "."; /* Substitute "." for empty filename */ - /* Seperate username and hostname */ + /* Separate username and hostname */ user = host; host = strrchr(host, '@'); if (host == NULL) { @@ -705,9 +730,62 @@ static void tolocal(int argc, char *argv[]) } /* + * We will issue a list command to get a remote directory. + */ +static void get_dir_list(int argc, char *argv[]) +{ + char *src, *host, *user; + char *cmd, *p, *q; + char c; + + src = argv[0]; + + /* Separate host from filename */ + host = src; + src = colon(src); + if (src == NULL) + bump("Local to local copy not supported"); + *src++ = '\0'; + if (*src == '\0') + src = "."; + /* Substitute "." for empty filename */ + + /* Separate username and hostname */ + user = host; + host = strrchr(host, '@'); + if (host == NULL) { + host = user; + user = NULL; + } else { + *host++ = '\0'; + if (*user == '\0') + user = NULL; + } + + cmd = smalloc(4*strlen(src) + 100); + strcpy(cmd, "ls -la '"); + p = cmd + strlen(cmd); + for (q = src; *q; q++) { + if (*q == '\'') { + *p++ = '\''; *p++ = '\\'; *p++ = '\''; *p++ = '\''; + } else { + *p++ = *q; + } + } + *p++ = '\''; + *p = '\0'; + + do_cmd(host, user, cmd); + sfree(cmd); + + while (ssh_recv(&c, 1) > 0) + fputc(c, stdout); /* thank heavens for buffered I/O */ +} + +/* * Initialize the Win$ock driver. */ -static void init_winsock() +static void init_winsock(void) { WORD winsock_ver; WSADATA wsadata; @@ -723,13 +801,20 @@ static void init_winsock() /* * Short description of parameters. */ -static void usage() +static void usage(void) { printf("PuTTY Secure Copy client\n"); printf("%s\n", ver); - printf("usage: scp [-p] [-q] [-r] [-v] [user@]host:source target\n"); - printf(" scp [-p] [-q] [-r] [-v] source [source..]" - " [user@]host:target\n"); + printf("Usage: pscp [options] [user@]host:source target\n"); + printf(" pscp [options] source [source...] [user@]host:target\n"); + printf(" pscp [options] -ls user@host:filespec\n"); + printf("Options:\n"); + printf(" -p preserve file attributes\n"); + printf(" -q quiet, don't show statistics\n"); + printf(" -r copy directories recursively\n"); + printf(" -v show verbose messages\n"); + printf(" -P port connect to specified port\n"); + printf(" -pw passw login with specified password\n"); exit(1); } @@ -739,6 +824,7 @@ static void usage() int main(int argc, char *argv[]) { int i; + int list = 0; init_winsock(); @@ -756,6 +842,12 @@ int main(int argc, char *argv[]) else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-?") == 0) usage(); + else if (strcmp(argv[i], "-P") == 0 && i+1 < argc) + portnumber = atoi(argv[++i]); + else if (strcmp(argv[i], "-pw") == 0 && i+1 < argc) + password = argv[++i]; + else if (strcmp(argv[i], "-ls") == 0) + list = 1; else if (strcmp(argv[i], "--") == 0) { i++; break; } else @@ -764,15 +856,23 @@ int main(int argc, char *argv[]) argc -= i; argv += i; - if (argc < 2) - usage(); - if (argc > 2) - targetshouldbedirectory = 1; + if (list) { + if (argc != 1) + usage(); + get_dir_list(argc, argv); - if (colon(argv[argc-1]) != NULL) - toremote(argc, argv); - else - tolocal(argc, argv); + } else { + + if (argc < 2) + usage(); + if (argc > 2) + targetshouldbedirectory = 1; + + if (colon(argv[argc-1]) != NULL) + toremote(argc, argv); + else + tolocal(argc, argv); + } if (connection_open) { char ch;