git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH v3 00/14] daemon-win32
@ 2010-10-10 13:20 Erik Faye-Lund
  2010-10-10 13:20 ` [PATCH v3 01/14] mingw: add network-wrappers for daemon Erik Faye-Lund
                   ` (13 more replies)
  0 siblings, 14 replies; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 13:20 UTC (permalink / raw)
  To: git; +Cc: msysgit, j6t

Almost 9 months have passed since I sent v2, and here's finally v3.

Not so much have happened since v2, the most significant change being
that I've replaced our win32-poll implementation with the one from
gnulib. This gives our the poll-features needed for git-daemon, and
prevents a nasty timing-bug that occured (on Windows) in the previous
series.

Some of the patches have been ejected;
* "daemon: use select() instead of poll()" because our poll now is
  sufficient.
* "daemon: use explicit file descriptor" because it wasn't needed
  anymore, not even in the previous version.

One patch might be a little bit controversial; "daemon: only use posix
features on posix systems". It replaces "mingw: compile git-daemon", and
changes the logic from opt-out is WIN32 is defined to opt-in if
_POSIX_VERSION defined.

The current version is based on top of junio/next, because the
ab/daemon-multi-select series touches some of the same code.

v2 msgid is <1263591033-4992-1-git-send-email-kusmabite@gmail.com> if
you're interrested in comparing.

Erik Faye-Lund (10):
  inet_ntop: fix a couple of old-style decls
  mingw: use real pid
  mingw: support waitpid with pid > 0 and WNOHANG
  mingw: add kill emulation
  daemon: use run-command api for async serving
  daemon: use full buffered mode for stderr
  daemon: report connection from root-process
  mingw: import poll-emulation from gnulib
  mingw: use poll-emulation from gnulib
  daemon: only use posix features on posix systems

Martin Storsjö (1):
  Improve the mingw getaddrinfo stub to handle more use cases

Mike Pape (3):
  mingw: add network-wrappers for daemon
  mingw: implement syslog
  compat: add inet_pton and inet_ntop prototypes

 Makefile            |   12 +-
 compat/inet_ntop.c  |   22 +--
 compat/inet_pton.c  |    8 +-
 compat/mingw.c      |  291 +++++++++++++++++++-------
 compat/mingw.h      |   56 ++++--
 compat/win32/poll.c |  596 +++++++++++++++++++++++++++++++++++++++++++++++++++
 compat/win32/poll.h |   53 +++++
 daemon.c            |  199 ++++++++++--------
 git-compat-util.h   |   10 +
 9 files changed, 1045 insertions(+), 202 deletions(-)
 create mode 100644 compat/win32/poll.c
 create mode 100644 compat/win32/poll.h

-- 
1.7.3.1.51.ge462f.dirty

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v3 01/14] mingw: add network-wrappers for daemon
  2010-10-10 13:20 [PATCH v3 00/14] daemon-win32 Erik Faye-Lund
@ 2010-10-10 13:20 ` Erik Faye-Lund
  2010-10-10 19:40   ` Eric Sunshine
  2010-10-10 13:20 ` [PATCH v3 02/14] mingw: implement syslog Erik Faye-Lund
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 13:20 UTC (permalink / raw)
  To: git; +Cc: msysgit, j6t, Mike Pape

From: Mike Pape <dotzenlabs@gmail.com>

git-daemon requires some socket-functionality that is not yet
supported in the Windows-port. This patch adds said functionality,
and makes sure WSAStartup gets called by socket(), since it is the
first network-call in git-daemon. In addition, a check is added to
prevent WSAStartup (and WSACleanup, though atexit) from being
called more than once, since git-daemon calls both socket() and
gethostbyname().

Signed-off-by: Mike Pape <dotzenlabs@gmail.com>
Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 compat/mingw.c |   43 ++++++++++++++++++++++++++++++++++++++++++-
 compat/mingw.h |   16 ++++++++++++++++
 2 files changed, 58 insertions(+), 1 deletions(-)

diff --git a/compat/mingw.c b/compat/mingw.c
index 6590f33..563ef1f 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -1175,7 +1175,10 @@ int mingw_getnameinfo(const struct sockaddr *sa, socklen_t salen,
 int mingw_socket(int domain, int type, int protocol)
 {
 	int sockfd;
-	SOCKET s = WSASocket(domain, type, protocol, NULL, 0, 0);
+	SOCKET s;
+
+	ensure_socket_initialization();
+	s = WSASocket(domain, type, protocol, NULL, 0, 0);
 	if (s == INVALID_SOCKET) {
 		/*
 		 * WSAGetLastError() values are regular BSD error codes
@@ -1205,6 +1208,44 @@ int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)
 	return connect(s, sa, sz);
 }
 
+#undef bind
+int mingw_bind(int sockfd, struct sockaddr *sa, size_t sz)
+{
+	SOCKET s = (SOCKET)_get_osfhandle(sockfd);
+	return bind(s, sa, sz);
+}
+
+#undef setsockopt
+int mingw_setsockopt(int sockfd, int lvl, int optname, void *optval, int optlen)
+{
+	SOCKET s = (SOCKET)_get_osfhandle(sockfd);
+	return setsockopt(s, lvl, optname, (const char*)optval, optlen);
+}
+
+#undef listen
+int mingw_listen(int sockfd, int backlog)
+{
+	SOCKET s = (SOCKET)_get_osfhandle(sockfd);
+	return listen(s, backlog);
+}
+
+#undef accept
+int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
+{
+	int sockfd2;
+
+	SOCKET s1 = (SOCKET)_get_osfhandle(sockfd1);
+	SOCKET s2 = accept(s1, sa, sz);
+
+	/* convert into a file descriptor */
+	if ((sockfd2 = _open_osfhandle(s2, O_RDWR|O_BINARY)) < 0) {
+		closesocket(s2);
+		return error("unable to make a socket file descriptor: %s",
+			strerror(errno));
+	}
+	return sockfd2;
+}
+
 #undef rename
 int mingw_rename(const char *pold, const char *pnew)
 {
diff --git a/compat/mingw.h b/compat/mingw.h
index 83e35e8..a5bde82 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -7,6 +7,7 @@
 
 typedef int pid_t;
 typedef int uid_t;
+typedef int socklen_t;
 #define hstrerror strerror
 
 #define S_IFLNK    0120000 /* Symbolic link */
@@ -47,6 +48,9 @@ typedef int uid_t;
 #define F_SETFD 2
 #define FD_CLOEXEC 0x1
 
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#define ECONNABORTED WSAECONNABORTED
+
 struct passwd {
 	char *pw_name;
 	char *pw_gecos;
@@ -225,6 +229,18 @@ int mingw_socket(int domain, int type, int protocol);
 int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz);
 #define connect mingw_connect
 
+int mingw_bind(int sockfd, struct sockaddr *sa, size_t sz);
+#define bind mingw_bind
+
+int mingw_setsockopt(int sockfd, int lvl, int optname, void *optval, int optlen);
+#define setsockopt mingw_setsockopt
+
+int mingw_listen(int sockfd, int backlog);
+#define listen mingw_listen
+
+int mingw_accept(int sockfd, struct sockaddr *sa, socklen_t *sz);
+#define accept mingw_accept
+
 int mingw_rename(const char*, const char*);
 #define rename mingw_rename
 
-- 
1.7.3.1.51.ge462f.dirty

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 02/14] mingw: implement syslog
  2010-10-10 13:20 [PATCH v3 00/14] daemon-win32 Erik Faye-Lund
  2010-10-10 13:20 ` [PATCH v3 01/14] mingw: add network-wrappers for daemon Erik Faye-Lund
@ 2010-10-10 13:20 ` Erik Faye-Lund
  2010-10-10 19:50   ` [msysGit] " Eric Sunshine
  2010-10-10 13:20 ` [PATCH v3 03/14] compat: add inet_pton and inet_ntop prototypes Erik Faye-Lund
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 13:20 UTC (permalink / raw)
  To: git; +Cc: msysgit, j6t, Mike Pape

From: Mike Pape <dotzenlabs@gmail.com>

Syslog does not usually exist on Windows, so we implement our own
using Window's ReportEvent mechanism.

Signed-off-by: Mike Pape <dotzenlabs@gmail.com>
Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 compat/mingw.c    |   60 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 compat/mingw.h    |   15 +++++++++++++
 daemon.c          |    2 -
 git-compat-util.h |    1 +
 4 files changed, 76 insertions(+), 2 deletions(-)

diff --git a/compat/mingw.c b/compat/mingw.c
index 563ef1f..cc5eb2c 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -1431,6 +1431,66 @@ int sigaction(int sig, struct sigaction *in, struct sigaction *out)
 	return 0;
 }
 
+static HANDLE ms_eventlog;
+
+void openlog(const char *ident, int logopt, int facility)
+{
+	if (ms_eventlog)
+		return;
+
+	ms_eventlog = RegisterEventSourceA(NULL, ident);
+
+	if (!ms_eventlog)
+		warning("RegisterEventSource() failed: %lu", GetLastError());
+}
+
+void syslog(int priority, const char *fmt, const char *arg)
+{
+	WORD logtype;
+
+	if (!ms_eventlog)
+		return;
+
+	if (strcmp(fmt, "%s")) {
+		warning("format string of syslog() not implemented");
+		return;
+	}
+
+	switch (priority) {
+	case LOG_EMERG:
+	case LOG_ALERT:
+	case LOG_CRIT:
+	case LOG_ERR:
+		logtype = EVENTLOG_ERROR_TYPE;
+		break;
+
+	case LOG_WARNING:
+		logtype = EVENTLOG_WARNING_TYPE;
+		break;
+
+	case LOG_NOTICE:
+	case LOG_INFO:
+	case LOG_DEBUG:
+	default:
+		logtype = EVENTLOG_INFORMATION_TYPE;
+		break;
+	}
+
+	/*
+	 * ReportEvent() doesn't handle strings containing %n, where n is
+	 * an integer. Such events must be reformatted by the caller.
+	 */
+	ReportEventA(ms_eventlog,
+	    logtype,
+	    0,
+	    0,
+	    NULL,
+	    1,
+	    0,
+	    (const char **)&arg,
+	    NULL);
+}
+
 #undef signal
 sig_handler_t mingw_signal(int sig, sig_handler_t handler)
 {
diff --git a/compat/mingw.h b/compat/mingw.h
index a5bde82..bbfcc0c 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -51,6 +51,19 @@ typedef int socklen_t;
 #define EAFNOSUPPORT WSAEAFNOSUPPORT
 #define ECONNABORTED WSAECONNABORTED
 
+#define LOG_PID     0x01
+
+#define LOG_EMERG   0
+#define LOG_ALERT   1
+#define LOG_CRIT    2
+#define LOG_ERR     3
+#define LOG_WARNING 4
+#define LOG_NOTICE  5
+#define LOG_INFO    6
+#define LOG_DEBUG   7
+
+#define LOG_DAEMON  (3<<3)
+
 struct passwd {
 	char *pw_name;
 	char *pw_gecos;
@@ -185,6 +198,8 @@ struct passwd *getpwuid(uid_t uid);
 int setitimer(int type, struct itimerval *in, struct itimerval *out);
 int sigaction(int sig, struct sigaction *in, struct sigaction *out);
 int link(const char *oldpath, const char *newpath);
+void openlog(const char *ident, int logopt, int facility);
+void syslog(int priority, const char *fmt, const char *arg);
 
 /*
  * replacements of existing functions
diff --git a/daemon.c b/daemon.c
index d6e20c6..d594375 100644
--- a/daemon.c
+++ b/daemon.c
@@ -5,8 +5,6 @@
 #include "strbuf.h"
 #include "string-list.h"
 
-#include <syslog.h>
-
 #ifndef HOST_NAME_MAX
 #define HOST_NAME_MAX 256
 #endif
diff --git a/git-compat-util.h b/git-compat-util.h
index 2af8d3e..8770854 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -119,6 +119,7 @@
 #include <netdb.h>
 #include <pwd.h>
 #include <inttypes.h>
+#include <syslog.h>
 #if defined(__CYGWIN__)
 #undef _XOPEN_SOURCE
 #include <grp.h>
-- 
1.7.3.1.51.ge462f.dirty

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 03/14] compat: add inet_pton and inet_ntop prototypes
  2010-10-10 13:20 [PATCH v3 00/14] daemon-win32 Erik Faye-Lund
  2010-10-10 13:20 ` [PATCH v3 01/14] mingw: add network-wrappers for daemon Erik Faye-Lund
  2010-10-10 13:20 ` [PATCH v3 02/14] mingw: implement syslog Erik Faye-Lund
@ 2010-10-10 13:20 ` Erik Faye-Lund
  2010-10-10 13:20 ` [PATCH v3 04/14] inet_ntop: fix a couple of old-style decls Erik Faye-Lund
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 13:20 UTC (permalink / raw)
  To: git; +Cc: msysgit, j6t, Mike Pape

From: Mike Pape <dotzenlabs@gmail.com>

Windows doesn't have inet_pton and inet_ntop, so
add prototypes in git-compat-util.h for them.

At the same time include git-compat-util.h in
the sources for these functions, so they use the
network-wrappers from there on Windows.

Signed-off-by: Mike Pape <dotzenlabs@gmail.com>
Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 Makefile           |    2 ++
 compat/inet_ntop.c |    6 +++---
 compat/inet_pton.c |    8 +++++---
 git-compat-util.h  |    8 ++++++++
 4 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/Makefile b/Makefile
index 1f1ce04..ebb51e3 100644
--- a/Makefile
+++ b/Makefile
@@ -1397,9 +1397,11 @@ endif
 endif
 ifdef NO_INET_NTOP
 	LIB_OBJS += compat/inet_ntop.o
+	BASIC_CFLAGS += -DNO_INET_NTOP
 endif
 ifdef NO_INET_PTON
 	LIB_OBJS += compat/inet_pton.o
+	BASIC_CFLAGS += -DNO_INET_PTON
 endif
 
 ifdef NO_ICONV
diff --git a/compat/inet_ntop.c b/compat/inet_ntop.c
index f444982..e5b46a0 100644
--- a/compat/inet_ntop.c
+++ b/compat/inet_ntop.c
@@ -17,9 +17,9 @@
 
 #include <errno.h>
 #include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
+
+#include "../git-compat-util.h"
+
 #include <stdio.h>
 #include <string.h>
 
diff --git a/compat/inet_pton.c b/compat/inet_pton.c
index 4078fc0..2ec995e 100644
--- a/compat/inet_pton.c
+++ b/compat/inet_pton.c
@@ -17,9 +17,9 @@
 
 #include <errno.h>
 #include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
+
+#include "../git-compat-util.h"
+
 #include <stdio.h>
 #include <string.h>
 
@@ -41,7 +41,9 @@
  */
 
 static int inet_pton4(const char *src, unsigned char *dst);
+#ifndef NO_IPV6
 static int inet_pton6(const char *src, unsigned char *dst);
+#endif
 
 /* int
  * inet_pton4(src, dst)
diff --git a/git-compat-util.h b/git-compat-util.h
index 8770854..100197f 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -387,6 +387,14 @@ static inline void *gitmempcpy(void *dest, const void *src, size_t n)
 }
 #endif
 
+#ifdef NO_INET_PTON
+int inet_pton(int af, const char *src, void *dst);
+#endif
+
+#ifdef NO_INET_NTOP
+const char *inet_ntop(int af, const void *src, char *dst, size_t size);
+#endif
+
 extern void release_pack_memory(size_t, int);
 
 typedef void (*try_to_free_t)(size_t);
-- 
1.7.3.1.51.ge462f.dirty

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 04/14] inet_ntop: fix a couple of old-style decls
  2010-10-10 13:20 [PATCH v3 00/14] daemon-win32 Erik Faye-Lund
                   ` (2 preceding siblings ...)
  2010-10-10 13:20 ` [PATCH v3 03/14] compat: add inet_pton and inet_ntop prototypes Erik Faye-Lund
@ 2010-10-10 13:20 ` Erik Faye-Lund
  2010-10-10 13:20 ` [PATCH v3 05/14] mingw: use real pid Erik Faye-Lund
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 13:20 UTC (permalink / raw)
  To: git; +Cc: msysgit, j6t

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 compat/inet_ntop.c |   16 +++-------------
 1 files changed, 3 insertions(+), 13 deletions(-)

diff --git a/compat/inet_ntop.c b/compat/inet_ntop.c
index e5b46a0..ea249c6 100644
--- a/compat/inet_ntop.c
+++ b/compat/inet_ntop.c
@@ -50,10 +50,7 @@
  *	Paul Vixie, 1996.
  */
 static const char *
-inet_ntop4(src, dst, size)
-	const u_char *src;
-	char *dst;
-	size_t size;
+inet_ntop4(const u_char *src, char *dst, size_t size)
 {
 	static const char fmt[] = "%u.%u.%u.%u";
 	char tmp[sizeof "255.255.255.255"];
@@ -78,10 +75,7 @@ inet_ntop4(src, dst, size)
  *	Paul Vixie, 1996.
  */
 static const char *
-inet_ntop6(src, dst, size)
-	const u_char *src;
-	char *dst;
-	size_t size;
+inet_ntop6(const u_char *src, char *dst, size_t size)
 {
 	/*
 	 * Note that int32_t and int16_t need only be "at least" large enough
@@ -178,11 +172,7 @@ inet_ntop6(src, dst, size)
  *	Paul Vixie, 1996.
  */
 const char *
-inet_ntop(af, src, dst, size)
-	int af;
-	const void *src;
-	char *dst;
-	size_t size;
+inet_ntop(int af, const void *src, char *dst, size_t size)
 {
 	switch (af) {
 	case AF_INET:
-- 
1.7.3.1.51.ge462f.dirty

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 05/14] mingw: use real pid
  2010-10-10 13:20 [PATCH v3 00/14] daemon-win32 Erik Faye-Lund
                   ` (3 preceding siblings ...)
  2010-10-10 13:20 ` [PATCH v3 04/14] inet_ntop: fix a couple of old-style decls Erik Faye-Lund
@ 2010-10-10 13:20 ` Erik Faye-Lund
  2010-10-10 19:53   ` Eric Sunshine
  2010-10-10 13:20 ` [PATCH v3 06/14] mingw: support waitpid with pid > 0 and WNOHANG Erik Faye-Lund
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 13:20 UTC (permalink / raw)
  To: git; +Cc: msysgit, j6t

