7c10c08758318ebe850fe1cdc7ac59fc816ab1bd
2 * psftp.c: front end for PSFTP.
12 #define PUTTY_DO_GLOBALS
20 * Since SFTP is a request-response oriented protocol, it requires
21 * no buffer management: when we send data, we stop and wait for an
22 * acknowledgement _anyway_, and so we can't possibly overfill our
26 /* ----------------------------------------------------------------------
27 * String handling routines.
33 char *p
= smalloc(len
+ 1);
38 /* Allocate the concatenation of N strings. Terminate arg list with NULL. */
39 char *dupcat(char *s1
, ...)
48 sn
= va_arg(ap
, char *);
61 sn
= va_arg(ap
, char *);
72 /* ----------------------------------------------------------------------
78 /* ----------------------------------------------------------------------
79 * Higher-level helper functions used in commands.
83 * Attempt to canonify a pathname starting from the pwd. If
84 * canonification fails, at least fall back to returning a _valid_
85 * pathname (though it may be ugly, eg /home/simon/../foobar).
87 char *canonify(char *name
)
89 char *fullname
, *canonname
;
92 fullname
= dupstr(name
);
95 if (pwd
[strlen(pwd
) - 1] == '/')
99 fullname
= dupcat(pwd
, slash
, name
, NULL
);
102 canonname
= fxp_realpath(fullname
);
109 * Attempt number 2. Some FXP_REALPATH implementations
110 * (glibc-based ones, in particular) require the _whole_
111 * path to point to something that exists, whereas others
112 * (BSD-based) only require all but the last component to
113 * exist. So if the first call failed, we should strip off
114 * everything from the last slash onwards and try again,
115 * then put the final component back on.
119 * - if the last component is "/." or "/..", then we don't
120 * bother trying this because there's no way it can work.
122 * - if the thing actually ends with a "/", we remove it
123 * before we start. Except if the string is "/" itself
124 * (although I can't see why we'd have got here if so,
125 * because surely "/" would have worked the first
126 * time?), in which case we don't bother.
128 * - if there's no slash in the string at all, give up in
129 * confusion (we expect at least one because of the way
130 * we constructed the string).
136 i
= strlen(fullname
);
137 if (i
> 2 && fullname
[i
- 1] == '/')
138 fullname
[--i
] = '\0'; /* strip trailing / unless at pos 0 */
139 while (i
> 0 && fullname
[--i
] != '/');
142 * Give up on special cases.
144 if (fullname
[i
] != '/' || /* no slash at all */
145 !strcmp(fullname
+ i
, "/.") || /* ends in /. */
146 !strcmp(fullname
+ i
, "/..") || /* ends in /.. */
147 !strcmp(fullname
, "/")) {
152 * Now i points at the slash. Deal with the final special
153 * case i==0 (ie the whole path was "/nonexistentfile").
155 fullname
[i
] = '\0'; /* separate the string */
157 canonname
= fxp_realpath("/");
159 canonname
= fxp_realpath(fullname
);
163 return fullname
; /* even that failed; give up */
166 * We have a canonical name for all but the last path
167 * component. Concatenate the last component and return.
169 returnname
= dupcat(canonname
,
170 canonname
[strlen(canonname
) - 1] ==
171 '/' ?
"" : "/", fullname
+ i
+ 1, NULL
);
178 /* ----------------------------------------------------------------------
179 * Actual sftp commands.
181 struct sftp_command
{
183 int nwords
, wordssize
;
184 int (*obey
) (struct sftp_command
*); /* returns <0 to quit */
187 int sftp_cmd_null(struct sftp_command
*cmd
)
192 int sftp_cmd_unknown(struct sftp_command
*cmd
)
194 printf("psftp: unknown command \"%s\"\n", cmd
->words
[0]);
198 int sftp_cmd_quit(struct sftp_command
*cmd
)
204 * List a directory. If no arguments are given, list pwd; otherwise
205 * list the directory given in words[1].
207 static int sftp_ls_compare(const void *av
, const void *bv
)
209 const struct fxp_name
*a
= (const struct fxp_name
*) av
;
210 const struct fxp_name
*b
= (const struct fxp_name
*) bv
;
211 return strcmp(a
->filename
, b
->filename
);
213 int sftp_cmd_ls(struct sftp_command
*cmd
)
215 struct fxp_handle
*dirh
;
216 struct fxp_names
*names
;
217 struct fxp_name
*ournames
;
218 int nnames
, namesize
;
227 cdir
= canonify(dir
);
229 printf("%s: %s\n", dir
, fxp_error());
233 printf("Listing directory %s\n", cdir
);
235 dirh
= fxp_opendir(cdir
);
237 printf("Unable to open %s: %s\n", dir
, fxp_error());
239 nnames
= namesize
= 0;
244 names
= fxp_readdir(dirh
);
246 if (fxp_error_type() == SSH_FX_EOF
)
248 printf("Reading directory %s: %s\n", dir
, fxp_error());
251 if (names
->nnames
== 0) {
252 fxp_free_names(names
);
256 if (nnames
+ names
->nnames
>= namesize
) {
257 namesize
+= names
->nnames
+ 128;
259 srealloc(ournames
, namesize
* sizeof(*ournames
));
262 for (i
= 0; i
< names
->nnames
; i
++)
263 ournames
[nnames
++] = names
->names
[i
];
265 names
->nnames
= 0; /* prevent free_names */
266 fxp_free_names(names
);
271 * Now we have our filenames. Sort them by actual file
272 * name, and then output the longname parts.
274 qsort(ournames
, nnames
, sizeof(*ournames
), sftp_ls_compare
);
279 for (i
= 0; i
< nnames
; i
++)
280 printf("%s\n", ournames
[i
].longname
);
289 * Change directories. We do this by canonifying the new name, then
290 * trying to OPENDIR it. Only if that succeeds do we set the new pwd.
292 int sftp_cmd_cd(struct sftp_command
*cmd
)
294 struct fxp_handle
*dirh
;
298 dir
= dupstr(homedir
);
300 dir
= canonify(cmd
->words
[1]);
303 printf("%s: %s\n", dir
, fxp_error());
307 dirh
= fxp_opendir(dir
);
309 printf("Directory %s: %s\n", dir
, fxp_error());
318 printf("Remote directory is now %s\n", pwd
);
324 * Get a file and save it at the local end.
326 int sftp_cmd_get(struct sftp_command
*cmd
)
328 struct fxp_handle
*fh
;
329 char *fname
, *outfname
;
333 if (cmd
->nwords
< 2) {
334 printf("get: expects a filename\n");
338 fname
= canonify(cmd
->words
[1]);
340 printf("%s: %s\n", cmd
->words
[1], fxp_error());
343 outfname
= (cmd
->nwords
== 2 ? cmd
->words
[1] : cmd
->words
[2]);
345 fh
= fxp_open(fname
, SSH_FXF_READ
);
347 printf("%s: %s\n", fname
, fxp_error());
351 fp
= fopen(outfname
, "wb");
353 printf("local: unable to open %s\n", outfname
);
359 printf("remote:%s => local:%s\n", fname
, outfname
);
361 offset
= uint64_make(0, 0);
364 * FIXME: we can use FXP_FSTAT here to get the file size, and
365 * thus put up a progress bar.
372 len
= fxp_read(fh
, buffer
, offset
, sizeof(buffer
));
373 if ((len
== -1 && fxp_error_type() == SSH_FX_EOF
) || len
== 0)
376 printf("error while reading: %s\n", fxp_error());
382 wlen
= fwrite(buffer
, 1, len
- wpos
, fp
);
384 printf("error while writing local file\n");
389 if (wpos
< len
) /* we had an error */
391 offset
= uint64_add32(offset
, len
);
402 * Send a file and store it at the remote end.
404 int sftp_cmd_put(struct sftp_command
*cmd
)
406 struct fxp_handle
*fh
;
407 char *fname
, *origoutfname
, *outfname
;
411 if (cmd
->nwords
< 2) {
412 printf("put: expects a filename\n");
416 fname
= cmd
->words
[1];
417 origoutfname
= (cmd
->nwords
== 2 ? cmd
->words
[1] : cmd
->words
[2]);
418 outfname
= canonify(origoutfname
);
420 printf("%s: %s\n", origoutfname
, fxp_error());
424 fp
= fopen(fname
, "rb");
426 printf("local: unable to open %s\n", fname
);
430 fh
= fxp_open(outfname
, SSH_FXF_WRITE
| SSH_FXF_CREAT
| SSH_FXF_TRUNC
);
432 printf("%s: %s\n", outfname
, fxp_error());
437 printf("local:%s => remote:%s\n", fname
, outfname
);
439 offset
= uint64_make(0, 0);
442 * FIXME: we can use FXP_FSTAT here to get the file size, and
443 * thus put up a progress bar.
449 len
= fread(buffer
, 1, sizeof(buffer
), fp
);
451 printf("error while reading local file\n");
453 } else if (len
== 0) {
456 if (!fxp_write(fh
, buffer
, offset
, len
)) {
457 printf("error while writing: %s\n", fxp_error());
460 offset
= uint64_add32(offset
, len
);
470 int sftp_cmd_mkdir(struct sftp_command
*cmd
)
476 if (cmd
->nwords
< 2) {
477 printf("mkdir: expects a directory\n");
481 dir
= canonify(cmd
->words
[1]);
483 printf("%s: %s\n", dir
, fxp_error());
487 result
= fxp_mkdir(dir
);
489 printf("mkdir %s: %s\n", dir
, fxp_error());
499 int sftp_cmd_rmdir(struct sftp_command
*cmd
)
505 if (cmd
->nwords
< 2) {
506 printf("rmdir: expects a directory\n");
510 dir
= canonify(cmd
->words
[1]);
512 printf("%s: %s\n", dir
, fxp_error());
516 result
= fxp_rmdir(dir
);
518 printf("rmdir %s: %s\n", dir
, fxp_error());
528 int sftp_cmd_rm(struct sftp_command
*cmd
)
534 if (cmd
->nwords
< 2) {
535 printf("rm: expects a filename\n");
539 fname
= canonify(cmd
->words
[1]);
541 printf("%s: %s\n", fname
, fxp_error());
545 result
= fxp_rm(fname
);
547 printf("rm %s: %s\n", fname
, fxp_error());
558 static struct sftp_cmd_lookup
{
560 int (*obey
) (struct sftp_command
*);
563 * List of sftp commands. This is binary-searched so it MUST be
567 "bye", sftp_cmd_quit
}, {
568 "cd", sftp_cmd_cd
}, {
569 "dir", sftp_cmd_ls
}, {
570 "exit", sftp_cmd_quit
}, {
571 "get", sftp_cmd_get
}, {
572 "ls", sftp_cmd_ls
}, {
573 "mkdir", sftp_cmd_mkdir
}, {
574 "put", sftp_cmd_put
}, {
575 "quit", sftp_cmd_quit
}, {
576 "rm", sftp_cmd_rm
}, {
577 "rmdir", sftp_cmd_rmdir
},};
579 /* ----------------------------------------------------------------------
580 * Command line reading and parsing.
582 struct sftp_command
*sftp_getcmd(FILE *fp
, int mode
, int modeflags
)
585 int linelen
, linesize
;
586 struct sftp_command
*cmd
;
590 if ((mode
== 0) || (modeflags
& 1)) {
595 cmd
= smalloc(sizeof(struct sftp_command
));
601 linesize
= linelen
= 0;
607 line
= srealloc(line
, linesize
);
608 ret
= fgets(line
+ linelen
, linesize
- linelen
, fp
);
613 if (!ret
|| (linelen
== 0 && line
[0] == '\0')) {
614 cmd
->obey
= sftp_cmd_quit
;
616 return cmd
; /* eof */
618 len
= linelen
+ strlen(line
+ linelen
);
620 if (line
[linelen
- 1] == '\n') {
622 line
[linelen
] = '\0';
628 * Parse the command line into words. The syntax is:
629 * - double quotes are removed, but cause spaces within to be
630 * treated as non-separating.
631 * - a double-doublequote pair is a literal double quote, inside
632 * _or_ outside quotes. Like this:
634 * firstword "second word" "this has ""quotes"" in" sodoes""this""
640 * >this has "quotes" in<
645 /* skip whitespace */
646 while (*p
&& (*p
== ' ' || *p
== '\t'))
648 /* mark start of word */
649 q
= r
= p
; /* q sits at start, r writes word */
652 if (!quoting
&& (*p
== ' ' || *p
== '\t'))
653 break; /* reached end of word */
654 else if (*p
== '"' && p
[1] == '"')
655 p
+= 2, *r
++ = '"'; /* a literal quote */
657 p
++, quoting
= !quoting
;
662 p
++; /* skip over the whitespace */
664 if (cmd
->nwords
>= cmd
->wordssize
) {
665 cmd
->wordssize
= cmd
->nwords
+ 16;
667 srealloc(cmd
->words
, cmd
->wordssize
* sizeof(char *));
669 cmd
->words
[cmd
->nwords
++] = q
;
673 * Now parse the first word and assign a function.
676 if (cmd
->nwords
== 0)
677 cmd
->obey
= sftp_cmd_null
;
681 cmd
->obey
= sftp_cmd_unknown
;
684 j
= sizeof(sftp_lookup
) / sizeof(*sftp_lookup
);
687 cmp
= strcmp(cmd
->words
[0], sftp_lookup
[k
].name
);
693 cmd
->obey
= sftp_lookup
[k
].obey
;
702 void do_sftp(int mode
, int modeflags
, char *batchfile
)
707 * Do protocol initialisation.
711 "Fatal: unable to initialise SFTP: %s\n", fxp_error());
716 * Find out where our home directory is.
718 homedir
= fxp_realpath(".");
721 "Warning: failed to resolve home directory: %s\n",
723 homedir
= dupstr(".");
725 printf("Remote working directory is %s\n", homedir
);
727 pwd
= dupstr(homedir
);
734 /* ------------------------------------------------------------------
735 * Now we're ready to do Real Stuff.
738 struct sftp_command
*cmd
;
739 cmd
= sftp_getcmd(stdin
, 0, 0);
742 if (cmd
->obey(cmd
) < 0)
746 fp
= fopen(batchfile
, "r");
748 printf("Fatal: unable to open %s\n", batchfile
);
752 struct sftp_command
*cmd
;
753 cmd
= sftp_getcmd(fp
, mode
, modeflags
);
756 if (cmd
->obey(cmd
) < 0)
758 if (fxp_error() != NULL
) {
759 if (!(modeflags
& 2))
768 /* ----------------------------------------------------------------------
769 * Dirty bits: integration with PuTTY.
772 static int verbose
= 0;
774 void verify_ssh_host_key(char *host
, int port
, char *keytype
,
775 char *keystr
, char *fingerprint
)
781 static const char absentmsg
[] =
782 "The server's host key is not cached in the registry. You\n"
783 "have no guarantee that the server is the computer you\n"
785 "The server's key fingerprint is:\n"
787 "If you trust this host, enter \"y\" to add the key to\n"
788 "PuTTY's cache and carry on connecting.\n"
789 "If you want to carry on connecting just once, without\n"
790 "adding the key to the cache, enter \"n\".\n"
791 "If you do not trust this host, press Return to abandon the\n"
793 "Store key in cache? (y/n) ";
795 static const char wrongmsg
[] =
796 "WARNING - POTENTIAL SECURITY BREACH!\n"
797 "The server's host key does not match the one PuTTY has\n"
798 "cached in the registry. This means that either the\n"
799 "server administrator has changed the host key, or you\n"
800 "have actually connected to another computer pretending\n"
801 "to be the server.\n"
802 "The new key fingerprint is:\n"
804 "If you were expecting this change and trust the new key,\n"
805 "enter \"y\" to update PuTTY's cache and continue connecting.\n"
806 "If you want to carry on connecting but without updating\n"
807 "the cache, enter \"n\".\n"
808 "If you want to abandon the connection completely, press\n"
809 "Return to cancel. Pressing Return is the ONLY guaranteed\n"
811 "Update cached key? (y/n, Return cancels connection) ";
813 static const char abandoned
[] = "Connection abandoned.\n";
818 * Verify the key against the registry.
820 ret
= verify_host_key(host
, port
, keytype
, keystr
);
822 if (ret
== 0) /* success - key matched OK */
825 if (ret
== 2) { /* key was different */
826 fprintf(stderr
, wrongmsg
, fingerprint
);
829 if (ret
== 1) { /* key was absent */
830 fprintf(stderr
, absentmsg
, fingerprint
);
834 hin
= GetStdHandle(STD_INPUT_HANDLE
);
835 GetConsoleMode(hin
, &savemode
);
836 SetConsoleMode(hin
, (savemode
| ENABLE_ECHO_INPUT
|
837 ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
));
838 ReadFile(hin
, line
, sizeof(line
) - 1, &i
, NULL
);
839 SetConsoleMode(hin
, savemode
);
841 if (line
[0] != '\0' && line
[0] != '\r' && line
[0] != '\n') {
842 if (line
[0] == 'y' || line
[0] == 'Y')
843 store_host_key(host
, port
, keytype
, keystr
);
845 fprintf(stderr
, abandoned
);
851 * Print an error message and perform a fatal exit.
853 void fatalbox(char *fmt
, ...)
855 char str
[0x100]; /* Make the size big enough */
858 strcpy(str
, "Fatal:");
859 vsprintf(str
+ strlen(str
), fmt
, ap
);
862 fprintf(stderr
, str
);
866 void connection_fatal(char *fmt
, ...)
868 char str
[0x100]; /* Make the size big enough */
871 strcpy(str
, "Fatal:");
872 vsprintf(str
+ strlen(str
), fmt
, ap
);
875 fprintf(stderr
, str
);
880 void logevent(char *string
)
884 void ldisc_send(char *buf
, int len
)
887 * This is only here because of the calls to ldisc_send(NULL,
888 * 0) in ssh.c. Nothing in PSFTP actually needs to use the
889 * ldisc as an ldisc. So if we get called with any real data, I
890 * want to know about it.
896 * Be told what socket we're supposed to be using.
898 static SOCKET sftp_ssh_socket
;
899 char *do_select(SOCKET skt
, int startup
)
902 sftp_ssh_socket
= skt
;
904 sftp_ssh_socket
= INVALID_SOCKET
;
907 extern int select_result(WPARAM
, LPARAM
);
910 * Receive a block of data from the SSH link. Block until all data
913 * To do this, we repeatedly call the SSH protocol module, with our
914 * own trap in from_backend() to catch the data that comes back. We
915 * do this until we have enough data.
918 static unsigned char *outptr
; /* where to put the data */
919 static unsigned outlen
; /* how much data required */
920 static unsigned char *pending
= NULL
; /* any spare data */
921 static unsigned pendlen
= 0, pendsize
= 0; /* length and phys. size of buffer */
922 int from_backend(int is_stderr
, char *data
, int datalen
)
924 unsigned char *p
= (unsigned char *) data
;
925 unsigned len
= (unsigned) datalen
;
928 * stderr data is just spouted to local stderr and otherwise
932 fwrite(data
, 1, len
, stderr
);
937 * If this is before the real session begins, just return.
943 unsigned used
= outlen
;
946 memcpy(outptr
, p
, used
);
954 if (pendsize
< pendlen
+ len
) {
955 pendsize
= pendlen
+ len
+ 4096;
956 pending
= (pending ?
srealloc(pending
, pendsize
) :
959 fatalbox("Out of memory");
961 memcpy(pending
+ pendlen
, p
, len
);
967 int sftp_recvdata(char *buf
, int len
)
969 outptr
= (unsigned char *) buf
;
973 * See if the pending-input block contains some of what we
977 unsigned pendused
= pendlen
;
978 if (pendused
> outlen
)
980 memcpy(outptr
, pending
, pendused
);
981 memmove(pending
, pending
+ pendused
, pendlen
- pendused
);
998 FD_SET(sftp_ssh_socket
, &readfds
);
999 if (select(1, &readfds
, NULL
, NULL
, NULL
) < 0)
1000 return 0; /* doom */
1001 select_result((WPARAM
) sftp_ssh_socket
, (LPARAM
) FD_READ
);
1006 int sftp_senddata(char *buf
, int len
)
1008 back
->send((unsigned char *) buf
, len
);
1013 * Loop through the ssh connection and authentication process.
1015 static void ssh_sftp_init(void)
1017 if (sftp_ssh_socket
== INVALID_SOCKET
)
1019 while (!back
->sendok()) {
1022 FD_SET(sftp_ssh_socket
, &readfds
);
1023 if (select(1, &readfds
, NULL
, NULL
, NULL
) < 0)
1025 select_result((WPARAM
) sftp_ssh_socket
, (LPARAM
) FD_READ
);
1029 static char *password
= NULL
;
1030 static int get_line(const char *prompt
, char *str
, int maxlen
, int is_pw
)
1033 DWORD savemode
, newmode
, i
;
1036 static int tried_once
= 0;
1041 strncpy(str
, password
, maxlen
);
1042 str
[maxlen
- 1] = '\0';
1048 hin
= GetStdHandle(STD_INPUT_HANDLE
);
1049 hout
= GetStdHandle(STD_OUTPUT_HANDLE
);
1050 if (hin
== INVALID_HANDLE_VALUE
|| hout
== INVALID_HANDLE_VALUE
) {
1051 fprintf(stderr
, "Cannot get standard input/output handles\n");
1055 GetConsoleMode(hin
, &savemode
);
1056 newmode
= savemode
| ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
;
1058 newmode
&= ~ENABLE_ECHO_INPUT
;
1060 newmode
|= ENABLE_ECHO_INPUT
;
1061 SetConsoleMode(hin
, newmode
);
1063 WriteFile(hout
, prompt
, strlen(prompt
), &i
, NULL
);
1064 ReadFile(hin
, str
, maxlen
- 1, &i
, NULL
);
1066 SetConsoleMode(hin
, savemode
);
1068 if ((int) i
> maxlen
)
1075 WriteFile(hout
, "\r\n", 2, &i
, NULL
);
1081 * Initialize the Win$ock driver.
1083 static void init_winsock(void)
1088 winsock_ver
= MAKEWORD(1, 1);
1089 if (WSAStartup(winsock_ver
, &wsadata
)) {
1090 fprintf(stderr
, "Unable to initialise WinSock");
1093 if (LOBYTE(wsadata
.wVersion
) != 1 || HIBYTE(wsadata
.wVersion
) != 1) {
1094 fprintf(stderr
, "WinSock version is incompatible with 1.1");
1100 * Short description of parameters.
1102 static void usage(void)
1104 printf("PuTTY Secure File Transfer (SFTP) client\n");
1105 printf("%s\n", ver
);
1106 printf("Usage: psftp [options] user@host\n");
1107 printf("Options:\n");
1108 printf(" -b file use specified batchfile\n");
1109 printf(" -bc output batchfile commands\n");
1110 printf(" -be don't stop batchfile processing if errors\n");
1111 printf(" -v show verbose messages\n");
1112 printf(" -P port connect to specified port\n");
1113 printf(" -pw passw login with specified password\n");
1118 * Main program. Parse arguments etc.
1120 int main(int argc
, char *argv
[])
1124 char *user
, *host
, *userhost
, *realhost
;
1128 char *batchfile
= NULL
;
1130 flags
= FLAG_STDERR
;
1131 ssh_get_line
= &get_line
;
1135 userhost
= user
= NULL
;
1137 for (i
= 1; i
< argc
; i
++) {
1138 if (argv
[i
][0] != '-') {
1142 userhost
= dupstr(argv
[i
]);
1143 } else if (strcmp(argv
[i
], "-v") == 0) {
1144 verbose
= 1, flags
|= FLAG_VERBOSE
;
1145 } else if (strcmp(argv
[i
], "-h") == 0 ||
1146 strcmp(argv
[i
], "-?") == 0) {
1148 } else if (strcmp(argv
[i
], "-l") == 0 && i
+ 1 < argc
) {
1150 } else if (strcmp(argv
[i
], "-P") == 0 && i
+ 1 < argc
) {
1151 portnumber
= atoi(argv
[++i
]);
1152 } else if (strcmp(argv
[i
], "-pw") == 0 && i
+ 1 < argc
) {
1153 password
= argv
[++i
];
1154 } else if (strcmp(argv
[i
], "-b") == 0 && i
+ 1 < argc
) {
1156 batchfile
= argv
[++i
];
1157 } else if (strcmp(argv
[i
], "-bc") == 0 && i
+ 1 < argc
) {
1158 modeflags
= modeflags
| 1;
1159 } else if (strcmp(argv
[i
], "-be") == 0 && i
+ 1 < argc
) {
1160 modeflags
= modeflags
| 2;
1161 } else if (strcmp(argv
[i
], "--") == 0) {
1172 if (argc
> 0 || !userhost
)
1175 /* Separate host and username */
1177 host
= strrchr(host
, '@');
1183 printf("psftp: multiple usernames specified; using \"%s\"\n",
1189 /* Try to load settings for this host */
1190 do_defaults(host
, &cfg
);
1191 if (cfg
.host
[0] == '\0') {
1192 /* No settings for this host; use defaults */
1193 do_defaults(NULL
, &cfg
);
1194 strncpy(cfg
.host
, host
, sizeof(cfg
.host
) - 1);
1195 cfg
.host
[sizeof(cfg
.host
) - 1] = '\0';
1200 if (user
!= NULL
&& user
[0] != '\0') {
1201 strncpy(cfg
.username
, user
, sizeof(cfg
.username
) - 1);
1202 cfg
.username
[sizeof(cfg
.username
) - 1] = '\0';
1204 if (!cfg
.username
[0]) {
1205 printf("login as: ");
1206 if (!fgets(cfg
.username
, sizeof(cfg
.username
), stdin
)) {
1207 fprintf(stderr
, "psftp: aborting\n");
1210 int len
= strlen(cfg
.username
);
1211 if (cfg
.username
[len
- 1] == '\n')
1212 cfg
.username
[len
- 1] = '\0';
1216 if (cfg
.protocol
!= PROT_SSH
)
1220 cfg
.port
= portnumber
;
1222 /* SFTP uses SSH2 by default always */
1225 /* Set up subsystem name. FIXME: fudge for SSH1. */
1226 strcpy(cfg
.remote_cmd
, "sftp");
1227 cfg
.ssh_subsys
= TRUE
;
1230 back
= &ssh_backend
;
1232 err
= back
->init(cfg
.host
, cfg
.port
, &realhost
);
1234 fprintf(stderr
, "ssh_init: %s", err
);
1238 if (verbose
&& realhost
!= NULL
)
1239 printf("Connected to %s\n", realhost
);
1241 do_sftp(mode
, modeflags
, batchfile
);
1243 if (back
!= NULL
&& back
->socket() != NULL
) {
1245 back
->special(TS_EOF
);
1246 sftp_recvdata(&ch
, 1);