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