The Windows port so far used process handles as PID. However,
this does not work consistently with getpid.

Change the code to use the real PID, and use OpenProcess to
get a process-handle. Store the PID and the process handle
in a table protected by a critical section, so we can safely
close the process handle later.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 compat/mingw.c |   70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 compat/mingw.h |   10 ++-----
 2 files changed, 72 insertions(+), 8 deletions(-)

diff --git a/compat/mingw.c b/compat/mingw.c
index cc5eb2c..4582345 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -702,6 +702,13 @@ static int env_compare(const void *a, const void *b)
 	return strcasecmp(*ea, *eb);
 }
 
+struct {
+	pid_t pid;
+	HANDLE proc;
+} *pinfo;
+static int num_pinfo;
+CRITICAL_SECTION pinfo_cs;
+
 static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,
 			      const char *dir,
 			      int prepend_cmd, int fhin, int fhout, int fherr)
@@ -794,7 +801,23 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,
 		return -1;
 	}
 	CloseHandle(pi.hThread);
-	return (pid_t)pi.hProcess;
+
+	/*
+	 * The process ID is the human-readable identifier of the process
+	 * that we want to present in log and error messages. The handle
+	 * is not useful for this purpose. But we cannot close it, either,
+	 * because it is not possible to turn a process ID into a process
+	 * handle after the process terminated.
+	 * Keep the handle in a list for waitpid.
+	 */
+	EnterCriticalSection(&pinfo_cs);
+	num_pinfo++;
+	pinfo = xrealloc(pinfo, sizeof(*pinfo) * num_pinfo);
+	pinfo[num_pinfo - 1].pid = pi.dwProcessId;
+	pinfo[num_pinfo - 1].proc = pi.hProcess;
+	LeaveCriticalSection(&pinfo_cs);
+
+	return (pid_t)pi.dwProcessId;
 }
 
 static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
@@ -1577,6 +1600,51 @@ char *getpass(const char *prompt)
 	return strbuf_detach(&buf, NULL);
 }
 
+pid_t waitpid(pid_t pid, int *status, unsigned options)
+{
+	HANDLE h = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
+	    FALSE, pid);
+	if (!h) {
+		errno = ECHILD;
+		return -1;
+	}
+
+	if (options == 0) {
+		int i;
+		if (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {
+			CloseHandle(h);
+			return 0;
+		}
+
+		if (status)
+			GetExitCodeProcess(h, (LPDWORD)status);
+
+		EnterCriticalSection(&pinfo_cs);
+
+		for (i = 0; i < num_pinfo; ++i)
+			if (pinfo[i].pid == pid)
+				break;
+
+		if (i < num_pinfo) {
+			CloseHandle(pinfo[i].proc);
+			memmove(pinfo + i, pinfo + i + 1,
+			    sizeof(*pinfo) * (num_pinfo - i - 1));
+			num_pinfo--;
+			pinfo = xrealloc(pinfo,
+			    sizeof(*pinfo) * num_pinfo);
+		}
+
+		LeaveCriticalSection(&pinfo_cs);
+
+		CloseHandle(h);
+		return pid;
+	}
+	CloseHandle(h);
+
+	errno = EINVAL;
+	return -1;
+}
+
 #ifndef NO_MINGW_REPLACE_READDIR
 /* MinGW readdir implementation to avoid extra lstats for Git */
 struct mingw_DIR
diff --git a/compat/mingw.h b/compat/mingw.h
index bbfcc0c..96ed931 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -153,13 +153,7 @@ static inline int mingw_unlink(const char *pathname)
 }
 #define unlink mingw_unlink
 
-static inline pid_t waitpid(pid_t pid, int *status, unsigned options)
-{
-	if (options == 0)
-		return _cwait(status, pid, 0);
-	errno = EINVAL;
-	return -1;
-}
+pid_t waitpid(pid_t pid, int *status, unsigned options);
 
 #ifndef NO_OPENSSL
 #include <openssl/ssl.h>
@@ -336,11 +330,13 @@ void free_environ(char **env);
 static int mingw_main(); \
 int main(int argc, const char **argv) \
 { \
+	extern CRITICAL_SECTION pinfo_cs; \
 	_fmode = _O_BINARY; \
 	_setmode(_fileno(stdin), _O_BINARY); \
 	_setmode(_fileno(stdout), _O_BINARY); \
 	_setmode(_fileno(stderr), _O_BINARY); \
 	argv[0] = xstrdup(_pgmptr); \
+	InitializeCriticalSection(&pinfo_cs); \
 	return mingw_main(argc, argv); \
 } \
 static int mingw_main(c,v)
-- 
1.7.3.1.51.ge462f.dirty

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 06/14] mingw: support waitpid with pid > 0 and WNOHANG
  2010-10-10 13:20 [PATCH v3 00/14] daemon-win32 Erik Faye-Lund
                   ` (4 preceding siblings ...)
  2010-10-10 13:20 ` [PATCH v3 05/14] mingw: use real pid Erik Faye-Lund
@ 2010-10-10 13:20 ` Erik Faye-Lund
  2010-10-10 13:20 ` [PATCH v3 07/14] mingw: add kill emulation Erik Faye-Lund
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 13:20 UTC (permalink / raw)
  To: git; +Cc: msysgit, j6t

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 compat/mingw.c |    6 ++++++
 compat/mingw.h |    1 +
 2 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/compat/mingw.c b/compat/mingw.c
index 4582345..55ea250 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -1609,6 +1609,12 @@ pid_t waitpid(pid_t pid, int *status, unsigned options)
 		return -1;
 	}
 
+	if (pid > 0 && options & WNOHANG) {
+		if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))
+			return 0;
+		options &= ~WNOHANG;
+	}
+
 	if (options == 0) {
 		int i;
 		if (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {
diff --git a/compat/mingw.h b/compat/mingw.h
index 96ed931..6d7a3f6 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -153,6 +153,7 @@ static inline int mingw_unlink(const char *pathname)
 }
 #define unlink mingw_unlink
 
+#define WNOHANG 1
 pid_t waitpid(pid_t pid, int *status, unsigned options);
 
 #ifndef NO_OPENSSL
-- 
1.7.3.1.51.ge462f.dirty

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 07/14] mingw: add kill emulation
  2010-10-10 13:20 [PATCH v3 00/14] daemon-win32 Erik Faye-Lund
                   ` (5 preceding siblings ...)
  2010-10-10 13:20 ` [PATCH v3 06/14] mingw: support waitpid with pid > 0 and WNOHANG Erik Faye-Lund
@ 2010-10-10 13:20 ` Erik Faye-Lund
  2010-10-10 13:20 ` [PATCH v3 08/14] daemon: use run-command api for async serving Erik Faye-Lund
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 13:20 UTC (permalink / raw)
  To: git; +Cc: msysgit, j6t

This is a quite limited kill-emulation; it can only handle
SIGTERM on positive pids. However, it's enough for git-daemon.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 compat/mingw.c |   19 +++++++++++++++++++
 compat/mingw.h |    3 +++
 2 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/compat/mingw.c b/compat/mingw.c
index 55ea250..44ea419 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -932,6 +932,25 @@ void mingw_execv(const char *cmd, char *const *argv)
 	mingw_execve(cmd, argv, environ);
 }
 
+int mingw_kill(pid_t pid, int sig)
+{
+	if (pid > 0 && sig == SIGTERM) {
+		HANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
+
+		if (TerminateProcess(h, -1)) {
+			CloseHandle(h);
+			return 0;
+		}
+
+		errno = err_win_to_posix(GetLastError());
+		CloseHandle(h);
+		return -1;
+	}
+
+	errno = EINVAL;
+	return -1;
+}
+
 static char **copy_environ(void)
 {
 	char **env;
diff --git a/compat/mingw.h b/compat/mingw.h
index 6d7a3f6..2218043 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -156,6 +156,9 @@ static inline int mingw_unlink(const char *pathname)
 #define WNOHANG 1
 pid_t waitpid(pid_t pid, int *status, unsigned options);
 
+#define kill mingw_kill
+int mingw_kill(pid_t pid, int sig);
+
 #ifndef NO_OPENSSL
 #include <openssl/ssl.h>
 static inline int mingw_SSL_set_fd(SSL *ssl, int fd)
-- 
1.7.3.1.51.ge462f.dirty

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 08/14] daemon: use run-command api for async serving
  2010-10-10 13:20 [PATCH v3 00/14] daemon-win32 Erik Faye-Lund
                   ` (6 preceding siblings ...)
  2010-10-10 13:20 ` [PATCH v3 07/14] mingw: add kill emulation Erik Faye-Lund
@ 2010-10-10 13:20 ` Erik Faye-Lund
  2010-10-10 19:56   ` [msysGit] " Eric Sunshine
  2010-10-10 13:20 ` [PATCH v3 09/14] daemon: use full buffered mode for stderr Erik Faye-Lund
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 13:20 UTC (permalink / raw)
  To: git; +Cc: msysgit, j6t

fork() is only available on POSIX, so to support git-daemon
on Windows we have to use something else.

Instead we invent the flag --serve, which is a stripped down
version of --inetd-mode. We use start_command() to call
git-daemon with this flag appended to serve clients.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 daemon.c |   86 +++++++++++++++++++++++++++++++-------------------------------
 1 files changed, 43 insertions(+), 43 deletions(-)

diff --git a/daemon.c b/daemon.c
index d594375..ee29c9f 100644
--- a/daemon.c
+++ b/daemon.c
@@ -614,17 +614,17 @@ static unsigned int live_children;
 
 static struct child {
 	struct child *next;
-	pid_t pid;
+	struct child_process cld;
 	struct sockaddr_storage address;
 } *firstborn;
 
-static void add_child(pid_t pid, struct sockaddr *addr, int addrlen)
+static void add_child(struct child_process *cld, struct sockaddr *addr, int addrlen)
 {
 	struct child *newborn, **cradle;
 
 	newborn = xcalloc(1, sizeof(*newborn));
 	live_children++;
-	newborn->pid = pid;
+	memcpy(&newborn->cld, cld, sizeof(*cld));
 	memcpy(&newborn->address, addr, addrlen);
 	for (cradle = &firstborn; *cradle; cradle = &(*cradle)->next)
 		if (!addrcmp(&(*cradle)->address, &newborn->address))
@@ -633,19 +633,6 @@ static void add_child(pid_t pid, struct sockaddr *addr, int addrlen)
 	*cradle = newborn;
 }
 
-static void remove_child(pid_t pid)
-{
-	struct child **cradle, *blanket;
-
-	for (cradle = &firstborn; (blanket = *cradle); cradle = &blanket->next)
-		if (blanket->pid == pid) {
-			*cradle = blanket->next;
-			live_children--;
-			free(blanket);
-			break;
-		}
-}
-
 /*
  * This gets called if the number of connections grows
  * past "max_connections".
@@ -654,14 +641,14 @@ static void remove_child(pid_t pid)
  */
 static void kill_some_child(void)
 {
-	const struct child *blanket, *next;
+	struct child *blanket, *next;
 
 	if (!(blanket = firstborn))
 		return;
 
 	for (; (next = blanket->next); blanket = next)
 		if (!addrcmp(&blanket->address, &next->address)) {
-			kill(blanket->pid, SIGTERM);
+			kill(blanket->cld.pid, SIGTERM);
 			break;
 		}
 }
@@ -671,18 +658,26 @@ static void check_dead_children(void)
 	int status;
 	pid_t pid;
 
-	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
-		const char *dead = "";
-		remove_child(pid);
-		if (!WIFEXITED(status) || (WEXITSTATUS(status) > 0))
-			dead = " (with error)";
-		loginfo("[%"PRIuMAX"] Disconnected%s", (uintmax_t)pid, dead);
-	}
+	struct child **cradle, *blanket;
+	for (cradle = &firstborn; (blanket = *cradle);)
+		if ((pid = waitpid(blanket->cld.pid, &status, WNOHANG)) > 1) {
+			const char *dead = "";
+			if (status)
+				dead = " (with error)";
+			loginfo("[%"PRIuMAX"] Disconnected%s", (uintmax_t)pid, dead);
+
+			/* remove the child */
+			*cradle = blanket->next;
+			live_children--;
+			free(blanket);
+		} else
+			cradle = &blanket->next;
 }
 
+char **cld_argv;
 static void handle(int incoming, struct sockaddr *addr, int addrlen)
 {
-	pid_t pid;
+	struct child_process cld = { 0 };
 
 	if (max_connections && live_children >= max_connections) {
 		kill_some_child();
@@ -695,22 +690,15 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)
 		}
 	}
 
-	if ((pid = fork())) {
-		close(incoming);
-		if (pid < 0) {
-			logerror("Couldn't fork %s", strerror(errno));
-			return;
-		}
-
-		add_child(pid, addr, addrlen);
-		return;
-	}
+	cld.argv = (const char **)cld_argv;
+	cld.in = incoming;
+	cld.out = dup(incoming);
 
-	dup2(incoming, 0);
-	dup2(incoming, 1);
+	if (start_command(&cld))
+		logerror("unable to fork");
+	else
+		add_child(&cld, addr, addrlen);
 	close(incoming);
-
-	exit(execute(addr));
 }
 
 static void child_handler(int signo)
@@ -991,7 +979,7 @@ int main(int argc, char **argv)
 {
 	int listen_port = 0;
 	struct string_list listen_addr = STRING_LIST_INIT_NODUP;
-	int inetd_mode = 0;
+	int serve_mode = 0, inetd_mode = 0;
 	const char *pid_file = NULL, *user_name = NULL, *group_name = NULL;
 	int detach = 0;
 	struct passwd *pass = NULL;
@@ -1017,7 +1005,12 @@ int main(int argc, char **argv)
 				continue;
 			}
 		}
+		if (!strcmp(arg, "--serve")) {
+			serve_mode = 1;
+			continue;
+		}
 		if (!strcmp(arg, "--inetd")) {
+			serve_mode = 1;
 			inetd_mode = 1;
 			log_syslog = 1;
 			continue;
@@ -1161,12 +1154,12 @@ int main(int argc, char **argv)
 		die("base-path '%s' does not exist or is not a directory",
 		    base_path);
 
-	if (inetd_mode) {
+	if (serve_mode) {
 		struct sockaddr_storage ss;
 		struct sockaddr *peer = (struct sockaddr *)&ss;
 		socklen_t slen = sizeof(ss);
 
-		if (!freopen("/dev/null", "w", stderr))
+		if (inetd_mode && !freopen("/dev/null", "w", stderr))
 			die_errno("failed to redirect stderr to /dev/null");
 
 		if (getpeername(0, peer, &slen))
@@ -1185,5 +1178,12 @@ int main(int argc, char **argv)
 	if (pid_file)
 		store_pid(pid_file);
 
+	/* prepare argv for serving-processes */
+	cld_argv = xmalloc(sizeof (char *) * (argc + 2));
+	for (i = 0; i < argc; ++i)
+		cld_argv[i] = argv[i];
+	cld_argv[argc] = "--serve";
+	cld_argv[argc+1] = NULL;
+
 	return serve(&listen_addr, listen_port, pass, gid);
 }
-- 
1.7.3.1.51.ge462f.dirty

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 09/14] daemon: use full buffered mode for stderr
  2010-10-10 13:20 [PATCH v3 00/14] daemon-win32 Erik Faye-Lund
                   ` (7 preceding siblings ...)
  2010-10-10 13:20 ` [PATCH v3 08/14] daemon: use run-command api for async serving Erik Faye-Lund
@ 2010-10-10 13:20 ` Erik Faye-Lund
  2010-10-10 13:20 ` [PATCH v3 10/14] Improve the mingw getaddrinfo stub to handle more use cases Erik Faye-Lund
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 13:20 UTC (permalink / raw)
  To: git; +Cc: msysgit, j6t

Windows doesn't support line buffered mode for file
streams, so let's just use full buffered mode with
a big buffer ("4096 should be enough for everyone")
and add explicit flushing.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 daemon.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/daemon.c b/daemon.c
index ee29c9f..82ba5c7 100644
--- a/daemon.c
+++ b/daemon.c
@@ -67,12 +67,14 @@ static void logreport(int priority, const char *err, va_list params)
 		syslog(priority, "%s", buf);
 	} else {
 		/*
-		 * Since stderr is set to linebuffered mode, the
+		 * Since stderr is set to buffered mode, the
 		 * logging of different processes will not overlap
+		 * unless they overflow the (rather big) buffers.
 		 */
 		fprintf(stderr, "[%"PRIuMAX"] ", (uintmax_t)getpid());
 		vfprintf(stderr, err, params);
 		fputc('\n', stderr);
+		fflush(stderr);
 	}
 }
 
@@ -1118,7 +1120,7 @@ int main(int argc, char **argv)
 		set_die_routine(daemon_die);
 	} else
 		/* avoid splitting a message in the middle */
-		setvbuf(stderr, NULL, _IOLBF, 0);
+		setvbuf(stderr, NULL, _IOFBF, 4096);
 
 	if (inetd_mode && (group_name || user_name))
 		die("--user and --group are incompatible with --inetd");
-- 
1.7.3.1.51.ge462f.dirty

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 10/14] Improve the mingw getaddrinfo stub to handle more use cases
  2010-10-10 13:20 [PATCH v3 00/14] daemon-win32 Erik Faye-Lund
                   ` (8 preceding siblings ...)
  2010-10-10 13:20 ` [PATCH v3 09/14] daemon: use full buffered mode for stderr Erik Faye-Lund
@ 2010-10-10 13:20 ` Erik Faye-Lund
  2010-10-10 13:20 ` [PATCH v3 11/14] daemon: report connection from root-process Erik Faye-Lund
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 13:20 UTC (permalink / raw)
  To: git; +Cc: msysgit, j6t, Martin Storsjö

From: Martin Storsjö <martin@martin.st>

Allow the node parameter to be null, which is used for getting
the default bind address.

Also allow the hints parameter to be null, to improve standard
conformance of the stub implementation a little.

Signed-off-by: Martin Storsjo <martin@martin.st>
---
 compat/mingw.c |   28 +++++++++++++++++++++-------
 1 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/compat/mingw.c b/compat/mingw.c
index 44ea419..32ca664 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -1035,19 +1035,22 @@ static int WSAAPI getaddrinfo_stub(const char *node, const char *service,
 				   const struct addrinfo *hints,
 				   struct addrinfo **res)
 {
-	struct hostent *h = gethostbyname(node);
+	struct hostent *h = NULL;
 	struct addrinfo *ai;
 	struct sockaddr_in *sin;
 
-	if (!h)
-		return WSAGetLastError();
+	if (node) {
+		h = gethostbyname(node);
+		if (!h)
+			return WSAGetLastError();
+	}
 
 	ai = xmalloc(sizeof(struct addrinfo));
 	*res = ai;
 	ai->ai_flags = 0;
 	ai->ai_family = AF_INET;
-	ai->ai_socktype = hints->ai_socktype;
-	switch (hints->ai_socktype) {
+	ai->ai_socktype = hints ? hints->ai_socktype : 0;
+	switch (ai->ai_socktype) {
 	case SOCK_STREAM:
 		ai->ai_protocol = IPPROTO_TCP;
 		break;
@@ -1059,14 +1062,25 @@ static int WSAAPI getaddrinfo_stub(const char *node, const char *service,
 		break;
 	}
 	ai->ai_addrlen = sizeof(struct sockaddr_in);
-	ai->ai_canonname = strdup(h->h_name);
+	if (hints && (hints->ai_flags & AI_CANONNAME))
+		ai->ai_canonname = h ? strdup(h->h_name) : NULL;
+	else
+		ai->ai_canonname = NULL;
 
 	sin = xmalloc(ai->ai_addrlen);
 	memset(sin, 0, ai->ai_addrlen);
 	sin->sin_family = AF_INET;
+	/* Note: getaddrinfo is supposed to allow service to be a string,
+	 * which should be looked up using getservbyname. This is
+	 * currently not implemented */
 	if (service)
 		sin->sin_port = htons(atoi(service));
-	sin->sin_addr = *(struct in_addr *)h->h_addr;
+	if (h)
+		sin->sin_addr = *(struct in_addr *)h->h_addr;
+	else if (hints && (hints->ai_flags & AI_PASSIVE))
+		sin->sin_addr.s_addr = INADDR_ANY;
+	else
+		sin->sin_addr.s_addr = INADDR_LOOPBACK;
 	ai->ai_addr = (struct sockaddr *)sin;
 	ai->ai_next = 0;
 	return 0;
-- 
1.7.3.1.51.ge462f.dirty

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 11/14] daemon: report connection from root-process
  2010-10-10 13:20 [PATCH v3 00/14] daemon-win32 Erik Faye-Lund
                   ` (9 preceding siblings ...)
  2010-10-10 13:20 ` [PATCH v3 10/14] Improve the mingw getaddrinfo stub to handle more use cases Erik Faye-Lund
@ 2010-10-10 13:20 ` Erik Faye-Lund
  2010-10-10 18:58   ` Johannes Sixt
  2010-10-10 13:20 ` [PATCH v3 12/14] mingw: import poll-emulation from gnulib Erik Faye-Lund
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 13:20 UTC (permalink / raw)
  To: git; +Cc: msysgit, j6t

