Windows PSCP now links against winsftp.c, and scp.c is now a

platform-independent source file. Haven't yet added the extra
abstraction routines to uxsftp.c to create a Unix PSCP port, but it
shouldn't take long.
Also in this checkin, a change of semantics in platform_default_s():
now strings returned from it are expected to be dynamically allocated.

[originally from svn r3420]
This commit is contained in:
Simon Tatham 2003-08-25 13:53:41 +00:00
Родитель 66fa6f320e
Коммит bfb9b28393
10 изменённых файлов: 726 добавлений и 450 удалений

4
Recipe
Просмотреть файл

@ -139,7 +139,8 @@ putty : [G] GUITERM NONSSH WINSSH be_all WINMISC win_res.res LIBS1
puttytel : [G] GUITERM NONSSH be_nossh WINMISC win_res.res LIBS1
plink : [C] plink console NONSSH WINSSH be_all logging WINMISC
+ plink.res LIBS2
pscp : [C] scp console WINSSH be_none SFTP wildcard WINMISC scp.res LIBS1
pscp : [C] scp winsftp console WINSSH be_none SFTP wildcard WINMISC
+ scp.res LIBS1
psftp : [C] psftp winsftp console WINSSH be_none SFTP WINMISC scp.res LIBS1
pageant : [G] pageant sshrsa sshpubk sshdes sshbn sshmd5 version tree234
@ -159,6 +160,7 @@ puttytel : [X] UXTERM uxmisc misc ldisc settings pty uxsel be_nossh uxstore
plink : [U] uxplink uxcons NONSSH UXSSH be_all logging UXMISC signal ux_x11
pscp : [U] scp uxsftp uxcons UXSSH be_none SFTP wildcard UXMISC
psftp : [U] psftp uxsftp uxcons UXSSH be_none SFTP UXMISC
PuTTY : [M] terminal wcwidth ldiscucs logging be_all mac macdlg macevlog

114
psftp.h
Просмотреть файл

@ -1,6 +1,6 @@
/*
* psftp.h: interface between psftp.c and each platform-specific
* SFTP module.
* psftp.h: interface between psftp.c / scp.c and each
* platform-specific SFTP module.
*/
#ifndef PUTTY_PSFTP_H
@ -19,6 +19,13 @@ char *psftp_getcwd(void);
*/
char *psftp_lcd(char *newdir);
/*
* Retrieve file times on a local file. Must return two unsigned
* longs in POSIX time_t format.
*/
void get_file_times(char *filename, unsigned long *mtime,
unsigned long *atime);
/*
* One iteration of the PSFTP event loop: wait for network data and
* process it, once.
@ -31,4 +38,107 @@ int ssh_sftp_loop_iteration(void);
*/
int psftp_main(int argc, char *argv[]);
/*
* These functions are used by PSCP to transmit progress updates
* and error information to a GUI window managing it. This will
* probably only ever be supported on Windows, so these functions
* can safely be stubs on all other platforms.
*/
void gui_update_stats(char *name, unsigned long size,
int percentage, unsigned long elapsed,
unsigned long done, unsigned long eta,
unsigned long ratebs);
void gui_send_errcount(int list, int errs);
void gui_send_char(int is_stderr, int c);
void gui_enable(char *arg);
/*
* It's likely that a given platform's implementation of file
* transfer utilities is going to want to do things with them that
* aren't present in stdio. Hence we supply an alternative
* abstraction for file access functions.
*
* This abstraction tells you the size and access times when you
* open an existing file (platforms may choose the meaning of the
* file times if it's not clear; whatever they choose will be what
* PSCP sends to the server as mtime and atime), and lets you set
* the times when saving a new file.
*
* On the other hand, the abstraction is pretty simple: it supports
* only opening a file and reading it, or creating a file and
* writing it. (FIXME: to use this in PSFTP it will also need to
* support seeking to a starting point for restarted transfers.)
* None of this read-and-write, seeking-back-and-forth stuff.
*/
typedef struct RFile RFile;
typedef struct WFile WFile;
/* Output params size, mtime and atime can all be NULL if desired */
RFile *open_existing_file(char *name, unsigned long *size,
unsigned long *mtime, unsigned long *atime);
/* Returns <0 on error, 0 on eof, or number of bytes read, as usual */
int read_from_file(RFile *f, void *buffer, int length);
/* Closes and frees the RFile */
void close_rfile(RFile *f);
WFile *open_new_file(char *name);
/* Returns <0 on error, 0 on eof, or number of bytes written, as usual */
int write_to_file(WFile *f, void *buffer, int length);
void set_file_times(WFile *f, unsigned long mtime, unsigned long atime);
/* Closes and frees the WFile */
void close_wfile(WFile *f);
/*
* Determine the type of a file: nonexistent, file, directory or
* weird. `weird' covers anything else - named pipes, Unix sockets,
* device files, fish, badgers, you name it. Things marked `weird'
* will be skipped over in recursive file transfers, so the only
* real reason for not lumping them in with `nonexistent' is that
* it allows a slightly more sane error message.
*/
enum {
FILE_TYPE_NONEXISTENT, FILE_TYPE_FILE, FILE_TYPE_DIRECTORY, FILE_TYPE_WEIRD
};
int file_type(char *name);
/*
* Read all the file names out of a directory.
*/
typedef struct DirHandle DirHandle;
DirHandle *open_directory(char *name);
/* The string returned from this will need freeing if not NULL */
char *read_filename(DirHandle *dir);
void close_directory(DirHandle *dir);
/*
* Test a filespec to see whether it's a local wildcard or not.
* Return values:
*
* - WCTYPE_WILDCARD (this is a wildcard).
* - WCTYPE_FILENAME (this is a single file name).
* - WCTYPE_NONEXISTENT (whichever it was, nothing of that name exists).
*
* Some platforms may choose not to support local wildcards when
* they come from the command line; in this case they simply never
* return WCTYPE_WILDCARD, but still test the file's existence.
* (However, all platforms will probably want to support wildcards
* inside the PSFTP CLI.)
*/
enum {
WCTYPE_NONEXISTENT, WCTYPE_FILENAME, WCTYPE_WILDCARD
};
int test_wildcard(char *name, int cmdline);
/*
* Actually return matching file names for a local wildcard.
*/
typedef struct WildcardMatcher WildcardMatcher;
WildcardMatcher *begin_wildcard_matching(char *name);
/* The string returned from this will need freeing if not NULL */
char *wildcard_get_filename(WildcardMatcher *dir);
void finish_wildcard_matching(WildcardMatcher *dir);
/*
* Create a directory. Returns 0 on error, !=0 on success.
*/
int create_directory(char *name);
#endif /* PUTTY_PSFTP_H */

