Ticket UUID: | 2384764107f0d084867503e16461f18b80f72e24 | ||
Title: | Make the http command working on Windows. | ||
Status: | Open | Type: | Feature_Request |
Severity: | Important | Priority: | Medium |
Subsystem: | Resolution: | Open | |
Last Modified: | 2009-09-21 00:37:14 | ||
Version Found In: | 0eb08b860c | ||
Description & Comments: | |||
This would make it possible to use Fossil with Inetd like servers on Windows, for example http://www.xmailserver.org/wininetd.html.
The following patch against Fossil version 0eb08b860c implements this functionality: diff -Naur fossil-src/src/cgi.c fossil-src-mod/src/cgi.c --- fossil-src/src/cgi.c 2009-09-13 09:37:48 +0000 +++ fossil-src-mod/src/cgi.c 2009-09-17 11:25:47 +0000 @@ -29,10 +29,11 @@ */ #include "config.h" #ifdef __MINGW32__ -# include <windows.h> /* for Sleep once server works again */ -# include <winsock2.h> /* socket operations */ -# define sleep Sleep /* windows does not have sleep, but Sleep */ -# include <ws2tcpip.h> +# include <windows.h> /* Windows specific declarations */ +# include <winsock2.h> /* Windows socket operations */ +# include <ws2tcpip.h> /* for socklen_t */ +# include <fcntl.h> +# include <io.h> #else # include <sys/socket.h> # include <netinet/in.h> @@ -1076,6 +1077,95 @@ return zResult; } +#ifdef __MINGW32__ +/* +** Data structure related to all variables for the windows socket environment. +*/ +typedef struct WinSocketData { + int fWSAInit; /* True, if Windows sockets initialized */ + SOCKET hSocket; /* Handle to the socket */ +} WinSocketData; + +static WinSocketData wsd; + +/* +** Exit handler routine. Make sure any remaining output gets flushed to the +** output stream. If the standard handles are redirected to a socket then +** make shure the socket gets closed properly and clean up the windows socket +** environment. +*/ +static void cgi_handle_http_request_exit(void) +{ + fflush(g.httpOut); + + if( wsd.hSocket != INVALID_SOCKET ){ + shutdown(wsd.hSocket, SD_BOTH); + closesocket(wsd.hSocket); + } + if (wsd.fWSAInit) { + WSACleanup(); + } + return; +} + +/* +** This routine initalizes the environment on windows for the +** cgi_handle_http_request routine. It sets the standard input and ouput +** handles to binary mode, initalizes the windows socket environment and tries +** to get the socket handle from the standard handles. It also establishs a +** exit routine to clean up on program exit. +*/ +void cgi_handle_http_request_init(void) +{ + WSADATA wd; + SOCKET hSock; + int socket_type; + int socket_type_len = sizeof(socket_type); + + /* + ** Initialize the windows socket data structure. + */ + wsd.fWSAInit = 0; + wsd.hSocket = INVALID_SOCKET; + + /* + ** Register the exit function. + */ + atexit(cgi_handle_http_request_exit); + + /* + ** Set the mode of the http input and output streams to binary. + */ + _setmode(_fileno(g.httpIn), _O_BINARY); + _setmode(_fileno(g.httpOut), _O_BINARY); + + /* + ** Initialize the windows socket API. This is required if we need to + ** call any other Windows Socket function. + */ + if( WSAStartup(MAKEWORD(2,2), &wd) == 0 ) wsd.fWSAInit = 1; + + /* + ** Windows Socket handles must be handled differently than file handles. + ** There is no function to detect if a file handle is a socket or not, so + ** lets call a socket function with the handle from stdin, and if there is + ** no error, assume it is a socket! + */ + if( wsd.fWSAInit ){ + hSock = (SOCKET)_get_osfhandle(_fileno(stdin)); + if( getsockopt (hSock, SOL_SOCKET, SO_TYPE, + (char *)&socket_type, &socket_type_len) == 0 ){ + wsd.hSocket = hSock; + } + } + return; +} + +# define CGI_SOCKET wsd.hSocket +#else +# define CGI_SOCKET fileno(g.httpIn) +#endif /* __MINGW32__ */ + /* ** This routine handles a single HTTP request which is coming in on ** standard input and which replies on standard output. @@ -1092,6 +1182,9 @@ size_t size = sizeof(struct sockaddr_in); char zLine[2000]; /* A single line of input. */ +#ifdef __MINGW32__ + cgi_handle_http_request_init(); +#endif g.fullHttpReply = 1; if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){ malformed_request(); @@ -1116,7 +1209,7 @@ cgi_setenv("PATH_INFO", zToken); cgi_setenv("QUERY_STRING", &zToken[i]); if( zIpAddr==0 && - getpeername(fileno(g.httpIn), (struct sockaddr*)&remoteName, + getpeername(CGI_SOCKET, (struct sockaddr*)&remoteName, (socklen_t*)&size)>=0 ){ zIpAddr = inet_ntoa(remoteName.sin_addr); --tsbg anonymous added on 2009-09-19 00:36:49: Test with current Fossil under Windows Vista: ================================================================ E:\dl\fossil-w32-20090915120431>fossil.exe http myclone.fossil GET / HTTP/1.0 Host: localhost HTTP/1.0 302 Moved Temporarily Date: Sat, 19 Sep 2009 00:30:23 GMT Connection: close Location: http://localhost/doc/tip/www/index.wiki Cache-control: no-cache, no-store Content-Type: text/html; charset=utf-8 Content-Length: 74 <html> <p>Redirect to http://localhost/doc/tip/www/index.wiki</p> </html> ======================= So it seems behave right, like declared. anonymous claiming to be tsbg added on 2009-09-19 08:46:37: Try it with the above mentioned WinInetd server, and you will see no output until you apply the patch. --tsbg anonymous claiming to be Andrey added on 2009-09-21 00:37:14: |