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