diff --git a/qse/cmd/awk/awk.c b/qse/cmd/awk/awk.c index cabc0176..a3ac84e4 100644 --- a/qse/cmd/awk/awk.c +++ b/qse/cmd/awk/awk.c @@ -52,6 +52,7 @@ # include #elif defined(__DOS__) # include +# include /* watt-32 */ #else # include # include @@ -1238,6 +1239,9 @@ int qse_main (int argc, qse_achar_t* argv[]) char locale[100]; UINT codepage; WSADATA wsadata; +#elif defined(__DOS__) + extern BOOL _watt_do_exit; + int sock_inited = 0; #else /* nothing special */ #endif @@ -1259,29 +1263,42 @@ int qse_main (int argc, qse_achar_t* argv[]) qse_setdflcmgrbyid (QSE_CMGR_SLMB); } - if (WSAStartup (MAKEWORD(2,0), &wsadata) != 0) - { - print_error (QSE_T("Failed to start up winsock\n")); - return -1; - } - #else setlocale (LC_ALL, ""); qse_setdflcmgrbyid (QSE_CMGR_SLMB); #endif - open_mpi (&mpi, argc, argv); - qse_openstdsios (); + +#if defined(_WIN32) + if (WSAStartup (MAKEWORD(2,0), &wsadata) != 0) + { + print_error (QSE_T("Failed to start up winsock\n")); + ret = -1; + goto oops; + } +#elif defined(__DOS__) +/* TODO: add an option to skip watt-32 */ + _watt_do_exit = 0; /* prevent sock_init from exiting upon failure */ + if (sock_init() != 0) + print_error (QSE_T("Failed to initialize watt-32\n")); + else sock_inited = 1; +#endif + + open_mpi (&mpi, argc, argv); + ret = qse_runmain (argc, argv, awk_main); - qse_closestdsios (); close_mpi (&mpi); #if defined(_WIN32) WSACleanup (); +#elif defined(__DOS__) + if (sock_inited) sock_exit (); #endif +oops: + qse_closestdsios (); return ret; } diff --git a/qse/cmd/http/httpd.c b/qse/cmd/http/httpd.c index 48ebc09d..7e214f4a 100644 --- a/qse/cmd/http/httpd.c +++ b/qse/cmd/http/httpd.c @@ -29,6 +29,7 @@ # include #elif defined(__DOS__) # include +# include /* watt-32 */ #else # include # include @@ -2715,6 +2716,8 @@ int qse_main (int argc, qse_achar_t* argv[]) char locale[100]; UINT codepage; WSADATA wsadata; +#elif defined(__DOS__) + extern BOOL _watt_do_exit; #else /* nothing */ #endif @@ -2736,25 +2739,36 @@ int qse_main (int argc, qse_achar_t* argv[]) qse_setdflcmgrbyid (QSE_CMGR_SLMB); } - if (WSAStartup (MAKEWORD(2,0), &wsadata) != 0) - { - qse_fprintf (QSE_STDERR, QSE_T("Failed to start up winsock\n")); - return -1; - } - #else setlocale (LC_ALL, ""); qse_setdflcmgrbyid (QSE_CMGR_SLMB); #endif + qse_openstdsios (); + +#if defined(_WIN32) + if (WSAStartup (MAKEWORD(2,0), &wsadata) != 0) + { + qse_fprintf (QSE_STDERR, QSE_T("Failed to start up winsock\n")); + ret = -1; + goto oops; + } +#elif defined(__DOS__) + _watt_do_exit = 0; /* prevent sock_init from exiting upon failure */ + if (sock_init () != 0) + { + qse_fprintf (QSE_STDERR, QSE_T("Failed to initialize watt-32\n")); + ret = -1; + goto oops; + } +#endif + #if defined(HAVE_SSL) SSL_load_error_strings (); SSL_library_init (); #endif - qse_openstdsios (); ret = qse_runmain (argc, argv, httpd_main); - qse_closestdsios (); #if defined(HAVE_SSL) /* ERR_remove_state() should be called for each thread if the application is thread */ @@ -2767,7 +2781,11 @@ int qse_main (int argc, qse_achar_t* argv[]) #if defined(_WIN32) WSACleanup (); +#elif defined(__DOS__) + sock_exit (); #endif +oops: + qse_closestdsios (); return ret; } diff --git a/qse/doc/page/awk-lang.md b/qse/doc/page/awk-lang.md index f630ed9f..29d89f1a 100644 --- a/qse/doc/page/awk-lang.md +++ b/qse/doc/page/awk-lang.md @@ -771,7 +771,7 @@ success and -1 on failure. + codepage: *cp949*, *cp950*, *utf8*, *slmb*, *mb8* + ctimeout, atimeout, rtimeout, wtimeout: the number of seconds. effective on socket based streams only. you may use a floating-point number for - lower resoluation than a second. a negative value turns off timeout. + lower resolution than a second. a negative value turns off timeout. See this sample that prints the contents of a document encoded in cp949. diff --git a/qse/lib/cmn/nwad-skad.c b/qse/lib/cmn/nwad-skad.c index 1a189e44..fe23de6d 100644 --- a/qse/lib/cmn/nwad-skad.c +++ b/qse/lib/cmn/nwad-skad.c @@ -45,7 +45,8 @@ # undef AF_UNIX # pragma library("tcpip32.lib") #elif defined(__DOS__) - /* TODO: consider watt-32 */ +# include /* watt-32 */ +# undef AF_UNIX #else # include # include diff --git a/qse/lib/cmn/nwio.c b/qse/lib/cmn/nwio.c index 1bcde653..8262f930 100644 --- a/qse/lib/cmn/nwio.c +++ b/qse/lib/cmn/nwio.c @@ -43,7 +43,14 @@ # include # endif #elif defined(__DOS__) - /* TODO: consider watt-32 */ +# include +# include +# define memset QSE_MEMSET /* FD_SET hardcodes memset() */ +# define select select_s +# define USE_SELECT + /* SO_RCVTIMEO doesn't work or i don't know how to get it to work. */ +# undef SO_RCVTIMEO +# undef SO_SNDTIMEO #else # include "syscall.h" # include @@ -137,12 +144,12 @@ static qse_nwio_errnum_t skerr_to_errnum (int e) } } -#elif defined(__DOS__) +/*#elif defined(__DOS__) static qse_nwio_errnum_t skerr_to_errnum (int e) { - /* TODO: */ + return QSE_NWIO_ESYSERR; -} +}*/ #else static qse_nwio_errnum_t skerr_to_errnum (int e) { @@ -239,12 +246,12 @@ static int wait_for_data (qse_nwio_t* nwio, const qse_ntime_t* tmout, int what) #else if (xret <= -1) #endif - { + { #if defined(_WIN32) nwio->errnum = skerr_to_errnum (WSAGetLastError()); #elif defined(__OS2__) nwio->errnum = skerr_to_errnum (sock_errno()); - #else + #else nwio->errnum = skerr_to_errnum (errno); #endif return -1; @@ -265,7 +272,7 @@ static int wait_for_data (qse_nwio_t* nwio, const qse_ntime_t* tmout, int what) tmout_msecs = QSE_SECNSEC_TO_MSEC (tmout->sec, tmout->nsec); xret = os2_select (&nwio->handle, count[0], count[1], 0, tmout_msecs); if (xret <= -1) - { + { nwio->errnum = skerr_to_errnum (sock_errno()); return -1; } @@ -640,8 +647,120 @@ int qse_nwio_init ( } #elif defined(__DOS__) - nwio->errnum = QSE_NWIO_ENOIMPL; - return -1; + + nwio->handle = socket (family, type, 0); + if (nwio->handle <= -1) + { + nwio->errnum = skerr_to_errnum (errno); + goto oops; + } + + if ((flags & QSE_NWIO_TCP) && (flags & QSE_NWIO_KEEPALIVE)) + { + int optval = 1; + setsockopt (nwio->handle, SOL_SOCKET, SO_KEEPALIVE, (void*)&optval, QSE_SIZEOF(optval)); + } + + if (flags & QSE_NWIO_PASSIVE) + { + qse_nwio_hnd_t handle; + + #if defined(SO_REUSEADDR) + if (flags & QSE_NWIO_REUSEADDR) + { + int optval = 1; + setsockopt (nwio->handle, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, QSE_SIZEOF(optval)); + } + #endif + + if (bind (nwio->handle, (struct sockaddr*)&addr, addrlen) <= -1) + { + nwio->errnum = skerr_to_errnum (errno); + goto oops; + } + + if (flags & QSE_NWIO_TCP) + { + if (listen (nwio->handle, 10) <= -1) + { + nwio->errnum = skerr_to_errnum (errno); + goto oops; + } + + if (TMOUT_ENABLED(nwio->tmout.a) && + wait_for_data (nwio, &nwio->tmout.a, 0) <= -1) goto oops; + + handle = accept (nwio->handle, (struct sockaddr*)&addr, &addrlen); + if (handle <= -1) + { + nwio->errnum = skerr_to_errnum (errno); + goto oops; + } + + close_s (nwio->handle); + nwio->handle = handle; + } + else if (flags & QSE_NWIO_UDP) + { + nwio->status |= STATUS_UDP_CONNECT; + } + } + else + { + int xret; + + if (TMOUT_ENABLED(nwio->tmout.c) && (flags & QSE_NWIO_TCP)) + { + int cmd = 1; + + if (ioctlsocket(nwio->handle, FIONBIO, (char*)&cmd) == SOCKET_ERROR) + { + nwio->errnum = skerr_to_errnum (errno); + goto oops; + } + } + + xret = connect (nwio->handle, (struct sockaddr*)&addr, addrlen); + + if (TMOUT_ENABLED(nwio->tmout.c) && (flags & QSE_NWIO_TCP)) + { + int cmd = 0; + + if ((xret == SOCKET_ERROR && errno != EWOULDBLOCK) || + ioctlsocket (nwio->handle, FIONBIO, (char*)&cmd) == SOCKET_ERROR) + { + nwio->errnum = skerr_to_errnum (errno); + goto oops; + } + + if (wait_for_data (nwio, &nwio->tmout.c, 1) <= -1) goto oops; + else + { + int xlen, xerr; + + xlen = QSE_SIZEOF(xerr); + if (getsockopt (nwio->handle, SOL_SOCKET, SO_ERROR, (char*)&xerr, &xlen) <= -1) + { + nwio->errnum = skerr_to_errnum (errno); + goto oops; + } + else if (xerr != 0) + { + nwio->errnum = skerr_to_errnum (xerr); + goto oops; + } + } + } + else + { + if (xret <= -1) + { + nwio->errnum = skerr_to_errnum (errno); + goto oops; + } + } + } + #else #if defined(SOCK_CLOEXEC) @@ -721,8 +840,7 @@ int qse_nwio_init ( int orgfl; orgfl = fcntl (nwio->handle, F_GETFL, 0); - if (orgfl <= -1 || - fcntl (nwio->handle, F_SETFL, orgfl | O_NONBLOCK) <= -1) + if (orgfl <= -1 || fcntl (nwio->handle, F_SETFL, orgfl | O_NONBLOCK) <= -1) { nwio->errnum = skerr_to_errnum (errno); goto oops; @@ -974,10 +1092,10 @@ static qse_ssize_t nwio_read (qse_nwio_t* nwio, void* buf, qse_size_t size) return n; -#elif defined(__DOS__) +/*#elif defined(__DOS__) nwio->errnum = QSE_NWIO_ENOIMPL; - return -1; + return -1; */ #else @@ -1109,10 +1227,10 @@ static qse_ssize_t nwio_write (qse_nwio_t* nwio, const void* data, qse_size_t si if (n <= -1) nwio->errnum = skerr_to_errnum (sock_errno()); return n; -#elif defined(__DOS__) +/*#elif defined(__DOS__) nwio->errnum = QSE_NWIO_ENOIMPL; - return -1; + return -1;*/ #else diff --git a/qse/lib/cmn/sck.c b/qse/lib/cmn/sck.c index c958fccc..9c517285 100644 --- a/qse/lib/cmn/sck.c +++ b/qse/lib/cmn/sck.c @@ -40,7 +40,7 @@ # include # endif #elif defined(__DOS__) - /* TODO: consider watt-32 */ +# include /* watt-32 */ #else # include "syscall.h" # include @@ -72,8 +72,9 @@ QSE_INLINE int qse_isvalidsckhnd (qse_sck_hnd_t handle) return handle >= 0; #elif defined(__DOS__) - /* TODO: */ - return 0; + + return handle >= 0; + #else return handle >= 0; #endif @@ -86,7 +87,7 @@ QSE_INLINE void qse_closesckhnd (qse_sck_hnd_t handle) #elif defined(__OS2__) soclose (handle); #elif defined(__DOS__) - /* TODO: */ + close_s (handle); #else QSE_CLOSE (handle); #endif @@ -101,7 +102,7 @@ QSE_INLINE void qse_shutsckhnd (qse_sck_hnd_t handle, qse_shutsckhnd_how_t how) #elif defined(__OS2__) shutdown (handle, how_v[how]); #elif defined(__DOS__) - /* TODO: */ + shutdown (handle, how_v[how]); #else shutdown (handle, how_v[how]); #endif @@ -211,7 +212,7 @@ void qse_sck_fini (qse_sck_t* sck) #elif defined(__OS2__) soclose (sck->handle); #elif defined(__DOS__) - /* TODO: */ + close_s (sck->handle) #else QSE_CLOSE (sck->handle); #endif diff --git a/qse/lib/http/httpd-std.c b/qse/lib/http/httpd-std.c index 347d5327..a4612832 100644 --- a/qse/lib/http/httpd-std.c +++ b/qse/lib/http/httpd-std.c @@ -75,6 +75,7 @@ # include # include /* watt-32 */ +# include /* watt-32 */ # define select select_s /* TODO: is this correct? */ # undef AF_UNIX @@ -791,6 +792,16 @@ static int set_socket_nonblock (qse_httpd_t* httpd, qse_sck_hnd_t fd, int enable } return 0; +#elif defined(__DOS__) + + if (ioctlsocket (fd, FIONBIO, (char*)&enabled) == SOCKET_ERROR) + { + qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM()); + return -1; + } + + return 0; + #elif defined(O_NONBLOCK) int flag = fcntl (fd, F_GETFL); @@ -970,7 +981,6 @@ qse_fprintf (QSE_STDERR, QSE_T("Failed to enable SO_REUSEPORT\n")); setsockopt (fd, SOL_IP, IP_TRANSPARENT, &flag, QSE_SIZEOF(flag)); #endif - if (server->dope.flags & QSE_HTTPD_SERVER_BINDTONWIF) { #if defined(SO_BINDTODEVICE)