]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - pscp.c
In the file-transfer applications, which only ever use the main
[PuTTY.git] / pscp.c
1 /*
2  * scp.c  -  Scp (Secure Copy) client for PuTTY.
3  * Joris van Rantwijk, Simon Tatham
4  *
5  * This is mainly based on ssh-1.2.26/scp.c by Timo Rinne & Tatu Ylonen.
6  * They, in turn, used stuff from BSD rcp.
7  * 
8  * (SGT, 2001-09-10: Joris van Rantwijk assures me that although
9  * this file as originally submitted was inspired by, and
10  * _structurally_ based on, ssh-1.2.26's scp.c, there wasn't any
11  * actual code duplicated, so the above comment shouldn't give rise
12  * to licensing issues.)
13  */
14
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <limits.h>
19 #include <time.h>
20 #include <assert.h>
21
22 #define PUTTY_DO_GLOBALS
23 #include "putty.h"
24 #include "psftp.h"
25 #include "ssh.h"
26 #include "sftp.h"
27 #include "storage.h"
28 #include "int64.h"
29
30 static int list = 0;
31 static int verbose = 0;
32 static int recursive = 0;
33 static int preserve = 0;
34 static int targetshouldbedirectory = 0;
35 static int statistics = 1;
36 static int prev_stats_len = 0;
37 static int scp_unsafe_mode = 0;
38 static int errs = 0;
39 static int try_scp = 1;
40 static int try_sftp = 1;
41 static int main_cmd_is_sftp = 0;
42 static int fallback_cmd_is_sftp = 0;
43 static int using_sftp = 0;
44
45 static Backend *back;
46 static void *backhandle;
47 static Config cfg;
48
49 static void source(char *src);
50 static void rsource(char *src);
51 static void sink(char *targ, char *src);
52
53 /*
54  * The maximum amount of queued data we accept before we stop and
55  * wait for the server to process some.
56  */
57 #define MAX_SCP_BUFSIZE 16384
58
59 void ldisc_send(void *handle, char *buf, int len, int interactive)
60 {
61     /*
62      * This is only here because of the calls to ldisc_send(NULL,
63      * 0) in ssh.c. Nothing in PSCP actually needs to use the ldisc
64      * as an ldisc. So if we get called with any real data, I want
65      * to know about it.
66      */
67     assert(len == 0);
68 }
69
70 static void tell_char(FILE * stream, char c)
71 {
72     fputc(c, stream);
73 }
74
75 static void tell_str(FILE * stream, char *str)
76 {
77     unsigned int i;
78
79     for (i = 0; i < strlen(str); ++i)
80         tell_char(stream, str[i]);
81 }
82
83 static void tell_user(FILE * stream, char *fmt, ...)
84 {
85     char *str, *str2;
86     va_list ap;
87     va_start(ap, fmt);
88     str = dupvprintf(fmt, ap);
89     va_end(ap);
90     str2 = dupcat(str, "\n", NULL);
91     sfree(str);
92     tell_str(stream, str2);
93     sfree(str2);
94 }
95
96 /*
97  *  Print an error message and perform a fatal exit.
98  */
99 void fatalbox(char *fmt, ...)
100 {
101     char *str, *str2;
102     va_list ap;
103     va_start(ap, fmt);
104     str = dupvprintf(fmt, ap);
105     str2 = dupcat("Fatal: ", str, "\n", NULL);
106     sfree(str);
107     va_end(ap);
108     tell_str(stderr, str2);
109     sfree(str2);
110     errs++;
111
112     cleanup_exit(1);
113 }
114 void modalfatalbox(char *fmt, ...)
115 {
116     char *str, *str2;
117     va_list ap;
118     va_start(ap, fmt);
119     str = dupvprintf(fmt, ap);
120     str2 = dupcat("Fatal: ", str, "\n", NULL);
121     sfree(str);
122     va_end(ap);
123     tell_str(stderr, str2);
124     sfree(str2);
125     errs++;
126
127     cleanup_exit(1);
128 }
129 void connection_fatal(void *frontend, char *fmt, ...)
130 {
131     char *str, *str2;
132     va_list ap;
133     va_start(ap, fmt);
134     str = dupvprintf(fmt, ap);
135     str2 = dupcat("Fatal: ", str, "\n", NULL);
136     sfree(str);
137     va_end(ap);
138     tell_str(stderr, str2);
139     sfree(str2);
140     errs++;
141
142     cleanup_exit(1);
143 }
144
145 /*
146  * In pscp, all agent requests should be synchronous, so this is a
147  * never-called stub.
148  */
149 void agent_schedule_callback(void (*callback)(void *, void *, int),
150                              void *callback_ctx, void *data, int len)
151 {
152     assert(!"We shouldn't be here");
153 }
154
155 /*
156  * Receive a block of data from the SSH link. Block until all data
157  * is available.
158  *
159  * To do this, we repeatedly call the SSH protocol module, with our
160  * own trap in from_backend() to catch the data that comes back. We
161  * do this until we have enough data.
162  */
163
164 static unsigned char *outptr;          /* where to put the data */
165 static unsigned outlen;                /* how much data required */
166 static unsigned char *pending = NULL;  /* any spare data */
167 static unsigned pendlen = 0, pendsize = 0;      /* length and phys. size of buffer */
168 int from_backend(void *frontend, int is_stderr, const char *data, int datalen)
169 {
170     unsigned char *p = (unsigned char *) data;
171     unsigned len = (unsigned) datalen;
172
173     /*
174      * stderr data is just spouted to local stderr and otherwise
175      * ignored.
176      */
177     if (is_stderr) {
178         if (len > 0)
179             fwrite(data, 1, len, stderr);
180         return 0;
181     }
182
183     if ((outlen > 0) && (len > 0)) {
184         unsigned used = outlen;
185         if (used > len)
186             used = len;
187         memcpy(outptr, p, used);
188         outptr += used;
189         outlen -= used;
190         p += used;
191         len -= used;
192     }
193
194     if (len > 0) {
195         if (pendsize < pendlen + len) {
196             pendsize = pendlen + len + 4096;
197             pending = sresize(pending, pendsize, unsigned char);
198         }
199         memcpy(pending + pendlen, p, len);
200         pendlen += len;
201     }
202
203     return 0;
204 }
205 int from_backend_untrusted(void *frontend_handle, const char *data, int len)
206 {
207     /*
208      * No "untrusted" output should get here (the way the code is
209      * currently, it's all diverted by FLAG_STDERR).
210      */
211     assert(!"Unexpected call to from_backend_untrusted()");
212     return 0; /* not reached */
213 }
214 static int ssh_scp_recv(unsigned char *buf, int len)
215 {
216     outptr = buf;
217     outlen = len;
218
219     /*
220      * See if the pending-input block contains some of what we
221      * need.
222      */
223     if (pendlen > 0) {
224         unsigned pendused = pendlen;
225         if (pendused > outlen)
226             pendused = outlen;
227         memcpy(outptr, pending, pendused);
228         memmove(pending, pending + pendused, pendlen - pendused);
229         outptr += pendused;
230         outlen -= pendused;
231         pendlen -= pendused;
232         if (pendlen == 0) {
233             pendsize = 0;
234             sfree(pending);
235             pending = NULL;
236         }
237         if (outlen == 0)
238             return len;
239     }
240
241     while (outlen > 0) {
242         if (back->exitcode(backhandle) >= 0 || ssh_sftp_loop_iteration() < 0)
243             return 0;                  /* doom */
244     }
245
246     return len;
247 }
248
249 /*
250  * Loop through the ssh connection and authentication process.
251  */
252 static void ssh_scp_init(void)
253 {
254     while (!back->sendok(backhandle)) {
255         if (ssh_sftp_loop_iteration() < 0)
256             return;                    /* doom */
257     }
258
259     /* Work out which backend we ended up using. */
260     if (!ssh_fallback_cmd(backhandle))
261         using_sftp = main_cmd_is_sftp;
262     else
263         using_sftp = fallback_cmd_is_sftp;
264
265     if (verbose) {
266         if (using_sftp)
267             tell_user(stderr, "Using SFTP");
268         else
269             tell_user(stderr, "Using SCP1");
270     }
271 }
272
273 /*
274  *  Print an error message and exit after closing the SSH link.
275  */
276 static void bump(char *fmt, ...)
277 {
278     char *str, *str2;
279     va_list ap;
280     va_start(ap, fmt);
281     str = dupvprintf(fmt, ap);
282     va_end(ap);
283     str2 = dupcat(str, "\n", NULL);
284     sfree(str);
285     tell_str(stderr, str2);
286     sfree(str2);
287     errs++;
288
289     if (back != NULL && back->connected(backhandle)) {
290         char ch;
291         back->special(backhandle, TS_EOF);
292         ssh_scp_recv((unsigned char *) &ch, 1);
293     }
294
295     cleanup_exit(1);
296 }
297
298 /*
299  *  Open an SSH connection to user@host and execute cmd.
300  */
301 static void do_cmd(char *host, char *user, char *cmd)
302 {
303     const char *err;
304     char *realhost;
305     void *logctx;
306
307     if (host == NULL || host[0] == '\0')
308         bump("Empty host name");
309
310     /*
311      * Remove fiddly bits of address: remove a colon suffix, and
312      * the square brackets around an IPv6 literal address.
313      */
314     if (host[0] == '[') {
315         host++;
316         host[strcspn(host, "]")] = '\0';
317     } else {
318         host[strcspn(host, ":")] = '\0';
319     }
320
321     /*
322      * If we haven't loaded session details already (e.g., from -load),
323      * try looking for a session called "host".
324      */
325     if (!loaded_session) {
326         /* Try to load settings for `host' into a temporary config */
327         Config cfg2;
328         cfg2.host[0] = '\0';
329         do_defaults(host, &cfg2);
330         if (cfg2.host[0] != '\0') {
331             /* Settings present and include hostname */
332             /* Re-load data into the real config. */
333             do_defaults(host, &cfg);
334         } else {
335             /* Session doesn't exist or mention a hostname. */
336             /* Use `host' as a bare hostname. */
337             strncpy(cfg.host, host, sizeof(cfg.host) - 1);
338             cfg.host[sizeof(cfg.host) - 1] = '\0';
339         }
340     } else {
341         /* Patch in hostname `host' to session details. */
342         strncpy(cfg.host, host, sizeof(cfg.host) - 1);
343         cfg.host[sizeof(cfg.host) - 1] = '\0';
344     }
345
346     /*
347      * Force use of SSH. (If they got the protocol wrong we assume the
348      * port is useless too.)
349      */
350     if (cfg.protocol != PROT_SSH) {
351         cfg.protocol = PROT_SSH;
352         cfg.port = 22;
353     }
354
355     /*
356      * Enact command-line overrides.
357      */
358     cmdline_run_saved(&cfg);
359
360     /*
361      * Trim leading whitespace off the hostname if it's there.
362      */
363     {
364         int space = strspn(cfg.host, " \t");
365         memmove(cfg.host, cfg.host+space, 1+strlen(cfg.host)-space);
366     }
367
368     /* See if host is of the form user@host */
369     if (cfg.host[0] != '\0') {
370         char *atsign = strrchr(cfg.host, '@');
371         /* Make sure we're not overflowing the user field */
372         if (atsign) {
373             if (atsign - cfg.host < sizeof cfg.username) {
374                 strncpy(cfg.username, cfg.host, atsign - cfg.host);
375                 cfg.username[atsign - cfg.host] = '\0';
376             }
377             memmove(cfg.host, atsign + 1, 1 + strlen(atsign + 1));
378         }
379     }
380
381     /*
382      * Remove any remaining whitespace from the hostname.
383      */
384     {
385         int p1 = 0, p2 = 0;
386         while (cfg.host[p2] != '\0') {
387             if (cfg.host[p2] != ' ' && cfg.host[p2] != '\t') {
388                 cfg.host[p1] = cfg.host[p2];
389                 p1++;
390             }
391             p2++;
392         }
393         cfg.host[p1] = '\0';
394     }
395
396     /* Set username */
397     if (user != NULL && user[0] != '\0') {
398         strncpy(cfg.username, user, sizeof(cfg.username) - 1);
399         cfg.username[sizeof(cfg.username) - 1] = '\0';
400     } else if (cfg.username[0] == '\0') {
401         user = get_username();
402         if (!user)
403             bump("Empty user name");
404         else {
405             if (verbose)
406                 tell_user(stderr, "Guessing user name: %s", user);
407             strncpy(cfg.username, user, sizeof(cfg.username) - 1);
408             cfg.username[sizeof(cfg.username) - 1] = '\0';
409             sfree(user);
410         }
411     }
412
413     /*
414      * Disable scary things which shouldn't be enabled for simple
415      * things like SCP and SFTP: agent forwarding, port forwarding,
416      * X forwarding.
417      */
418     cfg.x11_forward = 0;
419     cfg.agentfwd = 0;
420     cfg.portfwd[0] = cfg.portfwd[1] = '\0';
421     cfg.ssh_simple = TRUE;
422
423     /*
424      * Set up main and possibly fallback command depending on
425      * options specified by user.
426      * Attempt to start the SFTP subsystem as a first choice,
427      * falling back to the provided scp command if that fails.
428      */
429     cfg.remote_cmd_ptr2 = NULL;
430     if (try_sftp) {
431         /* First choice is SFTP subsystem. */
432         main_cmd_is_sftp = 1;
433         strcpy(cfg.remote_cmd, "sftp");
434         cfg.ssh_subsys = TRUE;
435         if (try_scp) {
436             /* Fallback is to use the provided scp command. */
437             fallback_cmd_is_sftp = 0;
438             cfg.remote_cmd_ptr2 = cmd;
439             cfg.ssh_subsys2 = FALSE;
440         } else {
441             /* Since we're not going to try SCP, we may as well try
442              * harder to find an SFTP server, since in the current
443              * implementation we have a spare slot. */
444             fallback_cmd_is_sftp = 1;
445             /* see psftp.c for full explanation of this kludge */
446             cfg.remote_cmd_ptr2 = 
447                 "test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server\n"
448                 "test -x /usr/local/lib/sftp-server && exec /usr/local/lib/sftp-server\n"
449                 "exec sftp-server";
450             cfg.ssh_subsys2 = FALSE;
451         }
452     } else {
453         /* Don't try SFTP at all; just try the scp command. */
454         main_cmd_is_sftp = 0;
455         cfg.remote_cmd_ptr = cmd;
456         cfg.ssh_subsys = FALSE;
457     }
458     cfg.nopty = TRUE;
459
460     back = &ssh_backend;
461
462     err = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port, &realhost, 
463                      0, cfg.tcp_keepalives);
464     if (err != NULL)
465         bump("ssh_init: %s", err);
466     logctx = log_init(NULL, &cfg);
467     back->provide_logctx(backhandle, logctx);
468     console_provide_logctx(logctx);
469     ssh_scp_init();
470     if (verbose && realhost != NULL)
471         tell_user(stderr, "Connected to %s\n", realhost);
472     sfree(realhost);
473 }
474
475 /*
476  *  Update statistic information about current file.
477  */
478 static void print_stats(char *name, uint64 size, uint64 done,
479                         time_t start, time_t now)
480 {
481     float ratebs;
482     unsigned long eta;
483     char *etastr;
484     int pct;
485     int len;
486     int elap;
487     double donedbl;
488     double sizedbl;
489
490     elap = (unsigned long) difftime(now, start);
491
492     if (now > start)
493         ratebs = (float) (uint64_to_double(done) / elap);
494     else
495         ratebs = (float) uint64_to_double(done);
496
497     if (ratebs < 1.0)
498         eta = (unsigned long) (uint64_to_double(uint64_subtract(size, done)));
499     else {
500         eta = (unsigned long)
501             ((uint64_to_double(uint64_subtract(size, done)) / ratebs));
502     }
503
504     etastr = dupprintf("%02ld:%02ld:%02ld",
505                        eta / 3600, (eta % 3600) / 60, eta % 60);
506
507     donedbl = uint64_to_double(done);
508     sizedbl = uint64_to_double(size);
509     pct = (int) (100 * (donedbl * 1.0 / sizedbl));
510
511     {
512         char donekb[40];
513         /* divide by 1024 to provide kB */
514         uint64_decimal(uint64_shift_right(done, 10), donekb);
515         len = printf("\r%-25.25s | %s kB | %5.1f kB/s | ETA: %8s | %3d%%",
516                      name,
517                      donekb, ratebs / 1024.0, etastr, pct);
518         if (len < prev_stats_len)
519             printf("%*s", prev_stats_len - len, "");
520         prev_stats_len = len;
521
522         if (uint64_compare(done, size) == 0)
523             printf("\n");
524
525         fflush(stdout);
526     }
527
528     free(etastr);
529 }
530
531 /*
532  *  Find a colon in str and return a pointer to the colon.
533  *  This is used to separate hostname from filename.
534  */
535 static char *colon(char *str)
536 {
537     /* We ignore a leading colon, since the hostname cannot be
538        empty. We also ignore a colon as second character because
539        of filenames like f:myfile.txt. */
540     if (str[0] == '\0' || str[0] == ':' ||
541         (str[0] != '[' && str[1] == ':'))
542         return (NULL);
543     while (*str != '\0' && *str != ':' && *str != '/' && *str != '\\') {
544         if (*str == '[') {
545             /* Skip over IPv6 literal addresses
546              * (eg: 'jeroen@[2001:db8::1]:myfile.txt') */
547             char *ipv6_end = strchr(str, ']');
548             if (ipv6_end) {
549                 str = ipv6_end;
550             }
551         }
552         str++;
553     }
554     if (*str == ':')
555         return (str);
556     else
557         return (NULL);
558 }
559
560 /*
561  * Return a pointer to the portion of str that comes after the last
562  * slash (or backslash or colon, if `local' is TRUE).
563  */
564 static char *stripslashes(char *str, int local)
565 {
566     char *p;
567
568     if (local) {
569         p = strchr(str, ':');
570         if (p) str = p+1;
571     }
572
573     p = strrchr(str, '/');
574     if (p) str = p+1;
575
576     if (local) {
577         p = strrchr(str, '\\');
578         if (p) str = p+1;
579     }
580
581     return str;
582 }
583
584 /*
585  * Determine whether a string is entirely composed of dots.
586  */
587 static int is_dots(char *str)
588 {
589     return str[strspn(str, ".")] == '\0';
590 }
591
592 /*
593  *  Wait for a response from the other side.
594  *  Return 0 if ok, -1 if error.
595  */
596 static int response(void)
597 {
598     char ch, resp, rbuf[2048];
599     int p;
600
601     if (ssh_scp_recv((unsigned char *) &resp, 1) <= 0)
602         bump("Lost connection");
603
604     p = 0;
605     switch (resp) {
606       case 0:                          /* ok */
607         return (0);
608       default:
609         rbuf[p++] = resp;
610         /* fallthrough */
611       case 1:                          /* error */
612       case 2:                          /* fatal error */
613         do {
614             if (ssh_scp_recv((unsigned char *) &ch, 1) <= 0)
615                 bump("Protocol error: Lost connection");
616             rbuf[p++] = ch;
617         } while (p < sizeof(rbuf) && ch != '\n');
618         rbuf[p - 1] = '\0';
619         if (resp == 1)
620             tell_user(stderr, "%s\n", rbuf);
621         else
622             bump("%s", rbuf);
623         errs++;
624         return (-1);
625     }
626 }
627
628 int sftp_recvdata(char *buf, int len)
629 {
630     return ssh_scp_recv((unsigned char *) buf, len);
631 }
632 int sftp_senddata(char *buf, int len)
633 {
634     back->send(backhandle, buf, len);
635     return 1;
636 }
637
638 /* ----------------------------------------------------------------------
639  * sftp-based replacement for the hacky `pscp -ls'.
640  */
641 static int sftp_ls_compare(const void *av, const void *bv)
642 {
643     const struct fxp_name *a = (const struct fxp_name *) av;
644     const struct fxp_name *b = (const struct fxp_name *) bv;
645     return strcmp(a->filename, b->filename);
646 }
647 void scp_sftp_listdir(char *dirname)
648 {
649     struct fxp_handle *dirh;
650     struct fxp_names *names;
651     struct fxp_name *ournames;
652     struct sftp_packet *pktin;
653     struct sftp_request *req, *rreq;
654     int nnames, namesize;
655     int i;
656
657     if (!fxp_init()) {
658         tell_user(stderr, "unable to initialise SFTP: %s", fxp_error());
659         errs++;
660         return;
661     }
662
663     printf("Listing directory %s\n", dirname);
664
665     sftp_register(req = fxp_opendir_send(dirname));
666     rreq = sftp_find_request(pktin = sftp_recv());
667     assert(rreq == req);
668     dirh = fxp_opendir_recv(pktin, rreq);
669
670     if (dirh == NULL) {
671         printf("Unable to open %s: %s\n", dirname, fxp_error());
672     } else {
673         nnames = namesize = 0;
674         ournames = NULL;
675
676         while (1) {
677
678             sftp_register(req = fxp_readdir_send(dirh));
679             rreq = sftp_find_request(pktin = sftp_recv());
680             assert(rreq == req);
681             names = fxp_readdir_recv(pktin, rreq);
682
683             if (names == NULL) {
684                 if (fxp_error_type() == SSH_FX_EOF)
685                     break;
686                 printf("Reading directory %s: %s\n", dirname, fxp_error());
687                 break;
688             }
689             if (names->nnames == 0) {
690                 fxp_free_names(names);
691                 break;
692             }
693
694             if (nnames + names->nnames >= namesize) {
695                 namesize += names->nnames + 128;
696                 ournames = sresize(ournames, namesize, struct fxp_name);
697             }
698
699             for (i = 0; i < names->nnames; i++)
700                 ournames[nnames++] = names->names[i];
701             names->nnames = 0;         /* prevent free_names */
702             fxp_free_names(names);
703         }
704         sftp_register(req = fxp_close_send(dirh));
705         rreq = sftp_find_request(pktin = sftp_recv());
706         assert(rreq == req);
707         fxp_close_recv(pktin, rreq);
708
709         /*
710          * Now we have our filenames. Sort them by actual file
711          * name, and then output the longname parts.
712          */
713         qsort(ournames, nnames, sizeof(*ournames), sftp_ls_compare);
714
715         /*
716          * And print them.
717          */
718         for (i = 0; i < nnames; i++)
719             printf("%s\n", ournames[i].longname);
720     }
721 }
722
723 /* ----------------------------------------------------------------------
724  * Helper routines that contain the actual SCP protocol elements,
725  * implemented both as SCP1 and SFTP.
726  */
727
728 static struct scp_sftp_dirstack {
729     struct scp_sftp_dirstack *next;
730     struct fxp_name *names;
731     int namepos, namelen;
732     char *dirpath;
733     char *wildcard;
734     int matched_something;             /* wildcard match set was non-empty */
735 } *scp_sftp_dirstack_head;
736 static char *scp_sftp_remotepath, *scp_sftp_currentname;
737 static char *scp_sftp_wildcard;
738 static int scp_sftp_targetisdir, scp_sftp_donethistarget;
739 static int scp_sftp_preserve, scp_sftp_recursive;
740 static unsigned long scp_sftp_mtime, scp_sftp_atime;
741 static int scp_has_times;
742 static struct fxp_handle *scp_sftp_filehandle;
743 static struct fxp_xfer *scp_sftp_xfer;
744 static uint64 scp_sftp_fileoffset;
745
746 int scp_source_setup(char *target, int shouldbedir)
747 {
748     if (using_sftp) {
749         /*
750          * Find out whether the target filespec is in fact a
751          * directory.
752          */
753         struct sftp_packet *pktin;
754         struct sftp_request *req, *rreq;
755         struct fxp_attrs attrs;
756         int ret;
757
758         if (!fxp_init()) {
759             tell_user(stderr, "unable to initialise SFTP: %s", fxp_error());
760             errs++;
761             return 1;
762         }
763
764         sftp_register(req = fxp_stat_send(target));
765         rreq = sftp_find_request(pktin = sftp_recv());
766         assert(rreq == req);
767         ret = fxp_stat_recv(pktin, rreq, &attrs);
768
769         if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS))
770             scp_sftp_targetisdir = 0;
771         else
772             scp_sftp_targetisdir = (attrs.permissions & 0040000) != 0;
773
774         if (shouldbedir && !scp_sftp_targetisdir) {
775             bump("pscp: remote filespec %s: not a directory\n", target);
776         }
777
778         scp_sftp_remotepath = dupstr(target);
779
780         scp_has_times = 0;
781     } else {
782         (void) response();
783     }
784     return 0;
785 }
786
787 int scp_send_errmsg(char *str)
788 {
789     if (using_sftp) {
790         /* do nothing; we never need to send our errors to the server */
791     } else {
792         back->send(backhandle, "\001", 1);/* scp protocol error prefix */
793         back->send(backhandle, str, strlen(str));
794     }
795     return 0;                          /* can't fail */
796 }
797
798 int scp_send_filetimes(unsigned long mtime, unsigned long atime)
799 {
800     if (using_sftp) {
801         scp_sftp_mtime = mtime;
802         scp_sftp_atime = atime;
803         scp_has_times = 1;
804         return 0;
805     } else {
806         char buf[80];
807         sprintf(buf, "T%lu 0 %lu 0\n", mtime, atime);
808         back->send(backhandle, buf, strlen(buf));
809         return response();
810     }
811 }
812
813 int scp_send_filename(char *name, uint64 size, int modes)
814 {
815     if (using_sftp) {
816         char *fullname;
817         struct sftp_packet *pktin;
818         struct sftp_request *req, *rreq;
819
820         if (scp_sftp_targetisdir) {
821             fullname = dupcat(scp_sftp_remotepath, "/", name, NULL);
822         } else {
823             fullname = dupstr(scp_sftp_remotepath);
824         }
825
826         sftp_register(req = fxp_open_send(fullname, SSH_FXF_WRITE |
827                                           SSH_FXF_CREAT | SSH_FXF_TRUNC));
828         rreq = sftp_find_request(pktin = sftp_recv());
829         assert(rreq == req);
830         scp_sftp_filehandle = fxp_open_recv(pktin, rreq);
831
832         if (!scp_sftp_filehandle) {
833             tell_user(stderr, "pscp: unable to open %s: %s",
834                       fullname, fxp_error());
835             errs++;
836             return 1;
837         }
838         scp_sftp_fileoffset = uint64_make(0, 0);
839         scp_sftp_xfer = xfer_upload_init(scp_sftp_filehandle,
840                                          scp_sftp_fileoffset);
841         sfree(fullname);
842         return 0;
843     } else {
844         char buf[40];
845         char sizestr[40];
846         uint64_decimal(size, sizestr);
847         sprintf(buf, "C%04o %s ", modes, sizestr);
848         back->send(backhandle, buf, strlen(buf));
849         back->send(backhandle, name, strlen(name));
850         back->send(backhandle, "\n", 1);
851         return response();
852     }
853 }
854
855 int scp_send_filedata(char *data, int len)
856 {
857     if (using_sftp) {
858         int ret;
859         struct sftp_packet *pktin;
860
861         if (!scp_sftp_filehandle) {
862             return 1;
863         }
864
865         while (!xfer_upload_ready(scp_sftp_xfer)) {
866             pktin = sftp_recv();
867             ret = xfer_upload_gotpkt(scp_sftp_xfer, pktin);
868             if (!ret) {
869                 tell_user(stderr, "error while writing: %s\n", fxp_error());
870                 errs++;
871                 return 1;
872             }
873         }
874
875         xfer_upload_data(scp_sftp_xfer, data, len);
876
877         scp_sftp_fileoffset = uint64_add32(scp_sftp_fileoffset, len);
878         return 0;
879     } else {
880         int bufsize = back->send(backhandle, data, len);
881
882         /*
883          * If the network transfer is backing up - that is, the
884          * remote site is not accepting data as fast as we can
885          * produce it - then we must loop on network events until
886          * we have space in the buffer again.
887          */
888         while (bufsize > MAX_SCP_BUFSIZE) {
889             if (ssh_sftp_loop_iteration() < 0)
890                 return 1;
891             bufsize = back->sendbuffer(backhandle);
892         }
893
894         return 0;
895     }
896 }
897
898 int scp_send_finish(void)
899 {
900     if (using_sftp) {
901         struct fxp_attrs attrs;
902         struct sftp_packet *pktin;
903         struct sftp_request *req, *rreq;
904         int ret;
905
906         while (!xfer_done(scp_sftp_xfer)) {
907             pktin = sftp_recv();
908             xfer_upload_gotpkt(scp_sftp_xfer, pktin);
909         }
910         xfer_cleanup(scp_sftp_xfer);
911
912         if (!scp_sftp_filehandle) {
913             return 1;
914         }
915         if (scp_has_times) {
916             attrs.flags = SSH_FILEXFER_ATTR_ACMODTIME;
917             attrs.atime = scp_sftp_atime;
918             attrs.mtime = scp_sftp_mtime;
919             sftp_register(req = fxp_fsetstat_send(scp_sftp_filehandle, attrs));
920             rreq = sftp_find_request(pktin = sftp_recv());
921             assert(rreq == req);
922             ret = fxp_fsetstat_recv(pktin, rreq);
923             if (!ret) {
924                 tell_user(stderr, "unable to set file times: %s\n", fxp_error());
925                 errs++;
926             }
927         }
928         sftp_register(req = fxp_close_send(scp_sftp_filehandle));
929         rreq = sftp_find_request(pktin = sftp_recv());
930         assert(rreq == req);
931         fxp_close_recv(pktin, rreq);
932         scp_has_times = 0;
933         return 0;
934     } else {
935         back->send(backhandle, "", 1);
936         return response();
937     }
938 }
939
940 char *scp_save_remotepath(void)
941 {
942     if (using_sftp)
943         return scp_sftp_remotepath;
944     else
945         return NULL;
946 }
947
948 void scp_restore_remotepath(char *data)
949 {
950     if (using_sftp)
951         scp_sftp_remotepath = data;
952 }
953
954 int scp_send_dirname(char *name, int modes)
955 {
956     if (using_sftp) {
957         char *fullname;
958         char const *err;
959         struct fxp_attrs attrs;
960         struct sftp_packet *pktin;
961         struct sftp_request *req, *rreq;
962         int ret;
963
964         if (scp_sftp_targetisdir) {
965             fullname = dupcat(scp_sftp_remotepath, "/", name, NULL);
966         } else {
967             fullname = dupstr(scp_sftp_remotepath);
968         }
969
970         /*
971          * We don't worry about whether we managed to create the
972          * directory, because if it exists already it's OK just to
973          * use it. Instead, we will stat it afterwards, and if it
974          * exists and is a directory we will assume we were either
975          * successful or it didn't matter.
976          */
977         sftp_register(req = fxp_mkdir_send(fullname));
978         rreq = sftp_find_request(pktin = sftp_recv());
979         assert(rreq == req);
980         ret = fxp_mkdir_recv(pktin, rreq);
981
982         if (!ret)
983             err = fxp_error();
984         else
985             err = "server reported no error";
986
987         sftp_register(req = fxp_stat_send(fullname));
988         rreq = sftp_find_request(pktin = sftp_recv());
989         assert(rreq == req);
990         ret = fxp_stat_recv(pktin, rreq, &attrs);
991
992         if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) ||
993             !(attrs.permissions & 0040000)) {
994             tell_user(stderr, "unable to create directory %s: %s",
995                       fullname, err);
996             errs++;
997             return 1;
998         }
999
1000         scp_sftp_remotepath = fullname;
1001
1002         return 0;
1003     } else {
1004         char buf[40];
1005         sprintf(buf, "D%04o 0 ", modes);
1006         back->send(backhandle, buf, strlen(buf));
1007         back->send(backhandle, name, strlen(name));
1008         back->send(backhandle, "\n", 1);
1009         return response();
1010     }
1011 }
1012
1013 int scp_send_enddir(void)
1014 {
1015     if (using_sftp) {
1016         sfree(scp_sftp_remotepath);
1017         return 0;
1018     } else {
1019         back->send(backhandle, "E\n", 2);
1020         return response();
1021     }
1022 }
1023
1024 /*
1025  * Yes, I know; I have an scp_sink_setup _and_ an scp_sink_init.
1026  * That's bad. The difference is that scp_sink_setup is called once
1027  * right at the start, whereas scp_sink_init is called to
1028  * initialise every level of recursion in the protocol.
1029  */
1030 int scp_sink_setup(char *source, int preserve, int recursive)
1031 {
1032     if (using_sftp) {
1033         char *newsource;
1034
1035         if (!fxp_init()) {
1036             tell_user(stderr, "unable to initialise SFTP: %s", fxp_error());
1037             errs++;
1038             return 1;
1039         }
1040         /*
1041          * It's possible that the source string we've been given
1042          * contains a wildcard. If so, we must split the directory
1043          * away from the wildcard itself (throwing an error if any
1044          * wildcardness comes before the final slash) and arrange
1045          * things so that a dirstack entry will be set up.
1046          */
1047         newsource = snewn(1+strlen(source), char);
1048         if (!wc_unescape(newsource, source)) {
1049             /* Yes, here we go; it's a wildcard. Bah. */
1050             char *dupsource, *lastpart, *dirpart, *wildcard;
1051             dupsource = dupstr(source);
1052             lastpart = stripslashes(dupsource, 0);
1053             wildcard = dupstr(lastpart);
1054             *lastpart = '\0';
1055             if (*dupsource && dupsource[1]) {
1056                 /*
1057                  * The remains of dupsource are at least two
1058                  * characters long, meaning the pathname wasn't
1059                  * empty or just `/'. Hence, we remove the trailing
1060                  * slash.
1061                  */
1062                 lastpart[-1] = '\0';
1063             } else if (!*dupsource) {
1064                 /*
1065                  * The remains of dupsource are _empty_ - the whole
1066                  * pathname was a wildcard. Hence we need to
1067                  * replace it with ".".
1068                  */
1069                 sfree(dupsource);
1070                 dupsource = dupstr(".");
1071             }
1072
1073             /*
1074              * Now we have separated our string into dupsource (the
1075              * directory part) and wildcard. Both of these will
1076              * need freeing at some point. Next step is to remove
1077              * wildcard escapes from the directory part, throwing
1078              * an error if it contains a real wildcard.
1079              */
1080             dirpart = snewn(1+strlen(dupsource), char);
1081             if (!wc_unescape(dirpart, dupsource)) {
1082                 tell_user(stderr, "%s: multiple-level wildcards unsupported",
1083                           source);
1084                 errs++;
1085                 sfree(dirpart);
1086                 sfree(wildcard);
1087                 sfree(dupsource);
1088                 return 1;
1089             }
1090
1091             /*
1092              * Now we have dirpart (unescaped, ie a valid remote
1093              * path), and wildcard (a wildcard). This will be
1094              * sufficient to arrange a dirstack entry.
1095              */
1096             scp_sftp_remotepath = dirpart;
1097             scp_sftp_wildcard = wildcard;
1098             sfree(dupsource);
1099         } else {
1100             scp_sftp_remotepath = newsource;
1101             scp_sftp_wildcard = NULL;
1102         }
1103         scp_sftp_preserve = preserve;
1104         scp_sftp_recursive = recursive;
1105         scp_sftp_donethistarget = 0;
1106         scp_sftp_dirstack_head = NULL;
1107     }
1108     return 0;
1109 }
1110
1111 int scp_sink_init(void)
1112 {
1113     if (!using_sftp) {
1114         back->send(backhandle, "", 1);
1115     }
1116     return 0;
1117 }
1118
1119 #define SCP_SINK_FILE   1
1120 #define SCP_SINK_DIR    2
1121 #define SCP_SINK_ENDDIR 3
1122 #define SCP_SINK_RETRY  4              /* not an action; just try again */
1123 struct scp_sink_action {
1124     int action;                        /* FILE, DIR, ENDDIR */
1125     char *buf;                         /* will need freeing after use */
1126     char *name;                        /* filename or dirname (not ENDDIR) */
1127     int mode;                          /* access mode (not ENDDIR) */
1128     uint64 size;                       /* file size (not ENDDIR) */
1129     int settime;                       /* 1 if atime and mtime are filled */
1130     unsigned long atime, mtime;        /* access times for the file */
1131 };
1132
1133 int scp_get_sink_action(struct scp_sink_action *act)
1134 {
1135     if (using_sftp) {
1136         char *fname;
1137         int must_free_fname;
1138         struct fxp_attrs attrs;
1139         struct sftp_packet *pktin;
1140         struct sftp_request *req, *rreq;
1141         int ret;
1142
1143         if (!scp_sftp_dirstack_head) {
1144             if (!scp_sftp_donethistarget) {
1145                 /*
1146                  * Simple case: we are only dealing with one file.
1147                  */
1148                 fname = scp_sftp_remotepath;
1149                 must_free_fname = 0;
1150                 scp_sftp_donethistarget = 1;
1151             } else {
1152                 /*
1153                  * Even simpler case: one file _which we've done_.
1154                  * Return 1 (finished).
1155                  */
1156                 return 1;
1157             }
1158         } else {
1159             /*
1160              * We're now in the middle of stepping through a list
1161              * of names returned from fxp_readdir(); so let's carry
1162              * on.
1163              */
1164             struct scp_sftp_dirstack *head = scp_sftp_dirstack_head;
1165             while (head->namepos < head->namelen &&
1166                    (is_dots(head->names[head->namepos].filename) ||
1167                     (head->wildcard &&
1168                      !wc_match(head->wildcard,
1169                                head->names[head->namepos].filename))))
1170                 head->namepos++;       /* skip . and .. */
1171             if (head->namepos < head->namelen) {
1172                 head->matched_something = 1;
1173                 fname = dupcat(head->dirpath, "/",
1174                                head->names[head->namepos++].filename,
1175                                NULL);
1176                 must_free_fname = 1;
1177             } else {
1178                 /*
1179                  * We've come to the end of the list; pop it off
1180                  * the stack and return an ENDDIR action (or RETRY
1181                  * if this was a wildcard match).
1182                  */
1183                 if (head->wildcard) {
1184                     act->action = SCP_SINK_RETRY;
1185                     if (!head->matched_something) {
1186                         tell_user(stderr, "pscp: wildcard '%s' matched "
1187                                   "no files", head->wildcard);
1188                         errs++;
1189                     }
1190                     sfree(head->wildcard);
1191
1192                 } else {
1193                     act->action = SCP_SINK_ENDDIR;
1194                 }
1195
1196                 sfree(head->dirpath);
1197                 sfree(head->names);
1198                 scp_sftp_dirstack_head = head->next;
1199                 sfree(head);
1200
1201                 return 0;
1202             }
1203         }
1204
1205         /*
1206          * Now we have a filename. Stat it, and see if it's a file
1207          * or a directory.
1208          */
1209         sftp_register(req = fxp_stat_send(fname));
1210         rreq = sftp_find_request(pktin = sftp_recv());
1211         assert(rreq == req);
1212         ret = fxp_stat_recv(pktin, rreq, &attrs);
1213
1214         if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) {
1215             tell_user(stderr, "unable to identify %s: %s", fname,
1216                       ret ? "file type not supplied" : fxp_error());
1217             errs++;
1218             return 1;
1219         }
1220
1221         if (attrs.permissions & 0040000) {
1222             struct scp_sftp_dirstack *newitem;
1223             struct fxp_handle *dirhandle;
1224             int nnames, namesize;
1225             struct fxp_name *ournames;
1226             struct fxp_names *names;
1227
1228             /*
1229              * It's a directory. If we're not in recursive mode,
1230              * this merits a complaint (which is fatal if the name
1231              * was specified directly, but not if it was matched by
1232              * a wildcard).
1233              * 
1234              * We skip this complaint completely if
1235              * scp_sftp_wildcard is set, because that's an
1236              * indication that we're not actually supposed to
1237              * _recursively_ transfer the dir, just scan it for
1238              * things matching the wildcard.
1239              */
1240             if (!scp_sftp_recursive && !scp_sftp_wildcard) {
1241                 tell_user(stderr, "pscp: %s: is a directory", fname);
1242                 errs++;
1243                 if (must_free_fname) sfree(fname);
1244                 if (scp_sftp_dirstack_head) {
1245                     act->action = SCP_SINK_RETRY;
1246                     return 0;
1247                 } else {
1248                     return 1;
1249                 }
1250             }
1251
1252             /*
1253              * Otherwise, the fun begins. We must fxp_opendir() the
1254              * directory, slurp the filenames into memory, return
1255              * SCP_SINK_DIR (unless this is a wildcard match), and
1256              * set targetisdir. The next time we're called, we will
1257              * run through the list of filenames one by one,
1258              * matching them against a wildcard if present.
1259              * 
1260              * If targetisdir is _already_ set (meaning we're
1261              * already in the middle of going through another such
1262              * list), we must push the other (target,namelist) pair
1263              * on a stack.
1264              */
1265             sftp_register(req = fxp_opendir_send(fname));
1266             rreq = sftp_find_request(pktin = sftp_recv());
1267             assert(rreq == req);
1268             dirhandle = fxp_opendir_recv(pktin, rreq);
1269
1270             if (!dirhandle) {
1271                 tell_user(stderr, "scp: unable to open directory %s: %s",
1272                           fname, fxp_error());
1273                 if (must_free_fname) sfree(fname);
1274                 errs++;
1275                 return 1;
1276             }
1277             nnames = namesize = 0;
1278             ournames = NULL;
1279             while (1) {
1280                 int i;
1281
1282                 sftp_register(req = fxp_readdir_send(dirhandle));
1283                 rreq = sftp_find_request(pktin = sftp_recv());
1284                 assert(rreq == req);
1285                 names = fxp_readdir_recv(pktin, rreq);
1286
1287                 if (names == NULL) {
1288                     if (fxp_error_type() == SSH_FX_EOF)
1289                         break;
1290                     tell_user(stderr, "scp: reading directory %s: %s\n",
1291                               fname, fxp_error());
1292                     if (must_free_fname) sfree(fname);
1293                     sfree(ournames);
1294                     errs++;
1295                     return 1;
1296                 }
1297                 if (names->nnames == 0) {
1298                     fxp_free_names(names);
1299                     break;
1300                 }
1301                 if (nnames + names->nnames >= namesize) {
1302                     namesize += names->nnames + 128;
1303                     ournames = sresize(ournames, namesize, struct fxp_name);
1304                 }
1305                 for (i = 0; i < names->nnames; i++) {
1306                     if (!strcmp(names->names[i].filename, ".") ||
1307                         !strcmp(names->names[i].filename, "..")) {
1308                         /*
1309                          * . and .. are normal consequences of
1310                          * reading a directory, and aren't worth
1311                          * complaining about.
1312                          */
1313                     } else if (!vet_filename(names->names[i].filename)) {
1314                         tell_user(stderr, "ignoring potentially dangerous server-"
1315                                   "supplied filename '%s'\n",
1316                                   names->names[i].filename);
1317                     } else
1318                         ournames[nnames++] = names->names[i];
1319                 }
1320                 names->nnames = 0;             /* prevent free_names */
1321                 fxp_free_names(names);
1322             }
1323             sftp_register(req = fxp_close_send(dirhandle));
1324             rreq = sftp_find_request(pktin = sftp_recv());
1325             assert(rreq == req);
1326             fxp_close_recv(pktin, rreq);
1327
1328             newitem = snew(struct scp_sftp_dirstack);
1329             newitem->next = scp_sftp_dirstack_head;
1330             newitem->names = ournames;
1331             newitem->namepos = 0;
1332             newitem->namelen = nnames;
1333             if (must_free_fname)
1334                 newitem->dirpath = fname;
1335             else
1336                 newitem->dirpath = dupstr(fname);
1337             if (scp_sftp_wildcard) {
1338                 newitem->wildcard = scp_sftp_wildcard;
1339                 newitem->matched_something = 0;
1340                 scp_sftp_wildcard = NULL;
1341             } else {
1342                 newitem->wildcard = NULL;
1343             }
1344             scp_sftp_dirstack_head = newitem;
1345
1346             if (newitem->wildcard) {
1347                 act->action = SCP_SINK_RETRY;
1348             } else {
1349                 act->action = SCP_SINK_DIR;
1350                 act->buf = dupstr(stripslashes(fname, 0));
1351                 act->name = act->buf;
1352                 act->size = uint64_make(0,0);     /* duhh, it's a directory */
1353                 act->mode = 07777 & attrs.permissions;
1354                 if (scp_sftp_preserve &&
1355                     (attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME)) {
1356                     act->atime = attrs.atime;
1357                     act->mtime = attrs.mtime;
1358                     act->settime = 1;
1359                 } else
1360                     act->settime = 0;
1361             }
1362             return 0;
1363
1364         } else {
1365             /*
1366              * It's a file. Return SCP_SINK_FILE.
1367              */
1368             act->action = SCP_SINK_FILE;
1369             act->buf = dupstr(stripslashes(fname, 0));
1370             act->name = act->buf;
1371             if (attrs.flags & SSH_FILEXFER_ATTR_SIZE) {
1372                 act->size = attrs.size;
1373             } else
1374                 act->size = uint64_make(ULONG_MAX,ULONG_MAX);   /* no idea */
1375             act->mode = 07777 & attrs.permissions;
1376             if (scp_sftp_preserve &&
1377                 (attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME)) {
1378                 act->atime = attrs.atime;
1379                 act->mtime = attrs.mtime;
1380                 act->settime = 1;
1381             } else
1382                 act->settime = 0;
1383             if (must_free_fname)
1384                 scp_sftp_currentname = fname;
1385             else
1386                 scp_sftp_currentname = dupstr(fname);
1387             return 0;
1388         }
1389
1390     } else {
1391         int done = 0;
1392         int i, bufsize;
1393         int action;
1394         char ch;
1395
1396         act->settime = 0;
1397         act->buf = NULL;
1398         bufsize = 0;
1399
1400         while (!done) {
1401             if (ssh_scp_recv((unsigned char *) &ch, 1) <= 0)
1402                 return 1;
1403             if (ch == '\n')
1404                 bump("Protocol error: Unexpected newline");
1405             i = 0;
1406             action = ch;
1407             do {
1408                 if (ssh_scp_recv((unsigned char *) &ch, 1) <= 0)
1409                     bump("Lost connection");
1410                 if (i >= bufsize) {
1411                     bufsize = i + 128;
1412                     act->buf = sresize(act->buf, bufsize, char);
1413                 }
1414                 act->buf[i++] = ch;
1415             } while (ch != '\n');
1416             act->buf[i - 1] = '\0';
1417             switch (action) {
1418               case '\01':                      /* error */
1419                 tell_user(stderr, "%s\n", act->buf);
1420                 errs++;
1421                 continue;                      /* go round again */
1422               case '\02':                      /* fatal error */
1423                 bump("%s", act->buf);
1424               case 'E':
1425                 back->send(backhandle, "", 1);
1426                 act->action = SCP_SINK_ENDDIR;
1427                 return 0;
1428               case 'T':
1429                 if (sscanf(act->buf, "%ld %*d %ld %*d",
1430                            &act->mtime, &act->atime) == 2) {
1431                     act->settime = 1;
1432                     back->send(backhandle, "", 1);
1433                     continue;          /* go round again */
1434                 }
1435                 bump("Protocol error: Illegal time format");
1436               case 'C':
1437               case 'D':
1438                 act->action = (action == 'C' ? SCP_SINK_FILE : SCP_SINK_DIR);
1439                 break;
1440               default:
1441                 bump("Protocol error: Expected control record");
1442             }
1443             /*
1444              * We will go round this loop only once, unless we hit
1445              * `continue' above.
1446              */
1447             done = 1;
1448         }
1449
1450         /*
1451          * If we get here, we must have seen SCP_SINK_FILE or
1452          * SCP_SINK_DIR.
1453          */
1454         {
1455             char sizestr[40];
1456         
1457             if (sscanf(act->buf, "%o %s %n", &act->mode, sizestr, &i) != 2)
1458                 bump("Protocol error: Illegal file descriptor format");
1459             act->size = uint64_from_decimal(sizestr);
1460             act->name = act->buf + i;
1461             return 0;
1462         }
1463     }
1464 }
1465
1466 int scp_accept_filexfer(void)
1467 {
1468     if (using_sftp) {
1469         struct sftp_packet *pktin;
1470         struct sftp_request *req, *rreq;
1471
1472         sftp_register(req = fxp_open_send(scp_sftp_currentname, SSH_FXF_READ));
1473         rreq = sftp_find_request(pktin = sftp_recv());
1474         assert(rreq == req);
1475         scp_sftp_filehandle = fxp_open_recv(pktin, rreq);
1476
1477         if (!scp_sftp_filehandle) {
1478             tell_user(stderr, "pscp: unable to open %s: %s",
1479                       scp_sftp_currentname, fxp_error());
1480             errs++;
1481             return 1;
1482         }
1483         scp_sftp_fileoffset = uint64_make(0, 0);
1484         scp_sftp_xfer = xfer_download_init(scp_sftp_filehandle,
1485                                            scp_sftp_fileoffset);
1486         sfree(scp_sftp_currentname);
1487         return 0;
1488     } else {
1489         back->send(backhandle, "", 1);
1490         return 0;                      /* can't fail */
1491     }
1492 }
1493
1494 int scp_recv_filedata(char *data, int len)
1495 {
1496     if (using_sftp) {
1497         struct sftp_packet *pktin;
1498         int ret, actuallen;
1499         void *vbuf;
1500
1501         xfer_download_queue(scp_sftp_xfer);
1502         pktin = sftp_recv();
1503         ret = xfer_download_gotpkt(scp_sftp_xfer, pktin);
1504
1505         if (ret < 0) {
1506             tell_user(stderr, "pscp: error while reading: %s", fxp_error());
1507             errs++;
1508             return -1;
1509         }
1510
1511         if (xfer_download_data(scp_sftp_xfer, &vbuf, &actuallen)) {
1512             /*
1513              * This assertion relies on the fact that the natural
1514              * block size used in the xfer manager is at most that
1515              * used in this module. I don't like crossing layers in
1516              * this way, but it'll do for now.
1517              */
1518             assert(actuallen <= len);
1519             memcpy(data, vbuf, actuallen);
1520             sfree(vbuf);
1521         } else
1522             actuallen = 0;
1523
1524         scp_sftp_fileoffset = uint64_add32(scp_sftp_fileoffset, actuallen);
1525
1526         return actuallen;
1527     } else {
1528         return ssh_scp_recv((unsigned char *) data, len);
1529     }
1530 }
1531
1532 int scp_finish_filerecv(void)
1533 {
1534     if (using_sftp) {
1535         struct sftp_packet *pktin;
1536         struct sftp_request *req, *rreq;
1537
1538         /*
1539          * Ensure that xfer_done() will work correctly, so we can
1540          * clean up any outstanding requests from the file
1541          * transfer.
1542          */
1543         xfer_set_error(scp_sftp_xfer);
1544         while (!xfer_done(scp_sftp_xfer)) {
1545             void *vbuf;
1546             int len;
1547
1548             pktin = sftp_recv();
1549             xfer_download_gotpkt(scp_sftp_xfer, pktin);
1550             if (xfer_download_data(scp_sftp_xfer, &vbuf, &len))
1551                 sfree(vbuf);
1552         }
1553         xfer_cleanup(scp_sftp_xfer);
1554
1555         sftp_register(req = fxp_close_send(scp_sftp_filehandle));
1556         rreq = sftp_find_request(pktin = sftp_recv());
1557         assert(rreq == req);
1558         fxp_close_recv(pktin, rreq);
1559         return 0;
1560     } else {
1561         back->send(backhandle, "", 1);
1562         return response();
1563     }
1564 }
1565
1566 /* ----------------------------------------------------------------------
1567  *  Send an error message to the other side and to the screen.
1568  *  Increment error counter.
1569  */
1570 static void run_err(const char *fmt, ...)
1571 {
1572     char *str, *str2;
1573     va_list ap;
1574     va_start(ap, fmt);
1575     errs++;
1576     str = dupvprintf(fmt, ap);
1577     str2 = dupcat("scp: ", str, "\n", NULL);
1578     sfree(str);
1579     scp_send_errmsg(str2);
1580     tell_user(stderr, "%s", str2);
1581     va_end(ap);
1582     sfree(str2);
1583 }
1584
1585 /*
1586  *  Execute the source part of the SCP protocol.
1587  */
1588 static void source(char *src)
1589 {
1590     uint64 size;
1591     unsigned long mtime, atime;
1592     char *last;
1593     RFile *f;
1594     int attr;
1595     uint64 i;
1596     uint64 stat_bytes;
1597     time_t stat_starttime, stat_lasttime;
1598
1599     attr = file_type(src);
1600     if (attr == FILE_TYPE_NONEXISTENT ||
1601         attr == FILE_TYPE_WEIRD) {
1602         run_err("%s: %s file or directory", src,
1603                 (attr == FILE_TYPE_WEIRD ? "Not a" : "No such"));
1604         return;
1605     }
1606
1607     if (attr == FILE_TYPE_DIRECTORY) {
1608         if (recursive) {
1609             /*
1610              * Avoid . and .. directories.
1611              */
1612             char *p;
1613             p = strrchr(src, '/');
1614             if (!p)
1615                 p = strrchr(src, '\\');
1616             if (!p)
1617                 p = src;
1618             else
1619                 p++;
1620             if (!strcmp(p, ".") || !strcmp(p, ".."))
1621                 /* skip . and .. */ ;
1622             else
1623                 rsource(src);
1624         } else {
1625             run_err("%s: not a regular file", src);
1626         }
1627         return;
1628     }
1629
1630     if ((last = strrchr(src, '/')) == NULL)
1631         last = src;
1632     else
1633         last++;
1634     if (strrchr(last, '\\') != NULL)
1635         last = strrchr(last, '\\') + 1;
1636     if (last == src && strchr(src, ':') != NULL)
1637         last = strchr(src, ':') + 1;
1638
1639     f = open_existing_file(src, &size, &mtime, &atime);
1640     if (f == NULL) {
1641         run_err("%s: Cannot open file", src);
1642         return;
1643     }
1644     if (preserve) {
1645         if (scp_send_filetimes(mtime, atime))
1646             return;
1647     }
1648
1649     if (verbose) {
1650         char sizestr[40];
1651         uint64_decimal(size, sizestr);
1652         tell_user(stderr, "Sending file %s, size=%s", last, sizestr);
1653     }
1654     if (scp_send_filename(last, size, 0644))
1655         return;
1656
1657     stat_bytes = uint64_make(0,0);
1658     stat_starttime = time(NULL);
1659     stat_lasttime = 0;
1660
1661     for (i = uint64_make(0,0);
1662          uint64_compare(i,size) < 0;
1663          i = uint64_add32(i,4096)) {
1664         char transbuf[4096];
1665         int j, k = 4096;
1666
1667         if (uint64_compare(uint64_add32(i, k),size) > 0) /* i + k > size */ 
1668             k = (uint64_subtract(size, i)).lo;  /* k = size - i; */
1669         if ((j = read_from_file(f, transbuf, k)) != k) {
1670             if (statistics)
1671                 printf("\n");
1672             bump("%s: Read error", src);
1673         }
1674         if (scp_send_filedata(transbuf, k))
1675             bump("%s: Network error occurred", src);
1676
1677         if (statistics) {
1678             stat_bytes = uint64_add32(stat_bytes, k);
1679             if (time(NULL) != stat_lasttime ||
1680                 (uint64_compare(uint64_add32(i, k), size) == 0)) {
1681                 stat_lasttime = time(NULL);
1682                 print_stats(last, size, stat_bytes,
1683                             stat_starttime, stat_lasttime);
1684             }
1685         }
1686
1687     }
1688     close_rfile(f);
1689
1690     (void) scp_send_finish();
1691 }
1692
1693 /*
1694  *  Recursively send the contents of a directory.
1695  */
1696 static void rsource(char *src)
1697 {
1698     char *last;
1699     char *save_target;
1700     DirHandle *dir;
1701
1702     if ((last = strrchr(src, '/')) == NULL)
1703         last = src;
1704     else
1705         last++;
1706     if (strrchr(last, '\\') != NULL)
1707         last = strrchr(last, '\\') + 1;
1708     if (last == src && strchr(src, ':') != NULL)
1709         last = strchr(src, ':') + 1;
1710
1711     /* maybe send filetime */
1712
1713     save_target = scp_save_remotepath();
1714
1715     if (verbose)
1716         tell_user(stderr, "Entering directory: %s", last);
1717     if (scp_send_dirname(last, 0755))
1718         return;
1719
1720     dir = open_directory(src);
1721     if (dir != NULL) {
1722         char *filename;
1723         while ((filename = read_filename(dir)) != NULL) {
1724             char *foundfile = dupcat(src, "/", filename, NULL);
1725             source(foundfile);
1726             sfree(foundfile);
1727             sfree(filename);
1728         }
1729     }
1730     close_directory(dir);
1731
1732     (void) scp_send_enddir();
1733
1734     scp_restore_remotepath(save_target);
1735 }
1736
1737 /*
1738  * Execute the sink part of the SCP protocol.
1739  */
1740 static void sink(char *targ, char *src)
1741 {
1742     char *destfname;
1743     int targisdir = 0;
1744     int exists;
1745     int attr;
1746     WFile *f;
1747     uint64 received;
1748     int wrerror = 0;
1749     uint64 stat_bytes;
1750     time_t stat_starttime, stat_lasttime;
1751     char *stat_name;
1752
1753     attr = file_type(targ);
1754     if (attr == FILE_TYPE_DIRECTORY)
1755         targisdir = 1;
1756
1757     if (targetshouldbedirectory && !targisdir)
1758         bump("%s: Not a directory", targ);
1759
1760     scp_sink_init();
1761     while (1) {
1762         struct scp_sink_action act;
1763         if (scp_get_sink_action(&act))
1764             return;
1765
1766         if (act.action == SCP_SINK_ENDDIR)
1767             return;
1768
1769         if (act.action == SCP_SINK_RETRY)
1770             continue;
1771
1772         if (targisdir) {
1773             /*
1774              * Prevent the remote side from maliciously writing to
1775              * files outside the target area by sending a filename
1776              * containing `../'. In fact, it shouldn't be sending
1777              * filenames with any slashes or colons in at all; so
1778              * we'll find the last slash, backslash or colon in the
1779              * filename and use only the part after that. (And
1780              * warn!)
1781              * 
1782              * In addition, we also ensure here that if we're
1783              * copying a single file and the target is a directory
1784              * (common usage: `pscp host:filename .') the remote
1785              * can't send us a _different_ file name. We can
1786              * distinguish this case because `src' will be non-NULL
1787              * and the last component of that will fail to match
1788              * (the last component of) the name sent.
1789              * 
1790              * Well, not always; if `src' is a wildcard, we do
1791              * expect to get back filenames that don't correspond
1792              * exactly to it. Ideally in this case, we would like
1793              * to ensure that the returned filename actually
1794              * matches the wildcard pattern - but one of SCP's
1795              * protocol infelicities is that wildcard matching is
1796              * done at the server end _by the server's rules_ and
1797              * so in general this is infeasible. Hence, we only
1798              * accept filenames that don't correspond to `src' if
1799              * unsafe mode is enabled or we are using SFTP (which
1800              * resolves remote wildcards on the client side and can
1801              * be trusted).
1802              */
1803             char *striptarget, *stripsrc;
1804
1805             striptarget = stripslashes(act.name, 1);
1806             if (striptarget != act.name) {
1807                 tell_user(stderr, "warning: remote host sent a compound"
1808                           " pathname '%s'", act.name);
1809                 tell_user(stderr, "         renaming local file to '%s'",
1810                           striptarget);
1811             }
1812
1813             /*
1814              * Also check to see if the target filename is '.' or
1815              * '..', or indeed '...' and so on because Windows
1816              * appears to interpret those like '..'.
1817              */
1818             if (is_dots(striptarget)) {
1819                 bump("security violation: remote host attempted to write to"
1820                      " a '.' or '..' path!");
1821             }
1822
1823             if (src) {
1824                 stripsrc = stripslashes(src, 1);
1825                 if (strcmp(striptarget, stripsrc) &&
1826                     !using_sftp && !scp_unsafe_mode) {
1827                     tell_user(stderr, "warning: remote host tried to write "
1828                               "to a file called '%s'", striptarget);
1829                     tell_user(stderr, "         when we requested a file "
1830                               "called '%s'.", stripsrc);
1831                     tell_user(stderr, "         If this is a wildcard, "
1832                               "consider upgrading to SSH-2 or using");
1833                     tell_user(stderr, "         the '-unsafe' option. Renaming"
1834                               " of this file has been disallowed.");
1835                     /* Override the name the server provided with our own. */
1836                     striptarget = stripsrc;
1837                 }
1838             }
1839
1840             if (targ[0] != '\0')
1841                 destfname = dir_file_cat(targ, striptarget);
1842             else
1843                 destfname = dupstr(striptarget);
1844         } else {
1845             /*
1846              * In this branch of the if, the target area is a
1847              * single file with an explicitly specified name in any
1848              * case, so there's no danger.
1849              */
1850             destfname = dupstr(targ);
1851         }
1852         attr = file_type(destfname);
1853         exists = (attr != FILE_TYPE_NONEXISTENT);
1854
1855         if (act.action == SCP_SINK_DIR) {
1856             if (exists && attr != FILE_TYPE_DIRECTORY) {
1857                 run_err("%s: Not a directory", destfname);
1858                 continue;
1859             }
1860             if (!exists) {
1861                 if (!create_directory(destfname)) {
1862                     run_err("%s: Cannot create directory", destfname);
1863                     continue;
1864                 }
1865             }
1866             sink(destfname, NULL);
1867             /* can we set the timestamp for directories ? */
1868             continue;
1869         }
1870
1871         f = open_new_file(destfname);
1872         if (f == NULL) {
1873             run_err("%s: Cannot create file", destfname);
1874             continue;
1875         }
1876
1877         if (scp_accept_filexfer())
1878             return;
1879
1880         stat_bytes = uint64_make(0, 0);
1881         stat_starttime = time(NULL);
1882         stat_lasttime = 0;
1883         stat_name = stripslashes(destfname, 1);
1884
1885         received = uint64_make(0, 0);
1886         while (uint64_compare(received,act.size) < 0) {
1887             char transbuf[32768];
1888             uint64 blksize;
1889             int read;
1890             blksize = uint64_make(0, 32768);
1891             if (uint64_compare(blksize,uint64_subtract(act.size,received)) > 0)
1892               blksize = uint64_subtract(act.size,received);
1893             read = scp_recv_filedata(transbuf, (int)blksize.lo);
1894             if (read <= 0)
1895                 bump("Lost connection");
1896             if (wrerror)
1897                 continue;
1898             if (write_to_file(f, transbuf, read) != (int)read) {
1899                 wrerror = 1;
1900                 /* FIXME: in sftp we can actually abort the transfer */
1901                 if (statistics)
1902                     printf("\r%-25.25s | %50s\n",
1903                            stat_name,
1904                            "Write error.. waiting for end of file");
1905                 continue;
1906             }
1907             if (statistics) {
1908                 stat_bytes = uint64_add32(stat_bytes,read);
1909                 if (time(NULL) > stat_lasttime ||
1910                     uint64_compare(uint64_add32(received, read), act.size) == 0) {
1911                     stat_lasttime = time(NULL);
1912                     print_stats(stat_name, act.size, stat_bytes,
1913                                 stat_starttime, stat_lasttime);
1914                 }
1915             }
1916             received = uint64_add32(received, read);
1917         }
1918         if (act.settime) {
1919             set_file_times(f, act.mtime, act.atime);
1920         }
1921
1922         close_wfile(f);
1923         if (wrerror) {
1924             run_err("%s: Write error", destfname);
1925             continue;
1926         }
1927         (void) scp_finish_filerecv();
1928         sfree(destfname);
1929         sfree(act.buf);
1930     }
1931 }
1932
1933 /*
1934  * We will copy local files to a remote server.
1935  */
1936 static void toremote(int argc, char *argv[])
1937 {
1938     char *src, *targ, *host, *user;
1939     char *cmd;
1940     int i, wc_type;
1941
1942     targ = argv[argc - 1];
1943
1944     /* Separate host from filename */
1945     host = targ;
1946     targ = colon(targ);
1947     if (targ == NULL)
1948         bump("targ == NULL in toremote()");
1949     *targ++ = '\0';
1950     if (*targ == '\0')
1951         targ = ".";
1952     /* Substitute "." for empty target */
1953
1954     /* Separate host and username */
1955     user = host;
1956     host = strrchr(host, '@');
1957     if (host == NULL) {
1958         host = user;
1959         user = NULL;
1960     } else {
1961         *host++ = '\0';
1962         if (*user == '\0')
1963             user = NULL;
1964     }
1965
1966     if (argc == 2) {
1967         if (colon(argv[0]) != NULL)
1968             bump("%s: Remote to remote not supported", argv[0]);
1969
1970         wc_type = test_wildcard(argv[0], 1);
1971         if (wc_type == WCTYPE_NONEXISTENT)
1972             bump("%s: No such file or directory\n", argv[0]);
1973         else if (wc_type == WCTYPE_WILDCARD)
1974             targetshouldbedirectory = 1;
1975     }
1976
1977     cmd = dupprintf("scp%s%s%s%s -t %s",
1978                     verbose ? " -v" : "",
1979                     recursive ? " -r" : "",
1980                     preserve ? " -p" : "",
1981                     targetshouldbedirectory ? " -d" : "", targ);
1982     do_cmd(host, user, cmd);
1983     sfree(cmd);
1984
1985     if (scp_source_setup(targ, targetshouldbedirectory))
1986         return;
1987
1988     for (i = 0; i < argc - 1; i++) {
1989         src = argv[i];
1990         if (colon(src) != NULL) {
1991             tell_user(stderr, "%s: Remote to remote not supported\n", src);
1992             errs++;
1993             continue;
1994         }
1995
1996         wc_type = test_wildcard(src, 1);
1997         if (wc_type == WCTYPE_NONEXISTENT) {
1998             run_err("%s: No such file or directory", src);
1999             continue;
2000         } else if (wc_type == WCTYPE_FILENAME) {
2001             source(src);
2002             continue;
2003         } else {
2004             WildcardMatcher *wc;
2005             char *filename;
2006
2007             wc = begin_wildcard_matching(src);
2008             if (wc == NULL) {
2009                 run_err("%s: No such file or directory", src);
2010                 continue;
2011             }
2012
2013             while ((filename = wildcard_get_filename(wc)) != NULL) {
2014                 source(filename);
2015                 sfree(filename);
2016             }
2017
2018             finish_wildcard_matching(wc);
2019         }
2020     }
2021 }
2022
2023 /*
2024  *  We will copy files from a remote server to the local machine.
2025  */
2026 static void tolocal(int argc, char *argv[])
2027 {
2028     char *src, *targ, *host, *user;
2029     char *cmd;
2030
2031     if (argc != 2)
2032         bump("More than one remote source not supported");
2033
2034     src = argv[0];
2035     targ = argv[1];
2036
2037     /* Separate host from filename */
2038     host = src;
2039     src = colon(src);
2040     if (src == NULL)
2041         bump("Local to local copy not supported");
2042     *src++ = '\0';
2043     if (*src == '\0')
2044         src = ".";
2045     /* Substitute "." for empty filename */
2046
2047     /* Separate username and hostname */
2048     user = host;
2049     host = strrchr(host, '@');
2050     if (host == NULL) {
2051         host = user;
2052         user = NULL;
2053     } else {
2054         *host++ = '\0';
2055         if (*user == '\0')
2056             user = NULL;
2057     }
2058
2059     cmd = dupprintf("scp%s%s%s%s -f %s",
2060                     verbose ? " -v" : "",
2061                     recursive ? " -r" : "",
2062                     preserve ? " -p" : "",
2063                     targetshouldbedirectory ? " -d" : "", src);
2064     do_cmd(host, user, cmd);
2065     sfree(cmd);
2066
2067     if (scp_sink_setup(src, preserve, recursive))
2068         return;
2069
2070     sink(targ, src);
2071 }
2072
2073 /*
2074  *  We will issue a list command to get a remote directory.
2075  */
2076 static void get_dir_list(int argc, char *argv[])
2077 {
2078     char *src, *host, *user;
2079     char *cmd, *p, *q;
2080     char c;
2081
2082     src = argv[0];
2083
2084     /* Separate host from filename */
2085     host = src;
2086     src = colon(src);
2087     if (src == NULL)
2088         bump("Local to local copy not supported");
2089     *src++ = '\0';
2090     if (*src == '\0')
2091         src = ".";
2092     /* Substitute "." for empty filename */
2093
2094     /* Separate username and hostname */
2095     user = host;
2096     host = strrchr(host, '@');
2097     if (host == NULL) {
2098         host = user;
2099         user = NULL;
2100     } else {
2101         *host++ = '\0';
2102         if (*user == '\0')
2103             user = NULL;
2104     }
2105
2106     cmd = snewn(4 * strlen(src) + 100, char);
2107     strcpy(cmd, "ls -la '");
2108     p = cmd + strlen(cmd);
2109     for (q = src; *q; q++) {
2110         if (*q == '\'') {
2111             *p++ = '\'';
2112             *p++ = '\\';
2113             *p++ = '\'';
2114             *p++ = '\'';
2115         } else {
2116             *p++ = *q;
2117         }
2118     }
2119     *p++ = '\'';
2120     *p = '\0';
2121
2122     do_cmd(host, user, cmd);
2123     sfree(cmd);
2124
2125     if (using_sftp) {
2126         scp_sftp_listdir(src);
2127     } else {
2128         while (ssh_scp_recv((unsigned char *) &c, 1) > 0)
2129             tell_char(stdout, c);
2130     }
2131 }
2132
2133 /*
2134  *  Short description of parameters.
2135  */
2136 static void usage(void)
2137 {
2138     printf("PuTTY Secure Copy client\n");
2139     printf("%s\n", ver);
2140     printf("Usage: pscp [options] [user@]host:source target\n");
2141     printf
2142         ("       pscp [options] source [source...] [user@]host:target\n");
2143     printf("       pscp [options] -ls [user@]host:filespec\n");
2144     printf("Options:\n");
2145     printf("  -V        print version information and exit\n");
2146     printf("  -pgpfp    print PGP key fingerprints and exit\n");
2147     printf("  -p        preserve file attributes\n");
2148     printf("  -q        quiet, don't show statistics\n");
2149     printf("  -r        copy directories recursively\n");
2150     printf("  -v        show verbose messages\n");
2151     printf("  -load sessname  Load settings from saved session\n");
2152     printf("  -P port   connect to specified port\n");
2153     printf("  -l user   connect with specified username\n");
2154     printf("  -pw passw login with specified password\n");
2155     printf("  -1 -2     force use of particular SSH protocol version\n");
2156     printf("  -4 -6     force use of IPv4 or IPv6\n");
2157     printf("  -C        enable compression\n");
2158     printf("  -i key    private key file for authentication\n");
2159     printf("  -noagent  disable use of Pageant\n");
2160     printf("  -agent    enable use of Pageant\n");
2161     printf("  -batch    disable all interactive prompts\n");
2162     printf("  -unsafe   allow server-side wildcards (DANGEROUS)\n");
2163     printf("  -sftp     force use of SFTP protocol\n");
2164     printf("  -scp      force use of SCP protocol\n");
2165 #if 0
2166     /*
2167      * -gui is an internal option, used by GUI front ends to get
2168      * pscp to pass progress reports back to them. It's not an
2169      * ordinary user-accessible option, so it shouldn't be part of
2170      * the command-line help. The only people who need to know
2171      * about it are programmers, and they can read the source.
2172      */
2173     printf
2174         ("  -gui hWnd GUI mode with the windows handle for receiving messages\n");
2175 #endif
2176     cleanup_exit(1);
2177 }
2178
2179 void version(void)
2180 {
2181     printf("pscp: %s\n", ver);
2182     cleanup_exit(1);
2183 }
2184
2185 void cmdline_error(char *p, ...)
2186 {
2187     va_list ap;
2188     fprintf(stderr, "pscp: ");
2189     va_start(ap, p);
2190     vfprintf(stderr, p, ap);
2191     va_end(ap);
2192     fprintf(stderr, "\n      try typing just \"pscp\" for help\n");
2193     exit(1);
2194 }
2195
2196 /*
2197  * Main program. (Called `psftp_main' because it gets called from
2198  * *sftp.c; bit silly, I know, but it had to be called _something_.)
2199  */
2200 int psftp_main(int argc, char *argv[])
2201 {
2202     int i;
2203
2204     default_protocol = PROT_TELNET;
2205
2206     flags = FLAG_STDERR
2207 #ifdef FLAG_SYNCAGENT
2208         | FLAG_SYNCAGENT
2209 #endif
2210         ;
2211     cmdline_tooltype = TOOLTYPE_FILETRANSFER;
2212     sk_init();
2213
2214     /* Load Default Settings before doing anything else. */
2215     do_defaults(NULL, &cfg);
2216     loaded_session = FALSE;
2217
2218     for (i = 1; i < argc; i++) {
2219         int ret;
2220         if (argv[i][0] != '-')
2221             break;
2222         ret = cmdline_process_param(argv[i], i+1<argc?argv[i+1]:NULL, 1, &cfg);
2223         if (ret == -2) {
2224             cmdline_error("option \"%s\" requires an argument", argv[i]);
2225         } else if (ret == 2) {
2226             i++;               /* skip next argument */
2227         } else if (ret == 1) {
2228             /* We have our own verbosity in addition to `flags'. */
2229             if (flags & FLAG_VERBOSE)
2230                 verbose = 1;
2231         } else if (strcmp(argv[i], "-pgpfp") == 0) {
2232             pgp_fingerprints();
2233             return 1;
2234         } else if (strcmp(argv[i], "-r") == 0) {
2235             recursive = 1;
2236         } else if (strcmp(argv[i], "-p") == 0) {
2237             preserve = 1;
2238         } else if (strcmp(argv[i], "-q") == 0) {
2239             statistics = 0;
2240         } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-?") == 0) {
2241             usage();
2242         } else if (strcmp(argv[i], "-V") == 0) {
2243             version();
2244         } else if (strcmp(argv[i], "-ls") == 0) {
2245             list = 1;
2246         } else if (strcmp(argv[i], "-batch") == 0) {
2247             console_batch_mode = 1;
2248         } else if (strcmp(argv[i], "-unsafe") == 0) {
2249             scp_unsafe_mode = 1;
2250         } else if (strcmp(argv[i], "-sftp") == 0) {
2251             try_scp = 0; try_sftp = 1;
2252         } else if (strcmp(argv[i], "-scp") == 0) {
2253             try_scp = 1; try_sftp = 0;
2254         } else if (strcmp(argv[i], "--") == 0) {
2255             i++;
2256             break;
2257         } else {
2258             cmdline_error("unknown option \"%s\"", argv[i]);
2259         }
2260     }
2261     argc -= i;
2262     argv += i;
2263     back = NULL;
2264
2265     if (list) {
2266         if (argc != 1)
2267             usage();
2268         get_dir_list(argc, argv);
2269
2270     } else {
2271
2272         if (argc < 2)
2273             usage();
2274         if (argc > 2)
2275             targetshouldbedirectory = 1;
2276
2277         if (colon(argv[argc - 1]) != NULL)
2278             toremote(argc, argv);
2279         else
2280             tolocal(argc, argv);
2281     }
2282
2283     if (back != NULL && back->connected(backhandle)) {
2284         char ch;
2285         back->special(backhandle, TS_EOF);
2286         ssh_scp_recv((unsigned char *) &ch, 1);
2287     }
2288     random_save_seed();
2289
2290     cmdline_cleanup();
2291     console_provide_logctx(NULL);
2292     back->free(backhandle);
2293     backhandle = NULL;
2294     back = NULL;
2295     sk_cleanup();
2296     return (errs == 0 ? 0 : 1);
2297 }
2298
2299 /* end */