| 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: | |||