Report incoming connections from the process that
accept() the connection instead of the handling
process.

This enables "Connection from"-reporting on
Windows, where getpeername(0, ...) consistently
fails.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 daemon.c |   70 +++++++++++++++++++++++++++++++++++--------------------------
 1 files changed, 40 insertions(+), 30 deletions(-)

diff --git a/daemon.c b/daemon.c
index 82ba5c7..54bbec2 100644
--- a/daemon.c
+++ b/daemon.c
@@ -521,33 +521,6 @@ static int execute(struct sockaddr *addr)
 	static char line[1000];
 	int pktlen, len, i;
 
-	if (addr) {
-		char addrbuf[256] = "";
-		int port = -1;
-
-		if (addr->sa_family == AF_INET) {
-			struct sockaddr_in *sin_addr = (void *) addr;
-			inet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf));
-			port = ntohs(sin_addr->sin_port);
-#ifndef NO_IPV6
-		} else if (addr && addr->sa_family == AF_INET6) {
-			struct sockaddr_in6 *sin6_addr = (void *) addr;
-
-			char *buf = addrbuf;
-			*buf++ = '['; *buf = '\0'; /* stpcpy() is cool */
-			inet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1);
-			strcat(buf, "]");
-
-			port = ntohs(sin6_addr->sin6_port);
-#endif
-		}
-		loginfo("Connection from %s:%d", addrbuf, port);
-		setenv("REMOTE_ADDR", addrbuf, 1);
-	}
-	else {
-		unsetenv("REMOTE_ADDR");
-	}
-
 	alarm(init_timeout ? init_timeout : timeout);
 	pktlen = packet_read_line(0, line, sizeof(line));
 	alarm(0);
@@ -676,10 +649,35 @@ static void check_dead_children(void)
 			cradle = &blanket->next;
 }
 
+static char *get_addrstr(int *port, struct sockaddr *addr)
+{
+	static char addrbuf[256] = "";
+	if (addr->sa_family == AF_INET) {
+		struct sockaddr_in *sin_addr = (void *) addr;
+		inet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf));
+		*port = ntohs(sin_addr->sin_port);
+#ifndef NO_IPV6
+	} else if (addr && addr->sa_family == AF_INET6) {
+		struct sockaddr_in6 *sin6_addr = (void *) addr;
+
+		char *buf = addrbuf;
+		*buf++ = '['; *buf = '\0'; /* stpcpy() is cool */
+		inet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1);
+		strcat(buf, "]");
+
+		*port = ntohs(sin6_addr->sin6_port);
+#endif
+	}
+	return addrbuf;
+}
+
 char **cld_argv;
 static void handle(int incoming, struct sockaddr *addr, int addrlen)
 {
 	struct child_process cld = { 0 };
+	char *addrstr, envbuf[300] = "REMOTE_ADDR=";
+	char *env[] = { envbuf, NULL };
+	int port = -1;
 
 	if (max_connections && live_children >= max_connections) {
 		kill_some_child();
@@ -692,14 +690,21 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)
 		}
 	}
 
+	addrstr = get_addrstr(&port, addr);
+	strcat(envbuf, addrstr);
+
+	cld.env = (const char **)env;
 	cld.argv = (const char **)cld_argv;
 	cld.in = incoming;
 	cld.out = dup(incoming);
 
 	if (start_command(&cld))
 		logerror("unable to fork");
-	else
+	else {
+		loginfo("[%"PRIuMAX"] Connection from %s:%d",
+		    (uintmax_t)cld.pid, addrstr, port);
 		add_child(&cld, addr, addrlen);
+	}
 	close(incoming);
 }
 
@@ -1164,8 +1169,13 @@ int main(int argc, char **argv)
 		if (inetd_mode && !freopen("/dev/null", "w", stderr))
 			die_errno("failed to redirect stderr to /dev/null");
 
-		if (getpeername(0, peer, &slen))
-			peer = NULL;
+		if (!getpeername(0, peer, &slen)) {
+			int port = -1;
+			char *addrstr = get_addrstr(&port, peer);
+			setenv("REMOTE_ADDR", addrstr, 1);
+			loginfo("[%"PRIuMAX"] Connection from %s:%d",
+			    (uintmax_t)getpid(), addrstr, port);
+		}
 
 		return execute(peer);
 	}
-- 
1.7.3.1.51.ge462f.dirty

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 12/14] mingw: import poll-emulation from gnulib
  2010-10-10 13:20 [PATCH v3 00/14] daemon-win32 Erik Faye-Lund
                   ` (10 preceding siblings ...)
  2010-10-10 13:20 ` [PATCH v3 11/14] daemon: report connection from root-process Erik Faye-Lund
@ 2010-10-10 13:20 ` Erik Faye-Lund
  2010-10-10 14:15   ` Ævar Arnfjörð Bjarmason
  2010-10-10 13:20 ` [PATCH v3 13/14] mingw: use " Erik Faye-Lund
  2010-10-10 13:20 ` [PATCH v3 14/14] daemon: only use posix features on posix systems Erik Faye-Lund
  13 siblings, 1 reply; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 13:20 UTC (permalink / raw)
  To: git; +Cc: msysgit, j6t

lib/poll.c and lib/poll.in.h imported from 0a05120 in
git://git.savannah.gnu.org/gnulib.git
---
 compat/win32/poll.c |  597 +++++++++++++++++++++++++++++++++++++++++++++++++++
 compat/win32/poll.h |   53 +++++
 2 files changed, 650 insertions(+), 0 deletions(-)
 create mode 100644 compat/win32/poll.c
 create mode 100644 compat/win32/poll.h

