diff --git a/include/stdio.h b/include/stdio.h index 989b7fc..ab17883 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -14,4 +14,17 @@ int vasprintf(char **str, const char *fmt, va_list ap); int asprintf(char **str, const char *fmt, ...); #endif +#ifdef _WIN32 +#include +#include + +static inline void +posix_perror(const char *s) +{ + fprintf(stderr, "%s: %s\n", s, strerror(errno)); +} + +#define perror(errnum) posix_perror(errnum) +#endif + #endif diff --git a/include/string.h b/include/string.h index a3263e7..c558a90 100644 --- a/include/string.h +++ b/include/string.h @@ -50,4 +50,20 @@ void * memmem(const void *big, size_t big_len, const void *little, size_t little_len); #endif +#ifdef _WIN32 +#include + +static inline char * +posix_strerror(int errnum) +{ + if (errnum == ECONNREFUSED) { + return "Connection refused"; + } + return strerror(errnum); +} + +#define strerror(errnum) posix_strerror(errnum) + +#endif + #endif diff --git a/include/win32netcompat.h b/include/win32netcompat.h index 3c716b0..51384d0 100644 --- a/include/win32netcompat.h +++ b/include/win32netcompat.h @@ -1,3 +1,10 @@ +/* + * Public domain + * + * BSD socket emulation code for Winsock2 + * Brent Cook + */ + #ifndef LIBCRYPTOCOMPAT_WIN32NETCOMPAT_H #define LIBCRYPTOCOMPAT_WIN32NETCOMPAT_H @@ -5,17 +12,149 @@ #include -#ifndef SHUT_RDWR #define SHUT_RDWR SD_BOTH -#endif +#define SHUT_RD SD_RECEIVE +#define SHUT_WR SD_SEND -#ifndef SHUT_RD -#define SHUT_RD SD_RECEIVE -#endif +#include +#include -#ifndef SHUT_WR -#define SHUT_WR SD_SEND -#endif +static int +wsa_errno(int err) +{ + switch (err) { + case WSAENOBUFS: + errno = ENOMEM; + break; + case WSAEACCES: + errno = EACCES; + break; + case WSANOTINITIALISED: + errno = EPERM; + break; + case WSAEHOSTUNREACH: + case WSAENETDOWN: + errno = EIO; + break; + case WSAEFAULT: + errno = EFAULT; + break; + case WSAEINTR: + errno = EINTR; + break; + case WSAEINVAL: + errno = EINVAL; + break; + case WSAEINPROGRESS: + errno = EINPROGRESS; + break; + case WSAEWOULDBLOCK: + errno = EAGAIN; + break; + case WSAEOPNOTSUPP: + errno = ENOTSUP; + break; + case WSAEMSGSIZE: + errno = EFBIG; + break; + case WSAENOTSOCK: + errno = ENOTSOCK; + break; + case WSAENOPROTOOPT: + errno = ENOPROTOOPT; + break; + case WSAECONNREFUSED: + errno = ECONNREFUSED; + break; + case WSAEAFNOSUPPORT: + errno = EAFNOSUPPORT; + break; + case WSAENETRESET: + case WSAENOTCONN: + case WSAECONNABORTED: + case WSAECONNRESET: + case WSAESHUTDOWN: + case WSAETIMEDOUT: + errno = EPIPE; + break; + } + return -1; +} + +static inline int +posix_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) +{ + int rc = connect(sockfd, addr, addrlen); + if (rc == SOCKET_ERROR) + return wsa_errno(WSAGetLastError()); + return rc; +} + +#define connect(sockfd, addr, addrlen) posix_connect(sockfd, addr, addrlen) + +static inline int +posix_close(int fd) +{ + if (closesocket(fd) == SOCKET_ERROR) { + int err = WSAGetLastError(); + return err == WSAENOTSOCK ? + close(fd) : wsa_errno(err); + } + return 0; +} + +#define close(fd) posix_close(fd) + +static inline ssize_t +posix_read(int fd, void *buf, size_t count) +{ + ssize_t rc = recv(fd, buf, count, 0); + if (rc == SOCKET_ERROR) { + int err = WSAGetLastError(); + return err == WSAENOTSOCK ? + read(fd, buf, count) : wsa_errno(err); + } + return rc; +} + +#define read(fd, buf, count) posix_read(fd, buf, count) + +static inline ssize_t +posix_write(int fd, const void *buf, size_t count) +{ + ssize_t rc = send(fd, buf, count, 0); + if (rc == SOCKET_ERROR) { + int err = WSAGetLastError(); + return err == WSAENOTSOCK ? + write(fd, buf, count) : wsa_errno(err); + } + return rc; +} + +#define write(fd, buf, count) posix_write(fd, buf, count) + +static inline int +posix_getsockopt(int sockfd, int level, int optname, + void *optval, socklen_t *optlen) +{ + int rc = getsockopt(sockfd, level, optname, (char *)optval, optlen); + return rc == 0 ? 0 : wsa_errno(WSAGetLastError()); + +} + +#define getsockopt(sockfd, level, optname, optval, optlen) \ + posix_getsockopt(sockfd, level, optname, optval, optlen) + +static inline int +posix_setsockopt(int sockfd, int level, int optname, + const void *optval, socklen_t optlen) +{ + int rc = setsockopt(sockfd, level, optname, (char *)optval, optlen); + return rc == 0 ? 0 : wsa_errno(WSAGetLastError()); +} + +#define setsockopt(sockfd, level, optname, optval, optlen) \ + posix_setsockopt(sockfd, level, optname, optval, optlen) #endif