diff --git a/.gitignore b/.gitignore index dcbf920..aa1a453 100644 --- a/.gitignore +++ b/.gitignore @@ -277,5 +277,17 @@ Makefile.in d2utmpa* configure contrib/win32/openssh/Win32-OpenSSH.VC.opendb +contrib/win32/openssh/Win32-OpenSSH.VC.db *.opendb *.db + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb \ No newline at end of file diff --git a/contrib/win32/openssh/config.h.vs b/contrib/win32/openssh/config.h.vs index 51e9445..38b38a8 100644 --- a/contrib/win32/openssh/config.h.vs +++ b/contrib/win32/openssh/config.h.vs @@ -1632,6 +1632,9 @@ #define HAVE_STRNCASECMP 1 #endif +/* Define to 1 if you have the locale.h header. */ +#define HAVE_LOCALE_H 1 + #define HAVE_STRUCT_IN6_ADDR 1 #define HAVE_STRUCT_SOCKADDR_IN6 1 #define HAVE_STRUCT_TIMEVAL 1 @@ -1725,6 +1728,6 @@ typedef long ssize_t; #define HAVE_MBLEN 1 #define SSHDIR "." -#define _PATH_SFTP_SERVER "./sftp-server.exe" -#define _PATH_SSH_PROGRAM "./ssh.exe" +#define _PATH_SFTP_SERVER "sftp-server.exe" +#define _PATH_SSH_PROGRAM "ssh.exe" #define _PATH_LS "dir" diff --git a/contrib/win32/openssh/paths.targets b/contrib/win32/openssh/paths.targets index 21322fe..0d37f85 100644 --- a/contrib/win32/openssh/paths.targets +++ b/contrib/win32/openssh/paths.targets @@ -4,10 +4,12 @@ $(SolutionDir)..\..\..\ $(SolutionDir)..\..\..\bin\ $(SolutionDir)lib\ - $(SolutionDir)..\..\..\..\OpenSSL\1.0.2d\VS2015\ - $(SolutionDir)..\..\..\..\OpenSSL\1.0.2d\VS2015\Win32\Release\ - $(SolutionDir)..\..\..\..\OpenSSL\1.0.2d\VS2015\Win32\Debug\ - $(SolutionDir)..\..\..\..\OpenSSL\1.0.2d\VS2015\x64\Release\ - $(SolutionDir)..\..\..\..\OpenSSL\1.0.2d\VS2015\x64\Debug\ + g:\openssl-1.0.2h-x64\OpenSSLInstallx64_vs2015-debug\ + g:\openssl-1.0.2h-x86\OpenSSLInstallx86_vs2015\ + g:\openssl-1.0.2h-x86\OpenSSLInstallx86_vs2015-debug\ + g:\openssl-1.0.2h-x64\OpenSSLInstallx64_vs2015\ + g:\openssl-1.0.2h-x64\OpenSSLInstallx64_vs2015-debug\ + g:\openssl-1.0.2h-arm-x86\OpenSSLInstallx86_vs2015\ + g:\openssl-1.0.2h-arm-x86\OpenSSLInstallx86_vs2015\ diff --git a/contrib/win32/openssh/scp.vcxproj b/contrib/win32/openssh/scp.vcxproj index f6b879f..18a8740 100644 --- a/contrib/win32/openssh/scp.vcxproj +++ b/contrib/win32/openssh/scp.vcxproj @@ -21,6 +21,7 @@ + @@ -116,6 +117,7 @@ Console true Netapi32.lib;win32iocompat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;win32compat.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Debug-Path)lib;%(AdditionalLibraryDirectories) wmainCRTStartup @@ -135,6 +137,7 @@ Console true Netapi32.lib;win32iocompat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;win32compat.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Debug-Path)lib;%(AdditionalLibraryDirectories) wmainCRTStartup @@ -158,6 +161,7 @@ true true Netapi32.lib;win32iocompat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;win32compat.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Release-Path)lib;%(AdditionalLibraryDirectories) wmainCRTStartup @@ -181,6 +185,7 @@ true true Netapi32.lib;win32iocompat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;win32compat.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Release-Path)lib;%(AdditionalLibraryDirectories) wmainCRTStartup diff --git a/contrib/win32/openssh/scp.vcxproj.filters b/contrib/win32/openssh/scp.vcxproj.filters index 4da1894..7aa9873 100644 --- a/contrib/win32/openssh/scp.vcxproj.filters +++ b/contrib/win32/openssh/scp.vcxproj.filters @@ -18,6 +18,9 @@ Source Files + + Source Files + diff --git a/contrib/win32/openssh/sftp-server.vcxproj b/contrib/win32/openssh/sftp-server.vcxproj index 1c91ed5..bcb75a8 100644 --- a/contrib/win32/openssh/sftp-server.vcxproj +++ b/contrib/win32/openssh/sftp-server.vcxproj @@ -23,6 +23,7 @@ + @@ -118,7 +119,8 @@ Console true - Netapi32.lib;win32iocompat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;win32compat.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Netapi32.lib;win32iocompat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;win32compat.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Debug-Path)lib;%(AdditionalLibraryDirectories) wmainCRTStartup diff --git a/contrib/win32/openssh/sftp-server.vcxproj.filters b/contrib/win32/openssh/sftp-server.vcxproj.filters index 7e84e8c..2179a95 100644 --- a/contrib/win32/openssh/sftp-server.vcxproj.filters +++ b/contrib/win32/openssh/sftp-server.vcxproj.filters @@ -24,6 +24,9 @@ Source Files + + Source Files + diff --git a/contrib/win32/openssh/sftp.vcxproj b/contrib/win32/openssh/sftp.vcxproj index dfd557d..b59ab65 100644 --- a/contrib/win32/openssh/sftp.vcxproj +++ b/contrib/win32/openssh/sftp.vcxproj @@ -25,6 +25,7 @@ + @@ -120,7 +121,8 @@ Console true - Netapi32.lib;win32iocompat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;win32compat.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Netapi32.lib;win32iocompat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;win32compat.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Debug-Path)lib;%(AdditionalLibraryDirectories) wmainCRTStartup @@ -140,7 +142,8 @@ Console true - Netapi32.lib;win32iocompat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;win32compat.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Netapi32.lib;win32iocompat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;win32compat.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Debug-Path)lib;%(AdditionalLibraryDirectories) wmainCRTStartup @@ -163,7 +166,8 @@ false true true - Netapi32.lib;win32iocompat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;win32compat.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Netapi32.lib;win32iocompat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;win32compat.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Release-Path)lib;%(AdditionalLibraryDirectories) wmainCRTStartup @@ -186,7 +190,8 @@ false true true - Netapi32.lib;win32iocompat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;win32compat.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Netapi32.lib;win32iocompat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;win32compat.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Release-Path)lib;%(AdditionalLibraryDirectories) wmainCRTStartup diff --git a/contrib/win32/openssh/sftp.vcxproj.filters b/contrib/win32/openssh/sftp.vcxproj.filters index 19d11ba..30e54f3 100644 --- a/contrib/win32/openssh/sftp.vcxproj.filters +++ b/contrib/win32/openssh/sftp.vcxproj.filters @@ -30,6 +30,9 @@ Source Files + + Source Files + diff --git a/contrib/win32/openssh/win32iocompat.vcxproj b/contrib/win32/openssh/win32iocompat.vcxproj index 1573471..167f8c6 100644 --- a/contrib/win32/openssh/win32iocompat.vcxproj +++ b/contrib/win32/openssh/win32iocompat.vcxproj @@ -150,8 +150,10 @@ - - + + + + @@ -170,9 +172,12 @@ - - - + + + + + + diff --git a/contrib/win32/openssh/win32iocompat.vcxproj.filters b/contrib/win32/openssh/win32iocompat.vcxproj.filters index 433a8c8..6b4ea8a 100644 --- a/contrib/win32/openssh/win32iocompat.vcxproj.filters +++ b/contrib/win32/openssh/win32iocompat.vcxproj.filters @@ -10,8 +10,10 @@ - - + + + + @@ -54,14 +56,22 @@ - + + inc + - + + + inc\sys + - + + + inc + diff --git a/contrib/win32/win32compat/fileio.c b/contrib/win32/win32compat/fileio.c index 415c14c..59a7d90 100644 --- a/contrib/win32/win32compat/fileio.c +++ b/contrib/win32/win32compat/fileio.c @@ -559,8 +559,15 @@ fileio_fstat(struct w32_io* pio, struct _stat64 *buf) { int fileio_stat(const char *path, struct _stat64 *buf) { - /* TODO - path is UTD -8, support unicode*/ - return _stat64(path, buf); + wchar_t wpath[MAX_PATH]; + wchar_t* wtmp = NULL; + + if ((wtmp = utf8_to_utf16(path)) == NULL) + fatal("failed to covert input arguments"); + wcscpy(&wpath[0], wtmp); + free(wtmp); + + return _wstat64(wpath, buf); } long diff --git a/contrib/win32/win32compat/inc/defs.h b/contrib/win32/win32compat/inc/defs.h index 7f49745..9338000 100644 --- a/contrib/win32/win32compat/inc/defs.h +++ b/contrib/win32/win32compat/inc/defs.h @@ -47,9 +47,10 @@ #define W32_SIGTERM 8 #define W32_SIGTTIN 9 #define W32_SIGTTOU 10 -#define W32_SIGWINCH 11 +#define W32_SIGWINCH 11 #define W32_SIGMAX 12 +#define W32_SIGSTOP 13 /* singprocmask "how" codes*/ #define SIG_BLOCK 0 diff --git a/contrib/win32/win32compat/inc/fcntl.h b/contrib/win32/win32compat/inc/fcntl.h index 8fe222f..8f874e5 100644 --- a/contrib/win32/win32compat/inc/fcntl.h +++ b/contrib/win32/win32compat/inc/fcntl.h @@ -11,4 +11,8 @@ #define O_TRUNC 0x0200 // open and truncate #define O_EXCL 0x0400 // open only if file doesn't already exist -#define O_BINARY 0x8000 // file mode is binary (untranslated) \ No newline at end of file +#define O_TEXT 0x4000 /* file mode is text (translated) */ +#define O_BINARY 0x8000 /* file mode is binary (untranslated) */ +#define O_WTEXT 0x10000 /* file mode is UTF16 (translated) */ +#define O_U16TEXT 0x20000 /* file mode is UTF16 no BOM (translated) */ +#define O_U8TEXT 0x40000 /* file mode is UTF8 no BOM (translated) */ diff --git a/contrib/win32/win32compat/inc/signal.h b/contrib/win32/win32compat/inc/signal.h index f99d990..71bfc97 100644 --- a/contrib/win32/win32compat/inc/signal.h +++ b/contrib/win32/win32compat/inc/signal.h @@ -12,6 +12,7 @@ #define mysignal(a,b) w32_signal((a), (b)) #define raise(a) w32_raise(a) #define kill(a,b) w32_kill((a), (b)) +#define ftruncate(a, b) w32_ftruncate((a), (b)) #define sigprocmask(a,b,c) w32_sigprocmask((a), (b), (c)) #define SIGINT W32_SIGINT @@ -26,6 +27,7 @@ #define SIGTTIN W32_SIGTTIN #define SIGTTOU W32_SIGTTOU #define SIGWINCH W32_SIGWINCH +#define SIGSTOP W32_SIGSTOP #define SIG_DFL W32_SIG_DFL #define SIG_IGN W32_SIG_IGN diff --git a/contrib/win32/win32compat/inc/sys/socket.h b/contrib/win32/win32compat/inc/sys/socket.h index 32b3ae1..a792438 100644 --- a/contrib/win32/win32compat/inc/sys/socket.h +++ b/contrib/win32/win32compat/inc/sys/socket.h @@ -13,12 +13,12 @@ #define getsockopt(a,b,c,d,e) w32_getsockopt((a), (b), (c), (d), (e)) #define getsockname(a,b,c) w32_getsockname((a), (b), (c)) #define getpeername(a,b,c) w32_getpeername((a), (b), (c)) -#define listen(a,b) w32_listen((a), (b)) -#define bind(a,b,c) w32_bind((a), (b), (c)) +#define listen(a,b) w32_listen((a), (b)) +#define bind(a,b,c) w32_bind((a), (b), (c)) #define connect(a,b,c) w32_connect((a), (b), (c)) #define recv(a,b,c,d) w32_recv((a), (b), (c), (d)) #define send(a,b,c,d) w32_send((a), (b), (c), (d)) #define shutdown(a,b) w32_shutdown((a), (b)) #define socketpair(a,b,c,d) w32_socketpair((a), (b), (c), (d)) -#define freeaddrinfo w32_freeaddrinfo -#define getaddrinfo w32_getaddrinfo +#define freeaddrinfo w32_freeaddrinfo +#define getaddrinfo w32_getaddrinfo diff --git a/contrib/win32/win32compat/inc/sys/stat.h b/contrib/win32/win32compat/inc/sys/stat.h index e18f2bb..b8a2521 100644 --- a/contrib/win32/win32compat/inc/sys/stat.h +++ b/contrib/win32/win32compat/inc/sys/stat.h @@ -29,6 +29,8 @@ #define stat w32_stat #define lstat w32_stat #define mkdir w32_mkdir +#define chdir w32_chdir +#define getcwd w32_getcwd struct w32_stat { dev_t st_dev; /* ID of device containing file */ diff --git a/contrib/win32/win32compat/inc/sys/wait.h b/contrib/win32/win32compat/inc/sys/wait.h index 25ad69f..312486b 100644 --- a/contrib/win32/win32compat/inc/sys/wait.h +++ b/contrib/win32/win32compat/inc/sys/wait.h @@ -13,5 +13,7 @@ #define WIFSIGNALED(w) FALSE #define WEXITSTATUS(w) w #define WTERMSIG(w) -1 +#define WNOHANG 1 +#define WUNTRACED 2 int waitpid(int pid, int *status, int options); \ No newline at end of file diff --git a/contrib/win32/win32compat/inc/unistd.h b/contrib/win32/win32compat/inc/unistd.h index f4831a8..d526aa8 100644 --- a/contrib/win32/win32compat/inc/unistd.h +++ b/contrib/win32/win32compat/inc/unistd.h @@ -24,6 +24,7 @@ #define open w32_open #define read w32_read #define write w32_write +#define writev w32_writev //#define isatty w32_isatty #define close w32_close #define dup w32_dup diff --git a/contrib/win32/win32compat/inc/w32posix.h b/contrib/win32/win32compat/inc/w32posix.h index 2c09793..eb67eaa 100644 --- a/contrib/win32/win32compat/inc/w32posix.h +++ b/contrib/win32/win32compat/inc/w32posix.h @@ -10,6 +10,15 @@ #include "defs.h" #include "utf.h" +#ifndef _OFF_T_DEFINED +#define _OFF_T_DEFINED + +typedef long _off_t; // file offset value + +#if !__STDC__ +typedef _off_t off_t; +#endif +#endif typedef struct w32_fd_set_ { unsigned char bitmap[MAX_FDS >> 3]; @@ -45,6 +54,7 @@ int w32_pipe(int *pfds); int w32_open(const char *pathname, int flags, ...); int w32_read(int fd, void *dst, size_t max); int w32_write(int fd, const void *buf, unsigned int max); +int w32_writev(int fd, const struct iovec *iov, int iovcnt); int w32_fstat(int fd, struct w32_stat *buf); int w32_stat(const char *path, struct w32_stat *buf); long w32_lseek( int fd, long offset, int origin); @@ -52,6 +62,8 @@ long w32_lseek( int fd, long offset, int origin); int w32_isatty(int fd); FILE* w32_fdopen(int fd, const char *mode); int w32_mkdir(const char *pathname, unsigned short mode); +int w32_chdir(const char *dirname); +char *w32_getcwd(char *buffer, int maxlen); /*common i/o*/ #define fcntl(a,b,...) w32_fcntl((a), (b), __VA_ARGS__) @@ -75,6 +87,7 @@ void w32_freeaddrinfo(struct addrinfo *); int w32_getaddrinfo(const char *, const char *, const struct addrinfo *, struct addrinfo **); FILE* w32_fopen_utf8(const char *, const char *); +int w32_ftruncate(int fd, off_t length); char* w32_programdir(); @@ -124,7 +137,6 @@ int sw_add_child(HANDLE child, DWORD pid); #define allocate_sfd(a, b) w32_allocate_fd_for_handle((a, b)) //#define WSHELPwopen(a, b) w32_open((a, b)) - /* TODO - These defs need to revisited and positioned appropriately */ #define environ _environ diff --git a/contrib/win32/win32compat/w32fd.c b/contrib/win32/win32compat/w32fd.c index 292f31a..8f0022f 100644 --- a/contrib/win32/win32compat/w32fd.c +++ b/contrib/win32/win32compat/w32fd.c @@ -36,6 +36,7 @@ #include #include #include +#include /* internal table that stores the fd to w32_io mapping*/ struct w32fd_table { @@ -384,6 +385,23 @@ w32_write(int fd, const void *buf, unsigned int max) { return fileio_write(fd_table.w32_ios[fd], buf, max); } +int w32_writev(int fd, const struct iovec *iov, int iovcnt) { + int written = 0; + int i = 0; + + CHECK_FD(fd); + + for (i = 0; i < iovcnt; i++) { + int ret = w32_write(fd, iov[i].iov_base, iov[i].iov_len); + + if (ret > 0) { + written += ret; + } + } + + return written; +} + int w32_fstat(int fd, struct w32_stat *buf) { CHECK_FD(fd); @@ -403,12 +421,36 @@ w32_lseek(int fd, long offset, int origin) { int w32_mkdir(const char *path_utf8, unsigned short mode) { - wchar_t *path_utf16 = utf8_to_utf16(path_utf8); - if (path_utf16 == NULL) { - errno = ENOMEM; - return -1; - } - return _wmkdir(path_utf16); + wchar_t *path_utf16 = utf8_to_utf16(path_utf8); + if (path_utf16 == NULL) { + errno = ENOMEM; + return -1; + } + return _wmkdir(path_utf16); +} + +int w32_chdir(const char *dirname_utf8) { + wchar_t *dirname_utf16 = utf8_to_utf16(dirname_utf8); + if (dirname_utf16 == NULL) { + errno = ENOMEM; + return -1; + } + + return _wchdir(dirname_utf16); +} + +char *w32_getcwd(char *buffer, int maxlen) { + wchar_t wdirname[MAX_PATH]; + char* putf8 = NULL; + + wchar_t *wpwd = _wgetcwd(&wdirname[0], MAX_PATH); + + if ((putf8 = utf16_to_utf8(&wdirname[0])) == NULL) + fatal("failed to convert input arguments"); + strcpy(buffer, putf8); + free(putf8); + + return buffer; } int @@ -806,4 +848,18 @@ w32_raise(int sig) { int w32_kill(int pid, int sig) { return sw_kill(pid, sig); +} + +int +w32_ftruncate(int fd, off_t length) { + CHECK_FD(fd); + + if (!SetEndOfFile(w32_fd_to_handle(fd))) + return -1; + if (!SetFileValidData(w32_fd_to_handle(fd), length)) + return -1; + if (!SetFilePointer(w32_fd_to_handle(fd), 0, 0, FILE_BEGIN)) + return -1; + + return 0; } \ No newline at end of file diff --git a/defines.h b/defines.h index 14b3bc3..2dd7432 100644 --- a/defines.h +++ b/defines.h @@ -172,6 +172,8 @@ enum # define S_IRWXU 0000700 /* read, write, execute */ # define S_IRWXG 0000070 /* read, write, execute */ # define S_IRWXO 0000007 /* read, write, execute */ +# define S_ISUID 0x800 +# define S_ISGID 0x400 #endif /* S_IXUSR */ #if !defined(MAP_ANON) && defined(MAP_ANONYMOUS) diff --git a/misc.c b/misc.c index 797e4cd..02a4d55 100644 --- a/misc.c +++ b/misc.c @@ -222,6 +222,8 @@ pwcopy(struct passwd *pw) #ifdef HAVE_STRUCT_PASSWD_PW_CLASS copy->pw_class = xstrdup(pw->pw_class); #endif + + copy->pw_dir = xstrdup(pw->pw_dir); copy->pw_shell = xstrdup(pw->pw_shell); return copy; @@ -431,9 +433,34 @@ char * colon(char *cp) { int flag = 0; + int len = 0; if (*cp == ':') /* Leading colon is part of file name. */ return NULL; + +#ifdef WINDOWS + for (; *cp; ++cp) { + len++; + + if (*cp == '[') + flag = 1; + + if (flag && *cp != ']') + continue; + + if (*cp == ']') + flag = 0; + + if (*cp == ':') { + if (len != 2) { // avoid x: format for drive letter in Windows + return (cp); + } + } + // if ( (*cp == '/') || (*cp == '\\') ) + // return (0); + } + return NULL; +#else if (*cp == '[') flag = 1; @@ -447,7 +474,8 @@ colon(char *cp) if (*cp == '/') return NULL; } - return NULL; + return NULL; +#endif } /* function to assist building execv() arguments */ diff --git a/progressmeter.c b/progressmeter.c index 233283d..3d6f56b 100644 --- a/progressmeter.c +++ b/progressmeter.c @@ -78,13 +78,23 @@ static volatile sig_atomic_t win_resized; /* for window resizing */ /* units for format_size */ static const char unit[] = " KMGT"; +#ifdef WINDOWS +extern int ScreenX; +#endif + static int can_output(void) { -#ifndef WIN32_FIXME//R - return (getpgrp() == tcgetpgrp(STDOUT_FILENO)); +#ifndef WINDOWS + return (getpgrp() == tcgetpgrp(STDOUT_FILENO)); #else - return 1; + DWORD dwProcessId = -1; + if (GetWindowThreadProcessId(GetStdHandle(STD_OUTPUT_HANDLE), &dwProcessId)) { + return(GetCurrentProcess() == dwProcessId); + } + else { + return -1; + } #endif } @@ -227,7 +237,14 @@ refresh_progress_meter(void) strlcat(buf, " ", win_size); } +#ifdef WINDOWS + wchar_t* wtmp = utf8_to_utf16(buf); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"\n", 1, 0, 0); + free(wtmp); +#else atomicio(vwrite, STDOUT_FILENO, buf, win_size - 1); +#endif last_update = now; } @@ -298,7 +315,7 @@ sig_winch(int sig) static void setscreensize(void) { - #ifndef WIN32_FIXME//N +#ifndef WINDOWS struct winsize winsize; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize) != -1 && @@ -310,6 +327,7 @@ setscreensize(void) } else win_size = DEFAULT_WINSIZE; win_size += 1; /* trailing \0 */ +#else + win_size = ConScreenSizeX() + 1; #endif - win_size = DEFAULT_WINSIZE + 1; } diff --git a/scp.c b/scp.c index e59a167..a9c2f1b 100644 --- a/scp.c +++ b/scp.c @@ -73,6 +73,14 @@ #include "includes.h" +#ifndef WINDOWS +#include +#else +#include +#include +#include "win32_dirent.h" +#endif + #include #include #ifdef HAVE_SYS_STAT_H @@ -93,10 +101,6 @@ #include -#ifndef WIN32_FIXME -#include -#endif - #include #include #include @@ -119,7 +123,7 @@ #include "misc.h" #include "progressmeter.h" -#ifdef WIN32_VS +#ifdef WINDOWS #include #endif extern char *__progname; @@ -159,14 +163,11 @@ char *ssh_program = _PATH_SSH_PROGRAM; pid_t do_cmd_pid = -1; -#ifdef WIN32_FIXME +#ifdef WINDOWS typedef BOOL bool; #define false FALSE #define true TRUE -char *win32colon(char *); -#define colon win32colon - #ifndef _SH_DENYNO #define _SH_DENYNO 0x40 #endif @@ -250,6 +251,9 @@ char *port = NULL; /* This is set password if given on the command line. */ char *password = NULL; +/* This is set ssh_config if given on the command line. */ +char *ssh_config = NULL; + int ipv_restrict = 0; #define ONLY_IPV4 1 @@ -287,27 +291,32 @@ CHAR g_HomeDir[MAX_PATH]; CHAR g_FSRoot[MAX_PATH]; int isRootedPath = 0; // set to 1 if we prepend a home root -char *TranslatePath(char *, bool *bDirSpec); int start_process_io(char *exename, char **argv, char **envv, HANDLE StdInput, HANDLE StdOutput, HANDLE StdError, unsigned long CreateFlags, PROCESS_INFORMATION *pi, char *homedir, char *lpDesktop); -// InitForMicrosoftWindows() will initialize Unix like settings in Windows operating system. +#ifdef WINDOWS struct passwd pw; char username[128]; + +// InitForMicrosoftWindows() will initialize Unix like settings in Windows operating system. int InitForMicrosoftWindows() { - int rc; - struct passwd *pwd; + int rc; + struct passwd *pwd; - /* Get user\'s passwd structure. We need this for the home directory. */ - pwd = &pw ; - rc = sizeof(username); - GetUserName(username,(LPDWORD)&rc); - pwd->pw_name = username; + /* Get user\'s passwd structure. We need this for the home directory. */ + pwd = &pw ; + rc = sizeof(username); + if (GetUserName(username, (LPDWORD)&rc)) { + pwd->pw_name = username; + } + else { + return GetLastError(); + } - return 0; + return 0; } // start of direntry functions in Windows NT like UNIX @@ -324,8 +333,8 @@ struct scp_dirent { }; typedef struct { - long hFile; - struct _finddata_t c_file; + long hFile; + struct _finddata_t c_file; } SCPDIR; @@ -343,21 +352,7 @@ char * fixslashes(char * str) return str; } -char * unfixslashes(char * str) -{ - int i; - if (str == NULL) - return str; - - int len = (int)strlen(str); - - for (i = 0; i < len; i++) - if (str[i] == '//') - str[i] = '/'; - return str; -} - -// force path separator to +// force path separator to sep char * forcepathsep(char * str, char sep) { int i; @@ -374,7 +369,6 @@ char * forcepathsep(char * str, char sep) if (sep == '/') antisep = '\\'; - int len = (int)strlen(str); for (i = 0; i < len; i++) @@ -406,13 +400,10 @@ bool getRootFrompath(char * path, char * root) return (lastslash != NULL); } - - /* * get option letter from argument vector */ - char * getfilenamefrompath(char * path) { char * lastslash; @@ -447,7 +438,7 @@ char * getfilenamefrompath(char * path) } return NULL; } - +#endif #define EMSG "" #define BADCH (int)'~' @@ -562,44 +553,6 @@ SCPDIR * scp_opendir(char *name) } } -/* Close the directory stream SCPDIRP. - Return 0 if successful, -1 if not. */ -int closedir(SCPDIR *dirp) -{ - if ( dirp && (dirp->hFile) ) { - _findclose( dirp->hFile ); - dirp->hFile = 0; - free (dirp); - } - - return 0; -} - -/* Read a directory entry from SCPDIRP. - Return a pointer to a `struct scp_dirent' describing the entry, - or NULL for EOF or error. The storage returned may be overwritten - by a later readdir call on the same SCPDIR stream. */ -struct scp_dirent *readdir(SCPDIR *dirp) -{ - struct scp_dirent *pdirentry; - - for (;;) { - if ( _findnext( dirp->hFile, &(dirp->c_file) ) == 0 ) { - if ( ( strcmp (dirp->c_file.name,".") == 0 ) || - ( strcmp (dirp->c_file.name,"..") == 0 ) ) { - continue ; - } - pdirentry = (struct scp_dirent *)malloc( sizeof(struct scp_dirent) ); - pdirentry->d_name = dirp->c_file.name ; - pdirentry->d_ino = 1; // a fictious one like UNIX to say it is nonzero - return pdirentry ; - } - else { - return (struct scp_dirent *) NULL; - } - } -} - int _utimedir (char *name, struct _utimbuf *filetime) { int rc, chandle; @@ -625,33 +578,59 @@ int _utimedir (char *name, struct _utimbuf *filetime) // end of direntry functions HANDLE hprocess=(HANDLE) 0; // we made it a global to stop child process(ssh) of scp #else + +/* Read a directory entry from SCPDIRP. +Return a pointer to a `struct scp_dirent' describing the entry, +or NULL for EOF or error. The storage returned may be overwritten +by a later readdir call on the same SCPDIR stream. */ +struct scp_dirent *readdir(SCPDIR *dirp) +{ + struct scp_dirent *pdirentry; + + for (;;) { + if (_findnext(dirp->hFile, &(dirp->c_file)) == 0) { + if ((strcmp(dirp->c_file.name, ".") == 0) || + (strcmp(dirp->c_file.name, "..") == 0)) { + continue; + } + pdirentry = (struct scp_dirent *)malloc(sizeof(struct scp_dirent)); + pdirentry->d_name = dirp->c_file.name; + pdirentry->d_ino = 1; // a fictious one like UNIX to say it is nonzero + return pdirentry; + } + else { + return (struct scp_dirent *) NULL; + } + } +} +#endif + static void killchild(int signo) { - if (do_cmd_pid > 1) { - kill(do_cmd_pid, signo ? signo : SIGTERM); - waitpid(do_cmd_pid, NULL, 0); - } + if (do_cmd_pid > 1) { + kill(do_cmd_pid, signo ? signo : SIGTERM); + waitpid(do_cmd_pid, NULL, 0); + } - if (signo) - _exit(1); - exit(1); + if (signo) + _exit(1); + exit(1); } static void suspchild(int signo) { - int status; + int status; - if (do_cmd_pid > 1) { - kill(do_cmd_pid, signo); - while (waitpid(do_cmd_pid, &status, WUNTRACED) == -1 && - errno == EINTR) - ; - kill(getpid(), SIGSTOP); - } + if (do_cmd_pid > 1) { + kill(do_cmd_pid, signo); + while (waitpid(do_cmd_pid, &status, WUNTRACED) == -1 && + errno == EINTR) + ; + kill(getpid(), SIGSTOP); + } } -#endif static int do_local_cmd(arglist *a) @@ -669,7 +648,7 @@ do_local_cmd(arglist *a) fprintf(stderr, " %s", a->list[i]); fprintf(stderr, "\n"); } - #ifdef WIN32_FIXME +#ifdef WINDOWS // flatten the cmd into a long space separated string and execute using system(cmd) api char cmdstr[2048] ; cmdstr[0] = '\0' ; @@ -680,7 +659,7 @@ do_local_cmd(arglist *a) if (system(cmdstr)) return (-1); // failure executing return (0); // success - #else +#else if ((pid = fork()) == -1) fatal("do_local_cmd: fork: %s", strerror(errno)); @@ -705,7 +684,7 @@ do_local_cmd(arglist *a) return (-1); return (0); - #endif +#endif } static int pipe_counter = 1; @@ -770,179 +749,186 @@ error: int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) { - #ifdef WIN32_FIXME - size_t i, j; +#ifdef WINDOWS + size_t i, j; - HANDLE hSaveStdout, hSaveStdin ; - HANDLE hstdout[2], hstdin[2] ; - PROCESS_INFORMATION pi; - SECURITY_ATTRIBUTES sa ; /* simple */ - int rc; - HANDLE rfdfromssh, wfdtossh ; - char *args[256]; + HANDLE hSaveStdout, hSaveStdin ; + HANDLE hstdout[2], hstdin[2] ; + PROCESS_INFORMATION pi; + SECURITY_ATTRIBUTES sa ; /* simple */ + int rc; + HANDLE rfdfromssh, wfdtossh ; + char *args[256]; - if (verbose_mode) - fprintf(stderr, "Executing: host %s, user %s, command %s\n", - host, remuser ? remuser : "(unspecified)", cmd); + if (verbose_mode) + fprintf(stderr, "Executing: host %s, user %s, command %s\n", + host, remuser ? remuser : "(unspecified)", cmd); // Child code in Windows OS will be a new created process of ssh.exe. // Child to execute the command on the remote host using ssh. - if (1) { // No fork in Windows OS, so we code it such that we use CreateProcess() + i = 0; + args[i++] = ssh_program; + size_t len; + for(j = 0; j < ssh_options_cnt; j++) { + args[i++] = "-o"; - i = 0; - args[i++] = ssh_program; - size_t len; - for(j = 0; j < ssh_options_cnt; j++) { - args[i++] = "-o"; + //args[i++] = ssh_options[j]; + len = strlen(ssh_options[j])+3; - //args[i++] = ssh_options[j]; - len = strlen(ssh_options[j])+3; + args[i] = (char *) malloc(len); // add quotes + strcpy_s(args[i],len, "\""); + strcat_s(args[i],len, ssh_options[j]); + strcat_s(args[i],len, "\""); + i++ ; - args[i] = (char *) malloc(len); // add quotes - strcpy_s(args[i],len, "\""); - strcat_s(args[i],len, ssh_options[j]); - strcat_s(args[i],len, "\""); - i++ ; + if (i > 250) + fatal("Too many -o options (total number of arguments is more than 256)"); + } + args[i++] = "-x"; + args[i++] = "-a"; + args[i++] = "\"-oFallBackToRsh no\""; // extra double quote needed for + // Windows platforms + //7/2/2001 args[i++] = "\"-oClearAllForwardings yes\""; + if (verbose_mode) + args[i++] = "-v"; + if (compress) + args[i++] = "-C"; + if (!use_privileged_port) + args[i++] = "-P"; + if (batchmode) + args[i++] = "\"-oBatchMode yes\""; + if (password != NULL) { + args[i++] = "-A"; + args[i++] = password; + } + if (cipher != NULL) { + args[i++] = "-c"; + args[i++] = cipher; + } + if (identity != NULL) { + args[i++] = "-i"; + args[i++] = identity; + } + if (port != NULL) { + args[i++] = "-p"; + args[i++] = port; + } + if (ssh_config) { + args[i++] = "-F"; + args[i++] = ssh_config; + } + if (remuser != NULL) { + args[i++] = "-l"; + args[i++] = remuser; + } - if (i > 250) - fatal("Too many -o options (total number of arguments is more than 256)"); - } - args[i++] = "-x"; - args[i++] = "-a"; - args[i++] = "\"-oFallBackToRsh no\""; // extra double quote needed for - // Windows platforms - //7/2/2001 args[i++] = "\"-oClearAllForwardings yes\""; - if (verbose_mode) - args[i++] = "-v"; - if (compress) - args[i++] = "-C"; - if (!use_privileged_port) - args[i++] = "-P"; - if (batchmode) - args[i++] = "\"-oBatchMode yes\""; - if (password != NULL) - { - args[i++] = "-A"; - args[i++] = password; - } - if (cipher != NULL) - { - args[i++] = "-c"; - args[i++] = cipher; - } - if (identity != NULL) - { - args[i++] = "-i"; - args[i++] = identity; - } - if (port != NULL) - { - args[i++] = "-p"; - args[i++] = port; - } - if (remuser != NULL) - { - args[i++] = "-l"; - args[i++] = remuser; - } + if (ipv_restrict == ONLY_IPV4) + args[i++] = "-4"; + if (ipv_restrict == ONLY_IPV6) + args[i++] = "-6"; - if (ipv_restrict == ONLY_IPV4) - args[i++] = "-4"; - if (ipv_restrict == ONLY_IPV6) - args[i++] = "-6"; + args[i++] = host; + args[i++] = cmd; + args[i++] = NULL; - args[i++] = host; - args[i++] = cmd; - args[i++] = NULL; + // Create a pair of pipes for communicating with ssh + // which we will spawn + // Do the plunmbing so that child ssh process to be spawned has its + // standard input from the pout[0] and its standard output going to + // pin[1] - // Create a pair of pipes for communicating with ssh - // which we will spawn - // Do the plunmbing so that child ssh process to be spawned has its - // standard input from the pout[0] and its standard output going to - // pin[1] + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = TRUE ; /* pipe handles to be inherited */ + sa.lpSecurityDescriptor = NULL; + /* command processor output redirected to a nameless pipe */ - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.bInheritHandle = TRUE ; /* pipe handles to be inherited */ - sa.lpSecurityDescriptor = NULL; - /* command processor output redirected to a nameless pipe */ + rc = CreateOverlappedPipe( &hstdout[0], &hstdout[1], &sa, 0 ) ; + /* read from this fd to get data from ssh.exe*/ - rc = CreateOverlappedPipe( &hstdout[0], &hstdout[1], &sa, 0 ) ; - /* read from this fd to get data from ssh.exe*/ + // make scp's pipe read handle not inheritable by ssh + rc = DuplicateHandle(GetCurrentProcess(), hstdout[0], + GetCurrentProcess(), (PHANDLE) &rfdfromssh, + 0, // this parm ignored if DUPLICATE_SAME_ACCESS below + FALSE, // not inherited + DUPLICATE_SAME_ACCESS); + CloseHandle(hstdout[0]); // this CloseHandle() is a crucial must do + hstdout[0] = rfdfromssh ; - // make scp's pipe read handle not inheritable by ssh - rc = DuplicateHandle(GetCurrentProcess(), hstdout[0], - GetCurrentProcess(), (PHANDLE) &rfdfromssh, - 0, // this parm ignored if DUPLICATE_SAME_ACCESS below - FALSE, // not inherited - DUPLICATE_SAME_ACCESS); - CloseHandle(hstdout[0]); // this CloseHandle() is a crucial must do - hstdout[0] = rfdfromssh ; + *fdin = _open_osfhandle((intptr_t)hstdout[0],0); + _setmode (*fdin, O_BINARY); // set this file handle for binary I/O + w32_allocate_fd_for_handle(hstdout[0], FALSE); + rc = CreateOverlappedPipe( &hstdin[0], &hstdin[1], &sa, 0 ) ; + /* write to this fd to get data into ssh.exe*/ - *fdin = _open_osfhandle((intptr_t)hstdout[0],0); - _setmode (*fdin, O_BINARY); // set this file handle for binary I/O + // make scp's pipe write handle not inheritable by ssh + rc = DuplicateHandle(GetCurrentProcess(), hstdin[1], + GetCurrentProcess(), (PHANDLE) &wfdtossh, + 0, // this parm ignored if DUPLICATE_SAME_ACCESS below + FALSE, // not inherited + DUPLICATE_SAME_ACCESS); + CloseHandle(hstdin[1]); // this CloseHandle() is a crucial must do + hstdin[1] = (HANDLE) wfdtossh ; - rc = CreateOverlappedPipe( &hstdin[0], &hstdin[1], &sa, 0 ) ; - /* write to this fd to get data into ssh.exe*/ + *fdout = _open_osfhandle((intptr_t)hstdin[1],0); + _setmode (*fdout, O_BINARY); // set this file handle for binary I/O + w32_allocate_fd_for_handle(hstdin[1], FALSE); - // make scp's pipe write handle not inheritable by ssh - rc = DuplicateHandle(GetCurrentProcess(), hstdin[1], - GetCurrentProcess(), (PHANDLE) &wfdtossh, - 0, // this parm ignored if DUPLICATE_SAME_ACCESS below - FALSE, // not inherited - DUPLICATE_SAME_ACCESS); - CloseHandle(hstdin[1]); // this CloseHandle() is a crucial must do - hstdin[1] = (HANDLE) wfdtossh ; + hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); + //hSaveStderr = GetStdHandle(STD_ERROR_HANDLE); + hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); + // Set a write handle to the pipe to be STDOUT. + SetStdHandle(STD_OUTPUT_HANDLE, hstdout[1]); + // Set a write handle to the pipe to be STDERR. + //SetStdHandle(STD_ERROR_HANDLE, hstdout[1]); + // Set a input handle to the pipe to be STDIN. + SetStdHandle(STD_INPUT_HANDLE, hstdin[0]); - *fdout = _open_osfhandle((intptr_t)hstdin[1],0); - _setmode (*fdout, O_BINARY); // set this file handle for binary I/O + // start the child process(ssh) + rc = start_process_io( + NULL, /* executable name with .ext found in argv[0] */ + &args[0], /* argv */ + NULL , + hstdin[0], /* std input for cmd.exe */ + hstdout[1], /* std output for cmd.exe */ + GetStdHandle(STD_ERROR_HANDLE), //hstdout[1], /* std error for cmd.exe */ + 0, // dwStartupFlags, + &pi, + NULL, /* current directory is default directory we set before */ + NULL + ); - hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); - //hSaveStderr = GetStdHandle(STD_ERROR_HANDLE); - hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); + if (port) + free(port); - // Set a write handle to the pipe to be STDOUT. - SetStdHandle(STD_OUTPUT_HANDLE, hstdout[1]); - // Set a write handle to the pipe to be STDERR. - //SetStdHandle(STD_ERROR_HANDLE, hstdout[1]); - // Set a input handle to the pipe to be STDIN. - SetStdHandle(STD_INPUT_HANDLE, hstdin[0]); + if (cipher) + free(cipher); + if (identity) + free(identity); - // start the child process(ssh) - rc = start_process_io( - NULL, /* executable name with .ext found in argv[0] */ - &args[0], /* argv */ - NULL , - hstdin[0], /* std input for cmd.exe */ - hstdout[1], /* std output for cmd.exe */ - GetStdHandle(STD_ERROR_HANDLE), //hstdout[1], /* std error for cmd.exe */ - 0, // dwStartupFlags, - &pi, - NULL, /* current directory is default directory we set before */ - NULL - ); + if (ssh_config) + free(ssh_config); - if (!rc) { - printf("%s could not be started\n", ssh_program); - exit(1); - } - else { - hprocess = pi.hProcess ; - } + if (!rc) { + printf("%s could not be started\n", ssh_program); + exit(1); + } + else { + hprocess = pi.hProcess ; + } - // After process creation, restore the saved STDOUT and STDERR. - SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout); - //SetStdHandle(STD_ERROR_HANDLE, hSaveStderr); - SetStdHandle(STD_INPUT_HANDLE, hSaveStdin); + // After process creation, restore the saved STDOUT and STDERR. + SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout); + //SetStdHandle(STD_ERROR_HANDLE, hSaveStderr); + SetStdHandle(STD_INPUT_HANDLE, hSaveStdin); - /* now close the pipe's side that the ssh.exe will use as write handle */ - CloseHandle(hstdout[1]) ; - /* now close the pipe's side that the ssh.exe will use as read handle */ - CloseHandle(hstdin[0]) ; - } + /* now close the pipe's side that the ssh.exe will use as write handle */ + CloseHandle(hstdout[1]) ; + /* now close the pipe's side that the ssh.exe will use as read handle */ + CloseHandle(hstdin[0]) ; // update passed variables with where other funstions should read and write // from to get I/O from above child process over pipe. @@ -950,8 +936,8 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) //*fdout = remout; //*fdin = remin; - return 0; - #else + return 0; +#else int pin[2], pout[2], reserved[2]; if (verbose_mode) @@ -1016,7 +1002,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) signal(SIGINT, killchild); signal(SIGHUP, killchild); return 0; - #endif +#endif } /* @@ -1027,8 +1013,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) int do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout) { - #ifndef WIN32_FIXME - +#ifndef WIN32_FIXME pid_t pid; int status; @@ -1062,7 +1047,7 @@ do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout) while (waitpid(pid, &status, 0) == -1) if (errno != EINTR) fatal("do_cmd2: waitpid: %s", strerror(errno)); - #endif +#endif return 0; } @@ -1103,10 +1088,12 @@ main(int argc, char **argv) extern char *optarg; extern int optind; +#ifdef WINDOWS + ConInit(STD_OUTPUT_HANDLE, TRUE); +#endif + /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ - #ifndef WIN32_FIXME sanitise_stdfd(); - #endif /* Copy argv, because we modify it */ newargv = xcalloc(MAX(argc + 1, 1), sizeof(*newargv)); @@ -1121,9 +1108,9 @@ main(int argc, char **argv) args.list = remote_remote_args.list = NULL; addargs(&args, "%s", ssh_program); addargs(&args, "-x"); - addargs(&args, "-oForwardAgent=no"); - addargs(&args, "-oPermitLocalCommand=no"); - addargs(&args, "-oClearAllForwardings=yes"); + addargs(&args, "\"-oForwardAgent no\""); + addargs(&args, "\"-oPermitLocalCommand no\""); + addargs(&args, "\"-oClearAllForwardings yes\""); fflag = tflag = 0; while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1) @@ -1132,32 +1119,67 @@ main(int argc, char **argv) case '1': case '2': case '4': + ipv_restrict = ONLY_IPV4; + break; case '6': + ipv_restrict = ONLY_IPV6; + break; case 'C': addargs(&args, "-%c", ch); addargs(&remote_remote_args, "-%c", ch); + + compress = ch; + break; case '3': throughlocal = 1; break; case 'o': case 'c': + addargs(&remote_remote_args, "-%c", ch); + addargs(&remote_remote_args, "%s", optarg); + addargs(&args, "-%c", ch); + addargs(&args, "%s", optarg); + + cipher = malloc(strlen(optarg) + 1); + if (cipher) + strcpy(cipher, optarg); + break; case 'i': - case 'F': + addargs(&remote_remote_args, "-%c", ch); + addargs(&remote_remote_args, "%s", optarg); + addargs(&args, "-%c", ch); + addargs(&args, "%s", optarg); + + identity = malloc(strlen(optarg) + 1); + if (identity) + strcpy(identity, optarg); + break; + case 'F': addargs(&remote_remote_args, "-%c", ch); addargs(&remote_remote_args, "%s", optarg); addargs(&args, "-%c", ch); addargs(&args, "%s", optarg); - break; + + ssh_config = malloc(strlen(optarg) + 1); + if (ssh_config) + strcpy(ssh_config, optarg); + break; case 'P': addargs(&remote_remote_args, "-p"); addargs(&remote_remote_args, "%s", optarg); addargs(&args, "-p"); addargs(&args, "%s", optarg); + + port = malloc(strlen(optarg) + 1); + if (port) + strcpy(port, optarg); break; case 'B': - addargs(&remote_remote_args, "-oBatchmode=yes"); - addargs(&args, "-oBatchmode=yes"); + addargs(&remote_remote_args, "\"-oBatchmode yes\""); + addargs(&args, "\"-oBatchmode yes\""); + + batchmode = 1; break; case 'l': limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024, @@ -1208,22 +1230,18 @@ main(int argc, char **argv) argc -= optind; argv += optind; - #ifndef WIN32_FIXME +#ifndef WINDOWS if ((pwd = getpwuid(userid = getuid())) == NULL) fatal("unknown user %u", (u_int) userid); - #else +#else InitForMicrosoftWindows(); // picks the username, user home dir - #endif +#endif if (!isatty(STDOUT_FILENO)) showprogress = 0; remin = STDIN_FILENO; remout = STDOUT_FILENO; - #ifdef WIN32_FIXME - _setmode(remin,O_BINARY); // needed for Windows OS to avoid CrLf translations of text mode - _setmode(remout,O_BINARY); - #endif if (fflag) { /* Follow "protocol", send data. */ @@ -1249,7 +1267,7 @@ main(int argc, char **argv) iamrecursive ? " -r" : "", pflag ? " -p" : "", targetshouldbedirectory ? " -d" : ""); - #ifndef WIN32_FIXME + #ifndef WINDOWS (void) signal(SIGPIPE, lostconn); #endif @@ -1264,7 +1282,7 @@ main(int argc, char **argv) * Finally check the exit status of the ssh process, if one was forked * and no error has occurred yet */ - #ifndef WIN32_FIXME +#ifndef WINDOWS if (do_cmd_pid != -1 && errs == 0) { if (remin != -1) (void) close(remin); @@ -1277,7 +1295,7 @@ main(int argc, char **argv) errs = 1; } } - #endif +#endif exit(errs != 0); } @@ -1380,7 +1398,7 @@ toremote(char *targ, int argc, char **argv) freeargs(&alist); addargs(&alist, "%s", ssh_program); addargs(&alist, "-x"); - addargs(&alist, "-oClearAllForwardings=yes"); + addargs(&alist, "-\"oClearAllForwardings yes\""); addargs(&alist, "-n"); for (j = 0; j < remote_remote_args.num; j++) { addargs(&alist, "%s", @@ -1443,7 +1461,6 @@ tolocal(int argc, char **argv) for (i = 0; i < argc - 1; i++) { if (!(src = colon(argv[i]))) { /* Local to local. */ - #ifndef WIN32_FIXME freeargs(&alist); addargs(&alist, "%s", _PATH_CP); if (iamrecursive) @@ -1455,7 +1472,6 @@ tolocal(int argc, char **argv) addargs(&alist, "%s", argv[argc-1]); if (do_local_cmd(&alist)) ++errs; - #endif continue; } *src++ = 0; @@ -1484,735 +1500,7 @@ tolocal(int argc, char **argv) remin = remout = -1; } } -#ifdef WIN32_FIXME -void -source(int argc, char *argv[]) -{ - struct stat stb; - static BUF buffer; - BUF *bp; - off_t i; - int haderr; - size_t amt, indx, result; - int fd; - char *last, *name, buf[16384]; - unsigned short locfmode; - char * originalname = NULL; - char aggregatePath[MAX_PATH] = ""; - char * pArgPath; - bool bDirSpec = false; - char * filenames[1024]; - int numfiles = 0; - - WIN32_FIND_DATA FindFileData; - HANDLE hFind; - - char FileRoot[MAX_PATH]; - bool bHasRoot = false; - - for (indx = 0; indx < (size_t)argc; ++indx) { - if (strchr(argv[indx],'*')) - { - bHasRoot = getRootFrompath(argv[indx],FileRoot); - - if (1){//!iamremote) { - hFind = FindFirstFile(argv[indx], &FindFileData); - if (hFind != INVALID_HANDLE_VALUE){ - - do { - if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) - if (bHasRoot) - { - filenames[numfiles] = (char *)malloc(MAX_PATH); - sprintf(filenames[numfiles++],"%s/%s",FileRoot,FindFileData.cFileName); - } - else - filenames[numfiles++] = strdup(FindFileData.cFileName); - - if (numfiles >= 1024) - { - break; - } - } - while (FindNextFile(hFind,&FindFileData)); - FindClose(hFind); - } - - } - // expand - } - else - filenames[numfiles++] = strdup(argv[indx]); - - if (numfiles >= 1024) - break; - } - - - // loop through filenames list - for (indx = 0; indx < (size_t)numfiles; ++indx) { - - { - pArgPath = filenames[indx]; - } - - originalname = pArgPath; - name = TranslatePath(pArgPath, &bDirSpec); - if (name == NULL) - { -// strerror_s(buf, EPERM); - strerror_s(buf, sizeof(buf), ENOENT); - run_err("%s: %s", pArgPath, buf); - continue; - } - - if (_sopen_s(&fd, name, O_RDONLY | O_BINARY, _SH_DENYNO, 0) != 0) { - // in NT, we have to check if it is a directory - if (stat(name, &stb) >= 0) { - goto switchpoint; - } - else - goto syserr; - } - - if (_fstati64(fd, &stb) < 0) { -syserr: - strerror_s(buf, sizeof(buf), errno); - run_err("%s: %s", originalname, buf); - goto next; - } -switchpoint: - switch (stb.st_mode & _S_IFMT) { - case _S_IFREG: - break; - case _S_IFDIR: - if (iamrecursive) { - rsource(name, &stb); - goto next; - } - /* FALLTHROUGH */ - default: - run_err("%s: not a regular file", name); - goto next; - } - - last = getfilenamefrompath(originalname); - - if (pflag) { - /* - * Make it compatible with possible future - * versions expecting microseconds. - */ - (void)sprintf_s(buf, sizeof(buf), "T%lu 0 %lu 0\n", - (unsigned long)stb.st_mtime, - (unsigned long)stb.st_atime); - (void)_write(remout, buf, (unsigned int)strlen(buf)); - if (response() < 0) - goto next; - } -//CHECK #define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) -//#define FILEMODEMASK (S_IRWXU|S_IRWXG|S_IRWXO) -#define FILEMODEMASK (S_IREAD|S_IWRITE|S_IEXEC) - locfmode = stb.st_mode & FILEMODEMASK; - locfmode |= ((locfmode & _S_IREAD) >> 3); // group access, just read bit now - locfmode |= ((locfmode & _S_IREAD) >> 6); // world access, just read bit now - - - (void)sprintf_s(buf, sizeof(buf), "C%04o %I64u %s\n", - (unsigned int)(locfmode), //(stb.st_mode & FILEMODEMASK), - (u_int64_t)stb.st_size, - last); - if (scpverbose) - { - fprintf(stderr, "Sending file modes: %s", buf); - fflush(stderr); - } - (void)_write(remout, buf, (unsigned int)strlen(buf)); - if (response() < 0) - goto next; - if ((bp = allocbuf(&buffer, fd, 16384)) == NULL) { -next: if (fd != -1) (void)_close(fd); - continue; - } -#ifdef WITH_SCP_STATS - if (!iamremote && statistics) - { - statbytes = 0; - ratebs = 0.0; - stat_starttime = time(NULL); - stat_starttimems = GetTickCount(); - } -#endif /* WITH_SCP_STATS */ - - /* Keep writing after an error so that we stay sync'd up. */ - for (haderr = 0, i = 0; i < (size_t)stb.st_size; i += bp->cnt) { - amt = bp->cnt; - if (i + amt > (size_t)stb.st_size) - amt = (size_t)(stb.st_size - i); - if (!haderr) { - result = _read(fd, bp->buf, (unsigned int)amt); - if (result != amt) - haderr = result >= 0 ? EIO : errno; - } - if (haderr) - { - (void)_write(remout, bp->buf, (unsigned int)amt); -#ifdef WITH_SCP_STATS - if (!iamremote && statistics) - { - if ((time(NULL) - stat_lasttime) > 0) - { - int bwritten; - bwritten = fprintf(SOME_STATS_FILE, - "\r%s : ERROR..continuing to end of file anyway", last); - stats_fixlen(bwritten); - fflush(SOME_STATS_FILE); - stat_lasttime = time(NULL); - } - } -#endif /* WITH_SCP_STATS */ - } - else { - result = _write(remout, bp->buf, (unsigned int)amt); - if (result != amt) - haderr = result >= 0 ? EIO : errno; -#ifdef WITH_SCP_STATS - if (!iamremote && statistics) - { - statbytes += result; - /* At least one second delay between - outputs, or if finished */ - if (time(NULL) - stat_lasttime > 0 || - //(result + i) == stb.st_size) - statbytes == stb.st_size) - { - int bwritten; - - if (time(NULL) == stat_starttime) - { - stat_starttime -= 1; - // stat_starttimems -= 1000; - } - ratebs = ssh_max(1.0, - (double) statbytes / - (time(NULL) - - stat_starttime)); - bwritten = - fprintf(SOME_STATS_FILE, - "\r%-25.25s | %10I64d KB | %7.1f kB/s | %s | %3d%%", - last, - statbytes / 1024, - ratebs / 1024, - stat_eta_new((int) ( GetTickCount() - stat_starttimems)), -//stat_eta((int) ( time(NULL) - stat_starttime)), - (int) (100.0 * - (double) statbytes / - stb.st_size)); - if (all_statistics && /*(result + i)*/ statbytes == - stb.st_size) - bwritten += fprintf(SOME_STATS_FILE, - "\n"); - fflush(SOME_STATS_FILE); - stats_fixlen(bwritten); - stat_lasttime = time(NULL); - } - } -#endif /* WITH_SCP_STATS */ - } - } - - - - if (_close(fd) < 0 && !haderr) - haderr = errno; - if (!haderr) - (void)_write(remout, "", 1); - else - { - strerror_s(buf, sizeof(buf), haderr); - run_err("%s: %s", originalname, buf); - } - (void)response(); - } - int ii; - if (numfiles > 0) - for (ii = 0;iist_mtime, - (unsigned long)statp->st_atime); - (void)_write(remout, path, (unsigned int)strlen(path)); - if (response() < 0) { - closedir(dirp); - return; - } - } - locfmode = statp->st_mode & FILEMODEMASK; - locfmode |= ((locfmode & (_S_IREAD | _S_IEXEC)) >> 3); // group access, read,exec bit now - locfmode |= ((locfmode & (_S_IREAD | _S_IEXEC)) >> 6); // world access, read,exec bit now - - (void)sprintf_s(path, sizeof(path), - "D%04o %d %.1024s\n", (unsigned int)(locfmode), - 0, last); - if (scpverbose) - fprintf(stderr, "Entering directory: %s", path); - (void)_write(remout, path, (unsigned int)strlen(path)); - if (response() < 0) { - closedir(dirp); - return; - } - while ((dp = readdir(dirp))) { - //if (dp->d_ino == 0) //commented out as not needed - // continue; - - if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) - continue; - if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path) - 1) { - run_err("%s/%s: name too long", name, dp->d_name); - continue; - } - (void)sprintf_s(path, sizeof(path), "%s/%s", name, dp->d_name); - vect[0] = path; - source(1, vect); - } - (void)closedir(dirp); - (void)_write(remout, "E\n", 2); - (void)response(); -} - -void sink(int argc, char *argv[]) -{ -// DWORD dwread; - static BUF buffer; - struct stat stb; - enum { YES, NO, DISPLAYED } wrerr; - BUF *bp; - size_t i, j, size; - size_t amt, count, exists, first; - int mask, mode, ofd, omode; - int setimes, targisdir, wrerrno = 0; - char ch, *cp, *np, *targ, *why, *vect[1], buf[16384]; - char aggregatePath[MAX_PATH] = ""; - struct _utimbuf ut; - int dummy_usec; - bool bDirSpec = false; - -#ifdef WITH_SCP_STATS - char *statslast; -#endif /* WITH_SCP_STATS */ - -#define SCREWUP(str) { why = str; goto screwup; } - - - - setimes = targisdir = 0; - _umask_s(0, &mask); - int oldmask; - if (!pflag) - _umask_s(mask,&oldmask); - if (argc != 1) { - if (!iamremote) - { - run_err("ambiguous target"); - exit(1); - } - int i; - for (i = 0; i"); - do { - if (_read(remin, &ch, sizeof(ch)) != sizeof(ch)) - SCREWUP("lost connection"); - *cp++ = ch; - } while (cp < &buf[sizeof(buf) - 1] && ch != '\n'); - *cp = 0; - - if (buf[0] == '\01' || buf[0] == '\02') { - if (iamremote == 0) - (void)_write(STDERR_FILENO, - buf + 1, (unsigned int)strlen(buf + 1)); - if (buf[0] == '\02') - exit(1); - ++errs; - continue; - } - if (buf[0] == 'E') { - (void)_write(remout, "", 1); - return; - } - - if (ch == '\n') - *--cp = 0; - -#define getnum(t) (t) = 0; \ - while (*cp >= '0' && *cp <= '9') (t) = (t) * 10 + (*cp++ - '0'); - cp = buf; - if (*cp == 'T') { - setimes++; - cp++; - getnum(ut.modtime); - if (*cp++ != ' ') - SCREWUP("mtime.sec not delimited"); - getnum(dummy_usec); - if (*cp++ != ' ') - SCREWUP("mtime.usec not delimited"); - getnum(ut.actime); - if (*cp++ != ' ') - SCREWUP("atime.sec not delimited"); - getnum(dummy_usec); - if (*cp++ != '\0') - SCREWUP("atime.usec not delimited"); - (void)_write(remout, "", 1); - goto keepgoing; // added 5/3/2001 by QI for -p not working !!! - // in place of next continue commented out - //continue; - } - if (*cp != 'C' && *cp != 'D') { - /* - * Check for the case "rcp remote:foo\* local:bar". - * In this case, the line "No match." can be returned - * by the shell before the rcp command on the remote is - * executed so the ^Aerror_message convention isn't - * followed. - */ - if (first) { - run_err("%s", cp); - exit(1); - } - SCREWUP("expected control record"); - } - mode = 0; - for (++cp; cp < buf + 5; cp++) { - if (*cp < '0' || *cp > '7') - SCREWUP("bad mode"); - mode = (mode << 3) | (*cp - '0'); - } - if (*cp++ != ' ') - SCREWUP("mode not delimited"); - - for (size = 0; *cp >= '0' && *cp <= '9';) - size = size * 10 + (*cp++ - '0'); - if (*cp++ != ' ') - SCREWUP("size not delimited"); - if (targisdir) { - static char *namebuf; - static unsigned int cursize; - size_t need; - - need = strlen(targ) + strlen(cp) + 250; - if (need > cursize) - namebuf = (char *)xmalloc(need); - (void)sprintf_s(namebuf, need, "%s%s%s", targ, - *targ ? "/" : "", cp); - np = namebuf; - } else - np = targ; - exists = stat(np, &stb) == 0; - if (buf[0] == 'D') { - int mod_flag = pflag; - if (exists) { - if (!S_ISDIR(stb.st_mode)) { - errno = ENOTDIR; - goto bad; - } - if (pflag) - (void)_chmod(np, mode); - } else { - /* Handle copying from a read-only directory */ - mod_flag = 1; - if (_mkdir(np) < 0) // was mkdir(np, mode | S_IRWXU) < 0) - { - if (errno == EEXIST) // stat returned didn't exist, but mkdir returned it does - see this when user doesn't have access - errno = EPERM; - np = targ; - goto bad; - } - } - vect[0] = np; - sink(1, vect); - if (setimes) { - setimes = 0; - //if (_utime(np, &ut) < 0) - // in NT cannot set directory time by _utime(), we have our - // call _utimedir() above in this file. - if (_utimedir(np, &ut) < 0) - //run_err("%s: set times: %s", np, strerror(errno)); - run_err("setting times on %s failed:", np ); - } - if (mod_flag) - (void)_chmod(np, mode); - continue; - } - omode = mode; -#ifdef HAVE_FTRUNCATE - /* Don't use O_TRUNC so the file doesn't get corrupted if - copying on itself. */ - ofd = open(np, O_WRONLY|O_CREAT|O_BINARY, mode); -#else /* HAVE_FTRUNCATE */ - _sopen_s(&ofd, np, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, _SH_DENYNO, S_IWRITE); -#endif /* HAVE_FTRUNCATE */ - if (ofd < 0) { -bad: strerror_s(buf, sizeof(buf), errno); - - if (isRootedPath && (strlen(np) > strlen(g_HomeDir))) - np += strlen(g_HomeDir); - run_err("%s: %s", np, buf); - continue; - } - (void)_write(remout, "", 1); - if ((bp = allocbuf(&buffer, ofd, 16384)) == NULL) { - (void)_close(ofd); - continue; - } - cp = bp->buf; - wrerr = NO; -#ifdef WITH_SCP_STATS - if (!iamremote && statistics) - { - statbytes = 0; - ratebs = 0.0; - stat_starttime = time(NULL); - stat_starttimems = GetTickCount(); - statslast = getfilenamefrompath(np); - - } -#endif /* WITH_SCP_STATS */ - for (count = i = 0; i < size; i += 16384) { - amt = 16384; - if (i + amt > size) - amt = size - i; - count += amt; - do { - j = _read(remin, cp, (unsigned int)amt); - if (j <= 0) { - strerror_s(buf, sizeof(buf), errno); - run_err("%s", j ? buf : - "dropped connection"); - exit(1); - } - -#ifdef WITH_SCP_STATS - if (!iamremote && statistics){ - int bwritten; - statbytes += j; - if ( (time(NULL) - stat_lasttime > 0) || ( statbytes == size) ) { - if (time(NULL) == stat_starttime) { - stat_starttime -= 1; -// stat_starttimems -= 1000; - } - ratebs = ssh_max(1.0, - (double) - statbytes / - (time(NULL) - - stat_starttime)); - bwritten = - fprintf(SOME_STATS_FILE, - "\r%-25.25s | %10I64d KB | %7.1f kB/s | %s | %3d%%", - statslast, - statbytes / 1024, - ratebs / 1024, -// stat_eta((int) -// (time(NULL) - stat_starttime)), - stat_eta_new((int)(GetTickCount() - stat_starttimems)), - (int) (100.0 * - (double) statbytes /size)); - if (all_statistics && statbytes == size) - bwritten += fprintf(SOME_STATS_FILE, "\n"); - fflush(SOME_STATS_FILE); - stats_fixlen(bwritten); - stat_lasttime = time(NULL); - } - } -#endif /* WITH_SCP_STATS */ - amt -= j; - cp += j; - } while (amt > 0); - if (count == bp->cnt) { - /* Keep reading so we stay sync'd up. */ - if (wrerr == NO) { - j = _write(ofd, bp->buf, (unsigned int)count); - if (j != count) { - wrerr = YES; - wrerrno = j >= 0 ? EIO : errno; - } - } - count = 0; - cp = bp->buf; - } - } // end of main 16384 byte read for loop - if (count != 0 && wrerr == NO && - (j = _write(ofd, bp->buf, (unsigned int)count)) != count) { - wrerr = YES; - wrerrno = j >= 0 ? EIO : errno; - } -#ifdef HAVE_FTRUNCATE - if (ftruncate(ofd, size)) { - run_err("%s: truncate: %s", np, strerror(errno)); - wrerr = DISPLAYED; - } -#endif /* HAVE_FTRUNCATE */ - if (pflag) { - if (exists || omode != mode) - { -#ifdef HAVE_FCHMOD - if (fchmod(ofd, omode)) { -#else /* HAVE_FCHMOD */ - if (_chmod(np, omode)) { -#endif /* HAVE_FCHMOD */ - strerror_s(buf, sizeof(buf), errno); - run_err("%s: set mode: %s", - np, buf); - } - } - } else { - if (!exists && omode != mode) -#ifdef HAVE_FCHMOD - if (fchmod(ofd, omode & ~mask)) { -#else /* HAVE_FCHMOD */ - if (_chmod(np, omode & ~mask)) { -#endif /* HAVE_FCHMOD */ - strerror_s(buf, sizeof(buf), errno); - run_err("%s: set mode: %s", - np, buf); - } - } - (void)_close(ofd); - (void)response(); - if (setimes && wrerr == NO) { - setimes = 0; - if (_utime(np, &ut) < 0) { - - // see if the error was due to read only file permission - if ( _access(np,2) < 0 ) { - // lacks write permission, so give it for now - _chmod(np, _S_IWRITE); - if (_utime(np, &ut) < 0) { - strerror_s(buf, sizeof(buf), errno); - run_err("%s: set times: %s", np, buf); - wrerr = DISPLAYED; - } - _chmod(np, _S_IREAD); // read only permission set again - } - else { - strerror_s(buf, sizeof(buf), errno); - run_err("%s: set times: %s", - np, buf); - wrerr = DISPLAYED; - } - } - } - switch(wrerr) { - case YES: - strerror_s(buf, sizeof(buf), errno); - run_err("%s: %s", np, buf); - break; - case NO: - (void)_write(remout, "", 1); - fflush(stdout); - fflush(stdin); - break; - case DISPLAYED: - break; - } - } - - if (targ) - LocalFree(targ); - - if ( first > 1 ) { - return; - } -screwup: - run_err("protocol error: %s", why); - exit(1); -} - -int response(void) -{ - char ch, *cp, resp, rbuf[2048]; - - if (_read(remin, &resp, sizeof(resp)) != sizeof(resp)) - lostconn(0); - - cp = rbuf; - switch(resp) { - case 0: /* ok */ - return (0); - default: - *cp++ = resp; - /* FALLTHROUGH */ - case 1: /* error, followed by error msg */ - case 2: /* fatal error, "" */ - do { - if (_read(remin, &ch, sizeof(ch)) != sizeof(ch)) - lostconn(0); - *cp++ = ch; - } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n'); - - if (!iamremote) - (void)_write(STDERR_FILENO, rbuf, (unsigned int)(cp - rbuf)); - ++errs; - if (resp == 1) - return (-1); - exit(1); - } - /* NOTREACHED */ -} -#else void source(int argc, char **argv) { @@ -2222,7 +1510,7 @@ source(int argc, char **argv) off_t i, statbytes; size_t amt, nr; int fd = -1, haderr, indx; - char *last, *name, buf[2048], encname[PATH_MAX]; + char *last, *lastf, *lastr, *name, buf[2048], encname[PATH_MAX]; int len; for (indx = 0; indx < argc; ++indx) { @@ -2259,10 +1547,22 @@ syserr: run_err("%s: %s", name, strerror(errno)); run_err("%s: not a regular file", name); goto next; } - if ((last = strrchr(name, '/')) == NULL) +#ifdef WINDOWS + if ((lastf = strrchr(name, '/')) == NULL && (lastr = strrchr(name, '\\')) == NULL) last = name; - else - ++last; + else { + if (lastf) + last = lastf; + if (lastr) + last = lastr; + ++last; + } +#else + if ((last = strrchr(name, '/')) == NULL) + last = name; + else + ++last; +#endif curfile = last; if (pflag) { if (do_times(remout, verbose_mode, &stb) < 0) @@ -2351,7 +1651,17 @@ rsource(char *name, struct stat *statp) (void) snprintf(path, sizeof path, "D%04o %d %.1024s\n", (u_int) (statp->st_mode & FILEMODEMASK), 0, last); if (verbose_mode) - fprintf(stderr, "Entering directory: %s", path); +#ifdef WINDOWS + { + printf("Entering directory: "); + wchar_t* wtmp = utf8_to_utf16(path); + WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), wtmp, wcslen(wtmp), 0, 0); + free(wtmp); + } +#else + fprintf(stderr, "Entering directory: %s", path); +#endif + (void) atomicio(vwrite, remout, path, strlen(path)); if (response() < 0) { closedir(dirp); @@ -2426,8 +1736,16 @@ sink(int argc, char **argv) } while (cp < &buf[sizeof(buf) - 1] && ch != '\n'); *cp = 0; if (verbose_mode) - fprintf(stderr, "Sink: %s", buf); - +#ifdef WINDOWS + { + printf("Sink: "); + wchar_t* wtmp = utf8_to_utf16(buf); + WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), wtmp, wcslen(wtmp), 0, 0); + free(wtmp); + } +#else + fprintf(stderr, "Sink: %s", buf); +#endif if (buf[0] == '\01' || buf[0] == '\02') { if (iamremote == 0) (void) atomicio(vwrite, STDERR_FILENO, @@ -2703,7 +2021,6 @@ response(void) } /* NOTREACHED */ } -#endif void usage(void) @@ -2739,7 +2056,7 @@ run_err(const char *fmt,...) fprintf(stderr, "\n"); } } -#ifndef WIN32_FIXME + void verifydir(char *cp) { @@ -2822,95 +2139,6 @@ lostconn(int signo) else exit(1); } -#else -char *win32colon(char *cp) -{ - int len=0; - bool bSkip = false; - - if (*cp == ':') /* Leading colon is part of file name. */ - return (0); - - for (; *cp; ++cp) { - len++; - - if (*cp == '[') - bSkip = true; - - if (bSkip && *cp!= ']') - continue; - - if (*cp == ']') - bSkip = false; - - if (*cp == ':') { - if ( len != 2 ) { // avoid x: format for drive letter in Windows - return (cp); - } - } - // if ( (*cp == '/') || (*cp == '\\') ) - // return (0); - } - return (0); -} - -void verifydir(char *cp) -{ - struct stat stb; - - if (!stat(cp, &stb)) { - if (S_ISDIR(stb.st_mode)) - return; - errno = ENOTDIR; - } - char buf[MAX_PATH]; - strerror_s(buf, sizeof(buf), errno); - run_err("%s: %s", cp, buf); - exit(1); -} - -int okname(char *cp0) -{ - return (1); -} - -BUF * -allocbuf(BUF *bp, int fd, int blksize) -{ - size_t size; -#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE - struct stat stb; - - if (fstat(fd, &stb) < 0) { - run_err("fstat: %s", strerror(errno)); - return (0); - } - size = roundup(stb.st_blksize, blksize); - if (size == 0) - size = blksize; -#else /* HAVE_STRUCT_STAT_ST_BLKSIZE */ - size = blksize; -#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ - if (bp->cnt >= size) - return (bp); - if (bp->buf == NULL) - bp->buf = xmalloc(size); - else - bp->buf = xreallocarray(bp->buf, 1, size); - memset(bp->buf, 0, size); - bp->cnt = size; - return (bp); -} - -void lostconn(int signo) -{ - if (!iamremote) - fprintf(stderr, "lost connection\n"); - exit(1); -} -#endif - -#ifdef WIN32_FIXME #ifdef WITH_SCP_STATS void stats_fixlen(int bwritten) @@ -2927,17 +2155,11 @@ void stats_fixlen(int bwritten) fflush(SOME_STATS_FILE); } - char *stat_eta_new(int msecs) { static char stat_result[32]; int hours = 0, mins = 0, secs = 0; - // hours = msecs / 3600000; - // msecs %= 3600000; - // mins = msecs / 60000; - // msecs %= 60000; - hours = msecs / 3600000; msecs %= 3600000; mins = msecs / 60000; @@ -2954,7 +2176,7 @@ char *stat_eta_new(int msecs) return(stat_result); } -char *stat_eta_old(int secs) +char *stat_eta(int secs) { static char stat_result[20]; int hours, mins; @@ -2964,83 +2186,12 @@ char *stat_eta_old(int secs) mins = secs / 60; secs %= 60; - sprintf_s(stat_result, sizeof(stat_result), "%02d:%02d:%02d", hours, mins, secs); + sprintf(stat_result, "%02d:%02d:%02d", hours, mins, secs); return(stat_result); } #endif /* WITH_SCP_STATS */ - -char *TranslatePath(char *path, bool *bDirSpec) -{ - char temp[MAX_PATH*2]; - char resolved[MAX_PATH]; - char * rootpath; - - if ( iamremote == 0) - return path; // if we are scp client, nothing special to do, return path we got. - - char *s = NULL; - - if (g_RootMode == M_ADMIN){ - rootpath = g_FSRoot; - }else{ - rootpath = g_HomeDir; - } - - if (!_strnicmp(path, rootpath, strlen(g_HomeDir))) - { // already set to home directory - strcpy_s(temp, sizeof(temp), path); // absolute path - } - else - { - if (path[1] != ':') - { - if (path[0] == '\\' || path[0] == '/') - sprintf_s(temp, sizeof(temp), "%s%s",rootpath,&path[1]); - else - sprintf_s(temp, sizeof(temp), "%s%s",rootpath,path); - } - else - strcpy(temp,path); - - } - fixslashes(temp); - PathCanonicalizeA(resolved,temp); - - - *bDirSpec = (resolved[strlen(temp)-1] == '\\'); - // Remove trailing slash unless it's a root spec (c:\ etc) - if (strcmp(&(resolved[1]),":\\") && resolved[strlen(temp)-1] == '\\') - resolved[strlen(temp)-1] = 0x00; - - if (strlen(resolved) == strlen(rootpath)-1) - { - // We specify a length of less than one because if we - // resolve to the scp home directory (i.e. user specified - // '.' for the target), then PathCanonicalize will strip - // the trailing slash. - if (_strnicmp(resolved, rootpath, strlen(g_HomeDir)-1)) - return NULL; - } - else if (!((g_RootMode == M_ADMIN) && resolved[1] == ':')){ - // if we are in admin mode and the user specified a drive, let it go through - if (_strnicmp(resolved, rootpath, strlen(rootpath))) - return NULL; - } - - // if we reach this point, the path is fine. We can actually just return path - // if the path doesn't begin with a slash - if (path[0] != '/' && path[0] != '\\') - return path; - - - s = (char *)LocalAlloc(LPTR,strlen(resolved)+1); - strcpy_s(s,strlen(resolved)+1,resolved); - isRootedPath = 1; - - return s; -} - +#ifdef WINDOWS /* start_process_io() input parameters: exename - name of executable @@ -3092,7 +2243,7 @@ int start_process_io(char *exename, char **argv, char **envv, ctr++; } - ret = CreateProcess( + ret = CreateProcess( exename, // given in form like "d:\\util\\cmd.exe" cmdbuf, /* in "arg0 arg1 arg2" form command line */ NULL, /* process security */ diff --git a/sftp-client.c b/sftp-client.c index 141234f..3034b77 100644 --- a/sftp-client.c +++ b/sftp-client.c @@ -109,30 +109,8 @@ } } - /** TODO - Move this to POSIX wrapper**/ - /* ??? What if fd is nonblocking ???*/ - int writev(int fd, struct iovec *iov, int iovcnt) - { - int written = 0; - - int i = 0; - - for (i = 0; i < iovcnt; i++) - { - int ret = write(fd, iov[i].iov_base, iov[i].iov_len); - - if (ret > 0) - { - written += ret; - } - } - - return written; - } - #endif - extern volatile sig_atomic_t interrupted; extern int showprogress; @@ -776,6 +754,7 @@ do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag) status = get_status(conn, id); if (status != SSH2_FX_OK && print_flag) error("Couldn't create directory: %s", fx2txt(status)); + errno = status; return status == SSH2_FX_OK ? 0 : -1; } @@ -1502,15 +1481,19 @@ do_download(struct sftp_conn *conn, const char *remote_path, error("Can't set times on \"%s\": %s", local_path, strerror(errno)); } -#ifndef WIN32_FIXME -// PRAGMA:TODO + if (fsync_flag) { debug("syncing \"%s\"", local_path); +#ifdef WINDOWS + if(FlushFileBuffers(local_fd)) + error("Couldn't sync file \"%s\": %s", + local_path, strerror(GetLastError())); +#else if (fsync(local_fd) == -1) error("Couldn't sync file \"%s\": %s", local_path, strerror(errno)); - } #endif + } } close(local_fd); sshbuf_free(msg); @@ -1657,15 +1640,7 @@ do_upload(struct sftp_conn *conn, const char *local_path, TAILQ_INIT(&acks); - #if(0)//def WIN32_FIXME - - if ((local_fd = _open(local_path, O_RDONLY | O_BINARY, 0)) == -1) { - - #else - if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) { - - #endif error("Couldn't open local file \"%s\" for reading: %s", local_path, strerror(errno)); return(-1); @@ -1904,7 +1879,7 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, * if it was created successfully. */ if (status != SSH2_FX_OK) { - if (status != SSH2_FX_FAILURE) + if (errno != SSH2_FX_FAILURE) return -1; if (do_stat(conn, dst, 0) == NULL) return -1; diff --git a/sftp-common.c b/sftp-common.c index b7f974b..513e0aa 100644 --- a/sftp-common.c +++ b/sftp-common.c @@ -26,7 +26,7 @@ #include "includes.h" -#ifdef WIN32_FIXME +#ifdef WINDOWS void strmode(mode_t mode, char *p); void strmode_from_attrib(unsigned attrib, char *p); #endif @@ -225,38 +225,32 @@ ls_file(const char *name, const struct stat *st, int remote, int si_units) char sbuf[FMT_SCALED_STRSIZE]; time_t now; -#ifndef WIN32_FIXME - strmode(st->st_mode, mode); -#else - strmode(st->st_mode, mode); + strmode(st->st_mode, mode); +#ifdef WINDOWS strmode_from_attrib(remote, mode); #endif if (!remote) { #ifndef WIN32_FIXME - user = user_from_uid(st->st_uid, 0); + user = user_from_uid(st->st_uid, 0); #else - user = "\0"; - snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid); - group = gbuf; + user = "\0"; + snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid); + group = gbuf; #endif } else { snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid); user = ubuf; -#ifdef WIN32_FIXME - - snprintf(gbuf, sizeof gbuf, "%u", (u_int) st -> st_gid); - - group = gbuf; - +#ifdef WINDOWS + snprintf(gbuf, sizeof gbuf, "%u", (u_int) st -> st_gid); + group = gbuf; #else - if (!remote) { - group = group_from_gid(st->st_gid, 0); - } else { - snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid); - group = gbuf; - } + if (!remote) { + group = group_from_gid(st->st_gid, 0); + } else { + snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid); + group = gbuf; + } #endif - } if (ltime != NULL) { now = time(NULL); @@ -283,7 +277,7 @@ ls_file(const char *name, const struct stat *st, int remote, int si_units) return xstrdup(buf); } -#ifdef WIN32_FIXME +#ifdef WINDOWS #include #include @@ -299,7 +293,6 @@ strmode_from_attrib(unsigned attrib, char *p) *p = '-'; } - void strmode(mode_t mode, char *p) { diff --git a/sftp-glob.c b/sftp-glob.c index 5ba93f2..fbe3294 100644 --- a/sftp-glob.c +++ b/sftp-glob.c @@ -22,7 +22,7 @@ # include #endif -#ifdef WIN32_VS +#ifdef WINDOWS #include "win32_dirent.h" #else #include @@ -37,10 +37,6 @@ #include "sftp-common.h" #include "sftp-client.h" -#ifdef WIN32_VS -#include "win32_dirent.c" -#endif - int remote_glob(struct sftp_conn *, const char *, int, int (*)(const char *, int), glob_t *); diff --git a/sftp-server.c b/sftp-server.c index 72477d8..09633af 100644 --- a/sftp-server.c +++ b/sftp-server.c @@ -61,11 +61,8 @@ #include "sftp.h" #include "sftp-common.h" -#ifdef WIN32_VS -#include "win32_dirent.c" -#endif - #ifdef WIN32_FIXME +#include char * get_inside_path(char *, BOOL, BOOL); int readlink(const char *path, char *link, int linklen); @@ -75,6 +72,7 @@ * stat requires paths * without slash at the end). */ + char *realpathWin32(const char *path, char resolved[PATH_MAX]); char *realpathWin32i(const char *path, char resolved[PATH_MAX]); #define realpath realpathWin32 @@ -2166,55 +2164,55 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) #ifdef WIN32_FIXME char *realpathWin32(const char *path, char resolved[PATH_MAX]) { - char realpath[PATH_MAX]; + char realpath[PATH_MAX]; - strlcpy(resolved, path + 1, sizeof(realpath)); - backslashconvert(resolved); - PathCanonicalizeA(realpath, resolved); - slashconvert(realpath); + strlcpy(resolved, path + 1, sizeof(realpath)); + backslashconvert(resolved); + PathCanonicalizeA(realpath, resolved); + slashconvert(realpath); - /* - * Store terminating slash in 'X:/' on Windows. - */ + /* + * Store terminating slash in 'X:/' on Windows. + */ - if (realpath[1] == ':' && realpath[2] == 0) - { - realpath[2] = '/'; - realpath[3] = 0; - } + if (realpath[1] == ':' && realpath[2] == 0) + { + realpath[2] = '/'; + realpath[3] = 0; + } - resolved[0] = *path; // will be our first slash in /x:/users/test1 format - strncpy(resolved + 1, realpath, sizeof(realpath)); - return resolved; + resolved[0] = *path; // will be our first slash in /x:/users/test1 format + strncpy(resolved + 1, realpath, sizeof(realpath)); + return resolved; } // like realpathWin32() but takes out the first slash so that windows systems can work on the actual file or directory char *realpathWin32i(const char *path, char resolved[PATH_MAX]) { - char realpath[PATH_MAX]; + char realpath[PATH_MAX]; - if (path[0] != '/') { - // absolute form x:/abc/def given, no first slash to take out - strlcpy(resolved, path, sizeof(realpath)); - } - else - strlcpy(resolved, path + 1, sizeof(realpath)); + if (path[0] != '/') { + // absolute form x:/abc/def given, no first slash to take out + strlcpy(resolved, path, sizeof(realpath)); + } + else + strlcpy(resolved, path + 1, sizeof(realpath)); - backslashconvert(resolved); - PathCanonicalizeA(realpath, resolved); - slashconvert(realpath); + backslashconvert(resolved); + PathCanonicalizeA(realpath, resolved); + slashconvert(realpath); - /* - * Store terminating slash in 'X:/' on Windows. - */ + /* + * Store terminating slash in 'X:/' on Windows. + */ - if (realpath[1] == ':' && realpath[2] == 0) - { - realpath[2] = '/'; - realpath[3] = 0; - } + if (realpath[1] == ':' && realpath[2] == 0) + { + realpath[2] = '/'; + realpath[3] = 0; + } - strncpy(resolved, realpath, sizeof(realpath)); - return resolved; + strncpy(resolved, realpath, sizeof(realpath)); + return resolved; } #endif diff --git a/sftp.c b/sftp.c index 5e17179..3332fb4 100644 --- a/sftp.c +++ b/sftp.c @@ -72,10 +72,7 @@ typedef void EditLine; #define DEFAULT_COPY_BUFLEN 32768 /* Size of buffer for up/download */ #define DEFAULT_NUM_REQUESTS 64 /* # concurrent outstanding requests */ - -#ifdef WIN32_FIXME - #define FAIL(X) if (X) goto fail -#endif +#define MAX_COMMAND_LINE 2048 #ifdef WIN32_VS #include "win32_dirent.h" @@ -290,17 +287,12 @@ help(void) static void local_do_shell(const char *args) { - #ifdef WIN32_FIXME - + #ifdef WINDOWS if (!*args) { args = (char *) getenv("ComSpec"); // get name of Windows cmd shell } system(args); // execute the shell or cmd given #else - - /* - * Original OpenSSH code. - */ int status; char *shell; pid_t pid; @@ -663,10 +655,38 @@ process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, free(tmp); resume |= global_aflag; - if (!quiet && resume) + if (!quiet && resume) +#ifdef WINDOWS + { + printf("Resuming "); + wchar_t* wtmp = utf8_to_utf16(g.gl_pathv[i]); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + printf(" to "); + free(wtmp); + wtmp = utf8_to_utf16(abs_dst); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"\n", 1, 0, 0); + free(wtmp); + } +#else printf("Resuming %s to %s\n", g.gl_pathv[i], abs_dst); - else if (!quiet && !resume) - printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); +#endif + else if (!quiet && !resume) +#ifdef WINDOWS + { + printf("Fetching "); + wchar_t* wtmp = utf8_to_utf16(g.gl_pathv[i]); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + printf(" to "); + free(wtmp); + wtmp = utf8_to_utf16(abs_dst); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"\n", 1, 0, 0); + free(wtmp); + } +#else + printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); +#endif if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, pflag || global_pflag, 1, resume, @@ -753,12 +773,40 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, } free(tmp); - resume |= global_aflag; + resume |= global_aflag; if (!quiet && resume) +#ifdef WINDOWS + { + printf("Resuming upload of "); + wchar_t* wtmp = utf8_to_utf16(g.gl_pathv[i]); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + printf(" to "); + free(wtmp); + wtmp = utf8_to_utf16(abs_dst); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"\n", 1, 0, 0); + free(wtmp); + } +#else printf("Resuming upload of %s to %s\n", g.gl_pathv[i], abs_dst); +#endif else if (!quiet && !resume) +#ifdef WINDOWS + { + printf("Uploading "); + wchar_t* wtmp = utf8_to_utf16(g.gl_pathv[i]); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + printf(" to "); + free(wtmp); + wtmp = utf8_to_utf16(abs_dst); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"\n", 1, 0, 0); + free(wtmp); + } +#else printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); +#endif if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { if (upload_dir(conn, g.gl_pathv[i], abs_dst, pflag || global_pflag, 1, resume, @@ -823,13 +871,12 @@ do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag) tmp = path_strip(path, strip_path); m += strlen(tmp); free(tmp); -#ifndef WIN32_FIXME +#ifdef WINDOWS + width = ConScreenSizeX(); +#else if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) width = ws.ws_col; #endif - - - columns = width / (m + 2); columns = MAX(columns, 1); colspace = width / columns; @@ -862,12 +909,37 @@ do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag) attrib_to_stat(&d[n]->a, &sb); lname = ls_file(fname, &sb, 1, (lflag & LS_SI_UNITS)); - printf("%s\n", lname); +#ifdef WINDOWS + wchar_t* wtmp = utf8_to_utf16(lname); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"\n", 1, 0, 0); + free(wtmp); +#else + printf("%s\n", lname); +#endif free(lname); - } else - printf("%s\n", d[n]->longname); - } else { - printf("%-*s", colspace, fname); + } + else { +#ifdef WINDOWS + wchar_t* wtmp = utf8_to_utf16(d[n]->longname); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"\n", 1, 0, 0); + free(wtmp); +#else + printf("%s\n", d[n]->longname); +#endif + } + } + else { +#ifdef WINDOWS + wchar_t* wtmp = utf8_to_utf16(fname); + // TODO: Deal with the sizing wprintf_s(L"%-*s", colspace, wtmp); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L" ", 1, 0, 0); + free(wtmp); +#else + printf("%-*s", colspace, fname); +#endif if (c >= columns) { printf("\n"); c = 1; @@ -926,14 +998,13 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path, return err; } - -#ifndef WIN32_FIXME +#ifdef WINDOWS + width = ConScreenSizeX(); +#else if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) width = ws.ws_col; #endif - - if (!(lflag & LS_SHORT_VIEW)) { /* Count entries for sort and find longest filename */ for (i = 0; g.gl_pathv[i]; i++) @@ -953,11 +1024,26 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path, } lname = ls_file(fname, g.gl_statv[i], 1, (lflag & LS_SI_UNITS)); - printf("%s\n", lname); - free(lname); +#ifdef WINDOWS + wchar_t* wtmp = utf8_to_utf16(lname); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"\n", 1, 0, 0); + free(wtmp); +#else + printf("%s\n", lname); +#endif + free(lname); } else { - printf("%-*s", colspace, fname); - if (c >= columns) { +#ifdef WINDOWS + wchar_t* wtmp = utf8_to_utf16(fname); + // TODO: Deal with the sizing wprintf_s(L"%-*s", colspace, wtmp); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L" ", 1, 0, 0); + free(wtmp); +#else + printf("%-*s", colspace, fname); +#endif + if (c >= columns) { printf("\n"); c = 1; } else @@ -1436,6 +1522,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, glob_t g; path1 = path2 = NULL; + cmdnum = parse_args(&cmd, &ignore_errors, &aflag, &fflag, &hflag, &iflag, &lflag, &pflag, &rflag, &sflag, &n_arg, &path1, &path2); if (ignore_errors != 0) @@ -1483,8 +1570,18 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, path1 = make_absolute(path1, *pwd); remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); for (i = 0; g.gl_pathv[i] && !interrupted; i++) { - if (!quiet) - printf("Removing %s\n", g.gl_pathv[i]); + if (!quiet) +#ifdef WINDOWS + { + printf("Removing "); + wchar_t* wtmp = utf8_to_utf16(g.gl_pathv[i]); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"\n", 1, 0, 0); + free(wtmp); + } +#else + printf("Removing %s\n", g.gl_pathv[i]); +#endif err = do_rm(conn, g.gl_pathv[i]); if (err != 0 && err_abort) break; @@ -1584,7 +1681,17 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); for (i = 0; g.gl_pathv[i] && !interrupted; i++) { if (!quiet) - printf("Changing mode on %s\n", g.gl_pathv[i]); +#ifdef WINDOWS + { + printf("Changing mode on "); + wchar_t* wtmp = utf8_to_utf16(g.gl_pathv[i]); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"\n", 1, 0, 0); + free(wtmp); + } +#else + printf("Changing mode on %s\n", g.gl_pathv[i]); +#endif err = do_setstat(conn, g.gl_pathv[i], &a); if (err != 0 && err_abort) break; @@ -1614,13 +1721,33 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; if (cmdnum == I_CHOWN) { if (!quiet) - printf("Changing owner on %s\n", - g.gl_pathv[i]); +#ifdef WINDOWS + { + printf("Changing owner on "); + wchar_t* wtmp = utf8_to_utf16(g.gl_pathv[i]); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"\n", 1, 0, 0); + free(wtmp); + } +#else + printf("Changing owner on %s\n", + g.gl_pathv[i]); +#endif aa->uid = n_arg; } else { if (!quiet) - printf("Changing group on %s\n", - g.gl_pathv[i]); +#ifdef WINDOWS + { + printf("Changing group on "); + wchar_t* wtmp = utf8_to_utf16(g.gl_pathv[i]); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"\n", 1, 0, 0); + free(wtmp); + } +#else + printf("Changing group on %s\n", + g.gl_pathv[i]); +#endif aa->gid = n_arg; } err = do_setstat(conn, g.gl_pathv[i], aa); @@ -1629,7 +1756,17 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, } break; case I_PWD: - printf("Remote working directory: %s\n", *pwd); +#ifdef WINDOWS + printf("Remote working directory: "); + { + wchar_t* wtmp = utf8_to_utf16(*pwd); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"\n", 1, 0, 0); + free(wtmp); + } +#else + printf("Remote working directory: %s\n", *pwd); +#endif break; case I_LPWD: if (!getcwd(path_buf, sizeof(path_buf))) { @@ -1637,7 +1774,17 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, err = -1; break; } - printf("Local working directory: %s\n", path_buf); +#ifdef WINDOWS + printf("Local working directory: "); + { + wchar_t* wtmp = utf8_to_utf16(path_buf); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"\n", 1, 0, 0); + free(wtmp); + } +#else + printf("Local working directory: %s\n", path_buf); +#endif break; case I_QUIT: /* Processed below */ @@ -2040,7 +2187,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) { char *remote_path; char *dir = NULL; - char cmd[2048]; + char cmd[MAX_COMMAND_LINE]; int err, interactive; EditLine *el = NULL; #ifdef USE_LIBEDIT @@ -2090,7 +2237,17 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) if (remote_is_dir(conn, dir) && file2 == NULL) { if (!quiet) - printf("Changing to: %s\n", dir); +#ifdef WINDOWS + { + printf("Changing to: "); + wchar_t* wtmp = utf8_to_utf16(dir); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wtmp, wcslen(wtmp), 0, 0); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"\n", 1, 0, 0); + free(wtmp); + } +#else + printf("Changing to: %s\n", dir); +#endif snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); if (parse_dispatch_command(conn, cmd, &remote_path, 1) != 0) { @@ -2115,7 +2272,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) free(dir); } - #ifndef WIN32_VS + #ifndef WINDOWS setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(infile, NULL, _IOLBF, 0); #endif @@ -2128,13 +2285,36 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) signal(SIGINT, SIG_IGN); if (el == NULL) { - if (interactive) - printf("sftp> "); - if (fgets(cmd, sizeof(cmd), infile) == NULL) { - if (interactive) - printf("\n"); - break; - } +#ifdef WINDOWS + if (interactive) { + wchar_t wcmd[MAX_COMMAND_LINE]; + printf("sftp> "); + if (fgetws(wcmd, sizeof(cmd)/sizeof(wchar_t), infile) == NULL) { + printf("\n"); + break; + } + else { + char *pcmd = NULL; + if ((pcmd = utf16_to_utf8(wcmd)) == NULL) + fatal("failed to convert input arguments"); + strcpy(cmd, pcmd); + free(pcmd); + } + } + else { + if (fgets(cmd, sizeof(cmd), infile) == NULL) { + break; + } + } +#else + if (interactive) { + printf("sftp> "); + if (fgets(cmd, sizeof(cmd), infile) == NULL) { + if (interactive) + printf("\n"); + break; + } +#endif if (!interactive) { /* Echo command */ printf("sftp> %s", cmd); if (strlen(cmd) > 0 && @@ -2187,9 +2367,6 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) static void connect_to_server(char *path, char **args, int *in, int *out) { - /* - * Original OpenSSH code. - */ int c_in, c_out; #ifdef USE_PIPES @@ -2210,9 +2387,9 @@ connect_to_server(char *path, char **args, int *in, int *out) c_in = c_out = inout[1]; #endif /* USE_PIPES */ -#ifdef WIN32_FIXME +#ifdef WINDOWS { - int i; + int i = 0; char fullCmd[MAX_PATH] = { 0 }; char ioArg[1024] = { 0 }; PROCESS_INFORMATION pi = { 0 }; @@ -2225,8 +2402,7 @@ connect_to_server(char *path, char **args, int *in, int *out) strncat(fullCmd, "\\", MAX_PATH); } strncat(fullCmd, path, MAX_PATH); - for (i = 1; args[i]; i++) - { + for (i = 1; args[i]; i++) { strncat(fullCmd, " ", MAX_PATH); strncat(fullCmd, args[i], MAX_PATH); } @@ -2337,36 +2513,36 @@ main(int argc, char **argv) size_t num_requests = DEFAULT_NUM_REQUESTS; long long limit_kbps = 0; -#ifdef WIN32_FIXME +#ifdef WINDOWS + /* + * Initialize I/O wrappers. + */ + w32posix_initialize(); setvbuf(stdout, NULL, _IONBF, 0); - #endif + ConInit(STD_OUTPUT_HANDLE, TRUE); + + #endif /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); -#ifndef WIN32_FIXME setlocale(LC_CTYPE, ""); -#endif __progname = ssh_get_progname(argv[0]); memset(&args, '\0', sizeof(args)); args.list = NULL; addargs(&args, "%s", ssh_program); - #ifdef WIN32_FIXME - addargs(&args, "-oForwardX11=no"); - addargs(&args, "-oForwardAgent=no"); - addargs(&args, "-oPermitLocalCommand=no"); - addargs(&args, "-oClearAllForwardings=yes"); - - #else - addargs(&args, "-oForwardX11 no"); - addargs(&args, "-oForwardAgent no"); - addargs(&args, "-oPermitLocalCommand no"); - addargs(&args, "-oClearAllForwardings yes"); -#endif + addargs(&args, "\"-oForwardX11 no\""); + addargs(&args, "\"-oForwardAgent no\""); + addargs(&args, "\"-oPermitLocalCommand no\""); + addargs(&args, "\"-oClearAllForwardings yes\""); + ll = SYSLOG_LEVEL_INFO; - infile = stdin; +#ifdef WINDOWS + _setmode(_fileno(stdin), O_U16TEXT); +#endif + infile = stdin; while ((ch = getopt(argc, argv, "1246afhpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) { @@ -2392,17 +2568,8 @@ main(int argc, char **argv) addargs(&args, "-%c", ch); break; case 'P': - #ifdef WIN32_FIXME - - addargs(&args, "-oPort=%s", optarg); - - #else - - addargs(&args, "-oPort %s", optarg); - - #endif - - break; + addargs(&args, "\"-oPort %s\"", optarg); + break; case 'v': if (debug_level < 3) { addargs(&args, "-v"); @@ -2436,17 +2603,8 @@ main(int argc, char **argv) fatal("%s (%s).", strerror(errno), optarg); showprogress = 0; quiet = batchmode = 1; - #ifdef WIN32_FIXME - - addargs(&args, "-obatchmode=yes"); - - #else - - addargs(&args, "-obatchmode yes"); - - #endif - - break; + addargs(&args, "\"-obatchmode yes\""); + break; case 'f': global_fflag = 1; break; @@ -2519,16 +2677,7 @@ main(int argc, char **argv) fprintf(stderr, "Missing hostname\n"); usage(); } - #ifdef WIN32_FIXME - - addargs(&args, "-oProtocol=%d", sshver); - - #else - - addargs(&args, "-oProtocol %d", sshver); - - #endif - + addargs(&args, "\"-oProtocol %d\"", sshver); /* no subsystem if the server-spec contains a '/' */ if (sftp_server == NULL || strchr(sftp_server, '/') == NULL) diff --git a/win32_dirent.c b/win32_dirent.c index 4036a8d..9812252 100644 --- a/win32_dirent.c +++ b/win32_dirent.c @@ -2,11 +2,11 @@ // directory entry functions in Windows platform like Ubix/Linux // opendir(), readdir(), closedir(). +#include #include #include #include #include -#include #include "win32_dirent.h" @@ -14,40 +14,53 @@ Return a DIR stream on the directory, or NULL if it could not be opened. */ DIR * opendir(char *name) { - struct _finddata_t c_file; - intptr_t hFile; - DIR *pdir; - char searchstr[256]; + struct _wfinddata_t c_file; + intptr_t hFile; + DIR *pdir; + wchar_t searchstr[MAX_PATH]; + wchar_t wname[MAX_PATH]; + int needed; - // add *.* for Windows _findfirst() search pattern - sprintf_s(searchstr, sizeof(searchstr), "%s\\*.*",name); + MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, MAX_PATH); - if ((hFile = _findfirst(searchstr, &c_file)) == -1L) { - if (1) // verbose - printf( "No files found for %s search.\n", name ); - return (DIR *) NULL; - } - else { - pdir = (DIR *) malloc( sizeof(DIR) ); - pdir->hFile = hFile ; - pdir->c_file = c_file ; - strcpy_s(pdir->initName,sizeof(pdir->initName), c_file.name); + // add *.* for Windows _findfirst() search pattern + swprintf_s(searchstr, MAX_PATH, L"%s\\*.*", wname); - return pdir ; - } + if ((hFile = _wfindfirst(searchstr, &c_file)) == -1L) { + if (1) // verbose + printf( "No files found for %s search.\n", name ); + return (DIR *) NULL; + } + else { + pdir = (DIR *) malloc( sizeof(DIR) ); + pdir->hFile = hFile ; + pdir->c_file.attrib = c_file.attrib ; + pdir->c_file.size = c_file.size; + pdir->c_file.time_access = c_file.time_access; + pdir->c_file.time_create = c_file.time_create; + pdir->c_file.time_write = c_file.time_write; + + if ((needed = WideCharToMultiByte(CP_UTF8, 0, c_file.name, -1, NULL, 0, NULL, NULL)) == 0 || + WideCharToMultiByte(CP_UTF8, 0, c_file.name, -1, pdir->c_file.name, needed, NULL, NULL) != needed) + fatal("failed to covert input arguments"); + + strcpy_s(pdir->initName, sizeof(pdir->initName), pdir->c_file.name); + + return pdir ; + } } /* Close the directory stream DIRP. Return 0 if successful, -1 if not. */ int closedir(DIR *dirp) { - if ( dirp && (dirp->hFile) ) { - _findclose( dirp->hFile ); - dirp->hFile = 0; - free (dirp); - } + if ( dirp && (dirp->hFile) ) { + _findclose( dirp->hFile ); + dirp->hFile = 0; + free (dirp); + } - return 0; + return 0; } /* Read a directory entry from DIRP. @@ -56,24 +69,33 @@ int closedir(DIR *dirp) by a later readdir call on the same DIR stream. */ struct dirent *readdir(void *avp) { - struct dirent *pdirentry; - DIR *dirp = (DIR *)avp; + int needed; + struct dirent *pdirentry; + struct _wfinddata_t c_file; + DIR *dirp = (DIR *)avp; + char *tmp = NULL; - for (;;) { - if ( _findnext( dirp->hFile, &(dirp->c_file) ) == 0 ) { - if ( ( strcmp (dirp->c_file.name,".") == 0 ) || - ( strcmp (dirp->c_file.name,"..") == 0 ) ) { - continue ; - } - pdirentry = (struct dirent *) malloc( sizeof(struct dirent) ); - pdirentry->d_name = dirp->c_file.name ; - pdirentry->d_ino = 1; // a fictious one like UNIX to say it is nonzero - return pdirentry ; - } - else { - return (struct dirent *) NULL; - } - } + for (;;) { + if ( _wfindnext( dirp->hFile, &c_file ) == 0 ) { + if ( ( wcscmp (c_file.name, L".") == 0 ) || + ( wcscmp (c_file.name, L"..") == 0 ) ) { + continue ; + } + pdirentry = (struct dirent *) malloc( sizeof(struct dirent) ); + + if ((tmp = utf16_to_utf8(pdirentry->d_name)) == NULL) + fatal("failed to covert input arguments"); + strcpy(c_file.name[0], tmp); + free(tmp); + tmp = NULL; + + pdirentry->d_ino = 1; // a fictious one like UNIX to say it is nonzero + return pdirentry ; + } + else { + return (struct dirent *) NULL; + } + } } // return last part of a path. The last path being a filename. diff --git a/win32_dirent.h b/win32_dirent.h index 29a3323..3859889 100644 --- a/win32_dirent.h +++ b/win32_dirent.h @@ -8,7 +8,8 @@ #define __DIRENT_H__ #include -#include +#include +#include // Windows directory structure content struct dirent { @@ -18,11 +19,11 @@ struct dirent { }; typedef struct { - intptr_t hFile; - struct _finddata_t c_file; - int bRoot; - int bDrive; - char initName[260]; + intptr_t hFile; + struct _finddata_t c_file; + int bRoot; + int bDrive; + char initName[260]; } DIR; DIR * opendir(char *name);