diff --git a/compat/win32/poll.c b/compat/win32/poll.c
new file mode 100644
index 0000000..7c52cb6
--- /dev/null
+++ b/compat/win32/poll.c
@@ -0,0 +1,597 @@
+/* Emulation for poll(2)
+   Contributed by Paolo Bonzini.
+
+   Copyright 2001-2003, 2006-2010 Free Software Foundation, Inc.
+
+   This file is part of gnulib.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Tell gcc not to warn about the (nfd < 0) tests, below.  */
+#if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
+# pragma GCC diagnostic ignored "-Wtype-limits"
+#endif
+
+#include <config.h>
+#include <alloca.h>
+
+#include <sys/types.h>
+#include "poll.h"
+#include <errno.h>
+#include <limits.h>
+#include <assert.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WIN32_NATIVE
+# include <winsock2.h>
+# include <windows.h>
+# include <io.h>
+# include <stdio.h>
+# include <conio.h>
+#else
+# include <sys/time.h>
+# include <sys/socket.h>
+# include <sys/select.h>
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_FILIO_H
+# include <sys/filio.h>
+#endif
+
+#include <time.h>
+
+#ifndef INFTIM
+# define INFTIM (-1)
+#endif
+
+/* BeOS does not have MSG_PEEK.  */
+#ifndef MSG_PEEK
+# define MSG_PEEK 0
+#endif
+
+#ifdef WIN32_NATIVE
+
+#define IsConsoleHandle(h) (((long) (h) & 3) == 3)
+
+static BOOL
+IsSocketHandle (HANDLE h)
+{
+  WSANETWORKEVENTS ev;
+
+  if (IsConsoleHandle (h))
+    return FALSE;
+
+  /* Under Wine, it seems that getsockopt returns 0 for pipes too.
+     WSAEnumNetworkEvents instead distinguishes the two correctly.  */
+  ev.lNetworkEvents = 0xDEADBEEF;
+  WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
+  return ev.lNetworkEvents != 0xDEADBEEF;
+}
+
+/* Declare data structures for ntdll functions.  */
+typedef struct _FILE_PIPE_LOCAL_INFORMATION {
+  ULONG NamedPipeType;
+  ULONG NamedPipeConfiguration;
+  ULONG MaximumInstances;
+  ULONG CurrentInstances;
+  ULONG InboundQuota;
+  ULONG ReadDataAvailable;
+  ULONG OutboundQuota;
+  ULONG WriteQuotaAvailable;
+  ULONG NamedPipeState;
+  ULONG NamedPipeEnd;
+} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
+
+typedef struct _IO_STATUS_BLOCK
+{
+  union {
+    DWORD Status;
+    PVOID Pointer;
+  } u;
+  ULONG_PTR Information;
+} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
+
+typedef enum _FILE_INFORMATION_CLASS {
+  FilePipeLocalInformation = 24
+} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
+
+typedef DWORD (WINAPI *PNtQueryInformationFile)
+         (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
+
+# ifndef PIPE_BUF
+#  define PIPE_BUF      512
+# endif
+
+/* Compute revents values for file handle H.  If some events cannot happen
+   for the handle, eliminate them from *P_SOUGHT.  */
+
+static int
+win32_compute_revents (HANDLE h, int *p_sought)
+{
+  int i, ret, happened;
+  INPUT_RECORD *irbuffer;
+  DWORD avail, nbuffer;
+  BOOL bRet;
+  IO_STATUS_BLOCK iosb;
+  FILE_PIPE_LOCAL_INFORMATION fpli;
+  static PNtQueryInformationFile NtQueryInformationFile;
+  static BOOL once_only;
+
+  switch (GetFileType (h))
+    {
+    case FILE_TYPE_PIPE:
+      if (!once_only)
+        {
+          NtQueryInformationFile = (PNtQueryInformationFile)
+            GetProcAddress (GetModuleHandle ("ntdll.dll"),
+                            "NtQueryInformationFile");
+          once_only = TRUE;
+        }
+
+      happened = 0;
+      if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
+        {
+          if (avail)
+            happened |= *p_sought & (POLLIN | POLLRDNORM);
+        }
+      else if (GetLastError () == ERROR_BROKEN_PIPE)
+        happened |= POLLHUP;
+
+      else
+        {
+          /* It was the write-end of the pipe.  Check if it is writable.
+             If NtQueryInformationFile fails, optimistically assume the pipe is
+             writable.  This could happen on Win9x, where NtQueryInformationFile
+             is not available, or if we inherit a pipe that doesn't permit
+             FILE_READ_ATTRIBUTES access on the write end (I think this should
+             not happen since WinXP SP2; WINE seems fine too).  Otherwise,
+             ensure that enough space is available for atomic writes.  */
+          memset (&iosb, 0, sizeof (iosb));
+          memset (&fpli, 0, sizeof (fpli));
+
+          if (!NtQueryInformationFile
+              || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
+                                         FilePipeLocalInformation)
+              || fpli.WriteQuotaAvailable >= PIPE_BUF
+              || (fpli.OutboundQuota < PIPE_BUF &&
+                  fpli.WriteQuotaAvailable == fpli.OutboundQuota))
+            happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
+        }
+      return happened;
+
+    case FILE_TYPE_CHAR:
+      ret = WaitForSingleObject (h, 0);
+      if (!IsConsoleHandle (h))
+        return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
+
+      nbuffer = avail = 0;
+      bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
+      if (bRet)
+        {
+          /* Input buffer.  */
+          *p_sought &= POLLIN | POLLRDNORM;
+          if (nbuffer == 0)
+            return POLLHUP;
+          if (!*p_sought)
+            return 0;
+
+          irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
+          bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
+          if (!bRet || avail == 0)
+            return POLLHUP;
+
+          for (i = 0; i < avail; i++)
+            if (irbuffer[i].EventType == KEY_EVENT)
+              return *p_sought;
+          return 0;
+        }
+      else
+        {
+          /* Screen buffer.  */
+          *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
+          return *p_sought;
+        }
+
+    default:
+      ret = WaitForSingleObject (h, 0);
+      if (ret == WAIT_OBJECT_0)
+        return *p_sought & ~(POLLPRI | POLLRDBAND);
+
+      return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
+    }
+}
+
+/* Convert fd_sets returned by select into revents values.  */
+
+static int
+win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
+{
+  int happened = 0;
+
+  if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
+    happened |= (POLLIN | POLLRDNORM) & sought;
+
+  else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
+    {
+      int r, error;
+
+      char data[64];
+      WSASetLastError (0);
+      r = recv (h, data, sizeof (data), MSG_PEEK);
+      error = WSAGetLastError ();
+      WSASetLastError (0);
+
+      if (r > 0 || error == WSAENOTCONN)
+        happened |= (POLLIN | POLLRDNORM) & sought;
+
+      /* Distinguish hung-up sockets from other errors.  */
+      else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
+               || error == WSAECONNABORTED || error == WSAENETRESET)
+        happened |= POLLHUP;
+
+      else
+        happened |= POLLERR;
+    }
+
+  if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
+    happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
+
+  if (lNetworkEvents & FD_OOB)
+    happened |= (POLLPRI | POLLRDBAND) & sought;
+
+  return happened;
+}
+
+#else /* !MinGW */
+
+/* Convert select(2) returned fd_sets into poll(2) revents values.  */
+static int
+compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
+{
+  int happened = 0;
+  if (FD_ISSET (fd, rfds))
+    {
+      int r;
+      int socket_errno;
+
+# if defined __MACH__ && defined __APPLE__
+      /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
+         for some kinds of descriptors.  Detect if this descriptor is a
+         connected socket, a server socket, or something else using a
+         0-byte recv, and use ioctl(2) to detect POLLHUP.  */
+      r = recv (fd, NULL, 0, MSG_PEEK);
+      socket_errno = (r < 0) ? errno : 0;
+      if (r == 0 || socket_errno == ENOTSOCK)
+        ioctl (fd, FIONREAD, &r);
+# else
+      char data[64];
+      r = recv (fd, data, sizeof (data), MSG_PEEK);
+      socket_errno = (r < 0) ? errno : 0;
+# endif
+      if (r == 0)
+        happened |= POLLHUP;
+
+      /* If the event happened on an unconnected server socket,
+         that's fine. */
+      else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
+        happened |= (POLLIN | POLLRDNORM) & sought;
+
+      /* Distinguish hung-up sockets from other errors.  */
+      else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
+               || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
+        happened |= POLLHUP;
+
+      else
+        happened |= POLLERR;
+    }
+
+  if (FD_ISSET (fd, wfds))
+    happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
+
+  if (FD_ISSET (fd, efds))
+    happened |= (POLLPRI | POLLRDBAND) & sought;
+
+  return happened;
+}
+#endif /* !MinGW */
+
+int
+poll (pfd, nfd, timeout)
+     struct pollfd *pfd;
+     nfds_t nfd;
+     int timeout;
+{
+#ifndef WIN32_NATIVE
+  fd_set rfds, wfds, efds;
+  struct timeval tv;
+  struct timeval *ptv;
+  int maxfd, rc;
+  nfds_t i;
+
+# ifdef _SC_OPEN_MAX
+  static int sc_open_max = -1;
+
+  if (nfd < 0
+      || (nfd > sc_open_max
+          && (sc_open_max != -1
+              || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
+    {
+      errno = EINVAL;
+      return -1;
+    }
+# else /* !_SC_OPEN_MAX */
+#  ifdef OPEN_MAX
+  if (nfd < 0 || nfd > OPEN_MAX)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+#  endif /* OPEN_MAX -- else, no check is needed */
+# endif /* !_SC_OPEN_MAX */
+
+  /* EFAULT is not necessary to implement, but let's do it in the
+     simplest case. */
+  if (!pfd)
+    {
+      errno = EFAULT;
+      return -1;
+    }
+
+  /* convert timeout number into a timeval structure */
+  if (timeout == 0)
+    {
+      ptv = &tv;
+      ptv->tv_sec = 0;
+      ptv->tv_usec = 0;
+    }
+  else if (timeout > 0)
+    {
+      ptv = &tv;
+      ptv->tv_sec = timeout / 1000;
+      ptv->tv_usec = (timeout % 1000) * 1000;
+    }
+  else if (timeout == INFTIM)
+    /* wait forever */
+    ptv = NULL;
+  else
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  /* create fd sets and determine max fd */
+  maxfd = -1;
+  FD_ZERO (&rfds);
+  FD_ZERO (&wfds);
+  FD_ZERO (&efds);
+  for (i = 0; i < nfd; i++)
+    {
+      if (pfd[i].fd < 0)
+        continue;
+
+      if (pfd[i].events & (POLLIN | POLLRDNORM))
+        FD_SET (pfd[i].fd, &rfds);
+
+      /* see select(2): "the only exceptional condition detectable
+         is out-of-band data received on a socket", hence we push
+         POLLWRBAND events onto wfds instead of efds. */
+      if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
+        FD_SET (pfd[i].fd, &wfds);
+      if (pfd[i].events & (POLLPRI | POLLRDBAND))
+        FD_SET (pfd[i].fd, &efds);
+      if (pfd[i].fd >= maxfd
+          && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
+                               | POLLRDNORM | POLLRDBAND
+                               | POLLWRNORM | POLLWRBAND)))
+        {
+          maxfd = pfd[i].fd;
+          if (maxfd > FD_SETSIZE)
+            {
+              errno = EOVERFLOW;
+              return -1;
+            }
+        }
+    }
+
+  /* examine fd sets */
+  rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
+  if (rc < 0)
+    return rc;
+
+  /* establish results */
+  rc = 0;
+  for (i = 0; i < nfd; i++)
+    if (pfd[i].fd < 0)
+      pfd[i].revents = 0;
+    else
+      {
+        int happened = compute_revents (pfd[i].fd, pfd[i].events,
+                                        &rfds, &wfds, &efds);
+        if (happened)
+          {
+            pfd[i].revents = happened;
+            rc++;
+          }
+      }
+
+  return rc;
+#else
+  static struct timeval tv0;
+  static HANDLE hEvent;
+  WSANETWORKEVENTS ev;
+  HANDLE h, handle_array[FD_SETSIZE + 2];
+  DWORD ret, wait_timeout, nhandles;
+  fd_set rfds, wfds, xfds;
+  BOOL poll_again;
+  MSG msg;
+  int rc = 0;
+  nfds_t i;
+
+  if (nfd < 0 || timeout < -1)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  if (!hEvent)
+    hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+
+  handle_array[0] = hEvent;
+  nhandles = 1;
+  FD_ZERO (&rfds);
+  FD_ZERO (&wfds);
+  FD_ZERO (&xfds);
+
+  /* Classify socket handles and create fd sets. */
+  for (i = 0; i < nfd; i++)
+    {
+      int sought = pfd[i].events;
+      pfd[i].revents = 0;
+      if (pfd[i].fd < 0)
+        continue;
+      if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
+                      | POLLPRI | POLLRDBAND)))
+        continue;
+
+      h = (HANDLE) _get_osfhandle (pfd[i].fd);
+      assert (h != NULL);
+      if (IsSocketHandle (h))
+        {
+          int requested = FD_CLOSE;
+
+          /* see above; socket handles are mapped onto select.  */
+          if (sought & (POLLIN | POLLRDNORM))
+            {
+              requested |= FD_READ | FD_ACCEPT;
+              FD_SET ((SOCKET) h, &rfds);
+            }
+          if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
+            {
+              requested |= FD_WRITE | FD_CONNECT;
+              FD_SET ((SOCKET) h, &wfds);
+            }
+          if (sought & (POLLPRI | POLLRDBAND))
+            {
+              requested |= FD_OOB;
+              FD_SET ((SOCKET) h, &xfds);
+            }
+
+          if (requested)
+            WSAEventSelect ((SOCKET) h, hEvent, requested);
+        }
+      else
+        {
+          /* Poll now.  If we get an event, do not poll again.  Also,
+             screen buffer handles are waitable, and they'll block until
+             a character is available.  win32_compute_revents eliminates
+             bits for the "wrong" direction. */
+          pfd[i].revents = win32_compute_revents (h, &sought);
+          if (sought)
+            handle_array[nhandles++] = h;
+          if (pfd[i].revents)
+            timeout = 0;
+        }
+    }
+
+  if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
+    {
+      /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
+         no need to call select again.  */
+      poll_again = FALSE;
+      wait_timeout = 0;
+    }
+  else
+    {
+      poll_again = TRUE;
+      if (timeout == INFTIM)
+        wait_timeout = INFINITE;
+      else
+        wait_timeout = timeout;
+    }
+
+  for (;;)
+    {
+      ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
+                                       wait_timeout, QS_ALLINPUT);
+
+      if (ret == WAIT_OBJECT_0 + nhandles)
+        {
+          /* new input of some other kind */
+          BOOL bRet;
+          while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
+            {
+              TranslateMessage (&msg);
+              DispatchMessage (&msg);
+            }
+        }
+      else
+        break;
+    }
+
+  if (poll_again)
+    select (0, &rfds, &wfds, &xfds, &tv0);
+
+  /* Place a sentinel at the end of the array.  */
+  handle_array[nhandles] = NULL;
+  nhandles = 1;
+  for (i = 0; i < nfd; i++)
+    {
+      int happened;
+
+      if (pfd[i].fd < 0)
+        continue;
+      if (!(pfd[i].events & (POLLIN | POLLRDNORM |
+                             POLLOUT | POLLWRNORM | POLLWRBAND)))
+        continue;
+
+      h = (HANDLE) _get_osfhandle (pfd[i].fd);
+      if (h != handle_array[nhandles])
+        {
+          /* It's a socket.  */
+          WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
+          WSAEventSelect ((SOCKET) h, 0, 0);
+
+          /* If we're lucky, WSAEnumNetworkEvents already provided a way
+             to distinguish FD_READ and FD_ACCEPT; this saves a recv later.  */
+          if (FD_ISSET ((SOCKET) h, &rfds)
+              && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
+            ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
+          if (FD_ISSET ((SOCKET) h, &wfds))
+            ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
+          if (FD_ISSET ((SOCKET) h, &xfds))
+            ev.lNetworkEvents |= FD_OOB;
+
+          happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
+                                                   ev.lNetworkEvents);
+        }
+      else
+        {
+          /* Not a socket.  */
+          int sought = pfd[i].events;
+          happened = win32_compute_revents (h, &sought);
+          nhandles++;
+        }
+
+       if ((pfd[i].revents |= happened) != 0)
+        rc++;
+    }
+
+  return rc;
+#endif
+}
diff --git a/compat/win32/poll.h b/compat/win32/poll.h
new file mode 100644
index 0000000..b7aa59d
--- /dev/null
+++ b/compat/win32/poll.h
@@ -0,0 +1,53 @@
+/* Header for poll(2) emulation
+   Contributed by Paolo Bonzini.
+
+   Copyright 2001, 2002, 2003, 2007, 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of gnulib.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _GL_POLL_H
+#define _GL_POLL_H
+
+/* fake a poll(2) environment */
+#define POLLIN      0x0001      /* any readable data available   */
+#define POLLPRI     0x0002      /* OOB/Urgent readable data      */
+#define POLLOUT     0x0004      /* file descriptor is writeable  */
+#define POLLERR     0x0008      /* some poll error occurred      */
+#define POLLHUP     0x0010      /* file descriptor was "hung up" */
+#define POLLNVAL    0x0020      /* requested events "invalid"    */
+#define POLLRDNORM  0x0040
+#define POLLRDBAND  0x0080
+#define POLLWRNORM  0x0100
+#define POLLWRBAND  0x0200
+
+struct pollfd
+{
+  int fd;                       /* which file descriptor to poll */
+  short events;                 /* events we are interested in   */
+  short revents;                /* events found on return        */
+};
+
+typedef unsigned long nfds_t;
+
+extern int poll (struct pollfd *pfd, nfds_t nfd, int timeout);
+
+/* Define INFTIM only if doing so conforms to POSIX.  */
+#if !defined (_POSIX_C_SOURCE) && !defined (_XOPEN_SOURCE)
+#define INFTIM (-1)
+#endif
+
+#endif /* _GL_POLL_H */
-- 
1.7.3.1.51.ge462f.dirty

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 13/14] mingw: use poll-emulation from gnulib
  2010-10-10 13:20 [PATCH v3 00/14] daemon-win32 Erik Faye-Lund
                   ` (11 preceding siblings ...)
  2010-10-10 13:20 ` [PATCH v3 12/14] mingw: import poll-emulation from gnulib Erik Faye-Lund
@ 2010-10-10 13:20 ` Erik Faye-Lund
  2010-10-10 13:20 ` [PATCH v3 14/14] daemon: only use posix features on posix systems Erik Faye-Lund
  13 siblings, 0 replies; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 13:20 UTC (permalink / raw)
  To: git; +Cc: msysgit, j6t

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 Makefile            |    2 +-
 compat/mingw.c      |   65 ---------------------------------------------------
 compat/mingw.h      |   11 --------
 compat/win32/poll.c |    3 +-
 git-compat-util.h   |    1 +
 5 files changed, 3 insertions(+), 79 deletions(-)

diff --git a/Makefile b/Makefile
index ebb51e3..42baa4d 100644
--- a/Makefile
+++ b/Makefile
@@ -1131,7 +1131,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
 	COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch -Icompat/win32
 	COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
 	COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o \
-		compat/win32/pthread.o
+		compat/win32/pthread.o compat/win32/poll.o
 	EXTLIBS += -lws2_32
 	PTHREAD_LIBS =
 	X = .exe
diff --git a/compat/mingw.c b/compat/mingw.c
index 32ca664..bbe45d0 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -408,71 +408,6 @@ int pipe(int filedes[2])
 	return 0;
 }
 