Просмотреть файл

@ -845,5 +845,6 @@ Filename filename_from_str(const char *string);
const char *filename_to_str(const Filename *fn);
int filename_equal(Filename f1, Filename f2);
int filename_is_null(Filename fn);
char *get_username(void); /* return value needs freeing */
#endif

441
scp.c
Просмотреть файл

@ -12,14 +12,6 @@
* to licensing issues.)
*/
#include <windows.h>
#ifndef AUTO_WINSOCK
#ifdef WINSOCK_TWO
#include <winsock2.h>
#else
#include <winsock.h>
#endif
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@ -29,54 +21,11 @@
#define PUTTY_DO_GLOBALS
#include "putty.h"
#include "psftp.h"
#include "ssh.h"
#include "sftp.h"
#include "winstuff.h"
#include "storage.h"
#define TIME_POSIX_TO_WIN(t, ft) (*(LONGLONG*)&(ft) = \
((LONGLONG) (t) + (LONGLONG) 11644473600) * (LONGLONG) 10000000)
#define TIME_WIN_TO_POSIX(ft, t) ((t) = (unsigned long) \
((*(LONGLONG*)&(ft)) / (LONGLONG) 10000000 - (LONGLONG) 11644473600))
/* GUI Adaptation - Sept 2000 */
/* This is just a base value from which the main message numbers are
* derived. */
#define WM_APP_BASE 0x8000
/* These two pass a single character value in wParam. They represent
* the visible output from PSCP. */
#define WM_STD_OUT_CHAR ( WM_APP_BASE+400 )
#define WM_STD_ERR_CHAR ( WM_APP_BASE+401 )
/* These pass a transfer status update. WM_STATS_CHAR passes a single
* character in wParam, and is called repeatedly to pass the name of
* the file, terminated with "\n". WM_STATS_SIZE passes the size of
* the file being transferred in wParam. WM_STATS_ELAPSED is called
* to pass the elapsed time (in seconds) in wParam, and
* WM_STATS_PERCENT passes the percentage of the transfer which is
* complete, also in wParam. */
#define WM_STATS_CHAR ( WM_APP_BASE+402 )
#define WM_STATS_SIZE ( WM_APP_BASE+403 )
#define WM_STATS_PERCENT ( WM_APP_BASE+404 )
#define WM_STATS_ELAPSED ( WM_APP_BASE+405 )
/* These are used at the end of a run to pass an error code in
* wParam: zero means success, nonzero means failure. WM_RET_ERR_CNT
* is used after a copy, and WM_LS_RET_ERR_CNT is used after a file
* list operation. */
#define WM_RET_ERR_CNT ( WM_APP_BASE+406 )
#define WM_LS_RET_ERR_CNT ( WM_APP_BASE+407 )
/* More transfer status update messages. WM_STATS_DONE passes the
* number of bytes sent so far in wParam. WM_STATS_ETA passes the
* estimated time to completion (in seconds). WM_STATS_RATEBS passes
* the average transfer rate (in bytes per second). */
#define WM_STATS_DONE ( WM_APP_BASE+408 )
#define WM_STATS_ETA ( WM_APP_BASE+409 )
#define WM_STATS_RATEBS ( WM_APP_BASE+410 )
static int list = 0;
static int verbose = 0;
static int recursive = 0;
@ -86,17 +35,7 @@ static int statistics = 1;
static int prev_stats_len = 0;
static int scp_unsafe_mode = 0;
static int errs = 0;
/* GUI Adaptation - Sept 2000 */
#define NAME_STR_MAX 2048
static char statname[NAME_STR_MAX + 1];
static unsigned long statsize = 0;
static unsigned long statdone = 0;
static unsigned long stateta = 0;
static unsigned long statratebs = 0;
static int statperct = 0;
static unsigned long statelapsed = 0;
static int gui_mode = 0;
static char *gui_hwnd = NULL;
static int using_sftp = 0;
static Backend *back;
@ -106,14 +45,6 @@ static Config cfg;
static void source(char *src);
static void rsource(char *src);
static void sink(char *targ, char *src);
/* GUI Adaptation - Sept 2000 */
static void tell_char(FILE * stream, char c);
static void tell_str(FILE * stream, char *str);
static void tell_user(FILE * stream, char *fmt, ...);
static void gui_update_stats(char *name, unsigned long size,
int percentage, unsigned long elapsed,
unsigned long done, unsigned long eta,
unsigned long ratebs);
/*
* The maximum amount of queued data we accept before we stop and
@ -132,23 +63,12 @@ void ldisc_send(void *handle, char *buf, int len, int interactive)
assert(len == 0);
}
/* GUI Adaptation - Sept 2000 */
static void send_msg(HWND h, UINT message, WPARAM wParam)
{
while (!PostMessage(h, message, wParam, 0))
SleepEx(1000, TRUE);
}
static void tell_char(FILE * stream, char c)
{
if (!gui_mode)
fputc(c, stream);
else {
unsigned int msg_id = WM_STD_OUT_CHAR;
if (stream == stderr)
msg_id = WM_STD_ERR_CHAR;
send_msg((HWND) atoi(gui_hwnd), msg_id, (WPARAM) c);
}
else
gui_send_char(stream == stderr, c);
}
static void tell_str(FILE * stream, char *str)
@ -172,48 +92,6 @@ static void tell_user(FILE * stream, char *fmt, ...)
sfree(str2);
}
static void gui_update_stats(char *name, unsigned long size,
int percentage, unsigned long elapsed,
unsigned long done, unsigned long eta,
unsigned long ratebs)
{
unsigned int i;
if (strcmp(name, statname) != 0) {
for (i = 0; i < strlen(name); ++i)
send_msg((HWND) atoi(gui_hwnd), WM_STATS_CHAR,
(WPARAM) name[i]);
send_msg((HWND) atoi(gui_hwnd), WM_STATS_CHAR, (WPARAM) '\n');
strcpy(statname, name);
}
if (statsize != size) {
send_msg((HWND) atoi(gui_hwnd), WM_STATS_SIZE, (WPARAM) size);
statsize = size;
}
if (statdone != done) {
send_msg((HWND) atoi(gui_hwnd), WM_STATS_DONE, (WPARAM) done);
statdone = done;
}
if (stateta != eta) {
send_msg((HWND) atoi(gui_hwnd), WM_STATS_ETA, (WPARAM) eta);
stateta = eta;
}
if (statratebs != ratebs) {
send_msg((HWND) atoi(gui_hwnd), WM_STATS_RATEBS, (WPARAM) ratebs);
statratebs = ratebs;
}
if (statelapsed != elapsed) {
send_msg((HWND) atoi(gui_hwnd), WM_STATS_ELAPSED,
(WPARAM) elapsed);
statelapsed = elapsed;
}
if (statperct != percentage) {
send_msg((HWND) atoi(gui_hwnd), WM_STATS_PERCENT,
(WPARAM) percentage);
statperct = percentage;
}
}
/*
* Print an error message and perform a fatal exit.
*/
@ -230,14 +108,8 @@ void fatalbox(char *fmt, ...)
sfree(str2);
errs++;
if (gui_mode) {
unsigned int msg_id = WM_RET_ERR_CNT;
if (list)
msg_id = WM_LS_RET_ERR_CNT;
while (!PostMessage
((HWND) atoi(gui_hwnd), msg_id, (WPARAM) errs,
0 /*lParam */ ))SleepEx(1000, TRUE);
}
if (gui_mode)
gui_send_errcount(list, errs);
cleanup_exit(1);
}
@ -254,14 +126,8 @@ void modalfatalbox(char *fmt, ...)
sfree(str2);
errs++;
if (gui_mode) {
unsigned int msg_id = WM_RET_ERR_CNT;
if (list)
msg_id = WM_LS_RET_ERR_CNT;
while (!PostMessage
((HWND) atoi(gui_hwnd), msg_id, (WPARAM) errs,
0 /*lParam */ ))SleepEx(1000, TRUE);
}
if (gui_mode)
gui_send_errcount(list, errs);
cleanup_exit(1);
}
@ -278,32 +144,12 @@ void connection_fatal(void *frontend, char *fmt, ...)
sfree(str2);
errs++;
if (gui_mode) {
unsigned int msg_id = WM_RET_ERR_CNT;
if (list)
msg_id = WM_LS_RET_ERR_CNT;
while (!PostMessage
((HWND) atoi(gui_hwnd), msg_id, (WPARAM) errs,
0 /*lParam */ ))SleepEx(1000, TRUE);
}
if (gui_mode)
gui_send_errcount(list, errs);
cleanup_exit(1);
}
/*
* Be told what socket we're supposed to be using.
*/
static SOCKET scp_ssh_socket;
char *do_select(SOCKET skt, int startup)
{
if (startup)
scp_ssh_socket = skt;
else
scp_ssh_socket = INVALID_SOCKET;
return NULL;
}
extern int select_result(WPARAM, LPARAM);
/*
* In pscp, all agent requests should be synchronous, so this is a
* never-called stub.
@ -373,17 +219,6 @@ int from_backend(void *frontend, int is_stderr, const char *data, int datalen)
return 0;
}
static int scp_process_network_event(void)
{
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(scp_ssh_socket, &readfds);
if (select(1, &readfds, NULL, NULL, NULL) < 0)
return 0; /* doom */
select_result((WPARAM) scp_ssh_socket, (LPARAM) FD_READ);
return 1;
}
static int ssh_scp_recv(unsigned char *buf, int len)
{
outptr = buf;
@ -412,7 +247,7 @@ static int ssh_scp_recv(unsigned char *buf, int len)
}
while (outlen > 0) {
if (!scp_process_network_event())
if (ssh_sftp_loop_iteration() < 0)
return 0; /* doom */
}
@ -424,15 +259,9 @@ static int ssh_scp_recv(unsigned char *buf, int len)
*/
static void ssh_scp_init(void)
{
if (scp_ssh_socket == INVALID_SOCKET)
return;
while (!back->sendok(backhandle)) {
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(scp_ssh_socket, &readfds);
if (select(1, &readfds, NULL, NULL, NULL) < 0)
if (ssh_sftp_loop_iteration() < 0)
return; /* doom */
select_result((WPARAM) scp_ssh_socket, (LPARAM) FD_READ);
}
using_sftp = !ssh_fallback_cmd(backhandle);
if (verbose) {
@ -465,14 +294,8 @@ static void bump(char *fmt, ...)
ssh_scp_recv(&ch, 1);
}
if (gui_mode) {
unsigned int msg_id = WM_RET_ERR_CNT;
if (list)
msg_id = WM_LS_RET_ERR_CNT;
while (!PostMessage
((HWND) atoi(gui_hwnd), msg_id, (WPARAM) errs,
0 /*lParam */ ))SleepEx(1000, TRUE);
}
if (gui_mode)
gui_send_errcount(list, errs);
cleanup_exit(1);
}
@ -484,7 +307,7 @@ static void do_cmd(char *host, char *user, char *cmd)
{
const char *err;
char *realhost;
DWORD namelen;
void *logctx;
if (host == NULL || host[0] == '\0')
bump("Empty host name");
@ -558,16 +381,16 @@ static void do_cmd(char *host, char *user, char *cmd)
strncpy(cfg.username, user, sizeof(cfg.username) - 1);
cfg.username[sizeof(cfg.username) - 1] = '\0';
} else if (cfg.username[0] == '\0') {
namelen = 0;
if (GetUserName(user, &namelen) == FALSE)
user = get_username();
if (!user)
bump("Empty user name");
user = snewn(namelen, char);
GetUserName(user, &namelen);
if (verbose)
tell_user(stderr, "Guessing user name: %s", user);
strncpy(cfg.username, user, sizeof(cfg.username) - 1);
cfg.username[sizeof(cfg.username) - 1] = '\0';
free(user);
else {
if (verbose)
tell_user(stderr, "Guessing user name: %s", user);
strncpy(cfg.username, user, sizeof(cfg.username) - 1);
cfg.username[sizeof(cfg.username) - 1] = '\0';
sfree(user);
}
}
/*
@ -632,11 +455,10 @@ static void print_stats(char *name, unsigned long size, unsigned long done,
pct = (int) (100 * (done * 1.0 / size));
if (gui_mode)
/* GUI Adaptation - Sept 2000 */
if (gui_mode) {
gui_update_stats(name, size, pct, elap, done, eta,
(unsigned long) ratebs);
else {
} else {
len = printf("\r%-25.25s | %10ld kB | %5.1f kB/s | ETA: %8s | %3d%%",
name, done / 1024, ratebs / 1024.0, etastr, pct);
if (len < prev_stats_len)
@ -991,7 +813,7 @@ int scp_send_filedata(char *data, int len)
* we have space in the buffer again.
*/
while (bufsize > MAX_SCP_BUFSIZE) {
if (!scp_process_network_event())
if (ssh_sftp_loop_iteration() < 0)
return 1;
bufsize = back->sendbuffer(backhandle);
}
@ -1645,20 +1467,23 @@ static void run_err(const char *fmt, ...)
static void source(char *src)
{
unsigned long size;
unsigned long mtime, atime;
char *last;
HANDLE f;
DWORD attr;
RFile *f;
int attr;
unsigned long i;
unsigned long stat_bytes;
time_t stat_starttime, stat_lasttime;
attr = GetFileAttributes(src);
if (attr == (DWORD) - 1) {
run_err("%s: No such file or directory", src);
attr = file_type(src);
if (attr == FILE_TYPE_NONEXISTENT ||
attr == FILE_TYPE_WEIRD) {
run_err("%s: %s file or directory", src,
(attr == FILE_TYPE_WEIRD ? "Not a" : "No such"));
return;
}
if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
if (attr == FILE_TYPE_DIRECTORY) {
if (recursive) {
/*
* Avoid . and .. directories.
@ -1690,24 +1515,16 @@ static void source(char *src)
if (last == src && strchr(src, ':') != NULL)
last = strchr(src, ':') + 1;
f = CreateFile(src, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, 0);
if (f == INVALID_HANDLE_VALUE) {
f = open_existing_file(src, &size, &mtime, &atime);
if (f == NULL) {
run_err("%s: Cannot open file", src);
return;
}
if (preserve) {
FILETIME actime, wrtime;
unsigned long mtime, atime;
GetFileTime(f, NULL, &actime, &wrtime);
TIME_WIN_TO_POSIX(actime, atime);
TIME_WIN_TO_POSIX(wrtime, mtime);
if (scp_send_filetimes(mtime, atime))
return;
}
size = GetFileSize(f, NULL);
if (verbose)
tell_user(stderr, "Sending file %s, size=%lu", last, size);
if (scp_send_filename(last, size, 0644))
@ -1719,11 +1536,11 @@ static void source(char *src)
for (i = 0; i < size; i += 4096) {
char transbuf[4096];
DWORD j, k = 4096;
int j, k = 4096;
if (i + k > size)
k = size - i;
if (!ReadFile(f, transbuf, k, &j, NULL) || j != k) {
if ((j = read_from_file(f, transbuf, k)) != k) {
if (statistics)
printf("\n");
bump("%s: Read error", src);
@ -1741,7 +1558,7 @@ static void source(char *src)
}
}
CloseHandle(f);
close_rfile(f);
(void) scp_send_finish();
}
@ -1751,11 +1568,9 @@ static void source(char *src)
*/
static void rsource(char *src)
{
char *last, *findfile;
char *last;
char *save_target;
HANDLE dir;
WIN32_FIND_DATA fdat;
int ok;
DirHandle *dir;
if ((last = strrchr(src, '/')) == NULL)
last = src;
@ -1775,22 +1590,17 @@ static void rsource(char *src)
if (scp_send_dirname(last, 0755))
return;
findfile = dupcat(src, "/*", NULL);
dir = FindFirstFile(findfile, &fdat);
ok = (dir != INVALID_HANDLE_VALUE);
while (ok) {
if (strcmp(fdat.cFileName, ".") == 0 ||
strcmp(fdat.cFileName, "..") == 0) {
/* ignore . and .. */
} else {
char *foundfile = dupcat(src, "/", fdat.cFileName, NULL);
dir = open_directory(src);
if (dir != NULL) {
char *filename;
while ((filename = read_filename(dir)) != NULL) {
char *foundfile = dupcat(src, "/", filename, NULL);
source(foundfile);
sfree(foundfile);
sfree(filename);
}
ok = FindNextFile(dir, &fdat);
}
FindClose(dir);
sfree(findfile);
close_directory(dir);
(void) scp_send_enddir();
@ -1805,16 +1615,16 @@ static void sink(char *targ, char *src)
char *destfname;
int targisdir = 0;
int exists;
DWORD attr;
HANDLE f;
int attr;
WFile *f;
unsigned long received;
int wrerror = 0;
unsigned long stat_bytes;
time_t stat_starttime, stat_lasttime;
char *stat_name;
attr = GetFileAttributes(targ);
if (attr != (DWORD) - 1 && (attr & FILE_ATTRIBUTE_DIRECTORY) != 0)
attr = file_type(targ);
if (attr == FILE_TYPE_DIRECTORY)
targisdir = 1;
if (targetshouldbedirectory && !targisdir)
@ -1912,16 +1722,16 @@ static void sink(char *targ, char *src)
*/
destfname = dupstr(targ);
}
attr = GetFileAttributes(destfname);
exists = (attr != (DWORD) - 1);
attr = file_type(destfname);
exists = (attr != FILE_TYPE_NONEXISTENT);
if (act.action == SCP_SINK_DIR) {
if (exists && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
if (exists && attr != FILE_TYPE_DIRECTORY) {
run_err("%s: Not a directory", destfname);
continue;
}
if (!exists) {
if (!CreateDirectory(destfname, NULL)) {
if (!create_directory(destfname)) {
run_err("%s: Cannot create directory", destfname);
continue;
}
@ -1931,9 +1741,8 @@ static void sink(char *targ, char *src)
continue;
}
f = CreateFile(destfname, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (f == INVALID_HANDLE_VALUE) {
f = open_new_file(destfname);
if (f == NULL) {
run_err("%s: Cannot create file", destfname);
continue;
}
@ -1949,17 +1758,16 @@ static void sink(char *targ, char *src)
received = 0;
while (received < act.size) {
char transbuf[4096];
DWORD blksize, read, written;
int blksize, read;
blksize = 4096;
if (blksize > act.size - received)
if (blksize > (int)(act.size - received))
blksize = act.size - received;
read = scp_recv_filedata(transbuf, blksize);
if (read <= 0)
bump("Lost connection");
if (wrerror)
continue;
if (!WriteFile(f, transbuf, read, &written, NULL) ||
written != read) {
if (write_to_file(f, transbuf, read) != (int)read) {
wrerror = 1;
/* FIXME: in sftp we can actually abort the transfer */
if (statistics)
@ -1980,13 +1788,10 @@ static void sink(char *targ, char *src)
received += read;
}
if (act.settime) {
FILETIME actime, wrtime;
TIME_POSIX_TO_WIN(act.atime, actime);
TIME_POSIX_TO_WIN(act.mtime, wrtime);
SetFileTime(f, NULL, &actime, &wrtime);
set_file_times(f, act.mtime, act.atime);
}
CloseHandle(f);
close_wfile(f);
if (wrerror) {
run_err("%s: Write error", destfname);
continue;
@ -2004,7 +1809,7 @@ static void toremote(int argc, char *argv[])
{
char *src, *targ, *host, *user;
char *cmd;
int i;
int i, wc_type;
targ = argv[argc - 1];
@ -2031,18 +1836,14 @@ static void toremote(int argc, char *argv[])
}
if (argc == 2) {
/* Find out if the source filespec covers multiple files
if so, we should set the targetshouldbedirectory flag */
HANDLE fh;
WIN32_FIND_DATA fdat;
if (colon(argv[0]) != NULL)
bump("%s: Remote to remote not supported", argv[0]);
fh = FindFirstFile(argv[0], &fdat);
if (fh == INVALID_HANDLE_VALUE)
wc_type = test_wildcard(argv[0], 1);
if (wc_type == WCTYPE_NONEXISTENT)
bump("%s: No such file or directory\n", argv[0]);
if (FindNextFile(fh, &fdat))
else if (wc_type == WCTYPE_WILDCARD)
targetshouldbedirectory = 1;
FindClose(fh);
}
cmd = dupprintf("scp%s%s%s%s -t %s",
@ -2056,9 +1857,6 @@ static void toremote(int argc, char *argv[])
scp_source_setup(targ, targetshouldbedirectory);
for (i = 0; i < argc - 1; i++) {
char *srcpath, *last;
HANDLE dir;
WIN32_FIND_DATA fdat;
src = argv[i];
if (colon(src) != NULL) {
tell_user(stderr, "%s: Remote to remote not supported\n", src);
@ -2066,49 +1864,30 @@ static void toremote(int argc, char *argv[])
continue;
}
/*
* Trim off the last pathname component of `src', to
* provide the base pathname which will be prepended to
* filenames returned from Find{First,Next}File.
*/
srcpath = dupstr(src);
last = stripslashes(srcpath, 1);
*last = '\0';
dir = FindFirstFile(src, &fdat);
if (dir == INVALID_HANDLE_VALUE) {
wc_type = test_wildcard(src, 1);
if (wc_type == WCTYPE_NONEXISTENT) {
run_err("%s: No such file or directory", src);
continue;
}
do {
} else if (wc_type == WCTYPE_FILENAME) {
source(src);
continue;
} else {
WildcardMatcher *wc;
char *filename;
/*
* Ensure that . and .. are never matched by wildcards,
* but only by deliberate action.
*/
if (!strcmp(fdat.cFileName, ".") ||
!strcmp(fdat.cFileName, "..")) {
/*
* Find*File has returned a special dir. We require
* that _either_ `src' ends in a backslash followed
* by that string, _or_ `src' is precisely that
* string.
*/
int len = strlen(src), dlen = strlen(fdat.cFileName);
if (len == dlen && !strcmp(src, fdat.cFileName)) {
/* ok */ ;
} else if (len > dlen + 1 && src[len - dlen - 1] == '\\' &&
!strcmp(src + len - dlen, fdat.cFileName)) {
/* ok */ ;
} else
continue; /* ignore this one */
wc = begin_wildcard_matching(src);
if (wc == NULL) {
run_err("%s: No such file or directory", src);
continue;
}
filename = dupcat(srcpath, fdat.cFileName, NULL);
source(filename);
sfree(filename);
} while (FindNextFile(dir, &fdat));
FindClose(dir);
sfree(srcpath);
while ((filename = wildcard_get_filename(wc)) != NULL) {
source(filename);
sfree(filename);
}
finish_wildcard_matching(wc);
}
}
}
@ -2222,21 +2001,6 @@ static void get_dir_list(int argc, char *argv[])
}
}
/*
* Initialize the Win$ock driver.
*/
static void init_winsock(void)
{
WORD winsock_ver;
WSADATA wsadata;
winsock_ver = MAKEWORD(1, 1);
if (WSAStartup(winsock_ver, &wsadata))
bump("Unable to initialise WinSock");
if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1)
bump("WinSock version is incompatible with 1.1");
}
/*
* Short description of parameters.
*/
@ -2288,18 +2052,22 @@ void cmdline_error(char *p, ...)
}
/*
* Main program (no, really?)
* Main program. (Called `psftp_main' because it gets called from
* *sftp.c; bit silly, I know, but it had to be called _something_.)
*/
int main(int argc, char *argv[])
int psftp_main(int argc, char *argv[])
{
int i;
default_protocol = PROT_TELNET;
flags = FLAG_STDERR | FLAG_SYNCAGENT;
flags = FLAG_STDERR
#ifdef FLAG_SYNCAGENT
| FLAG_SYNCAGENT
#endif
;
cmdline_tooltype = TOOLTYPE_FILETRANSFER;
ssh_get_line = &console_get_line;
init_winsock();
sk_init();
for (i = 1; i < argc; i++) {
@ -2324,7 +2092,7 @@ int main(int argc, char *argv[])
} else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-?") == 0) {
usage();
} else if (strcmp(argv[i], "-gui") == 0 && i + 1 < argc) {
gui_hwnd = argv[++i];
gui_enable(argv[++i]);
gui_mode = 1;
console_batch_mode = TRUE;
} else if (strcmp(argv[i], "-ls") == 0) {
@ -2367,18 +2135,11 @@ int main(int argc, char *argv[])
back->special(backhandle, TS_EOF);
ssh_scp_recv(&ch, 1);
}
WSACleanup();
random_save_seed();
/* GUI Adaptation - August 2000 */
if (gui_mode) {
unsigned int msg_id = WM_RET_ERR_CNT;
if (list)
msg_id = WM_LS_RET_ERR_CNT;
while (!PostMessage
((HWND) atoi(gui_hwnd), msg_id, (WPARAM) errs,
0 /*lParam */ ))SleepEx(1000, TRUE);
}
if (gui_mode)
gui_send_errcount(list, errs);
return (errs == 0 ? 0 : 1);
}

Просмотреть файл

@ -29,6 +29,7 @@ static void gpps(void *handle, const char *name, const char *def,
pdef = platform_default_s(name);
if (pdef) {
strncpy(val, pdef, len);
sfree(pdef);
} else {
strncpy(val, def, len);
}

Просмотреть файл

@ -5,6 +5,8 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <pwd.h>
#include "putty.h"
@ -19,6 +21,8 @@ unsigned long getticks(void)
return tv.tv_sec * 1000000 + tv.tv_usec;
}
Filename filename_from_str(const char *str)
{
Filename ret;
@ -57,3 +61,43 @@ void dputs(char *buf)
fflush(debug_fp);
}
#endif
char *get_username(void)
{
struct passwd *p;
uid_t uid = getuid();
char *user, *ret = NULL;
/*
* First, find who we think we are using getlogin. If this
* agrees with our uid, we'll go along with it. This should
* allow sharing of uids between several login names whilst
* coping correctly with people who have su'ed.
*/
user = getlogin();
setpwent();
if (user)
p = getpwnam(user);
else
p = NULL;
if (p && p->pw_uid == uid) {
/*
* The result of getlogin() really does correspond to
* our uid. Fine.
*/
ret = user;
} else {
/*
* If that didn't work, for whatever reason, we'll do
* the simpler version: look up our uid in the password
* file and map it straight to a name.
*/
p = getpwuid(uid);
if (!p)
return NULL;
ret = p->pw_name;
}
endpwent();
return dupstr(ret);
}

Просмотреть файл

@ -74,48 +74,11 @@ static Config cfg;
char *platform_default_s(const char *name)
{
if (!strcmp(name, "X11Display"))
return getenv("DISPLAY");
return dupstr(getenv("DISPLAY"));
if (!strcmp(name, "TermType"))
return getenv("TERM");
if (!strcmp(name, "UserName")) {
/*
* Remote login username will default to the local username.
*/
struct passwd *p;
uid_t uid = getuid();
char *user, *ret = NULL;
/*
* First, find who we think we are using getlogin. If this
* agrees with our uid, we'll go along with it. This should
* allow sharing of uids between several login names whilst
* coping correctly with people who have su'ed.
*/
user = getlogin();
setpwent();
if (user)
p = getpwnam(user);
else
p = NULL;
if (p && p->pw_uid == uid) {
/*
* The result of getlogin() really does correspond to
* our uid. Fine.
*/
ret = user;
} else {
/*
* If that didn't work, for whatever reason, we'll do
* the simpler version: look up our uid in the password
* file and map it straight to a name.
*/
p = getpwuid(uid);
ret = p->pw_name;
}
endpwent();
return ret;
}
return dupstr(getenv("TERM"));
if (!strcmp(name, "UserName"))
return get_username();
return NULL;
}

Просмотреть файл

@ -1,12 +1,11 @@
/*
* uxsftp.c: the Unix-specific parts of PSFTP.
* uxsftp.c: the Unix-specific parts of PSFTP and PSCP.
*/
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <pwd.h>
#include "putty.h"
#include "psftp.h"
@ -34,45 +33,6 @@ void platform_get_x11_auth(char *display, int *protocol,
*/
char *platform_default_s(const char *name)
{
if (!strcmp(name, "UserName")) {
/*
* Remote login username will default to the local username.
*/
struct passwd *p;
uid_t uid = getuid();
char *user, *ret = NULL;
/*
* First, find who we think we are using getlogin. If this
* agrees with our uid, we'll go along with it. This should
* allow sharing of uids between several login names whilst
* coping correctly with people who have su'ed.
*/
user = getlogin();
setpwent();
if (user)
p = getpwnam(user);
else
p = NULL;
if (p && p->pw_uid == uid) {
/*
* The result of getlogin() really does correspond to
* our uid. Fine.
*/
ret = user;
} else {
/*
* If that didn't work, for whatever reason, we'll do
* the simpler version: look up our uid in the password
* file and map it straight to a name.
*/
p = getpwuid(uid);
ret = p->pw_name;
}
endpwent();
return ret;
}
return NULL;
}
@ -98,6 +58,18 @@ Filename platform_default_filename(const char *name)
return ret;
}
/*
* Stubs for the GUI feedback mechanism in Windows PSCP.
*/
void gui_update_stats(char *name, unsigned long size,
int percentage, unsigned long elapsed,
unsigned long done, unsigned long eta,
unsigned long ratebs) {}
void gui_send_errcount(int list, int errs) {}
void gui_send_char(int is_stderr, int c) {}
void gui_enable(char *arg) {}
/*
* Set local current directory. Returns NULL on success, or else an
* error message which must be freed after printing.

Просмотреть файл

@ -39,6 +39,21 @@ int filename_is_null(Filename fn)
return !*fn.path;
}
char *get_username(void)
{
DWORD namelen;
char *user;
namelen = 0;
if (GetUserName(NULL, &namelen) == FALSE)
return NULL;
user = snewn(namelen, char);
GetUserName(user, &namelen);
return user;
}
int SaneDialogBox(HINSTANCE hinst,
LPCTSTR tmpl,
HWND hwndparent,

457
winsftp.c
Просмотреть файл

@ -1,45 +1,141 @@
/*
* winsftp.c: the Windows-specific parts of PSFTP.
* winsftp.c: the Windows-specific parts of PSFTP and PSCP.
*/
#include <windows.h>
#ifndef AUTO_WINSOCK
#ifdef WINSOCK_TWO
#include <winsock2.h>
#else
#include <winsock.h>
#endif
#endif
#include "putty.h"
#include "psftp.h"
/*
* Be told what socket we're supposed to be using.
/* ----------------------------------------------------------------------
* Interface to GUI driver program.
*/
static SOCKET sftp_ssh_socket;
char *do_select(SOCKET skt, int startup)
/* This is just a base value from which the main message numbers are
* derived. */
#define WM_APP_BASE 0x8000
/* These two pass a single character value in wParam. They represent
* the visible output from PSCP. */
#define WM_STD_OUT_CHAR ( WM_APP_BASE+400 )
#define WM_STD_ERR_CHAR ( WM_APP_BASE+401 )
/* These pass a transfer status update. WM_STATS_CHAR passes a single
* character in wParam, and is called repeatedly to pass the name of
* the file, terminated with "\n". WM_STATS_SIZE passes the size of
* the file being transferred in wParam. WM_STATS_ELAPSED is called
* to pass the elapsed time (in seconds) in wParam, and
* WM_STATS_PERCENT passes the percentage of the transfer which is
* complete, also in wParam. */
#define WM_STATS_CHAR ( WM_APP_BASE+402 )
#define WM_STATS_SIZE ( WM_APP_BASE+403 )
#define WM_STATS_PERCENT ( WM_APP_BASE+404 )
#define WM_STATS_ELAPSED ( WM_APP_BASE+405 )
/* These are used at the end of a run to pass an error code in
* wParam: zero means success, nonzero means failure. WM_RET_ERR_CNT
* is used after a copy, and WM_LS_RET_ERR_CNT is used after a file
* list operation. */
#define WM_RET_ERR_CNT ( WM_APP_BASE+406 )
#define WM_LS_RET_ERR_CNT ( WM_APP_BASE+407 )
/* More transfer status update messages. WM_STATS_DONE passes the
* number of bytes sent so far in wParam. WM_STATS_ETA passes the
* estimated time to completion (in seconds). WM_STATS_RATEBS passes
* the average transfer rate (in bytes per second). */
#define WM_STATS_DONE ( WM_APP_BASE+408 )
#define WM_STATS_ETA ( WM_APP_BASE+409 )
#define WM_STATS_RATEBS ( WM_APP_BASE+410 )
#define NAME_STR_MAX 2048
static char statname[NAME_STR_MAX + 1];
static unsigned long statsize = 0;
static unsigned long statdone = 0;
static unsigned long stateta = 0;
static unsigned long statratebs = 0;
static int statperct = 0;
static unsigned long statelapsed = 0;
static HWND gui_hwnd = NULL;
static void send_msg(HWND h, UINT message, WPARAM wParam)
{
if (startup)
sftp_ssh_socket = skt;
else
sftp_ssh_socket = INVALID_SOCKET;
return NULL;
while (!PostMessage(h, message, wParam, 0))
SleepEx(1000, TRUE);
}
extern int select_result(WPARAM, LPARAM);
/*
* Initialize the WinSock driver.
*/
static void init_winsock(void)
void gui_send_char(int is_stderr, int c)
{
WORD winsock_ver;
WSADATA wsadata;
unsigned int msg_id = WM_STD_OUT_CHAR;
if (is_stderr)
msg_id = WM_STD_ERR_CHAR;
send_msg(gui_hwnd, msg_id, (WPARAM) c);
}
winsock_ver = MAKEWORD(1, 1);
if (WSAStartup(winsock_ver, &wsadata)) {
fprintf(stderr, "Unable to initialise WinSock");
cleanup_exit(1);
void gui_send_errcount(int list, int errs)
{
unsigned int msg_id = WM_RET_ERR_CNT;
if (list)
msg_id = WM_LS_RET_ERR_CNT;
while (!PostMessage(gui_hwnd, msg_id, (WPARAM) errs, 0))
SleepEx(1000, TRUE);
}
void gui_update_stats(char *name, unsigned long size,
int percentage, unsigned long elapsed,
unsigned long done, unsigned long eta,
unsigned long ratebs)
{
unsigned int i;
if (strcmp(name, statname) != 0) {
for (i = 0; i < strlen(name); ++i)
send_msg(gui_hwnd, WM_STATS_CHAR, (WPARAM) name[i]);
send_msg(gui_hwnd, WM_STATS_CHAR, (WPARAM) '\n');
strcpy(statname, name);
}
if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1) {
fprintf(stderr, "WinSock version is incompatible with 1.1");
cleanup_exit(1);
if (statsize != size) {
send_msg(gui_hwnd, WM_STATS_SIZE, (WPARAM) size);
statsize = size;
}
if (statdone != done) {
send_msg(gui_hwnd, WM_STATS_DONE, (WPARAM) done);
statdone = done;
}
if (stateta != eta) {
send_msg(gui_hwnd, WM_STATS_ETA, (WPARAM) eta);
stateta = eta;
}
if (statratebs != ratebs) {
send_msg(gui_hwnd, WM_STATS_RATEBS, (WPARAM) ratebs);
statratebs = ratebs;
}
if (statelapsed != elapsed) {
send_msg(gui_hwnd, WM_STATS_ELAPSED, (WPARAM) elapsed);
statelapsed = elapsed;
}
if (statperct != percentage) {
send_msg(gui_hwnd, WM_STATS_PERCENT, (WPARAM) percentage);
statperct = percentage;
}
}
void gui_enable(char *arg)
{
gui_hwnd = (HWND) atoi(arg);
}
/* ----------------------------------------------------------------------
* File access abstraction.
*/
/*
* Set local current directory. Returns NULL on success, or else an
* error message which must be freed after printing.
@ -79,6 +175,317 @@ char *psftp_getcwd(void)
return ret;
}
#define TIME_POSIX_TO_WIN(t, ft) (*(LONGLONG*)&(ft) = \
((LONGLONG) (t) + (LONGLONG) 11644473600) * (LONGLONG) 10000000)
#define TIME_WIN_TO_POSIX(ft, t) ((t) = (unsigned long) \
((*(LONGLONG*)&(ft)) / (LONGLONG) 10000000 - (LONGLONG) 11644473600))
struct RFile {
HANDLE h;
};
RFile *open_existing_file(char *name, unsigned long *size,
unsigned long *mtime, unsigned long *atime)
{
HANDLE h;
RFile *ret;
h = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, 0);
if (h == INVALID_HANDLE_VALUE)
return NULL;
ret = snew(RFile);
ret->h = h;
if (size)
*size = GetFileSize(h, NULL);
if (mtime || atime) {
FILETIME actime, wrtime;
GetFileTime(h, NULL, &actime, &wrtime);
if (atime)
TIME_WIN_TO_POSIX(actime, *atime);
if (mtime)
TIME_WIN_TO_POSIX(wrtime, *mtime);
}
return ret;
}
int read_from_file(RFile *f, void *buffer, int length)
{
int ret, read;
ret = ReadFile(f->h, buffer, length, &read, NULL);
if (!ret)
return -1; /* error */
else
return read;
}
void close_rfile(RFile *f)
{
CloseHandle(f->h);
sfree(f);
}
struct WFile {
HANDLE h;
};
WFile *open_new_file(char *name)
{
HANDLE h;
WFile *ret;
h = CreateFile(name, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (h == INVALID_HANDLE_VALUE)
return NULL;
ret = snew(WFile);
ret->h = h;
return ret;
}
int write_to_file(WFile *f, void *buffer, int length)
{
int ret, written;
ret = WriteFile(f->h, buffer, length, &written, NULL);
if (!ret)
return -1; /* error */
else
return written;
}
void set_file_times(WFile *f, unsigned long mtime, unsigned long atime)
{
FILETIME actime, wrtime;
TIME_POSIX_TO_WIN(atime, actime);
TIME_POSIX_TO_WIN(mtime, wrtime);
SetFileTime(f->h, NULL, &actime, &wrtime);
}
void close_wfile(WFile *f)
{
CloseHandle(f->h);
sfree(f);
}
int file_type(char *name)
{
DWORD attr;
attr = GetFileAttributes(name);
/* We know of no `weird' files under Windows. */
if (attr == (DWORD)-1)
return FILE_TYPE_NONEXISTENT;
else if (attr & FILE_ATTRIBUTE_DIRECTORY)
return FILE_TYPE_DIRECTORY;
else
return FILE_TYPE_FILE;
}
struct DirHandle {
HANDLE h;
char *name;
};
DirHandle *open_directory(char *name)
{
HANDLE h;
WIN32_FIND_DATA fdat;
char *findfile;
DirHandle *ret;
/* To enumerate files in dir `foo', we search for `foo/*'. */
findfile = dupcat(name, "/*", NULL);
h = FindFirstFile(findfile, &fdat);
if (h == INVALID_HANDLE_VALUE)
return NULL;
ret = snew(DirHandle);
ret->h = h;
ret->name = dupstr(fdat.cFileName);
return ret;
}
char *read_filename(DirHandle *dir)
{
if (!dir->name) {
WIN32_FIND_DATA fdat;
int ok = FindNextFile(dir->h, &fdat);
if (ok)
dir->name = dupstr(fdat.cFileName);
}
if (dir->name) {
char *ret = dir->name;
dir->name = NULL;
return ret;
} else
return NULL;
}
void close_directory(DirHandle *dir)
{
FindClose(dir->h);
if (dir->name)
sfree(dir->name);
sfree(dir);
}
int test_wildcard(char *name, int cmdline)
{
HANDLE fh;
WIN32_FIND_DATA fdat;
/* First see if the exact name exists. */
if (GetFileAttributes(name) != (DWORD)-1)
return WCTYPE_FILENAME;
/* Otherwise see if a wildcard match finds anything. */
fh = FindFirstFile(name, &fdat);
if (fh == INVALID_HANDLE_VALUE)
return WCTYPE_NONEXISTENT;
FindClose(fh);
return WCTYPE_WILDCARD;
}
struct WildcardMatcher {
HANDLE h;
char *name;
char *srcpath;
};
/*
* Return a pointer to the portion of str that comes after the last
* slash (or backslash or colon, if `local' is TRUE).
*/
static char *stripslashes(char *str, int local)
{
char *p;
if (local) {
p = strchr(str, ':');
if (p) str = p+1;
}
p = strrchr(str, '/');
if (p) str = p+1;
if (local) {
p = strrchr(str, '\\');
if (p) str = p+1;
}
return str;
}
WildcardMatcher *begin_wildcard_matching(char *name)
{
HANDLE h;
WIN32_FIND_DATA fdat;
WildcardMatcher *ret;
char *last;
h = FindFirstFile(name, &fdat);
if (h == INVALID_HANDLE_VALUE)
return NULL;
ret = snew(WildcardMatcher);
ret->h = h;
ret->srcpath = dupstr(name);
last = stripslashes(ret->srcpath, 1);
*last = '\0';
if (fdat.cFileName[0] == '.' &&
(fdat.cFileName[1] == '\0' ||
(fdat.cFileName[1] == '.' && fdat.cFileName[2] == '\0')))
ret->name = NULL;
else
ret->name = dupcat(ret->srcpath, fdat.cFileName, NULL);
return ret;
}
char *wildcard_get_filename(WildcardMatcher *dir)
{
while (!dir->name) {
WIN32_FIND_DATA fdat;
int ok = FindNextFile(dir->h, &fdat);
if (!ok)
return NULL;
if (fdat.cFileName[0] == '.' &&
(fdat.cFileName[1] == '\0' ||
(fdat.cFileName[1] == '.' && fdat.cFileName[2] == '\0')))
dir->name = NULL;
else
dir->name = dupcat(dir->srcpath, fdat.cFileName, NULL);
}
if (dir->name) {
char *ret = dir->name;
dir->name = NULL;
return ret;
} else
return NULL;
}
void finish_wildcard_matching(WildcardMatcher *dir)
{
FindClose(dir->h);
if (dir->name)
sfree(dir->name);
sfree(dir->srcpath);
sfree(dir);
}
int create_directory(char *name)
{
return CreateDirectory(name, NULL) != 0;
}
/* ----------------------------------------------------------------------
* Platform-specific network handling.
*/
/*
* Be told what socket we're supposed to be using.
*/
static SOCKET sftp_ssh_socket;
char *do_select(SOCKET skt, int startup)
{
if (startup)
sftp_ssh_socket = skt;
else
sftp_ssh_socket = INVALID_SOCKET;
return NULL;
}
extern int select_result(WPARAM, LPARAM);
/*
* Initialize the WinSock driver.
*/
static void init_winsock(void)
{
WORD winsock_ver;
WSADATA wsadata;
winsock_ver = MAKEWORD(1, 1);
if (WSAStartup(winsock_ver, &wsadata)) {
fprintf(stderr, "Unable to initialise WinSock");
cleanup_exit(1);
}
if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1) {
fprintf(stderr, "WinSock version is incompatible with 1.1");
cleanup_exit(1);
}
}
/*
* Wait for some network data and process it.
*/
@ -98,7 +505,7 @@ int ssh_sftp_loop_iteration(void)
return 0;
}
/*
/* ----------------------------------------------------------------------
* Main program. Parse arguments etc.
*/
int main(int argc, char *argv[])