diff --git a/contrib/win32/openssh/win32iocompat.vcxproj b/contrib/win32/openssh/win32iocompat.vcxproj index c753642..1af6c14 100644 --- a/contrib/win32/openssh/win32iocompat.vcxproj +++ b/contrib/win32/openssh/win32iocompat.vcxproj @@ -145,6 +145,7 @@ + diff --git a/contrib/win32/win32compat/fileio.c b/contrib/win32/win32compat/fileio.c index b178fff..9e15194 100644 --- a/contrib/win32/win32compat/fileio.c +++ b/contrib/win32/win32compat/fileio.c @@ -136,9 +136,7 @@ fileio_pipe(struct w32_io* pio[2]) { memset(pio_write, 0, sizeof(struct w32_io)); pio_read->handle = read_handle; - pio_read->internal.state = PIPE_READ_END; pio_write->handle = write_handle; - pio_write->internal.state = PIPE_WRITE_END; pio[0] = pio_read; pio[1] = pio_write; @@ -281,7 +279,6 @@ fileio_open(const char *pathname, int flags, int mode) { return pio; } - VOID CALLBACK ReadCompletionRoutine( _In_ DWORD dwErrorCode, _In_ DWORD dwNumberOfBytesTransfered, @@ -301,8 +298,8 @@ VOID CALLBACK ReadCompletionRoutine( /* initiate an async read */ int fileio_ReadFileEx(struct w32_io* pio) { - HANDLE h = pio->handle; debug2("ReadFileEx io:%p", pio); + if (pio->read_details.buf == NULL){ pio->read_details.buf = malloc(READ_BUFFER_SIZE); if (!pio->read_details.buf) { @@ -313,11 +310,7 @@ fileio_ReadFileEx(struct w32_io* pio) { pio->read_details.buf_size = READ_BUFFER_SIZE; } - /* get underlying handle for standard io */ - if (pio->type == STD_IO_FD) - h = GetStdHandle(pio->std_handle); - - if (ReadFileEx(h, pio->read_details.buf, pio->read_details.buf_size, + if (ReadFileEx(WINHANDLE(pio), pio->read_details.buf, pio->read_details.buf_size, &pio->read_overlapped, &ReadCompletionRoutine)) pio->read_details.pending = TRUE; else { @@ -335,11 +328,6 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max) { int bytes_copied; debug3("read - io:%p remaining:%d", pio, pio->read_details.remaining); - if ((pio->type == PIPE_FD) && (pio->internal.state == PIPE_WRITE_END)) { - debug("read - ERROR: called on write end of pipe, io:%p", pio); - errno = EBADF; - return -1; - } /* if read is pending */ if (pio->read_details.pending) { @@ -357,7 +345,8 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max) { if (fileio_is_io_available(pio, TRUE) == FALSE) { if (-1 == fileio_ReadFileEx(pio)) { - if ((pio->type == PIPE_FD) && (errno == ERROR_NEGATIVE_SEEK)) { + if ((FILETYPE(pio) == FILE_TYPE_PIPE) + && (errno == ERROR_NEGATIVE_SEEK)) { /* write end of the pipe closed */ debug2("read - no more data, io:%p", pio); errno = 0; @@ -433,14 +422,8 @@ VOID CALLBACK WriteCompletionRoutine( int fileio_write(struct w32_io* pio, const void *buf, unsigned int max) { int bytes_copied; - HANDLE h = pio->handle; debug2("write - io:%p", pio); - if ((pio->type == PIPE_FD) && (pio->internal.state == PIPE_READ_END)) { - debug("write - ERROR: write called on a read end of pipe, io:%p", pio); - errno = EBADF; - return -1; - } if (pio->write_details.pending) { if (w32_io_is_blocking(pio)) @@ -478,11 +461,7 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) { bytes_copied = min(max, pio->write_details.buf_size); memcpy(pio->write_details.buf, buf, bytes_copied); - /* get underlying handle for standard io */ - if (pio->type == STD_IO_FD) - h = GetStdHandle(pio->std_handle); - - if (WriteFileEx(h, pio->write_details.buf, bytes_copied, + if (WriteFileEx(WINHANDLE(pio), pio->write_details.buf, bytes_copied, &pio->write_overlapped, &WriteCompletionRoutine)) { pio->write_details.pending = TRUE; pio->write_details.remaining = bytes_copied; @@ -507,8 +486,8 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) { } else { errno = errno_from_Win32LastError(); - /* read end of the pipe closed */ - if ((pio->type == PIPE_FD) && (errno == ERROR_NEGATIVE_SEEK)) { + /* read end of the pipe closed ? */ + if ((FILETYPE(pio) == FILE_TYPE_PIPE) && (errno == ERROR_NEGATIVE_SEEK)) { debug("write - ERROR:read end of the pipe closed, io:%p", pio); errno = EPIPE; } @@ -551,17 +530,6 @@ fileio_lseek(struct w32_io* pio, long offset, int origin) { return 0; } -/* isatty() implementation */ -int -fileio_isatty(struct w32_io* pio) { - if (GetFileType(pio->handle) == FILE_TYPE_CHAR) - return 1; - else { - errno = EINVAL; - return 0; - } -} - /* fdopen implementation */ FILE* fileio_fdopen(struct w32_io* pio, const char *mode) { @@ -617,12 +585,14 @@ fileio_on_select(struct w32_io* pio, BOOL rd) { int fileio_close(struct w32_io* pio) { + debug2("fileclose - pio:%p", pio); - CancelIo(pio->handle); + + CancelIo(WINHANDLE(pio)); //let queued APCs (if any) drain SleepEx(0, TRUE); if (pio->type != STD_IO_FD) {//STD handles are never explicitly closed - CloseHandle(pio->handle); + CloseHandle(WINHANDLE(pio)); if (pio->read_details.buf) free(pio->read_details.buf); diff --git a/contrib/win32/win32compat/termio.c b/contrib/win32/win32compat/termio.c new file mode 100644 index 0000000..6076c89 --- /dev/null +++ b/contrib/win32/win32compat/termio.c @@ -0,0 +1,62 @@ + +#include "w32fd.h" +#include "inc/defs.h" + +/* Win7 - Read Term Support - START*/ + +int +fileio_initiateReadTerm_Win7(struct w32_io* pio) { + + if (pio->read_details.pending || w32_io_is_io_available(pio, TRUE)) { + debug("Win7 term read - ERROR - called in wrong state"); + errno = EINVAL; + return -1; + } + + return 0; +} + +/* Win7 - Read Term Support - END*/ + +int +termio_on_select(struct w32_io* pio, BOOL rd) { + return fileio_on_select(pio, rd); +} + +int +termio_read(struct w32_io* pio, void *dst, unsigned int max) { + return fileio_read(pio, dst, max); +} + +int +termio_write(struct w32_io* pio, const void *buf, unsigned int max) { + //{ + // /* assert that io is in blocking mode */ + // if (w32_io_is_blocking(pio) == FALSE) { + // debug("write - ERROR, nonblocking write to term is not supported"); + // errno = ENOTSUP; + // return -1; + // } + // pio->write_details.remaining = bytes_copied; + // if (!WriteFile(h, buf, bytes_copied, &pio->write_details.completed, NULL)) + // pio->write_details.error = GetLastError(); + // else if (bytes_copied != pio->write_details.completed) + // pio->write_details.error = ERROR_INTERNAL_ERROR; + + // if (pio->write_details.error != 0) { + // debug("write - ERROR writing to term %d", pio->write_details.error); + // errno = errno_from_Win32Error(pio->write_details.error); + // return -1; + // } + // else { + // pio->write_details.completed = 0; + // return bytes_copied; + // } + + //} + return fileio_write(pio, buf, max); +} + +int termio_close(struct w32_io* pio) { + return fileio_close(pio); +} \ No newline at end of file diff --git a/contrib/win32/win32compat/w32fd.c b/contrib/win32/win32compat/w32fd.c index 4823849..8d42ae1 100644 --- a/contrib/win32/win32compat/w32fd.c +++ b/contrib/win32/win32compat/w32fd.c @@ -152,8 +152,13 @@ w32_io_on_select(struct w32_io* pio, BOOL rd) { if ((pio->type == SOCK_FD)) return socketio_on_select(pio, rd); - else - return fileio_on_select(pio, rd); + else + switch (FILETYPE(pio)) { + case FILE_TYPE_CHAR: + return termio_on_select(pio, rd); + default: + return fileio_on_select(pio, rd); + } } #define CHECK_FD(fd) do { \ @@ -284,6 +289,7 @@ int w32_send(int fd, const void *buf, size_t len, int flags) { CHECK_FD(fd); + CHECK_SOCK_IO(fd_table.w32_ios[fd]); return socketio_send(fd_table.w32_ios[fd], buf, len, flags); } @@ -324,8 +330,8 @@ w32_pipe(int *pfds) { if (-1 == fileio_pipe(pio)) return -1; - pio[0]->type = PIPE_FD; - pio[1]->type = PIPE_FD; + pio[0]->type = NONSOCK_FD; + pio[1]->type = NONSOCK_FD; fd_table_set(pio[0], read_index); fd_table_set(pio[1], write_index); pfds[0] = read_index; @@ -348,7 +354,7 @@ w32_open(const char *pathname, int flags, ...) { if (pio == NULL) return -1; - pio->type = FILE_FD; + pio->type = NONSOCK_FD; fd_table_set(pio, min_index); debug("open - handle:%p, io:%p, fd:%d", pio->handle, pio, min_index); debug3("open - path:%s", pathname); @@ -358,17 +364,31 @@ w32_open(const char *pathname, int flags, ...) { int w32_read(int fd, void *dst, unsigned int max) { CHECK_FD(fd); + if (fd_table.w32_ios[fd]->type == SOCK_FD) return socketio_recv(fd_table.w32_ios[fd], dst, max, 0); - return fileio_read(fd_table.w32_ios[fd], dst, max); + else + switch (FILETYPE(fd_table.w32_ios[fd])) { + case FILE_TYPE_CHAR: + return termio_read(fd_table.w32_ios[fd], dst, max); + default: + return fileio_read(fd_table.w32_ios[fd], dst, max); + } } int w32_write(int fd, const void *buf, unsigned int max) { CHECK_FD(fd); + if (fd_table.w32_ios[fd]->type == SOCK_FD) return socketio_send(fd_table.w32_ios[fd], buf, max, 0); - return fileio_write(fd_table.w32_ios[fd], buf, max); + else + switch (FILETYPE(fd_table.w32_ios[fd])) { + case FILE_TYPE_CHAR: + return termio_write(fd_table.w32_ios[fd], buf, max); + default: + return fileio_write(fd_table.w32_ios[fd], buf, max); + } } int @@ -395,11 +415,20 @@ w32_mkdir(const char *pathname, unsigned short mode) { int w32_isatty(int fd) { + struct w32_io* pio; if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) { errno = EBADF; return 0; } - return fileio_isatty(fd_table.w32_ios[fd]); + + pio = fd_table.w32_ios[fd]; + + if (FILETYPE(pio) == FILE_TYPE_CHAR) + return 1; + else { + errno = EINVAL; + return 0; + } } FILE* @@ -423,10 +452,16 @@ w32_close(int fd) { debug("close - io:%p, type:%d, fd:%d, table_index:%d", pio, pio->type, fd, pio->table_index); fd_table_clear(pio->table_index); - if ((pio->type == SOCK_FD)) + + if (pio->type == SOCK_FD) return socketio_close(pio); else - return fileio_close(pio); + switch (FILETYPE(pio)) { + case FILE_TYPE_CHAR: + return termio_close(pio); + default: + return fileio_close(pio); + } } int @@ -690,7 +725,7 @@ w32_dup(int oldfd) { memset(pio, 0, sizeof(struct w32_io)); pio->handle = target; - pio->type = FILE_FD; + pio->type = NONSOCK_FD; fd_table_set(pio, min_index); return min_index; } @@ -746,7 +781,7 @@ int w32_allocate_fd_for_handle(HANDLE h, BOOL is_sock) { } memset(pio, 0, sizeof(struct w32_io)); - pio->type = is_sock? SOCK_FD : FILE_FD; + pio->type = is_sock? SOCK_FD : NONSOCK_FD; pio->handle = h; fd_table_set(pio, min_index); return min_index; diff --git a/contrib/win32/win32compat/w32fd.h b/contrib/win32/win32compat/w32fd.h index 2ddce2d..b15861e 100644 --- a/contrib/win32/win32compat/w32fd.h +++ b/contrib/win32/win32compat/w32fd.h @@ -13,9 +13,8 @@ enum w32_io_type { UNKNOWN_FD = 0, SOCK_FD = 1, /*maps a socket fd*/ - FILE_FD = 2, /*maps a file fd*/ - PIPE_FD = 3, /*maps a pipe fd*/ - STD_IO_FD = 5 /*maps a std fd*/ + NONSOCK_FD = 2, /*maps a file fd, pipe fd or a tty fd*/ + STD_IO_FD = 5 /*maps a std fd - ex. STDIN_FILE*/ }; enum w32_io_sock_state { @@ -26,11 +25,6 @@ enum w32_io_sock_state { SOCK_CONNECTED = 4 /*connect completed on socket*/ }; -enum w32_io_pipe_state { - PIPE_READ_END = 1, /*read end of a pipe()*/ - PIPE_WRITE_END = 2 /*write end of a pipe()*/ -}; - /* * This sturcture encapsulates the state info needed to map a File Descriptor * to Win32 Handle @@ -81,6 +75,9 @@ struct w32_io { }internal; }; +#define WINHANDLE(pio) (((pio)->type == STD_IO_FD)? GetStdHandle((pio)->std_handle):(pio)->handle) +#define FILETYPE(pio) (GetFileType(WINHANDLE(pio))) + BOOL w32_io_is_blocking(struct w32_io*); BOOL w32_io_is_io_available(struct w32_io* pio, BOOL rd); int wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds); @@ -118,9 +115,14 @@ int fileio_write(struct w32_io* pio, const void *buf, unsigned int max); int fileio_fstat(struct w32_io* pio, struct _stat64 *buf); int fileio_stat(const char *path, struct _stat64 *buf); long fileio_lseek(struct w32_io* pio, long offset, int origin); -int fileio_isatty(struct w32_io* pio); FILE* fileio_fdopen(struct w32_io* pio, const char *mode); +/* terminal io specific versions */ +int termio_on_select(struct w32_io* pio, BOOL rd); +int termio_read(struct w32_io* pio, void *dst, unsigned int max); +int termio_write(struct w32_io* pio, const void *buf, unsigned int max); +int termio_close(struct w32_io* pio); + /* signal related APIs*/ void signalio_initialize(); //int signalio_add_child(HANDLE child); diff --git a/readpass.c b/readpass.c index f8aae68..fa11ae7 100644 --- a/readpass.c +++ b/readpass.c @@ -334,57 +334,44 @@ read_passphrase(const char *prompt, int flags) /* * Show prompt for user. */ - HANDLE c_in = CreateFileA("CONIN$", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL); - HANDLE c_out = CreateFileA("CONOUT$", GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL); - int tmp; - int originalMode, tmpMode; + _cputs(prompt); - GetConsoleMode(c_in, &originalMode); - SetConsoleMode(c_in, ENABLE_LINE_INPUT); - //SetConsoleMode(c_in, (originalMode & ~(ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT))); + len = retr = 0; + int bufsize = sizeof(buf); - GetConsoleMode(c_in, &tmpMode); + while (_kbhit()) + _getch(); - WriteFile(c_out, prompt, strlen(prompt), &tmp, NULL); - // write(STDOUT_FILENO, prompt, strlen(prompt)); - ReadFile(c_in, buf, 1024, &tmp, NULL); - buf[tmp - 2] = '\0'; - SetConsoleMode(c_in, originalMode); - CloseHandle(c_in); - CloseHandle(c_out); + while ( len < bufsize ) { - // len = retr = 0; - // int bufsize = sizeof(buf); - - //while (_kbhit()) - // _getch(); - - //while ( len < bufsize ) { - - // buf[len] = (unsigned char) _getch() ; + buf[len] = (unsigned char) _getch() ; - // if ( buf[len] == '\r' ) { - // if (_kbhit() ) - // _getch(); // read linefeed if its there - // break; - // } - // else if ( buf[len] == '\n' ) { - // break; - // } - // else if ( buf[len] == '\b' ) { // backspace - // if (len > 0 ) - // len--; // overwrite last character - // } - // else { + if ( buf[len] == '\r' ) { + if (_kbhit() ) + _getch(); // read linefeed if its there + break; + } + else if ( buf[len] == '\n' ) { + break; + } + else if ( buf[len] == '\b' ) { // backspace + if (len > 0 ) + len--; // overwrite last character + } + else if (buf[len] == '\003') { + /* exit on Ctrl+C */ + fatal(""); + } + else { - // //_putch( (int) '*' ); // show a star in place of what is typed - // len++; // keep reading in the loop - // } - //} + //_putch( (int) '*' ); // show a star in place of what is typed + len++; // keep reading in the loop + } + } - //buf[len] = '\0' ; // get rid of the cr/lf - //write(STDOUT_FILENO,"\n", strlen("\n")); // show a newline as we do not echo password or the line + buf[len] = '\0' ; // get rid of the cr/lf + _cputs("\n"); // show a newline as we do not echo password or the line ret = xstrdup(buf);