-int poll(struct pollfd *ufds, unsigned int nfds, int timeout)
-{
-	int i, pending;
-
-	if (timeout >= 0) {
-		if (nfds == 0) {
-			Sleep(timeout);
-			return 0;
-		}
-		return errno = EINVAL, error("poll timeout not supported");
-	}
-
-	/* When there is only one fd to wait for, then we pretend that
-	 * input is available and let the actual wait happen when the
-	 * caller invokes read().
-	 */
-	if (nfds == 1) {
-		if (!(ufds[0].events & POLLIN))
-			return errno = EINVAL, error("POLLIN not set");
-		ufds[0].revents = POLLIN;
-		return 0;
-	}
-
-repeat:
-	pending = 0;
-	for (i = 0; i < nfds; i++) {
-		DWORD avail = 0;
-		HANDLE h = (HANDLE) _get_osfhandle(ufds[i].fd);
-		if (h == INVALID_HANDLE_VALUE)
-			return -1;	/* errno was set */
-
-		if (!(ufds[i].events & POLLIN))
-			return errno = EINVAL, error("POLLIN not set");
-
-		/* this emulation works only for pipes */
-		if (!PeekNamedPipe(h, NULL, 0, NULL, &avail, NULL)) {
-			int err = GetLastError();
-			if (err == ERROR_BROKEN_PIPE) {
-				ufds[i].revents = POLLHUP;
-				pending++;
-			} else {
-				errno = EINVAL;
-				return error("PeekNamedPipe failed,"
-					" GetLastError: %u", err);
-			}
-		} else if (avail) {
-			ufds[i].revents = POLLIN;
-			pending++;
-		} else
-			ufds[i].revents = 0;
-	}
-	if (!pending) {
-		/* The only times that we spin here is when the process
-		 * that is connected through the pipes is waiting for
-		 * its own input data to become available. But since
-		 * the process (pack-objects) is itself CPU intensive,
-		 * it will happily pick up the time slice that we are
-		 * relinquishing here.
-		 */
-		Sleep(0);
-		goto repeat;
-	}
-	return 0;
-}
-
 struct tm *gmtime_r(const time_t *timep, struct tm *result)
 {
 	/* gmtime() in MSVCRT.DLL is thread-safe, but not reentrant */
diff --git a/compat/mingw.h b/compat/mingw.h
index 2218043..aed49d8 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -72,16 +72,6 @@ struct passwd {
 
 extern char *getpass(const char *prompt);
 
-#ifndef POLLIN
-struct pollfd {
-	int fd;           /* file descriptor */
-	short events;     /* requested events */
-	short revents;    /* returned events */
-};
-#define POLLIN 1
-#define POLLHUP 2
-#endif
-
 typedef void (__cdecl *sig_handler_t)(int);
 struct sigaction {
 	sig_handler_t sa_handler;
@@ -188,7 +178,6 @@ int pipe(int filedes[2]);
 unsigned int sleep (unsigned int seconds);
 int mkstemp(char *template);
 int gettimeofday(struct timeval *tv, void *tz);
-int poll(struct pollfd *ufds, unsigned int nfds, int timeout);
 struct tm *gmtime_r(const time_t *timep, struct tm *result);
 struct tm *localtime_r(const time_t *timep, struct tm *result);
 int getpagesize(void);	/* defined in MinGW's libgcc.a */
diff --git a/compat/win32/poll.c b/compat/win32/poll.c
index 7c52cb6..c1ca0d2 100644
--- a/compat/win32/poll.c
+++ b/compat/win32/poll.c
@@ -24,8 +24,7 @@
 # pragma GCC diagnostic ignored "-Wtype-limits"
 #endif
 
-#include <config.h>
-#include <alloca.h>
+#include <malloc.h>
 
 #include <sys/types.h>
 #include "poll.h"
diff --git a/git-compat-util.h b/git-compat-util.h
index 100197f..f16a092 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -82,6 +82,7 @@
 #define WIN32_LEAN_AND_MEAN  /* stops windows.h including winsock.h */
 #include <winsock2.h>
 #include <windows.h>
+#include "compat/win32/poll.h"
 #endif
 
 #include <unistd.h>
-- 
1.7.3.1.51.ge462f.dirty

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 14/14] daemon: only use posix features on posix systems
  2010-10-10 13:20 [PATCH v3 00/14] daemon-win32 Erik Faye-Lund
                   ` (12 preceding siblings ...)
  2010-10-10 13:20 ` [PATCH v3 13/14] mingw: use " Erik Faye-Lund
@ 2010-10-10 13:20 ` Erik Faye-Lund
  2010-10-10 19:40   ` Ævar Arnfjörð Bjarmason
  13 siblings, 1 reply; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 13:20 UTC (permalink / raw)
  To: git; +Cc: msysgit, j6t

Windows does not supply the POSIX-functions fork(), setuuid(), setgid(),
setsid() and initgroups(). Disable support for --user, --group and
--detach on platforms lacking _POSIX_VERSION.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---

This might be a bit controversial; does anyone know of any systems that
implements fork(), setuuid(), setgid() and setsid() but does not define
_POSIX_VERSION? Perhaps we should have a separate makefile-switch instead?

 Makefile |    8 +++-----
 daemon.c |   43 +++++++++++++++++++++++++++++++------------
 2 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/Makefile b/Makefile
index 42baa4d..f5992da 100644
--- a/Makefile
+++ b/Makefile
@@ -401,6 +401,7 @@ EXTRA_PROGRAMS =
 # ... and all the rest that could be moved out of bindir to gitexecdir
 PROGRAMS += $(EXTRA_PROGRAMS)
 
+PROGRAM_OBJS += daemon.o
 PROGRAM_OBJS += fast-import.o
 PROGRAM_OBJS += imap-send.o
 PROGRAM_OBJS += shell.o
@@ -1064,7 +1065,6 @@ ifeq ($(uname_S),Windows)
 	NO_SVN_TESTS = YesPlease
 	NO_PERL_MAKEMAKER = YesPlease
 	RUNTIME_PREFIX = YesPlease
-	NO_POSIX_ONLY_PROGRAMS = YesPlease
 	NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
 	NO_NSEC = YesPlease
 	USE_WIN32_MMAP = YesPlease
@@ -1117,7 +1117,6 @@ ifneq (,$(findstring MINGW,$(uname_S)))
 	NO_SVN_TESTS = YesPlease
 	NO_PERL_MAKEMAKER = YesPlease
 	RUNTIME_PREFIX = YesPlease
-	NO_POSIX_ONLY_PROGRAMS = YesPlease
 	NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
 	NO_NSEC = YesPlease
 	USE_WIN32_MMAP = YesPlease
@@ -1128,6 +1127,8 @@ ifneq (,$(findstring MINGW,$(uname_S)))
 	NO_PYTHON = YesPlease
 	BLK_SHA1 = YesPlease
 	ETAGS_TARGET = ETAGS
+	NO_INET_PTON = YesPlease
+	NO_INET_NTOP = YesPlease
 	COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch -Icompat/win32
 	COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
 	COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o \
@@ -1246,9 +1247,6 @@ ifdef ZLIB_PATH
 endif
 EXTLIBS += -lz
 
-ifndef NO_POSIX_ONLY_PROGRAMS
-	PROGRAM_OBJS += daemon.o
-endif
 ifndef NO_OPENSSL
 	OPENSSL_LIBSSL = -lssl
 	ifdef OPENSSLDIR
diff --git a/daemon.c b/daemon.c
index 54bbec2..56a9bed 100644
--- a/daemon.c
+++ b/daemon.c
@@ -23,10 +23,12 @@ static const char daemon_usage[] =
 "           [--strict-paths] [--base-path=path] [--base-path-relaxed]\n"
 "           [--user-path | --user-path=path]\n"
 "           [--interpolated-path=path]\n"
-"           [--reuseaddr] [--detach] [--pid-file=file]\n"
+"           [--reuseaddr] [--pid-file=file]\n"
 "           [--[enable|disable|allow-override|forbid-override]=service]\n"
 "           [--inetd | [--listen=host_or_ipaddr] [--port=n]\n"
-"                      [--user=user [--group=group]]\n"
+#ifdef _POSIX_VERSION
+"           [--detach] [--user=user [--group=group]]\n"
+#endif
 "           [directory...]";
 
 /* List of acceptable pathname prefixes */
@@ -593,7 +595,7 @@ static struct child {
 	struct sockaddr_storage address;
 } *firstborn;
 
-static void add_child(struct child_process *cld, struct sockaddr *addr, int addrlen)
+static void add_child(struct child_process *cld, struct sockaddr *addr, socklen_t addrlen)
 {
 	struct child *newborn, **cradle;
 
@@ -672,7 +674,7 @@ static char *get_addrstr(int *port, struct sockaddr *addr)
 }
 
 char **cld_argv;
-static void handle(int incoming, struct sockaddr *addr, int addrlen)
+static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)
 {
 	struct child_process cld = { 0 };
 	char *addrstr, envbuf[300] = "REMOTE_ADDR=";
@@ -908,7 +910,7 @@ static int service_loop(struct socketlist *socklist)
 		for (i = 0; i < socklist->nr; i++) {
 			if (pfd[i].revents & POLLIN) {
 				struct sockaddr_storage ss;
-				unsigned int sslen = sizeof(ss);
+				socklen_t sslen = sizeof(ss);
 				int incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen);
 				if (incoming < 0) {
 					switch (errno) {
@@ -938,6 +940,7 @@ static void sanitize_stdfds(void)
 		close(fd);
 }
 
+#ifdef _POSIX_VERSION
 static void daemonize(void)
 {
 	switch (fork()) {
@@ -955,6 +958,7 @@ static void daemonize(void)
 	close(2);
 	sanitize_stdfds();
 }
+#endif
 
 static void store_pid(const char *path)
 {
@@ -965,7 +969,12 @@ static void store_pid(const char *path)
 		die_errno("failed to write pid file '%s'", path);
 }
 
-static int serve(struct string_list *listen_addr, int listen_port, struct passwd *pass, gid_t gid)
+#ifdef _POSIX_VERSION
+static struct passwd *pass;
+static gid_t gid;
+#endif
+
+static int serve(struct string_list *listen_addr, int listen_port)
 {
 	struct socketlist socklist = { NULL, 0, 0 };
 
@@ -974,10 +983,12 @@ static int serve(struct string_list *listen_addr, int listen_port, struct passwd
 		die("unable to allocate any listen sockets on port %u",
 		    listen_port);
 
+#ifdef _POSIX_VERSION
 	if (pass && gid &&
 	    (initgroups(pass->pw_name, gid) || setgid (gid) ||
 	     setuid(pass->pw_uid)))
 		die("cannot drop privileges");
+#endif
 
 	return service_loop(&socklist);
 }
@@ -987,11 +998,11 @@ int main(int argc, char **argv)
 	int listen_port = 0;
 	struct string_list listen_addr = STRING_LIST_INIT_NODUP;
 	int serve_mode = 0, inetd_mode = 0;
-	const char *pid_file = NULL, *user_name = NULL, *group_name = NULL;
+	const char *pid_file = NULL;
+#ifdef _POSIX_VERSION
 	int detach = 0;
-	struct passwd *pass = NULL;
-	struct group *group;
-	gid_t gid = 0;
+	const char *user_name = NULL, *group_name = NULL;
+#endif
 	int i;
 
 	git_extract_argv0_path(argv[0]);
@@ -1080,6 +1091,7 @@ int main(int argc, char **argv)
 			pid_file = arg + 11;
 			continue;
 		}
+#ifdef _POSIX_VERSION
 		if (!strcmp(arg, "--detach")) {
 			detach = 1;
 			log_syslog = 1;
@@ -1093,6 +1105,7 @@ int main(int argc, char **argv)
 			group_name = arg + 8;
 			continue;
 		}
+#endif
 		if (!prefixcmp(arg, "--enable=")) {
 			enable_service(arg + 9, 1);
 			continue;
@@ -1127,14 +1140,17 @@ int main(int argc, char **argv)
 		/* avoid splitting a message in the middle */
 		setvbuf(stderr, NULL, _IOFBF, 4096);
 
+#ifdef _POSIX_VERSION
 	if (inetd_mode && (group_name || user_name))
 		die("--user and --group are incompatible with --inetd");
+#endif
 
 	if (inetd_mode && (listen_port || (listen_addr.nr > 0)))
 		die("--listen= and --port= are incompatible with --inetd");
 	else if (listen_port == 0)
 		listen_port = DEFAULT_GIT_PORT;
 
+#ifdef _POSIX_VERSION
 	if (group_name && !user_name)
 		die("--group supplied without --user");
 
@@ -1146,13 +1162,14 @@ int main(int argc, char **argv)
 		if (!group_name)
 			gid = pass->pw_gid;
 		else {
-			group = getgrnam(group_name);
+			struct group *group = getgrnam(group_name);
 			if (!group)
 				die("group not found - %s", group_name);
 
 			gid = group->gr_gid;
 		}
 	}
+#endif
 
 	if (strict_paths && (!ok_paths || !*ok_paths))
 		die("option --strict-paths requires a whitelist");
@@ -1180,11 +1197,13 @@ int main(int argc, char **argv)
 		return execute(peer);
 	}
 
+#ifdef _POSIX_VERSION
 	if (detach) {
 		daemonize();
 		loginfo("Ready to rumble");
 	}
 	else
+#endif
 		sanitize_stdfds();
 
 	if (pid_file)
@@ -1197,5 +1216,5 @@ int main(int argc, char **argv)
 	cld_argv[argc] = "--serve";
 	cld_argv[argc+1] = NULL;
 
-	return serve(&listen_addr, listen_port, pass, gid);
+	return serve(&listen_addr, listen_port);
 }
-- 
1.7.3.1.51.ge462f.dirty

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 12/14] mingw: import poll-emulation from gnulib
  2010-10-10 13:20 ` [PATCH v3 12/14] mingw: import poll-emulation from gnulib Erik Faye-Lund
@ 2010-10-10 14:15   ` Ævar Arnfjörð Bjarmason
  2010-10-10 14:28     ` Erik Faye-Lund
  0 siblings, 1 reply; 43+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2010-10-10 14:15 UTC (permalink / raw)
  To: Erik Faye-Lund; +Cc: git, msysgit, j6t

On Sun, Oct 10, 2010 at 13:20, Erik Faye-Lund <kusmabite@gmail.com> wrote:
> lib/poll.c and lib/poll.in.h imported from 0a05120 in
> git://git.savannah.gnu.org/gnulib.git

Having fought with importing things from gnulib myself using their
tools it would be useful to note in the commit message *how* you
imported this. Did you use the gnulib command with some archane
options so it wouldn't touch the build system while it was at it, or
did you just copy the relevant files manually?

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 12/14] mingw: import poll-emulation from gnulib
  2010-10-10 14:15   ` Ævar Arnfjörð Bjarmason
@ 2010-10-10 14:28     ` Erik Faye-Lund
  2010-10-10 19:34       ` Erik Faye-Lund
  0 siblings, 1 reply; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 14:28 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason; +Cc: git, msysgit, j6t

On Sun, Oct 10, 2010 at 4:15 PM, Ævar Arnfjörð Bjarmason
<avarab@gmail.com> wrote:
> On Sun, Oct 10, 2010 at 13:20, Erik Faye-Lund <kusmabite@gmail.com> wrote:
>> lib/poll.c and lib/poll.in.h imported from 0a05120 in
>> git://git.savannah.gnu.org/gnulib.git
>
> Having fought with importing things from gnulib myself using their
> tools it would be useful to note in the commit message *how* you
> imported this. Did you use the gnulib command with some archane
> options so it wouldn't touch the build system while it was at it, or
> did you just copy the relevant files manually?
>

Sorry if that was unclear - I just copied the files (verbatim).
Patching to make it compile for us comes in the next patch.

I didn't even know that there was a gnulib tool to extract code, but a
quick google-search shows that there is. I'll look into using the tool
instead for the next round.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 11/14] daemon: report connection from root-process
  2010-10-10 13:20 ` [PATCH v3 11/14] daemon: report connection from root-process Erik Faye-Lund
@ 2010-10-10 18:58   ` Johannes Sixt
  2010-10-10 19:31     ` Erik Faye-Lund
  0 siblings, 1 reply; 43+ messages in thread
From: Johannes Sixt @ 2010-10-10 18:58 UTC (permalink / raw)
  To: Erik Faye-Lund; +Cc: git, msysgit

On Sonntag, 10. Oktober 2010, Erik Faye-Lund wrote:
> Report incoming connections from the process that
> accept() the connection instead of the handling
> process.
>
> This enables "Connection from"-reporting on
> Windows, where getpeername(0, ...) consistently
> fails.

Is this from the process that you invoke with --serve? then this failure could 
be due to Winsockets not being initilized. Did you check that?

-- Hannes

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 11/14] daemon: report connection from root-process
  2010-10-10 18:58   ` Johannes Sixt
@ 2010-10-10 19:31     ` Erik Faye-Lund
  2010-10-10 19:42       ` Erik Faye-Lund
  0 siblings, 1 reply; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 19:31 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: git, msysgit

On Sun, Oct 10, 2010 at 8:58 PM, Johannes Sixt <j6t@kdbg.org> wrote:
> On Sonntag, 10. Oktober 2010, Erik Faye-Lund wrote:
>> Report incoming connections from the process that
>> accept() the connection instead of the handling
>> process.
>>
>> This enables "Connection from"-reporting on
>> Windows, where getpeername(0, ...) consistently
>> fails.
>
> Is this from the process that you invoke with --serve? then this failure could
> be due to Winsockets not being initilized. Did you check that?
>

I've tried that, and unfortunately it lack of socket initialization
does not seem to be the reason :(

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 12/14] mingw: import poll-emulation from gnulib
  2010-10-10 14:28     ` Erik Faye-Lund
@ 2010-10-10 19:34       ` Erik Faye-Lund
  2010-10-10 19:51         ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 19:34 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason; +Cc: git, msysgit, j6t

On Sun, Oct 10, 2010 at 4:28 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:
> On Sun, Oct 10, 2010 at 4:15 PM, Ævar Arnfjörð Bjarmason
> <avarab@gmail.com> wrote:
>> On Sun, Oct 10, 2010 at 13:20, Erik Faye-Lund <kusmabite@gmail.com> wrote:
>>> lib/poll.c and lib/poll.in.h imported from 0a05120 in
>>> git://git.savannah.gnu.org/gnulib.git
>>
>> Having fought with importing things from gnulib myself using their
>> tools it would be useful to note in the commit message *how* you
>> imported this. Did you use the gnulib command with some archane
>> options so it wouldn't touch the build system while it was at it, or
>> did you just copy the relevant files manually?
>>
>
> Sorry if that was unclear - I just copied the files (verbatim).
> Patching to make it compile for us comes in the next patch.
>
> I didn't even know that there was a gnulib tool to extract code, but a
> quick google-search shows that there is. I'll look into using the tool
> instead for the next round.
>

I've had a quick look at it, and it really doesn't seem like
gnulib-tool is suited for us here. It seems to be intended on pure
autoconf-projects, and starts including all kinds of things that we
don't need. We only care about poll-emulation on Windows, and we don't
need autoconf to tell us if it should be used or not.

So I'm not in favor of using gnulib-tool, and going with the current
method of verbatim copy with a separate fix-up commit. But perhaps I
should clarify the commit message so other people can easily upgrade
the emulation later...

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 14/14] daemon: only use posix features on posix systems
  2010-10-10 13:20 ` [PATCH v3 14/14] daemon: only use posix features on posix systems Erik Faye-Lund
@ 2010-10-10 19:40   ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 43+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2010-10-10 19:40 UTC (permalink / raw)
  To: Erik Faye-Lund; +Cc: git, msysgit, j6t

On Sun, Oct 10, 2010 at 13:20, Erik Faye-Lund <kusmabite@gmail.com> wrote:
> Windows does not supply the POSIX-functions fork(), setuuid(), setgid(),
> setsid() and initgroups(). Disable support for --user, --group and
> --detach on platforms lacking _POSIX_VERSION.

FWIW I checked if Perl's fork() emulation with threads on Windows
could emulate this, but no:

    perl -E '
    if (my $pid = fork()) {
      say "$$: child running as $pid"
    } else {
      sleep 1;
      say "$$: running in the background"
    }'

On Unix that would detach the process from the terminal, but on
Windows with threads the original process only returns after the child
has finished.

I didn't expect it to act differently, but I thought I'd note it here
in case anyone had it in mind to implement --detach on Windows.

> This might be a bit controversial; does anyone know of any systems that
> implements fork(), setuuid(), setgid() and setsid() but does not define
> _POSIX_VERSION? Perhaps we should have a separate makefile-switch instead?

Even if it's defined it's more self-documenting to have our own
HAVE_POSIX_GOODIES (or something like that) instead.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 01/14] mingw: add network-wrappers for daemon
  2010-10-10 13:20 ` [PATCH v3 01/14] mingw: add network-wrappers for daemon Erik Faye-Lund
@ 2010-10-10 19:40   ` Eric Sunshine
  2010-10-10 20:20     ` Erik Faye-Lund
  0 siblings, 1 reply; 43+ messages in thread
From: Eric Sunshine @ 2010-10-10 19:40 UTC (permalink / raw)
  To: Erik Faye-Lund; +Cc: git, msysgit, j6t, Mike Pape

On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:
> From: Mike Pape<dotzenlabs@gmail.com>
>
> git-daemon requires some socket-functionality that is not yet
> supported in the Windows-port. This patch adds said functionality,
> and makes sure WSAStartup gets called by socket(), since it is the
> first network-call in git-daemon. In addition, a check is added to
> prevent WSAStartup (and WSACleanup, though atexit) from being
> called more than once, since git-daemon calls both socket() and
> gethostbyname().
>
> Signed-off-by: Mike Pape<dotzenlabs@gmail.com>
> Signed-off-by: Erik Faye-Lund<kusmabite@gmail.com>
> ---
> diff --git a/compat/mingw.c b/compat/mingw.c
> index 6590f33..563ef1f 100644
> --- a/compat/mingw.c
> +++ b/compat/mingw.c
> +#undef accept
> +int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
> +{
> +	int sockfd2;
> +
> +	SOCKET s1 = (SOCKET)_get_osfhandle(sockfd1);
> +	SOCKET s2 = accept(s1, sa, sz);
> +
> +	/* convert into a file descriptor */
> +	if ((sockfd2 = _open_osfhandle(s2, O_RDWR|O_BINARY))<  0) {
> +		closesocket(s2);
> +		return error("unable to make a socket file descriptor: %s",
> +			strerror(errno));

Is 'errno' from _open_osfhandle() still valid when handed to strerror() 
or has it been clobbered by closesocket()?

Corollary: Does _open_osfhandle() indeed set 'errno', or is it more 
appropriate to call WSAGetLastError()? (The documentation I read for 
_open_osfhandle() did not say anything about how to determine the reason 
for failure.)

-- ES

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 11/14] daemon: report connection from root-process
  2010-10-10 19:31     ` Erik Faye-Lund
@ 2010-10-10 19:42       ` Erik Faye-Lund
  2010-10-10 20:14         ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 19:42 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: git, msysgit

On Sun, Oct 10, 2010 at 9:31 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:
> On Sun, Oct 10, 2010 at 8:58 PM, Johannes Sixt <j6t@kdbg.org> wrote:
>> On Sonntag, 10. Oktober 2010, Erik Faye-Lund wrote:
>>> Report incoming connections from the process that
>>> accept() the connection instead of the handling
>>> process.
>>>
>>> This enables "Connection from"-reporting on
>>> Windows, where getpeername(0, ...) consistently
>>> fails.
>>
>> Is this from the process that you invoke with --serve? then this failure could
>> be due to Winsockets not being initilized. Did you check that?
>>
>
> I've tried that, and unfortunately it lack of socket initialization
> does not seem to be the reason :(
>

But looking at it a bit more, I can do the following code-reduction on
top, changing this to a +10 lines to a -2 lines patch ;)

diff --git a/daemon.c b/daemon.c
index 56a9bed..e9a4839 100644
--- a/daemon.c
+++ b/daemon.c
@@ -518,7 +518,7 @@ static void parse_host_arg(char *extra_args, int buflen)
 }


-static int execute(struct sockaddr *addr)
+static int execute()
 {
 	static char line[1000];
 	int pktlen, len, i;
@@ -1179,22 +1179,10 @@ int main(int argc, char **argv)
 		    base_path);

 	if (serve_mode) {
-		struct sockaddr_storage ss;
-		struct sockaddr *peer = (struct sockaddr *)&ss;
-		socklen_t slen = sizeof(ss);
-
 		if (inetd_mode && !freopen("/dev/null", "w", stderr))
 			die_errno("failed to redirect stderr to /dev/null");

-		if (!getpeername(0, peer, &slen)) {
-			int port = -1;
-			char *addrstr = get_addrstr(&port, peer);
-			setenv("REMOTE_ADDR", addrstr, 1);
-			loginfo("[%"PRIuMAX"] Connection from %s:%d",
-			    (uintmax_t)getpid(), addrstr, port);
-		}
-
-		return execute(peer);
+		return execute();
 	}

 #ifdef _POSIX_VERSION

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [msysGit] [PATCH v3 02/14] mingw: implement syslog
  2010-10-10 13:20 ` [PATCH v3 02/14] mingw: implement syslog Erik Faye-Lund
@ 2010-10-10 19:50   ` Eric Sunshine
  2010-10-10 20:37     ` Erik Faye-Lund
  0 siblings, 1 reply; 43+ messages in thread
From: Eric Sunshine @ 2010-10-10 19:50 UTC (permalink / raw)
  To: Erik Faye-Lund; +Cc: git, msysgit, j6t, Mike Pape

On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:
> From: Mike Pape<dotzenlabs@gmail.com>
>
> Syslog does not usually exist on Windows, so we implement our own
> using Window's ReportEvent mechanism.
>
> Signed-off-by: Mike Pape<dotzenlabs@gmail.com>
> Signed-off-by: Erik Faye-Lund<kusmabite@gmail.com>
> ---
> +void syslog(int priority, const char *fmt, const char *arg)
> +{
> +	WORD logtype;
> +
> +	if (!ms_eventlog)
> +		return;
> +
> +	if (strcmp(fmt, "%s")) {
> +		warning("format string of syslog() not implemented");
> +		return;
> +	}

It is not exactly clear what the intention is here. Is this trying to 
say that no formatting directives are allowed in 'fmt' or what? The 
simple case it is actually checking (where 'fmt' is solely '%s') could 
easily be handled manually, as could more complex formats.

> +	/*
> +	 * ReportEvent() doesn't handle strings containing %n, where n is
> +	 * an integer. Such events must be reformatted by the caller.
> +	 */
> +	ReportEventA(ms_eventlog,
> +	    logtype,
> +	    0,
> +	    0,
> +	    NULL,
> +	    1,
> +	    0,
> +	    (const char **)&arg,
> +	    NULL);

The comment about '%n' seems to be warning about a potential problem but 
does not actually protect against it. Should this issue be handled?

-- ES

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 12/14] mingw: import poll-emulation from gnulib
  2010-10-10 19:34       ` Erik Faye-Lund
@ 2010-10-10 19:51         ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 43+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2010-10-10 19:51 UTC (permalink / raw)
  To: kusmabite; +Cc: git, msysgit, j6t

On Sun, Oct 10, 2010 at 19:34, Erik Faye-Lund <kusmabite@gmail.com> wrote:
> On Sun, Oct 10, 2010 at 4:28 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:
>> On Sun, Oct 10, 2010 at 4:15 PM, Ævar Arnfjörð Bjarmason
>> <avarab@gmail.com> wrote:
>>> On Sun, Oct 10, 2010 at 13:20, Erik Faye-Lund <kusmabite@gmail.com> wrote:
>>>> lib/poll.c and lib/poll.in.h imported from 0a05120 in
>>>> git://git.savannah.gnu.org/gnulib.git
>>>
>>> Having fought with importing things from gnulib myself using their
>>> tools it would be useful to note in the commit message *how* you
>>> imported this. Did you use the gnulib command with some archane
>>> options so it wouldn't touch the build system while it was at it, or
>>> did you just copy the relevant files manually?
>>>
>>
>> Sorry if that was unclear - I just copied the files (verbatim).
>> Patching to make it compile for us comes in the next patch.
>>
>> I didn't even know that there was a gnulib tool to extract code, but a
>> quick google-search shows that there is. I'll look into using the tool
>> instead for the next round.
>>
>
> I've had a quick look at it, and it really doesn't seem like
> gnulib-tool is suited for us here. It seems to be intended on pure
> autoconf-projects, and starts including all kinds of things that we
> don't need. We only care about poll-emulation on Windows, and we don't
> need autoconf to tell us if it should be used or not.

The only reason I asked was that I tried to use gnulib-tool at one
point and reached the same conclusion. But in my case I wanted it to
resolve dependencies (i.e. bring in multiple projects), so not using
it was its own pain.

I just thought I'd ask in case you'd spent more time on getting it to
work.

> So I'm not in favor of using gnulib-tool, and going with the current
> method of verbatim copy with a separate fix-up commit. But perhaps I
> should clarify the commit message so other people can easily upgrade
> the emulation later...

By all means don't use gnulib, but noting how to upgrade things when
we add anything external in compat/ is a good idea.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 05/14] mingw: use real pid
  2010-10-10 13:20 ` [PATCH v3 05/14] mingw: use real pid Erik Faye-Lund
@ 2010-10-10 19:53   ` Eric Sunshine
  2010-10-10 20:52     ` Erik Faye-Lund
  0 siblings, 1 reply; 43+ messages in thread
From: Eric Sunshine @ 2010-10-10 19:53 UTC (permalink / raw)
  To: Erik Faye-Lund; +Cc: git, msysgit, j6t

On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:
> The Windows port so far used process handles as PID. However,
> this does not work consistently with getpid.

Perhaps this could be elaborated a bit to explain the interaction with 
getpid() and how it is causing problems for daemon mode. For the casual 
reader, it is not immediately obvious what is failing or why this patch 
is needed.

-- ES

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [msysGit] [PATCH v3 08/14] daemon: use run-command api for async serving
  2010-10-10 13:20 ` [PATCH v3 08/14] daemon: use run-command api for async serving Erik Faye-Lund
@ 2010-10-10 19:56   ` Eric Sunshine
  2010-10-10 20:42     ` Erik Faye-Lund
  0 siblings, 1 reply; 43+ messages in thread
From: Eric Sunshine @ 2010-10-10 19:56 UTC (permalink / raw)
  To: Erik Faye-Lund; +Cc: git, msysgit, j6t

On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:
> fork() is only available on POSIX, so to support git-daemon
> on Windows we have to use something else.
>
> Instead we invent the flag --serve, which is a stripped down
> version of --inetd-mode. We use start_command() to call
> git-daemon with this flag appended to serve clients.
>
> Signed-off-by: Erik Faye-Lund<kusmabite@gmail.com>
> ---
> @@ -654,14 +641,14 @@ static void remove_child(pid_t pid)
>    */
>   static void kill_some_child(void)
>   {
> -	const struct child *blanket, *next;
> +	struct child *blanket, *next;

It is not immediately obvious why 'const' was dropped.

> @@ -671,18 +658,26 @@ static void check_dead_children(void)
>   	int status;
>   	pid_t pid;
>
> -	while ((pid = waitpid(-1,&status, WNOHANG))>  0) {
> -		const char *dead = "";
> -		remove_child(pid);
> -		if (!WIFEXITED(status) || (WEXITSTATUS(status)>  0))
> -			dead = " (with error)";
> -		loginfo("[%"PRIuMAX"] Disconnected%s", (uintmax_t)pid, dead);
> -	}
> +	struct child **cradle, *blanket;
> +	for (cradle =&firstborn; (blanket = *cradle);)
> +		if ((pid = waitpid(blanket->cld.pid,&status, WNOHANG))>  1) {
> +			const char *dead = "";
> +			if (status)
> +				dead = " (with error)";
> +			loginfo("[%"PRIuMAX"] Disconnected%s", (uintmax_t)pid, dead);
> +
> +			/* remove the child */
> +			*cradle = blanket->next;
> +			live_children--;
> +			free(blanket);
> +		} else
> +			cradle =&blanket->next;
>   }
>
> +char **cld_argv;
>   static void handle(int incoming, struct sockaddr *addr, int addrlen)
>   {

Should 'cld_argv' be declared static?

-- ES

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 11/14] daemon: report connection from root-process
  2010-10-10 19:42       ` Erik Faye-Lund
@ 2010-10-10 20:14         ` Ævar Arnfjörð Bjarmason
  2010-10-10 20:48           ` Erik Faye-Lund
  0 siblings, 1 reply; 43+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2010-10-10 20:14 UTC (permalink / raw)
  To: kusmabite; +Cc: Johannes Sixt, git, msysgit

On Sun, Oct 10, 2010 at 19:42, Erik Faye-Lund <kusmabite@gmail.com> wrote:

> -static int execute(struct sockaddr *addr)
> +static int execute()

Isn't execute(void) more portable?

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 01/14] mingw: add network-wrappers for daemon
  2010-10-10 19:40   ` Eric Sunshine
@ 2010-10-10 20:20     ` Erik Faye-Lund
  2010-10-10 21:19       ` Eric Sunshine
  0 siblings, 1 reply; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 20:20 UTC (permalink / raw)
  To: Eric Sunshine; +Cc: git, msysgit, j6t, Mike Pape

On Sun, Oct 10, 2010 at 9:40 PM, Eric Sunshine <ericsunshine@gmail.com> wrote:
> On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:
>>
>> From: Mike Pape<dotzenlabs@gmail.com>
>>
>> git-daemon requires some socket-functionality that is not yet
>> supported in the Windows-port. This patch adds said functionality,
>> and makes sure WSAStartup gets called by socket(), since it is the
>> first network-call in git-daemon. In addition, a check is added to
>> prevent WSAStartup (and WSACleanup, though atexit) from being
>> called more than once, since git-daemon calls both socket() and
>> gethostbyname().
>>
>> Signed-off-by: Mike Pape<dotzenlabs@gmail.com>
>> Signed-off-by: Erik Faye-Lund<kusmabite@gmail.com>
>> ---
>> diff --git a/compat/mingw.c b/compat/mingw.c
>> index 6590f33..563ef1f 100644
>> --- a/compat/mingw.c
>> +++ b/compat/mingw.c
>> +#undef accept
>> +int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
>> +{
>> +       int sockfd2;
>> +
>> +       SOCKET s1 = (SOCKET)_get_osfhandle(sockfd1);
>> +       SOCKET s2 = accept(s1, sa, sz);
>> +
>> +       /* convert into a file descriptor */
>> +       if ((sockfd2 = _open_osfhandle(s2, O_RDWR|O_BINARY))<  0) {
>> +               closesocket(s2);
>> +               return error("unable to make a socket file descriptor:
>> %s",
>> +                       strerror(errno));
>
> Is 'errno' from _open_osfhandle() still valid when handed to strerror() or
> has it been clobbered by closesocket()?
>
> Corollary: Does _open_osfhandle() indeed set 'errno', or is it more
> appropriate to call WSAGetLastError()? (The documentation I read for
> _open_osfhandle() did not say anything about how to determine the reason for
> failure.)
>

_open_osfhandle seems to set both errno and the winsock-error.
closesocket() sets the winsock-error but not the CRT. I've just tested
with a very simple application:

---8<---
#include <winsock2.h>
#include <io.h>
#include <fcntl.h>
#include <stdio.h>

const char *win32_strerror(DWORD dw)
{
	static char tmp[4096];
	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw,
	    MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
	    tmp, sizeof(tmp), NULL);
	return tmp;
}

int main()
{
	WSADATA wsa = {0};

	WSAStartup(MAKEWORD(2, 0), &wsa);
	printf("errno: '%s'\nWSAGetLastError: '%s'\n",
	    strerror(errno), win32_strerror(WSAGetLastError()));
	errno = 0;

	_open_osfhandle(-1, O_RDWR | O_BINARY);
	printf("errno: '%s'\nWSAGetLastError: '%s'\n",
	    strerror(errno), win32_strerror(WSAGetLastError()));
	errno = 0;

	closesocket(-1);
	printf("errno: '%s'\nWSAGetLastError: '%s'\n",
	    strerror(errno), win32_strerror(WSAGetLastError()));

	return 0;
}

---8<---

The output is:

---8<---
errno: 'Result too large'
WSAGetLastError: 'The operation completed successfully.
'
errno: 'Bad file descriptor'
WSAGetLastError: 'The handle is invalid.
'
errno: 'No error'
WSAGetLastError: 'An operation was attempted on something that is not a socket.
'
---8<---

So, it seems that WSAGetLastError() gets clobbered by closesocket(),
but not errno.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [msysGit] [PATCH v3 02/14] mingw: implement syslog
  2010-10-10 19:50   ` [msysGit] " Eric Sunshine
@ 2010-10-10 20:37     ` Erik Faye-Lund
  2010-10-10 20:51       ` Johannes Sixt
  2010-10-10 21:28       ` Eric Sunshine
  0 siblings, 2 replies; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 20:37 UTC (permalink / raw)
  To: Eric Sunshine; +Cc: git, msysgit, j6t, Mike Pape

On Sun, Oct 10, 2010 at 9:50 PM, Eric Sunshine <ericsunshine@gmail.com> wrote:
> On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:
>>
>> From: Mike Pape<dotzenlabs@gmail.com>
>>
>> Syslog does not usually exist on Windows, so we implement our own
>> using Window's ReportEvent mechanism.
>>
>> Signed-off-by: Mike Pape<dotzenlabs@gmail.com>
>> Signed-off-by: Erik Faye-Lund<kusmabite@gmail.com>
>> ---
>> +void syslog(int priority, const char *fmt, const char *arg)
>> +{
>> +       WORD logtype;
>> +
>> +       if (!ms_eventlog)
>> +               return;
>> +
>> +       if (strcmp(fmt, "%s")) {
>> +               warning("format string of syslog() not implemented");
>> +               return;
>> +       }
>
> It is not exactly clear what the intention is here. Is this trying to say
> that no formatting directives are allowed in 'fmt' or what? The simple case
> it is actually checking (where 'fmt' is solely '%s') could easily be handled
> manually, as could more complex formats.
>

This is the result of the feed-back in v1, where we tried to implement
all format strings. But that turned out to be very complex (due to the
lack of a portable va_copy()) and since we control all call-sites for
syslog and already only use "%s" as the format, it should be OK.

Perhaps that should be mentioned in the commit message...

>> +       /*
>> +        * ReportEvent() doesn't handle strings containing %n, where n is
>> +        * an integer. Such events must be reformatted by the caller.
>> +        */
>> +       ReportEventA(ms_eventlog,
>> +           logtype,
>> +           0,
>> +           0,
>> +           NULL,
>> +           1,
>> +           0,
>> +           (const char **)&arg,
>> +           NULL);
>
> The comment about '%n' seems to be warning about a potential problem but
> does not actually protect against it. Should this issue be handled?
>

This is again an issue that was discussed in the first round.
ReportEvent() CANNOT report a string containing "%n" (where n is an
integer). And while we could probably try to work around it by
inserting a space or something, and I don't think we ever were able to
find a case where we could report a string containing "%n" in the
first place...

Are you suggesting that we report an error when we can't report the
string correctly? We could do that, but I'm not sure how the end-user
would benefit from that. ReportEvent is used to report errors (unless
the --verbose flag has been specified), and reporting that we can't
present an error message strike me as a bit confusing... Even the
corrupted error message is probably better :P

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 08/14] daemon: use run-command api for async serving
  2010-10-10 19:56   ` [msysGit] " Eric Sunshine
@ 2010-10-10 20:42     ` Erik Faye-Lund
  0 siblings, 0 replies; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 20:42 UTC (permalink / raw)
  To: Eric Sunshine; +Cc: git, msysgit, j6t

On Sun, Oct 10, 2010 at 9:56 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:
> On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:
>>
>> fork() is only available on POSIX, so to support git-daemon
>> on Windows we have to use something else.
>>
>> Instead we invent the flag --serve, which is a stripped down
>> version of --inetd-mode. We use start_command() to call
>> git-daemon with this flag appended to serve clients.
>>
>> Signed-off-by: Erik Faye-Lund<kusmabite@gmail.com>
>> ---
>> @@ -654,14 +641,14 @@ static void remove_child(pid_t pid)
>>   */
>>  static void kill_some_child(void)
>>  {
>> -       const struct child *blanket, *next;
>> +       struct child *blanket, *next;
>
> It is not immediately obvious why 'const' was dropped.
>

It's a left-over hunk from a previous version. Thanks for pointing it out!

>> @@ -671,18 +658,26 @@ static void check_dead_children(void)
>>        int status;
>>        pid_t pid;
>>
>> -       while ((pid = waitpid(-1,&status, WNOHANG))>  0) {
>> -               const char *dead = "";
>> -               remove_child(pid);
>> -               if (!WIFEXITED(status) || (WEXITSTATUS(status)>  0))
>> -                       dead = " (with error)";
>> -               loginfo("[%"PRIuMAX"] Disconnected%s", (uintmax_t)pid,
>> dead);
>> -       }
>> +       struct child **cradle, *blanket;
>> +       for (cradle =&firstborn; (blanket = *cradle);)
>> +               if ((pid = waitpid(blanket->cld.pid,&status, WNOHANG))>
>>  1) {
>> +                       const char *dead = "";
>> +                       if (status)
>> +                               dead = " (with error)";
>> +                       loginfo("[%"PRIuMAX"] Disconnected%s",
>> (uintmax_t)pid, dead);
>> +
>> +                       /* remove the child */
>> +                       *cradle = blanket->next;
>> +                       live_children--;
>> +                       free(blanket);
>> +               } else
>> +                       cradle =&blanket->next;
>>  }
>>
>> +char **cld_argv;
>>  static void handle(int incoming, struct sockaddr *addr, int addrlen)
>>  {
>
> Should 'cld_argv' be declared static?
>

Yes it should, thanks!

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 11/14] daemon: report connection from root-process
  2010-10-10 20:14         ` Ævar Arnfjörð Bjarmason
@ 2010-10-10 20:48           ` Erik Faye-Lund
  0 siblings, 0 replies; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 20:48 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason; +Cc: Johannes Sixt, git, msysgit

On Sun, Oct 10, 2010 at 10:14 PM, Ævar Arnfjörð Bjarmason
<avarab@gmail.com> wrote:
> On Sun, Oct 10, 2010 at 19:42, Erik Faye-Lund <kusmabite@gmail.com> wrote:
>
>> -static int execute(struct sockaddr *addr)
>> +static int execute()
>
> Isn't execute(void) more portable?
>

Yes, it is. Thanks!

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [msysGit] [PATCH v3 02/14] mingw: implement syslog
  2010-10-10 20:37     ` Erik Faye-Lund
@ 2010-10-10 20:51       ` Johannes Sixt
  2010-10-10 21:17         ` Erik Faye-Lund
  2010-10-10 21:28       ` Eric Sunshine
  1 sibling, 1 reply; 43+ messages in thread
From: Johannes Sixt @ 2010-10-10 20:51 UTC (permalink / raw)
  To: kusmabite; +Cc: Eric Sunshine, git, msysgit, Mike Pape

On Sonntag, 10. Oktober 2010, Erik Faye-Lund wrote:
> On Sun, Oct 10, 2010 at 9:50 PM, Eric Sunshine <ericsunshine@gmail.com> 
wrote:
> > On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:
> >> +       /*
> >> +        * ReportEvent() doesn't handle strings containing %n, where n
> >> is +        * an integer. Such events must be reformatted by the caller.
> >> +        */
> >
> > The comment about '%n' seems to be warning about a potential problem but
> > does not actually protect against it. Should this issue be handled?
>
> This is again an issue that was discussed in the first round.
> ReportEvent() CANNOT report a string containing "%n" (where n is an
> integer). And while we could probably try to work around it by
> inserting a space or something, and I don't think we ever were able to
> find a case where we could report a string containing "%n" in the
> first place...

I recall that it was mentioned that this could happen for IPv6 addresses?

-- Hannes

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 05/14] mingw: use real pid
  2010-10-10 19:53   ` Eric Sunshine
@ 2010-10-10 20:52     ` Erik Faye-Lund
  2010-10-10 21:56       ` Eric Sunshine
  0 siblings, 1 reply; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 20:52 UTC (permalink / raw)
  To: Eric Sunshine; +Cc: git, msysgit, j6t

On Sun, Oct 10, 2010 at 9:53 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:
> On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:
>>
>> The Windows port so far used process handles as PID. However,
>> this does not work consistently with getpid.
>
> Perhaps this could be elaborated a bit to explain the interaction with
> getpid() and how it is causing problems for daemon mode. For the casual
> reader, it is not immediately obvious what is failing or why this patch is
> needed.
>

Good point. How about something like this?

"The Windows port so far used process handles as PID. However, this is
not consistent with what getpid returns.

PIDs are system-global identifiers, but process handles are local to a
process. Using PIDs instead of process handles allows for instance a
user to kill a hung process with the Task Manager, something that
would have been impossible with process handles."

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [msysGit] [PATCH v3 02/14] mingw: implement syslog
  2010-10-10 20:51       ` Johannes Sixt
@ 2010-10-10 21:17         ` Erik Faye-Lund
  0 siblings, 0 replies; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 21:17 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: Eric Sunshine, git, msysgit, Mike Pape

On Sun, Oct 10, 2010 at 10:51 PM, Johannes Sixt <j6t@kdbg.org> wrote:
> On Sonntag, 10. Oktober 2010, Erik Faye-Lund wrote:
>> On Sun, Oct 10, 2010 at 9:50 PM, Eric Sunshine <ericsunshine@gmail.com>
> wrote:
>> > On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:
>> >> +       /*
>> >> +        * ReportEvent() doesn't handle strings containing %n, where n
>> >> is +        * an integer. Such events must be reformatted by the caller.
>> >> +        */
>> >
>> > The comment about '%n' seems to be warning about a potential problem but
>> > does not actually protect against it. Should this issue be handled?
>>
>> This is again an issue that was discussed in the first round.
>> ReportEvent() CANNOT report a string containing "%n" (where n is an
>> integer). And while we could probably try to work around it by
>> inserting a space or something, and I don't think we ever were able to
>> find a case where we could report a string containing "%n" in the
>> first place...
>
> I recall that it was mentioned that this could happen for IPv6 addresses?
>

Ah, that's right. Microsoft even mentions it in MSDN: "Note that the
string that you log cannot contain %n, where n is an integer value
(for example, %1) because the event viewer treats it as an insertion
string. Because an IPv6 address can contain this character sequence,
you cannot log an event message that contains an IPv6 address".

What should we do about it? Error out?

Strangely enough, reporting strings with "%1" works fine when I test
it now. Perhaps this is dependent on the windows-version?

Yep, it is. On Vista 64 it seems to work, but on WinXP it does not.
The string gets expanded into itself 100 times, and then there's
apparently a recursion test.

Also, it is only %1 that does not report correctly on WinXP, probably
because of a check against the wNumStrings-parameter. Even strings
like %11 does not expand.

FormatMessage has the FORMAT_MESSAGE_IGNORE_INSERTS-flag to avoid this
kind of expansion, but unfortunately I can't find similar
functionality for ReportEvent :(

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 01/14] mingw: add network-wrappers for daemon
  2010-10-10 20:20     ` Erik Faye-Lund
@ 2010-10-10 21:19       ` Eric Sunshine
  0 siblings, 0 replies; 43+ messages in thread
From: Eric Sunshine @ 2010-10-10 21:19 UTC (permalink / raw)
  To: kusmabite; +Cc: git, msysgit, j6t, Mike Pape

On 10/10/2010 4:20 PM, Erik Faye-Lund wrote:
> On Sun, Oct 10, 2010 at 9:40 PM, Eric Sunshine<ericsunshine@gmail.com>  wrote:
>> On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:
>>>
>>> From: Mike Pape<dotzenlabs@gmail.com>
>>>
>>> git-daemon requires some socket-functionality that is not yet
>>> supported in the Windows-port. This patch adds said functionality,
>>> and makes sure WSAStartup gets called by socket(), since it is the
>>> first network-call in git-daemon. In addition, a check is added to
>>> prevent WSAStartup (and WSACleanup, though atexit) from being
>>> called more than once, since git-daemon calls both socket() and
>>> gethostbyname().
>>>
>>> Signed-off-by: Mike Pape<dotzenlabs@gmail.com>
>>> Signed-off-by: Erik Faye-Lund<kusmabite@gmail.com>
>>> ---
>>> diff --git a/compat/mingw.c b/compat/mingw.c
>>> index 6590f33..563ef1f 100644
>>> --- a/compat/mingw.c
>>> +++ b/compat/mingw.c
>>> +#undef accept
>>> +int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
>>> +{
>>> +       int sockfd2;
>>> +
>>> +       SOCKET s1 = (SOCKET)_get_osfhandle(sockfd1);
>>> +       SOCKET s2 = accept(s1, sa, sz);
>>> +
>>> +       /* convert into a file descriptor */
>>> +       if ((sockfd2 = _open_osfhandle(s2, O_RDWR|O_BINARY))<    0) {
>>> +               closesocket(s2);
>>> +               return error("unable to make a socket file descriptor:
>>> %s",
>>> +                       strerror(errno));
>>
>> Is 'errno' from _open_osfhandle() still valid when handed to strerror() or
>> has it been clobbered by closesocket()?
>>
>> Corollary: Does _open_osfhandle() indeed set 'errno', or is it more
>> appropriate to call WSAGetLastError()? (The documentation I read for
>> _open_osfhandle() did not say anything about how to determine the reason for
>> failure.)
>>
>
> _open_osfhandle seems to set both errno and the winsock-error.
> closesocket() sets the winsock-error but not the CRT. I've just tested
> with a very simple application:
> So, it seems that WSAGetLastError() gets clobbered by closesocket(),
> but not errno.

Thank you for checking. Even if it is not strictly needed in this case, 
for the sake of clarity (and to avoid having this question repeated in 
the future), it might be worthwhile to save 'errno' or the result of 
WSAGetLastError() in a temporary before invoking closesocket(), and then 
pass the temporary to strerror().

-- ES

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [msysGit] [PATCH v3 02/14] mingw: implement syslog
  2010-10-10 20:37     ` Erik Faye-Lund
  2010-10-10 20:51       ` Johannes Sixt
@ 2010-10-10 21:28       ` Eric Sunshine
  2010-10-10 22:16         ` Erik Faye-Lund
  1 sibling, 1 reply; 43+ messages in thread
From: Eric Sunshine @ 2010-10-10 21:28 UTC (permalink / raw)
  To: kusmabite; +Cc: git, msysgit, j6t, Mike Pape

On 10/10/2010 4:37 PM, Erik Faye-Lund wrote:
> On Sun, Oct 10, 2010 at 9:50 PM, Eric Sunshine<ericsunshine@gmail.com>  wrote:
>> On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:
>>>
>>> From: Mike Pape<dotzenlabs@gmail.com>
>>>
>>> Syslog does not usually exist on Windows, so we implement our own
>>> using Window's ReportEvent mechanism.
>>>
>>> Signed-off-by: Mike Pape<dotzenlabs@gmail.com>
>>> Signed-off-by: Erik Faye-Lund<kusmabite@gmail.com>
>>> ---
>>> +void syslog(int priority, const char *fmt, const char *arg)
>>> +{
>>> +       WORD logtype;
>>> +
>>> +       if (!ms_eventlog)
>>> +               return;
>>> +
>>> +       if (strcmp(fmt, "%s")) {
>>> +               warning("format string of syslog() not implemented");
>>> +               return;
>>> +       }
>>
>> It is not exactly clear what the intention is here. Is this trying to say
>> that no formatting directives are allowed in 'fmt' or what? The simple case
>> it is actually checking (where 'fmt' is solely '%s') could easily be handled
>> manually, as could more complex formats.
>>
>
> This is the result of the feed-back in v1, where we tried to implement
> all format strings.

In retrospect, when thinking more carefully about the conditional 
expression, I suppose the code is self-documenting, though perhaps a 
comment in code or in commit message would help.

> But that turned out to be very complex (due to the
> lack of a portable va_copy()) and since we control all call-sites for
> syslog and already only use "%s" as the format, it should be OK.

Do you mean vsnprintf() rather than va_copy()?

>>> +       /*
>>> +        * ReportEvent() doesn't handle strings containing %n, where n is
>>> +        * an integer. Such events must be reformatted by the caller.
>>> +        */
>>> +       ReportEventA(ms_eventlog,
>>> +           logtype,
>>> +           0,
>>> +           0,
>>> +           NULL,
>>> +           1,
>>> +           0,
>>> +           (const char **)&arg,
>>> +           NULL);
>>
>> The comment about '%n' seems to be warning about a potential problem but
>> does not actually protect against it. Should this issue be handled?
>>
>
> This is again an issue that was discussed in the first round.
> ReportEvent() CANNOT report a string containing "%n" (where n is an
> integer). And while we could probably try to work around it by
> inserting a space or something, and I don't think we ever were able to
> find a case where we could report a string containing "%n" in the
> first place...
>
> Are you suggesting that we report an error when we can't report the
> string correctly? We could do that, but I'm not sure how the end-user
> would benefit from that. ReportEvent is used to report errors (unless
> the --verbose flag has been specified), and reporting that we can't
> present an error message strike me as a bit confusing... Even the
> corrupted error message is probably better :P

I am not suggesting reporting an error. As a first-time reader of the 
code, I was trying to understand the presence of the comment which did 
not really seem to relate to the code. Perhaps adding a "FIXME" to the 
comment saying that the condition should perhaps be handled in the 
future would help to explain the comments presence.

(On the other hand, for the '%s' check above, the code does report a 
warning and then exits, so it is not inconceivable that a '%n' could 
also emit a warning.)

-- ES

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 05/14] mingw: use real pid
  2010-10-10 20:52     ` Erik Faye-Lund
@ 2010-10-10 21:56       ` Eric Sunshine
  0 siblings, 0 replies; 43+ messages in thread
From: Eric Sunshine @ 2010-10-10 21:56 UTC (permalink / raw)
  To: kusmabite; +Cc: git, msysgit, j6t

On 10/10/2010 4:52 PM, Erik Faye-Lund wrote:
> On Sun, Oct 10, 2010 at 9:53 PM, Eric Sunshine<sunshine@sunshineco.com>  wrote:
>> On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:
>>>
>>> The Windows port so far used process handles as PID. However,
>>> this does not work consistently with getpid.
>>
>> Perhaps this could be elaborated a bit to explain the interaction with
>> getpid() and how it is causing problems for daemon mode. For the casual
>> reader, it is not immediately obvious what is failing or why this patch is
>> needed.
>>
>
> Good point. How about something like this?

Thanks. This sort of explanation could indeed be helpful as part of the 
commit message.

> "The Windows port so far used process handles as PID. However, this is
> not consistent with what getpid returns.
>
> PIDs are system-global identifiers, but process handles are local to a
> process. Using PIDs instead of process handles allows for instance a
> user to kill a hung process with the Task Manager, something that
> would have been impossible with process handles."

Minor nit: Add commas around 'for instance': "...handles allows, for 
instance, a user..."

These also could be combined into a single paragraph.

-- ES

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [msysGit] [PATCH v3 02/14] mingw: implement syslog
  2010-10-10 21:28       ` Eric Sunshine
@ 2010-10-10 22:16         ` Erik Faye-Lund
  2010-10-10 22:23           ` Erik Faye-Lund
  2010-10-10 23:20           ` Eric Sunshine
  0 siblings, 2 replies; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 22:16 UTC (permalink / raw)
  To: Eric Sunshine; +Cc: git, msysgit, j6t, Mike Pape

On Sun, Oct 10, 2010 at 11:28 PM, Eric Sunshine <ericsunshine@gmail.com> wrote:
> On 10/10/2010 4:37 PM, Erik Faye-Lund wrote:
>>
>> On Sun, Oct 10, 2010 at 9:50 PM, Eric Sunshine<ericsunshine@gmail.com>
>>  wrote:
>>>
>>> On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:
>>>>
>>>> From: Mike Pape<dotzenlabs@gmail.com>
>>>>
>>>> Syslog does not usually exist on Windows, so we implement our own
>>>> using Window's ReportEvent mechanism.
>>>>
>>>> Signed-off-by: Mike Pape<dotzenlabs@gmail.com>
>>>> Signed-off-by: Erik Faye-Lund<kusmabite@gmail.com>
>>>> ---
>>>> +void syslog(int priority, const char *fmt, const char *arg)
>>>> +{
>>>> +       WORD logtype;
>>>> +
>>>> +       if (!ms_eventlog)
>>>> +               return;
>>>> +
>>>> +       if (strcmp(fmt, "%s")) {
>>>> +               warning("format string of syslog() not implemented");
>>>> +               return;
>>>> +       }
>>>
>>> It is not exactly clear what the intention is here. Is this trying to say
>>> that no formatting directives are allowed in 'fmt' or what? The simple
>>> case
>>> it is actually checking (where 'fmt' is solely '%s') could easily be
>>> handled
>>> manually, as could more complex formats.
>>>
>>
>> This is the result of the feed-back in v1, where we tried to implement
>> all format strings.
>
> In retrospect, when thinking more carefully about the conditional
> expression, I suppose the code is self-documenting, though perhaps a comment
> in code or in commit message would help.
>
>> But that turned out to be very complex (due to the
>> lack of a portable va_copy()) and since we control all call-sites for
>> syslog and already only use "%s" as the format, it should be OK.
>
> Do you mean vsnprintf() rather than va_copy()?
>

OK, I had to read some old discussions to figure out what the issue was :)

The problem was lack of portable va_copy, because I tried to add a
non-variadic version of strbuf_addf(), namely strbuf_vaddf() to do the
work.

I guess it could be implemented pretty easily with vsnprintf(),
though. I was afraid of doing that originally because I know there's
portability issues with the return value of snprintf. Luckily it seems
that we have a fix for that in compat/sprintf.c, and we rely on the
return value being correct in strbuf_addf() so it would probably be
safe.

Something like this (on top)

---8<---
diff --git a/compat/mingw.c b/compat/mingw.c
index bbe45d0..e3f3f92 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -1435,17 +1435,24 @@ void openlog(const char *ident, int logopt,
int facility)
 		warning("RegisterEventSource() failed: %lu", GetLastError());
 }

-void syslog(int priority, const char *fmt, const char *arg)
+void syslog(int priority, const char *fmt, ...)
 {
 	WORD logtype;
+	char *str;
+	int str_len;
+	va_list ap;

 	if (!ms_eventlog)
 		return;

-	if (strcmp(fmt, "%s")) {
-		warning("format string of syslog() not implemented");
-		return;
-	}
+	va_start(ap, fmt);
+	str_len = vsnprintf(NULL, 0, fmt, ap);
+	va_end(ap);
+
+	str = malloc(str_len + 1);
+	va_start(ap, fmt);
+	vsnprintf(str, str_len, fmt, ap);
+	va_end(ap);

 	switch (priority) {
 	case LOG_EMERG:
@@ -1478,8 +1485,9 @@ void syslog(int priority, const char *fmt, const
char *arg)
 	    NULL,
 	    1,
 	    0,
-	    (const char **)&arg,
+	    (const char **)&str,
 	    NULL);
+	free(str);
 }

 #undef signal
diff --git a/compat/mingw.h b/compat/mingw.h
index aed49d8..45a63a0 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -186,7 +186,7 @@ int setitimer(int type, struct itimerval *in,
struct itimerval *out);
 int sigaction(int sig, struct sigaction *in, struct sigaction *out);
 int link(const char *oldpath, const char *newpath);
 void openlog(const char *ident, int logopt, int facility);
-void syslog(int priority, const char *fmt, const char *arg);
+void syslog(int priority, const char *fmt, ...);

 /*
  * replacements of existing functions
---8<---

>> Are you suggesting that we report an error when we can't report the
>> string correctly? We could do that, but I'm not sure how the end-user
>> would benefit from that. ReportEvent is used to report errors (unless
>> the --verbose flag has been specified), and reporting that we can't
>> present an error message strike me as a bit confusing... Even the
>> corrupted error message is probably better :P
>
> I am not suggesting reporting an error. As a first-time reader of the code,
> I was trying to understand the presence of the comment which did not really
> seem to relate to the code. Perhaps adding a "FIXME" to the comment saying
> that the condition should perhaps be handled in the future would help to
> explain the comments presence.
>

A FIXME would certainly a good idea, if I don't just end up supporting
varargs here.

> (On the other hand, for the '%s' check above, the code does report a warning
> and then exits, so it is not inconceivable that a '%n' could also emit a
> warning.)
>

I guess I could add something like this:

if (strstr(arg, "%1"))
	warning("arg contains %1, message might be corrupted");

I don't want to return in that case, because I think some output is
better than no output, and it seems to work on Vista. In fact, working
on Vista is kind of demotivating me to add such a warning in the first
place...

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [msysGit] [PATCH v3 02/14] mingw: implement syslog
  2010-10-10 22:16         ` Erik Faye-Lund
@ 2010-10-10 22:23           ` Erik Faye-Lund
  2010-10-10 23:20           ` Eric Sunshine
  1 sibling, 0 replies; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-10 22:23 UTC (permalink / raw)
  To: Eric Sunshine; +Cc: git, msysgit, j6t, Mike Pape

On Mon, Oct 11, 2010 at 12:16 AM, Erik Faye-Lund <kusmabite@gmail.com> wrote:
> On Sun, Oct 10, 2010 at 11:28 PM, Eric Sunshine <ericsunshine@gmail.com> wrote:
>> On 10/10/2010 4:37 PM, Erik Faye-Lund wrote:
>>> Are you suggesting that we report an error when we can't report the
>>> string correctly? We could do that, but I'm not sure how the end-user
>>> would benefit from that. ReportEvent is used to report errors (unless
>>> the --verbose flag has been specified), and reporting that we can't
>>> present an error message strike me as a bit confusing... Even the
>>> corrupted error message is probably better :P
>>
>> I am not suggesting reporting an error. As a first-time reader of the code,
>> I was trying to understand the presence of the comment which did not really
>> seem to relate to the code. Perhaps adding a "FIXME" to the comment saying
>> that the condition should perhaps be handled in the future would help to
>> explain the comments presence.
>>
>
> A FIXME would certainly a good idea, if I don't just end up supporting
> varargs here.
>

Uhm, excuse me for confusing the different comments :P

Yes, a FIXME should definitely be added. And I definitely need to seep now! ;)

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 02/14] mingw: implement syslog
  2010-10-10 22:16         ` Erik Faye-Lund
  2010-10-10 22:23           ` Erik Faye-Lund
@ 2010-10-10 23:20           ` Eric Sunshine
  2010-10-11 15:28             ` [msysGit] " Erik Faye-Lund
  1 sibling, 1 reply; 43+ messages in thread
From: Eric Sunshine @ 2010-10-10 23:20 UTC (permalink / raw)
  To: kusmabite; +Cc: git, msysgit, j6t, Mike Pape

On 10/10/2010 6:16 PM, Erik Faye-Lund wrote:
> On Sun, Oct 10, 2010 at 11:28 PM, Eric Sunshine<ericsunshine@gmail.com>  wrote:
>> On 10/10/2010 4:37 PM, Erik Faye-Lund wrote:
>>> This is the result of the feed-back in v1, where we tried to implement
>>> all format strings. But that turned out to be very complex (due to the
>>> lack of a portable va_copy()) and since we control all call-sites for
>>> syslog and already only use "%s" as the format, it should be OK.
>>
>> Do you mean vsnprintf() rather than va_copy()?
>
> The problem was lack of portable va_copy, because I tried to add a
> non-variadic version of strbuf_addf(), namely strbuf_vaddf() to do the
> work.
>
> I guess it could be implemented pretty easily with vsnprintf(),
> though. I was afraid of doing that originally because I know there's
> portability issues with the return value of snprintf. Luckily it seems
> that we have a fix for that in compat/sprintf.c, and we rely on the
> return value being correct in strbuf_addf() so it would probably be
> safe.
>
> Something like this (on top)
>
> diff --git a/compat/mingw.c b/compat/mingw.c
> index bbe45d0..e3f3f92 100644
> --- a/compat/mingw.c
> +++ b/compat/mingw.c
> @@ -1435,17 +1435,24 @@ void openlog(const char *ident, int logopt,
> int facility)
>   		warning("RegisterEventSource() failed: %lu", GetLastError());
>   }
>
> -void syslog(int priority, const char *fmt, const char *arg)
> +void syslog(int priority, const char *fmt, ...)
>   {
>   	WORD logtype;
> +	char *str;
> +	int str_len;
> +	va_list ap;
>
>   	if (!ms_eventlog)
>   		return;
>
> -	if (strcmp(fmt, "%s")) {
> -		warning("format string of syslog() not implemented");
> -		return;
> -	}
> +	va_start(ap, fmt);
> +	str_len = vsnprintf(NULL, 0, fmt, ap);
> +	va_end(ap);

vsnprintf() can return -1 on error (even the compat/snprintf.c version 
can do so), so perhaps check for this condition before the subsequent 
malloc(str_len+1)?

> +
> +	str = malloc(str_len + 1);
> +	va_start(ap, fmt);
> +	vsnprintf(str, str_len, fmt, ap);
> +	va_end(ap);
>
>   	switch (priority) {
>   	case LOG_EMERG:
> @@ -1478,8 +1485,9 @@ void syslog(int priority, const char *fmt, const
> char *arg)
>   	    NULL,
>   	    1,
>   	    0,
> -	    (const char **)&arg,
> +	    (const char **)&str,
>   	    NULL);
> +	free(str);
>   }

Other than the note about -1 return value, this revision looks fine.

>> (On the other hand, for the '%s' check above, the code does report a warning
>> and then exits, so it is not inconceivable that a '%n' could also emit a
>> warning.)
>
> I guess I could add something like this:
>
> if (strstr(arg, "%1"))
> 	warning("arg contains %1, message might be corrupted");
>
> I don't want to return in that case, because I think some output is
> better than no output, and it seems to work on Vista.

Rather than emitting a warning, it might be reasonable to perform a 
simple transformation on the string if it contains a %1 (or %n 
generally) in order to avoid ReportEvent()'s shortcoming. Even something 
as simple as inserting a space between '%' and '1' might be sufficiently 
defensive.

-- ES

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [msysGit] [PATCH v3 02/14] mingw: implement syslog
  2010-10-10 23:20           ` Eric Sunshine
@ 2010-10-11 15:28             ` Erik Faye-Lund
  2010-10-11 15:59               ` Erik Faye-Lund
  0 siblings, 1 reply; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-11 15:28 UTC (permalink / raw)
  To: Eric Sunshine; +Cc: git, msysgit, j6t, Mike Pape

On Mon, Oct 11, 2010 at 1:20 AM, Eric Sunshine <ericsunshine@gmail.com> wrote:
> On 10/10/2010 6:16 PM, Erik Faye-Lund wrote:
>>
>> On Sun, Oct 10, 2010 at 11:28 PM, Eric Sunshine<ericsunshine@gmail.com>
>>  wrote:
>>> (On the other hand, for the '%s' check above, the code does report a
>>> warning
>>> and then exits, so it is not inconceivable that a '%n' could also emit a
>>> warning.)
>>
>> I guess I could add something like this:
>>
>> if (strstr(arg, "%1"))
>>        warning("arg contains %1, message might be corrupted");
>>
>> I don't want to return in that case, because I think some output is
>> better than no output, and it seems to work on Vista.
>
> Rather than emitting a warning, it might be reasonable to perform a simple
> transformation on the string if it contains a %1 (or %n generally) in order
> to avoid ReportEvent()'s shortcoming. Even something as simple as inserting
> a space between '%' and '1' might be sufficiently defensive.
>

Yes, but I'm tempted to defer fixing this until we see that it's a
problem in reality. The logic to somehow escape such sequences looks a
bit nasty in my head. But perhaps strbuf_expand() is the right hammer
for this use...

Then the logical next question becomes what we should expand it to.
Does "%1" -> "% 1" make sense for IPv6 addresses?

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [msysGit] [PATCH v3 02/14] mingw: implement syslog
  2010-10-11 15:28             ` [msysGit] " Erik Faye-Lund
@ 2010-10-11 15:59               ` Erik Faye-Lund
  0 siblings, 0 replies; 43+ messages in thread
From: Erik Faye-Lund @ 2010-10-11 15:59 UTC (permalink / raw)
  To: Eric Sunshine; +Cc: git, msysgit, j6t, Mike Pape

On Mon, Oct 11, 2010 at 5:28 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:
> On Mon, Oct 11, 2010 at 1:20 AM, Eric Sunshine <ericsunshine@gmail.com> wrote:
>> On 10/10/2010 6:16 PM, Erik Faye-Lund wrote:
>>>
>>> On Sun, Oct 10, 2010 at 11:28 PM, Eric Sunshine<ericsunshine@gmail.com>
>>>  wrote:
>>>> (On the other hand, for the '%s' check above, the code does report a
>>>> warning
>>>> and then exits, so it is not inconceivable that a '%n' could also emit a
>>>> warning.)
>>>
>>> I guess I could add something like this:
>>>
>>> if (strstr(arg, "%1"))
>>>        warning("arg contains %1, message might be corrupted");
>>>
>>> I don't want to return in that case, because I think some output is
>>> better than no output, and it seems to work on Vista.
>>
>> Rather than emitting a warning, it might be reasonable to perform a simple
>> transformation on the string if it contains a %1 (or %n generally) in order
>> to avoid ReportEvent()'s shortcoming. Even something as simple as inserting
>> a space between '%' and '1' might be sufficiently defensive.
>>
>
> Yes, but I'm tempted to defer fixing this until we see that it's a
> problem in reality. The logic to somehow escape such sequences looks a
> bit nasty in my head. But perhaps strbuf_expand() is the right hammer
> for this use...
>
> Then the logical next question becomes what we should expand it to.
> Does "%1" -> "% 1" make sense for IPv6 addresses?
>

Something along these lines? (on top of the previous patch, uhm, with
some local modifications. Sorry, I'm not at home and do not have the
original version at hand. I'm sure you get the picture, though...)

I also added a +1 that was missing and caused the string to be capped.

diff --git a/compat/mingw.c b/compat/mingw.c
index ae6b448..d1444d2 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -1438,6 +1438,11 @@ void openlog(const char *ident, int logopt, int facility)

 void syslog(int priority, const char *fmt, ...)
 {
+	struct strbuf sb = STRBUF_INIT;
+	struct strbuf_expand_dict_entry dict[] = {
+		{"1", "% 1"},
+		{NULL, NULL}
+	};
 	WORD logtype;
 	char *str;
 	int str_len;
@@ -1457,8 +1462,9 @@ void syslog(int priority, const char *fmt, ...)

 	str = malloc(str_len + 1);
 	va_start(ap, fmt);
-	vsnprintf(str, str_len, fmt, ap);
+	vsnprintf(str, str_len + 1, fmt, ap);
 	va_end(ap);
+	strbuf_expand(&sb, str, strbuf_expand_dict_cb, &dict);

 	switch (priority) {
 	case LOG_EMERG:
@@ -1480,10 +1486,6 @@ void syslog(int priority, const char *fmt, ...)
 		break;
 	}

-	/*
-	 * FIXME: ReportEvent() doesn't handle strings containing "%1".
-	 * Such events must currently be reformatted by the caller.
-	 */
 	ReportEventA(ms_eventlog,
 	    logtype,
 	    0,
@@ -1491,9 +1493,10 @@ void syslog(int priority, const char *fmt, ...)
 	    NULL,
 	    1,
 	    0,
-	    (const char **)&str,
+	    (const char **)&sb.buf,
 	    NULL);
 	free(str);
+	sb_release(&sb);
 }

 #undef signal
diff --git a/daemon.c b/daemon.c

^ permalink raw reply related	[flat|nested] 43+ messages in thread

end of thread, other threads:[~2010-10-11 16:00 UTC | newest]

Thread overview: 43+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-10 13:20 [PATCH v3 00/14] daemon-win32 Erik Faye-Lund
2010-10-10 13:20 ` [PATCH v3 01/14] mingw: add network-wrappers for daemon Erik Faye-Lund
2010-10-10 19:40   ` Eric Sunshine
2010-10-10 20:20     ` Erik Faye-Lund
2010-10-10 21:19       ` Eric Sunshine
2010-10-10 13:20 ` [PATCH v3 02/14] mingw: implement syslog Erik Faye-Lund
2010-10-10 19:50   ` [msysGit] " Eric Sunshine
2010-10-10 20:37     ` Erik Faye-Lund
2010-10-10 20:51       ` Johannes Sixt
2010-10-10 21:17         ` Erik Faye-Lund
2010-10-10 21:28       ` Eric Sunshine
2010-10-10 22:16         ` Erik Faye-Lund
2010-10-10 22:23           ` Erik Faye-Lund
2010-10-10 23:20           ` Eric Sunshine
2010-10-11 15:28             ` [msysGit] " Erik Faye-Lund
2010-10-11 15:59               ` Erik Faye-Lund
2010-10-10 13:20 ` [PATCH v3 03/14] compat: add inet_pton and inet_ntop prototypes Erik Faye-Lund
2010-10-10 13:20 ` [PATCH v3 04/14] inet_ntop: fix a couple of old-style decls Erik Faye-Lund
2010-10-10 13:20 ` [PATCH v3 05/14] mingw: use real pid Erik Faye-Lund
2010-10-10 19:53   ` Eric Sunshine
2010-10-10 20:52     ` Erik Faye-Lund
2010-10-10 21:56       ` Eric Sunshine
2010-10-10 13:20 ` [PATCH v3 06/14] mingw: support waitpid with pid > 0 and WNOHANG Erik Faye-Lund
2010-10-10 13:20 ` [PATCH v3 07/14] mingw: add kill emulation Erik Faye-Lund
2010-10-10 13:20 ` [PATCH v3 08/14] daemon: use run-command api for async serving Erik Faye-Lund
2010-10-10 19:56   ` [msysGit] " Eric Sunshine
2010-10-10 20:42     ` Erik Faye-Lund
2010-10-10 13:20 ` [PATCH v3 09/14] daemon: use full buffered mode for stderr Erik Faye-Lund
2010-10-10 13:20 ` [PATCH v3 10/14] Improve the mingw getaddrinfo stub to handle more use cases Erik Faye-Lund
2010-10-10 13:20 ` [PATCH v3 11/14] daemon: report connection from root-process Erik Faye-Lund
2010-10-10 18:58   ` Johannes Sixt
2010-10-10 19:31     ` Erik Faye-Lund
2010-10-10 19:42       ` Erik Faye-Lund
2010-10-10 20:14         ` Ævar Arnfjörð Bjarmason
2010-10-10 20:48           ` Erik Faye-Lund
2010-10-10 13:20 ` [PATCH v3 12/14] mingw: import poll-emulation from gnulib Erik Faye-Lund
2010-10-10 14:15   ` Ævar Arnfjörð Bjarmason
2010-10-10 14:28     ` Erik Faye-Lund
2010-10-10 19:34       ` Erik Faye-Lund
2010-10-10 19:51         ` Ævar Arnfjörð Bjarmason
2010-10-10 13:20 ` [PATCH v3 13/14] mingw: use " Erik Faye-Lund
2010-10-10 13:20 ` [PATCH v3 14/14] daemon: only use posix features on posix systems Erik Faye-Lund
2010-10-10 19:40   ` Ævar Arnfjörð Bjarmason

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).