{"thread":{"id":"25410","subject":"[PATCH v3 00/14] daemon-win32","startedAt":"2010-10-10T13:20:40Z","lastAt":"2010-10-11T15:59:59Z","messageCount":43,"participants":["Erik Faye-Lund","Ævar Arnfjörð Bjarmason","Johannes Sixt","Eric Sunshine"],"isPatch":true,"patchVersion":3,"patchTotal":14},"messages":[{"id":"153129","messageId":"1286716854-5744-1-git-send-email-kusmabite@gmail.com","threadId":"25410","inReplyTo":null,"subject":"[PATCH v3 00/14] daemon-win32","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T13:20:40Z","receivedAt":"2010-10-10T13:20:40Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Almost 9 months have passed since I sent v2, and here's finally v3.\n\nNot so much have happened since v2, the most significant change being\nthat I've replaced our win32-poll implementation with the one from\ngnulib. This gives our the poll-features needed for git-daemon, and\nprevents a nasty timing-bug that occured (on Windows) in the previous\nseries.\n\nSome of the patches have been ejected;\n* \"daemon: use select() instead of poll()\" because our poll now is\n  sufficient.\n* \"daemon: use explicit file descriptor\" because it wasn't needed\n  anymore, not even in the previous version.\n\nOne patch might be a little bit controversial; \"daemon: only use posix\nfeatures on posix systems\". It replaces \"mingw: compile git-daemon\", and\nchanges the logic from opt-out is WIN32 is defined to opt-in if\n_POSIX_VERSION defined.\n\nThe current version is based on top of junio/next, because the\nab/daemon-multi-select series touches some of the same code.\n\nv2 msgid is <1263591033-4992-1-git-send-email-kusmabite@gmail.com> if\nyou're interrested in comparing.\n\nErik Faye-Lund (10):\n  inet_ntop: fix a couple of old-style decls\n  mingw: use real pid\n  mingw: support waitpid with pid > 0 and WNOHANG\n  mingw: add kill emulation\n  daemon: use run-command api for async serving\n  daemon: use full buffered mode for stderr\n  daemon: report connection from root-process\n  mingw: import poll-emulation from gnulib\n  mingw: use poll-emulation from gnulib\n  daemon: only use posix features on posix systems\n\nMartin Storsjö (1):\n  Improve the mingw getaddrinfo stub to handle more use cases\n\nMike Pape (3):\n  mingw: add network-wrappers for daemon\n  mingw: implement syslog\n  compat: add inet_pton and inet_ntop prototypes\n\n Makefile            |   12 +-\n compat/inet_ntop.c  |   22 +--\n compat/inet_pton.c  |    8 +-\n compat/mingw.c      |  291 +++++++++++++++++++-------\n compat/mingw.h      |   56 ++++--\n compat/win32/poll.c |  596 +++++++++++++++++++++++++++++++++++++++++++++++++++\n compat/win32/poll.h |   53 +++++\n daemon.c            |  199 ++++++++++--------\n git-compat-util.h   |   10 +\n 9 files changed, 1045 insertions(+), 202 deletions(-)\n create mode 100644 compat/win32/poll.c\n create mode 100644 compat/win32/poll.h\n\n-- \n1.7.3.1.51.ge462f.dirty\n"},{"id":"153131","messageId":"1286716854-5744-2-git-send-email-kusmabite@gmail.com","threadId":"25410","inReplyTo":"1286716854-5744-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v3 01/14] mingw: add network-wrappers for daemon","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T13:20:41Z","receivedAt":"2010-10-10T13:20:41Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"From: Mike Pape <dotzenlabs@gmail.com>\n\ngit-daemon requires some socket-functionality that is not yet\nsupported in the Windows-port. This patch adds said functionality,\nand makes sure WSAStartup gets called by socket(), since it is the\nfirst network-call in git-daemon. In addition, a check is added to\nprevent WSAStartup (and WSACleanup, though atexit) from being\ncalled more than once, since git-daemon calls both socket() and\ngethostbyname().\n\nSigned-off-by: Mike Pape <dotzenlabs@gmail.com>\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n compat/mingw.c |   43 ++++++++++++++++++++++++++++++++++++++++++-\n compat/mingw.h |   16 ++++++++++++++++\n 2 files changed, 58 insertions(+), 1 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 6590f33..563ef1f 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1175,7 +1175,10 @@ int mingw_getnameinfo(const struct sockaddr *sa, socklen_t salen,\n int mingw_socket(int domain, int type, int protocol)\n {\n \tint sockfd;\n-\tSOCKET s = WSASocket(domain, type, protocol, NULL, 0, 0);\n+\tSOCKET s;\n+\n+\tensure_socket_initialization();\n+\ts = WSASocket(domain, type, protocol, NULL, 0, 0);\n \tif (s == INVALID_SOCKET) {\n \t\t/*\n \t\t * WSAGetLastError() values are regular BSD error codes\n@@ -1205,6 +1208,44 @@ int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)\n \treturn connect(s, sa, sz);\n }\n \n+#undef bind\n+int mingw_bind(int sockfd, struct sockaddr *sa, size_t sz)\n+{\n+\tSOCKET s = (SOCKET)_get_osfhandle(sockfd);\n+\treturn bind(s, sa, sz);\n+}\n+\n+#undef setsockopt\n+int mingw_setsockopt(int sockfd, int lvl, int optname, void *optval, int optlen)\n+{\n+\tSOCKET s = (SOCKET)_get_osfhandle(sockfd);\n+\treturn setsockopt(s, lvl, optname, (const char*)optval, optlen);\n+}\n+\n+#undef listen\n+int mingw_listen(int sockfd, int backlog)\n+{\n+\tSOCKET s = (SOCKET)_get_osfhandle(sockfd);\n+\treturn listen(s, backlog);\n+}\n+\n+#undef accept\n+int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)\n+{\n+\tint sockfd2;\n+\n+\tSOCKET s1 = (SOCKET)_get_osfhandle(sockfd1);\n+\tSOCKET s2 = accept(s1, sa, sz);\n+\n+\t/* convert into a file descriptor */\n+\tif ((sockfd2 = _open_osfhandle(s2, O_RDWR|O_BINARY)) < 0) {\n+\t\tclosesocket(s2);\n+\t\treturn error(\"unable to make a socket file descriptor: %s\",\n+\t\t\tstrerror(errno));\n+\t}\n+\treturn sockfd2;\n+}\n+\n #undef rename\n int mingw_rename(const char *pold, const char *pnew)\n {\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex 83e35e8..a5bde82 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -7,6 +7,7 @@\n \n typedef int pid_t;\n typedef int uid_t;\n+typedef int socklen_t;\n #define hstrerror strerror\n \n #define S_IFLNK    0120000 /* Symbolic link */\n@@ -47,6 +48,9 @@ typedef int uid_t;\n #define F_SETFD 2\n #define FD_CLOEXEC 0x1\n \n+#define EAFNOSUPPORT WSAEAFNOSUPPORT\n+#define ECONNABORTED WSAECONNABORTED\n+\n struct passwd {\n \tchar *pw_name;\n \tchar *pw_gecos;\n@@ -225,6 +229,18 @@ int mingw_socket(int domain, int type, int protocol);\n int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz);\n #define connect mingw_connect\n \n+int mingw_bind(int sockfd, struct sockaddr *sa, size_t sz);\n+#define bind mingw_bind\n+\n+int mingw_setsockopt(int sockfd, int lvl, int optname, void *optval, int optlen);\n+#define setsockopt mingw_setsockopt\n+\n+int mingw_listen(int sockfd, int backlog);\n+#define listen mingw_listen\n+\n+int mingw_accept(int sockfd, struct sockaddr *sa, socklen_t *sz);\n+#define accept mingw_accept\n+\n int mingw_rename(const char*, const char*);\n #define rename mingw_rename\n \n-- \n1.7.3.1.51.ge462f.dirty\n"},{"id":"153133","messageId":"1286716854-5744-3-git-send-email-kusmabite@gmail.com","threadId":"25410","inReplyTo":"1286716854-5744-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v3 02/14] mingw: implement syslog","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T13:20:42Z","receivedAt":"2010-10-10T13:20:42Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"From: Mike Pape <dotzenlabs@gmail.com>\n\nSyslog does not usually exist on Windows, so we implement our own\nusing Window's ReportEvent mechanism.\n\nSigned-off-by: Mike Pape <dotzenlabs@gmail.com>\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n compat/mingw.c    |   60 +++++++++++++++++++++++++++++++++++++++++++++++++++++\n compat/mingw.h    |   15 +++++++++++++\n daemon.c          |    2 -\n git-compat-util.h |    1 +\n 4 files changed, 76 insertions(+), 2 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 563ef1f..cc5eb2c 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1431,6 +1431,66 @@ int sigaction(int sig, struct sigaction *in, struct sigaction *out)\n \treturn 0;\n }\n \n+static HANDLE ms_eventlog;\n+\n+void openlog(const char *ident, int logopt, int facility)\n+{\n+\tif (ms_eventlog)\n+\t\treturn;\n+\n+\tms_eventlog = RegisterEventSourceA(NULL, ident);\n+\n+\tif (!ms_eventlog)\n+\t\twarning(\"RegisterEventSource() failed: %lu\", GetLastError());\n+}\n+\n+void syslog(int priority, const char *fmt, const char *arg)\n+{\n+\tWORD logtype;\n+\n+\tif (!ms_eventlog)\n+\t\treturn;\n+\n+\tif (strcmp(fmt, \"%s\")) {\n+\t\twarning(\"format string of syslog() not implemented\");\n+\t\treturn;\n+\t}\n+\n+\tswitch (priority) {\n+\tcase LOG_EMERG:\n+\tcase LOG_ALERT:\n+\tcase LOG_CRIT:\n+\tcase LOG_ERR:\n+\t\tlogtype = EVENTLOG_ERROR_TYPE;\n+\t\tbreak;\n+\n+\tcase LOG_WARNING:\n+\t\tlogtype = EVENTLOG_WARNING_TYPE;\n+\t\tbreak;\n+\n+\tcase LOG_NOTICE:\n+\tcase LOG_INFO:\n+\tcase LOG_DEBUG:\n+\tdefault:\n+\t\tlogtype = EVENTLOG_INFORMATION_TYPE;\n+\t\tbreak;\n+\t}\n+\n+\t/*\n+\t * ReportEvent() doesn't handle strings containing %n, where n is\n+\t * an integer. Such events must be reformatted by the caller.\n+\t */\n+\tReportEventA(ms_eventlog,\n+\t    logtype,\n+\t    0,\n+\t    0,\n+\t    NULL,\n+\t    1,\n+\t    0,\n+\t    (const char **)&arg,\n+\t    NULL);\n+}\n+\n #undef signal\n sig_handler_t mingw_signal(int sig, sig_handler_t handler)\n {\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex a5bde82..bbfcc0c 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -51,6 +51,19 @@ typedef int socklen_t;\n #define EAFNOSUPPORT WSAEAFNOSUPPORT\n #define ECONNABORTED WSAECONNABORTED\n \n+#define LOG_PID     0x01\n+\n+#define LOG_EMERG   0\n+#define LOG_ALERT   1\n+#define LOG_CRIT    2\n+#define LOG_ERR     3\n+#define LOG_WARNING 4\n+#define LOG_NOTICE  5\n+#define LOG_INFO    6\n+#define LOG_DEBUG   7\n+\n+#define LOG_DAEMON  (3<<3)\n+\n struct passwd {\n \tchar *pw_name;\n \tchar *pw_gecos;\n@@ -185,6 +198,8 @@ struct passwd *getpwuid(uid_t uid);\n int setitimer(int type, struct itimerval *in, struct itimerval *out);\n int sigaction(int sig, struct sigaction *in, struct sigaction *out);\n int link(const char *oldpath, const char *newpath);\n+void openlog(const char *ident, int logopt, int facility);\n+void syslog(int priority, const char *fmt, const char *arg);\n \n /*\n  * replacements of existing functions\ndiff --git a/daemon.c b/daemon.c\nindex d6e20c6..d594375 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -5,8 +5,6 @@\n #include \"strbuf.h\"\n #include \"string-list.h\"\n \n-#include <syslog.h>\n-\n #ifndef HOST_NAME_MAX\n #define HOST_NAME_MAX 256\n #endif\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 2af8d3e..8770854 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -119,6 +119,7 @@\n #include <netdb.h>\n #include <pwd.h>\n #include <inttypes.h>\n+#include <syslog.h>\n #if defined(__CYGWIN__)\n #undef _XOPEN_SOURCE\n #include <grp.h>\n-- \n1.7.3.1.51.ge462f.dirty\n"},{"id":"153132","messageId":"1286716854-5744-4-git-send-email-kusmabite@gmail.com","threadId":"25410","inReplyTo":"1286716854-5744-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v3 03/14] compat: add inet_pton and inet_ntop prototypes","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T13:20:43Z","receivedAt":"2010-10-10T13:20:43Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"From: Mike Pape <dotzenlabs@gmail.com>\n\nWindows doesn't have inet_pton and inet_ntop, so\nadd prototypes in git-compat-util.h for them.\n\nAt the same time include git-compat-util.h in\nthe sources for these functions, so they use the\nnetwork-wrappers from there on Windows.\n\nSigned-off-by: Mike Pape <dotzenlabs@gmail.com>\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n Makefile           |    2 ++\n compat/inet_ntop.c |    6 +++---\n compat/inet_pton.c |    8 +++++---\n git-compat-util.h  |    8 ++++++++\n 4 files changed, 18 insertions(+), 6 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 1f1ce04..ebb51e3 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1397,9 +1397,11 @@ endif\n endif\n ifdef NO_INET_NTOP\n \tLIB_OBJS += compat/inet_ntop.o\n+\tBASIC_CFLAGS += -DNO_INET_NTOP\n endif\n ifdef NO_INET_PTON\n \tLIB_OBJS += compat/inet_pton.o\n+\tBASIC_CFLAGS += -DNO_INET_PTON\n endif\n \n ifdef NO_ICONV\ndiff --git a/compat/inet_ntop.c b/compat/inet_ntop.c\nindex f444982..e5b46a0 100644\n--- a/compat/inet_ntop.c\n+++ b/compat/inet_ntop.c\n@@ -17,9 +17,9 @@\n \n #include <errno.h>\n #include <sys/types.h>\n-#include <sys/socket.h>\n-#include <netinet/in.h>\n-#include <arpa/inet.h>\n+\n+#include \"../git-compat-util.h\"\n+\n #include <stdio.h>\n #include <string.h>\n \ndiff --git a/compat/inet_pton.c b/compat/inet_pton.c\nindex 4078fc0..2ec995e 100644\n--- a/compat/inet_pton.c\n+++ b/compat/inet_pton.c\n@@ -17,9 +17,9 @@\n \n #include <errno.h>\n #include <sys/types.h>\n-#include <sys/socket.h>\n-#include <netinet/in.h>\n-#include <arpa/inet.h>\n+\n+#include \"../git-compat-util.h\"\n+\n #include <stdio.h>\n #include <string.h>\n \n@@ -41,7 +41,9 @@\n  */\n \n static int inet_pton4(const char *src, unsigned char *dst);\n+#ifndef NO_IPV6\n static int inet_pton6(const char *src, unsigned char *dst);\n+#endif\n \n /* int\n  * inet_pton4(src, dst)\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 8770854..100197f 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -387,6 +387,14 @@ static inline void *gitmempcpy(void *dest, const void *src, size_t n)\n }\n #endif\n \n+#ifdef NO_INET_PTON\n+int inet_pton(int af, const char *src, void *dst);\n+#endif\n+\n+#ifdef NO_INET_NTOP\n+const char *inet_ntop(int af, const void *src, char *dst, size_t size);\n+#endif\n+\n extern void release_pack_memory(size_t, int);\n \n typedef void (*try_to_free_t)(size_t);\n-- \n1.7.3.1.51.ge462f.dirty\n"},{"id":"153134","messageId":"1286716854-5744-5-git-send-email-kusmabite@gmail.com","threadId":"25410","inReplyTo":"1286716854-5744-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v3 04/14] inet_ntop: fix a couple of old-style decls","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T13:20:44Z","receivedAt":"2010-10-10T13:20:44Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n compat/inet_ntop.c |   16 +++-------------\n 1 files changed, 3 insertions(+), 13 deletions(-)\n\ndiff --git a/compat/inet_ntop.c b/compat/inet_ntop.c\nindex e5b46a0..ea249c6 100644\n--- a/compat/inet_ntop.c\n+++ b/compat/inet_ntop.c\n@@ -50,10 +50,7 @@\n  *\tPaul Vixie, 1996.\n  */\n static const char *\n-inet_ntop4(src, dst, size)\n-\tconst u_char *src;\n-\tchar *dst;\n-\tsize_t size;\n+inet_ntop4(const u_char *src, char *dst, size_t size)\n {\n \tstatic const char fmt[] = \"%u.%u.%u.%u\";\n \tchar tmp[sizeof \"255.255.255.255\"];\n@@ -78,10 +75,7 @@ inet_ntop4(src, dst, size)\n  *\tPaul Vixie, 1996.\n  */\n static const char *\n-inet_ntop6(src, dst, size)\n-\tconst u_char *src;\n-\tchar *dst;\n-\tsize_t size;\n+inet_ntop6(const u_char *src, char *dst, size_t size)\n {\n \t/*\n \t * Note that int32_t and int16_t need only be \"at least\" large enough\n@@ -178,11 +172,7 @@ inet_ntop6(src, dst, size)\n  *\tPaul Vixie, 1996.\n  */\n const char *\n-inet_ntop(af, src, dst, size)\n-\tint af;\n-\tconst void *src;\n-\tchar *dst;\n-\tsize_t size;\n+inet_ntop(int af, const void *src, char *dst, size_t size)\n {\n \tswitch (af) {\n \tcase AF_INET:\n-- \n1.7.3.1.51.ge462f.dirty\n"},{"id":"153136","messageId":"1286716854-5744-6-git-send-email-kusmabite@gmail.com","threadId":"25410","inReplyTo":"1286716854-5744-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v3 05/14] mingw: use real pid","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T13:20:45Z","receivedAt":"2010-10-10T13:20:45Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"The Windows port so far used process handles as PID. However,\nthis does not work consistently with getpid.\n\nChange the code to use the real PID, and use OpenProcess to\nget a process-handle. Store the PID and the process handle\nin a table protected by a critical section, so we can safely\nclose the process handle later.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n compat/mingw.c |   70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-\n compat/mingw.h |   10 ++-----\n 2 files changed, 72 insertions(+), 8 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex cc5eb2c..4582345 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -702,6 +702,13 @@ static int env_compare(const void *a, const void *b)\n \treturn strcasecmp(*ea, *eb);\n }\n \n+struct {\n+\tpid_t pid;\n+\tHANDLE proc;\n+} *pinfo;\n+static int num_pinfo;\n+CRITICAL_SECTION pinfo_cs;\n+\n static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,\n \t\t\t      const char *dir,\n \t\t\t      int prepend_cmd, int fhin, int fhout, int fherr)\n@@ -794,7 +801,23 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,\n \t\treturn -1;\n \t}\n \tCloseHandle(pi.hThread);\n-\treturn (pid_t)pi.hProcess;\n+\n+\t/*\n+\t * The process ID is the human-readable identifier of the process\n+\t * that we want to present in log and error messages. The handle\n+\t * is not useful for this purpose. But we cannot close it, either,\n+\t * because it is not possible to turn a process ID into a process\n+\t * handle after the process terminated.\n+\t * Keep the handle in a list for waitpid.\n+\t */\n+\tEnterCriticalSection(&pinfo_cs);\n+\tnum_pinfo++;\n+\tpinfo = xrealloc(pinfo, sizeof(*pinfo) * num_pinfo);\n+\tpinfo[num_pinfo - 1].pid = pi.dwProcessId;\n+\tpinfo[num_pinfo - 1].proc = pi.hProcess;\n+\tLeaveCriticalSection(&pinfo_cs);\n+\n+\treturn (pid_t)pi.dwProcessId;\n }\n \n static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,\n@@ -1577,6 +1600,51 @@ char *getpass(const char *prompt)\n \treturn strbuf_detach(&buf, NULL);\n }\n \n+pid_t waitpid(pid_t pid, int *status, unsigned options)\n+{\n+\tHANDLE h = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,\n+\t    FALSE, pid);\n+\tif (!h) {\n+\t\terrno = ECHILD;\n+\t\treturn -1;\n+\t}\n+\n+\tif (options == 0) {\n+\t\tint i;\n+\t\tif (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {\n+\t\t\tCloseHandle(h);\n+\t\t\treturn 0;\n+\t\t}\n+\n+\t\tif (status)\n+\t\t\tGetExitCodeProcess(h, (LPDWORD)status);\n+\n+\t\tEnterCriticalSection(&pinfo_cs);\n+\n+\t\tfor (i = 0; i < num_pinfo; ++i)\n+\t\t\tif (pinfo[i].pid == pid)\n+\t\t\t\tbreak;\n+\n+\t\tif (i < num_pinfo) {\n+\t\t\tCloseHandle(pinfo[i].proc);\n+\t\t\tmemmove(pinfo + i, pinfo + i + 1,\n+\t\t\t    sizeof(*pinfo) * (num_pinfo - i - 1));\n+\t\t\tnum_pinfo--;\n+\t\t\tpinfo = xrealloc(pinfo,\n+\t\t\t    sizeof(*pinfo) * num_pinfo);\n+\t\t}\n+\n+\t\tLeaveCriticalSection(&pinfo_cs);\n+\n+\t\tCloseHandle(h);\n+\t\treturn pid;\n+\t}\n+\tCloseHandle(h);\n+\n+\terrno = EINVAL;\n+\treturn -1;\n+}\n+\n #ifndef NO_MINGW_REPLACE_READDIR\n /* MinGW readdir implementation to avoid extra lstats for Git */\n struct mingw_DIR\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex bbfcc0c..96ed931 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -153,13 +153,7 @@ static inline int mingw_unlink(const char *pathname)\n }\n #define unlink mingw_unlink\n \n-static inline pid_t waitpid(pid_t pid, int *status, unsigned options)\n-{\n-\tif (options == 0)\n-\t\treturn _cwait(status, pid, 0);\n-\terrno = EINVAL;\n-\treturn -1;\n-}\n+pid_t waitpid(pid_t pid, int *status, unsigned options);\n \n #ifndef NO_OPENSSL\n #include <openssl/ssl.h>\n@@ -336,11 +330,13 @@ void free_environ(char **env);\n static int mingw_main(); \\\n int main(int argc, const char **argv) \\\n { \\\n+\textern CRITICAL_SECTION pinfo_cs; \\\n \t_fmode = _O_BINARY; \\\n \t_setmode(_fileno(stdin), _O_BINARY); \\\n \t_setmode(_fileno(stdout), _O_BINARY); \\\n \t_setmode(_fileno(stderr), _O_BINARY); \\\n \targv[0] = xstrdup(_pgmptr); \\\n+\tInitializeCriticalSection(&pinfo_cs); \\\n \treturn mingw_main(argc, argv); \\\n } \\\n static int mingw_main(c,v)\n-- \n1.7.3.1.51.ge462f.dirty\n"},{"id":"153135","messageId":"1286716854-5744-7-git-send-email-kusmabite@gmail.com","threadId":"25410","inReplyTo":"1286716854-5744-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v3 06/14] mingw: support waitpid with pid > 0 and WNOHANG","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T13:20:46Z","receivedAt":"2010-10-10T13:20:46Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n compat/mingw.c |    6 ++++++\n compat/mingw.h |    1 +\n 2 files changed, 7 insertions(+), 0 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 4582345..55ea250 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1609,6 +1609,12 @@ pid_t waitpid(pid_t pid, int *status, unsigned options)\n \t\treturn -1;\n \t}\n \n+\tif (pid > 0 && options & WNOHANG) {\n+\t\tif (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))\n+\t\t\treturn 0;\n+\t\toptions &= ~WNOHANG;\n+\t}\n+\n \tif (options == 0) {\n \t\tint i;\n \t\tif (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex 96ed931..6d7a3f6 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -153,6 +153,7 @@ static inline int mingw_unlink(const char *pathname)\n }\n #define unlink mingw_unlink\n \n+#define WNOHANG 1\n pid_t waitpid(pid_t pid, int *status, unsigned options);\n \n #ifndef NO_OPENSSL\n-- \n1.7.3.1.51.ge462f.dirty\n"},{"id":"153138","messageId":"1286716854-5744-8-git-send-email-kusmabite@gmail.com","threadId":"25410","inReplyTo":"1286716854-5744-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v3 07/14] mingw: add kill emulation","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T13:20:47Z","receivedAt":"2010-10-10T13:20:47Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"This is a quite limited kill-emulation; it can only handle\nSIGTERM on positive pids. However, it's enough for git-daemon.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n compat/mingw.c |   19 +++++++++++++++++++\n compat/mingw.h |    3 +++\n 2 files changed, 22 insertions(+), 0 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 55ea250..44ea419 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -932,6 +932,25 @@ void mingw_execv(const char *cmd, char *const *argv)\n \tmingw_execve(cmd, argv, environ);\n }\n \n+int mingw_kill(pid_t pid, int sig)\n+{\n+\tif (pid > 0 && sig == SIGTERM) {\n+\t\tHANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, pid);\n+\n+\t\tif (TerminateProcess(h, -1)) {\n+\t\t\tCloseHandle(h);\n+\t\t\treturn 0;\n+\t\t}\n+\n+\t\terrno = err_win_to_posix(GetLastError());\n+\t\tCloseHandle(h);\n+\t\treturn -1;\n+\t}\n+\n+\terrno = EINVAL;\n+\treturn -1;\n+}\n+\n static char **copy_environ(void)\n {\n \tchar **env;\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex 6d7a3f6..2218043 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -156,6 +156,9 @@ static inline int mingw_unlink(const char *pathname)\n #define WNOHANG 1\n pid_t waitpid(pid_t pid, int *status, unsigned options);\n \n+#define kill mingw_kill\n+int mingw_kill(pid_t pid, int sig);\n+\n #ifndef NO_OPENSSL\n #include <openssl/ssl.h>\n static inline int mingw_SSL_set_fd(SSL *ssl, int fd)\n-- \n1.7.3.1.51.ge462f.dirty\n"},{"id":"153137","messageId":"1286716854-5744-9-git-send-email-kusmabite@gmail.com","threadId":"25410","inReplyTo":"1286716854-5744-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v3 08/14] daemon: use run-command api for async serving","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T13:20:48Z","receivedAt":"2010-10-10T13:20:48Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"fork() is only available on POSIX, so to support git-daemon\non Windows we have to use something else.\n\nInstead we invent the flag --serve, which is a stripped down\nversion of --inetd-mode. We use start_command() to call\ngit-daemon with this flag appended to serve clients.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n daemon.c |   86 +++++++++++++++++++++++++++++++-------------------------------\n 1 files changed, 43 insertions(+), 43 deletions(-)\n\ndiff --git a/daemon.c b/daemon.c\nindex d594375..ee29c9f 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -614,17 +614,17 @@ static unsigned int live_children;\n \n static struct child {\n \tstruct child *next;\n-\tpid_t pid;\n+\tstruct child_process cld;\n \tstruct sockaddr_storage address;\n } *firstborn;\n \n-static void add_child(pid_t pid, struct sockaddr *addr, int addrlen)\n+static void add_child(struct child_process *cld, struct sockaddr *addr, int addrlen)\n {\n \tstruct child *newborn, **cradle;\n \n \tnewborn = xcalloc(1, sizeof(*newborn));\n \tlive_children++;\n-\tnewborn->pid = pid;\n+\tmemcpy(&newborn->cld, cld, sizeof(*cld));\n \tmemcpy(&newborn->address, addr, addrlen);\n \tfor (cradle = &firstborn; *cradle; cradle = &(*cradle)->next)\n \t\tif (!addrcmp(&(*cradle)->address, &newborn->address))\n@@ -633,19 +633,6 @@ static void add_child(pid_t pid, struct sockaddr *addr, int addrlen)\n \t*cradle = newborn;\n }\n \n-static void remove_child(pid_t pid)\n-{\n-\tstruct child **cradle, *blanket;\n-\n-\tfor (cradle = &firstborn; (blanket = *cradle); cradle = &blanket->next)\n-\t\tif (blanket->pid == pid) {\n-\t\t\t*cradle = blanket->next;\n-\t\t\tlive_children--;\n-\t\t\tfree(blanket);\n-\t\t\tbreak;\n-\t\t}\n-}\n-\n /*\n  * This gets called if the number of connections grows\n  * past \"max_connections\".\n@@ -654,14 +641,14 @@ static void remove_child(pid_t pid)\n  */\n static void kill_some_child(void)\n {\n-\tconst struct child *blanket, *next;\n+\tstruct child *blanket, *next;\n \n \tif (!(blanket = firstborn))\n \t\treturn;\n \n \tfor (; (next = blanket->next); blanket = next)\n \t\tif (!addrcmp(&blanket->address, &next->address)) {\n-\t\t\tkill(blanket->pid, SIGTERM);\n+\t\t\tkill(blanket->cld.pid, SIGTERM);\n \t\t\tbreak;\n \t\t}\n }\n@@ -671,18 +658,26 @@ static void check_dead_children(void)\n \tint status;\n \tpid_t pid;\n \n-\twhile ((pid = waitpid(-1, &status, WNOHANG)) > 0) {\n-\t\tconst char *dead = \"\";\n-\t\tremove_child(pid);\n-\t\tif (!WIFEXITED(status) || (WEXITSTATUS(status) > 0))\n-\t\t\tdead = \" (with error)\";\n-\t\tloginfo(\"[%\"PRIuMAX\"] Disconnected%s\", (uintmax_t)pid, dead);\n-\t}\n+\tstruct child **cradle, *blanket;\n+\tfor (cradle = &firstborn; (blanket = *cradle);)\n+\t\tif ((pid = waitpid(blanket->cld.pid, &status, WNOHANG)) > 1) {\n+\t\t\tconst char *dead = \"\";\n+\t\t\tif (status)\n+\t\t\t\tdead = \" (with error)\";\n+\t\t\tloginfo(\"[%\"PRIuMAX\"] Disconnected%s\", (uintmax_t)pid, dead);\n+\n+\t\t\t/* remove the child */\n+\t\t\t*cradle = blanket->next;\n+\t\t\tlive_children--;\n+\t\t\tfree(blanket);\n+\t\t} else\n+\t\t\tcradle = &blanket->next;\n }\n \n+char **cld_argv;\n static void handle(int incoming, struct sockaddr *addr, int addrlen)\n {\n-\tpid_t pid;\n+\tstruct child_process cld = { 0 };\n \n \tif (max_connections && live_children >= max_connections) {\n \t\tkill_some_child();\n@@ -695,22 +690,15 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)\n \t\t}\n \t}\n \n-\tif ((pid = fork())) {\n-\t\tclose(incoming);\n-\t\tif (pid < 0) {\n-\t\t\tlogerror(\"Couldn't fork %s\", strerror(errno));\n-\t\t\treturn;\n-\t\t}\n-\n-\t\tadd_child(pid, addr, addrlen);\n-\t\treturn;\n-\t}\n+\tcld.argv = (const char **)cld_argv;\n+\tcld.in = incoming;\n+\tcld.out = dup(incoming);\n \n-\tdup2(incoming, 0);\n-\tdup2(incoming, 1);\n+\tif (start_command(&cld))\n+\t\tlogerror(\"unable to fork\");\n+\telse\n+\t\tadd_child(&cld, addr, addrlen);\n \tclose(incoming);\n-\n-\texit(execute(addr));\n }\n \n static void child_handler(int signo)\n@@ -991,7 +979,7 @@ int main(int argc, char **argv)\n {\n \tint listen_port = 0;\n \tstruct string_list listen_addr = STRING_LIST_INIT_NODUP;\n-\tint inetd_mode = 0;\n+\tint serve_mode = 0, inetd_mode = 0;\n \tconst char *pid_file = NULL, *user_name = NULL, *group_name = NULL;\n \tint detach = 0;\n \tstruct passwd *pass = NULL;\n@@ -1017,7 +1005,12 @@ int main(int argc, char **argv)\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t}\n+\t\tif (!strcmp(arg, \"--serve\")) {\n+\t\t\tserve_mode = 1;\n+\t\t\tcontinue;\n+\t\t}\n \t\tif (!strcmp(arg, \"--inetd\")) {\n+\t\t\tserve_mode = 1;\n \t\t\tinetd_mode = 1;\n \t\t\tlog_syslog = 1;\n \t\t\tcontinue;\n@@ -1161,12 +1154,12 @@ int main(int argc, char **argv)\n \t\tdie(\"base-path '%s' does not exist or is not a directory\",\n \t\t    base_path);\n \n-\tif (inetd_mode) {\n+\tif (serve_mode) {\n \t\tstruct sockaddr_storage ss;\n \t\tstruct sockaddr *peer = (struct sockaddr *)&ss;\n \t\tsocklen_t slen = sizeof(ss);\n \n-\t\tif (!freopen(\"/dev/null\", \"w\", stderr))\n+\t\tif (inetd_mode && !freopen(\"/dev/null\", \"w\", stderr))\n \t\t\tdie_errno(\"failed to redirect stderr to /dev/null\");\n \n \t\tif (getpeername(0, peer, &slen))\n@@ -1185,5 +1178,12 @@ int main(int argc, char **argv)\n \tif (pid_file)\n \t\tstore_pid(pid_file);\n \n+\t/* prepare argv for serving-processes */\n+\tcld_argv = xmalloc(sizeof (char *) * (argc + 2));\n+\tfor (i = 0; i < argc; ++i)\n+\t\tcld_argv[i] = argv[i];\n+\tcld_argv[argc] = \"--serve\";\n+\tcld_argv[argc+1] = NULL;\n+\n \treturn serve(&listen_addr, listen_port, pass, gid);\n }\n-- \n1.7.3.1.51.ge462f.dirty\n"},{"id":"153139","messageId":"1286716854-5744-10-git-send-email-kusmabite@gmail.com","threadId":"25410","inReplyTo":"1286716854-5744-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v3 09/14] daemon: use full buffered mode for stderr","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T13:20:49Z","receivedAt":"2010-10-10T13:20:49Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Windows doesn't support line buffered mode for file\nstreams, so let's just use full buffered mode with\na big buffer (\"4096 should be enough for everyone\")\nand add explicit flushing.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n daemon.c |    6 ++++--\n 1 files changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/daemon.c b/daemon.c\nindex ee29c9f..82ba5c7 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -67,12 +67,14 @@ static void logreport(int priority, const char *err, va_list params)\n \t\tsyslog(priority, \"%s\", buf);\n \t} else {\n \t\t/*\n-\t\t * Since stderr is set to linebuffered mode, the\n+\t\t * Since stderr is set to buffered mode, the\n \t\t * logging of different processes will not overlap\n+\t\t * unless they overflow the (rather big) buffers.\n \t\t */\n \t\tfprintf(stderr, \"[%\"PRIuMAX\"] \", (uintmax_t)getpid());\n \t\tvfprintf(stderr, err, params);\n \t\tfputc('\\n', stderr);\n+\t\tfflush(stderr);\n \t}\n }\n \n@@ -1118,7 +1120,7 @@ int main(int argc, char **argv)\n \t\tset_die_routine(daemon_die);\n \t} else\n \t\t/* avoid splitting a message in the middle */\n-\t\tsetvbuf(stderr, NULL, _IOLBF, 0);\n+\t\tsetvbuf(stderr, NULL, _IOFBF, 4096);\n \n \tif (inetd_mode && (group_name || user_name))\n \t\tdie(\"--user and --group are incompatible with --inetd\");\n-- \n1.7.3.1.51.ge462f.dirty\n"},{"id":"153140","messageId":"1286716854-5744-11-git-send-email-kusmabite@gmail.com","threadId":"25410","inReplyTo":"1286716854-5744-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v3 10/14] Improve the mingw getaddrinfo stub to handle more use cases","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T13:20:50Z","receivedAt":"2010-10-10T13:20:50Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"From: Martin Storsjö <martin@martin.st>\n\nAllow the node parameter to be null, which is used for getting\nthe default bind address.\n\nAlso allow the hints parameter to be null, to improve standard\nconformance of the stub implementation a little.\n\nSigned-off-by: Martin Storsjo <martin@martin.st>\n---\n compat/mingw.c |   28 +++++++++++++++++++++-------\n 1 files changed, 21 insertions(+), 7 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 44ea419..32ca664 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1035,19 +1035,22 @@ static int WSAAPI getaddrinfo_stub(const char *node, const char *service,\n \t\t\t\t   const struct addrinfo *hints,\n \t\t\t\t   struct addrinfo **res)\n {\n-\tstruct hostent *h = gethostbyname(node);\n+\tstruct hostent *h = NULL;\n \tstruct addrinfo *ai;\n \tstruct sockaddr_in *sin;\n \n-\tif (!h)\n-\t\treturn WSAGetLastError();\n+\tif (node) {\n+\t\th = gethostbyname(node);\n+\t\tif (!h)\n+\t\t\treturn WSAGetLastError();\n+\t}\n \n \tai = xmalloc(sizeof(struct addrinfo));\n \t*res = ai;\n \tai->ai_flags = 0;\n \tai->ai_family = AF_INET;\n-\tai->ai_socktype = hints->ai_socktype;\n-\tswitch (hints->ai_socktype) {\n+\tai->ai_socktype = hints ? hints->ai_socktype : 0;\n+\tswitch (ai->ai_socktype) {\n \tcase SOCK_STREAM:\n \t\tai->ai_protocol = IPPROTO_TCP;\n \t\tbreak;\n@@ -1059,14 +1062,25 @@ static int WSAAPI getaddrinfo_stub(const char *node, const char *service,\n \t\tbreak;\n \t}\n \tai->ai_addrlen = sizeof(struct sockaddr_in);\n-\tai->ai_canonname = strdup(h->h_name);\n+\tif (hints && (hints->ai_flags & AI_CANONNAME))\n+\t\tai->ai_canonname = h ? strdup(h->h_name) : NULL;\n+\telse\n+\t\tai->ai_canonname = NULL;\n \n \tsin = xmalloc(ai->ai_addrlen);\n \tmemset(sin, 0, ai->ai_addrlen);\n \tsin->sin_family = AF_INET;\n+\t/* Note: getaddrinfo is supposed to allow service to be a string,\n+\t * which should be looked up using getservbyname. This is\n+\t * currently not implemented */\n \tif (service)\n \t\tsin->sin_port = htons(atoi(service));\n-\tsin->sin_addr = *(struct in_addr *)h->h_addr;\n+\tif (h)\n+\t\tsin->sin_addr = *(struct in_addr *)h->h_addr;\n+\telse if (hints && (hints->ai_flags & AI_PASSIVE))\n+\t\tsin->sin_addr.s_addr = INADDR_ANY;\n+\telse\n+\t\tsin->sin_addr.s_addr = INADDR_LOOPBACK;\n \tai->ai_addr = (struct sockaddr *)sin;\n \tai->ai_next = 0;\n \treturn 0;\n-- \n1.7.3.1.51.ge462f.dirty\n"},{"id":"153141","messageId":"1286716854-5744-12-git-send-email-kusmabite@gmail.com","threadId":"25410","inReplyTo":"1286716854-5744-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v3 11/14] daemon: report connection from root-process","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T13:20:51Z","receivedAt":"2010-10-10T13:20:51Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Report incoming connections from the process that\naccept() the connection instead of the handling\nprocess.\n\nThis enables \"Connection from\"-reporting on\nWindows, where getpeername(0, ...) consistently\nfails.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n daemon.c |   70 +++++++++++++++++++++++++++++++++++--------------------------\n 1 files changed, 40 insertions(+), 30 deletions(-)\n\ndiff --git a/daemon.c b/daemon.c\nindex 82ba5c7..54bbec2 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -521,33 +521,6 @@ static int execute(struct sockaddr *addr)\n \tstatic char line[1000];\n \tint pktlen, len, i;\n \n-\tif (addr) {\n-\t\tchar addrbuf[256] = \"\";\n-\t\tint port = -1;\n-\n-\t\tif (addr->sa_family == AF_INET) {\n-\t\t\tstruct sockaddr_in *sin_addr = (void *) addr;\n-\t\t\tinet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf));\n-\t\t\tport = ntohs(sin_addr->sin_port);\n-#ifndef NO_IPV6\n-\t\t} else if (addr && addr->sa_family == AF_INET6) {\n-\t\t\tstruct sockaddr_in6 *sin6_addr = (void *) addr;\n-\n-\t\t\tchar *buf = addrbuf;\n-\t\t\t*buf++ = '['; *buf = '\\0'; /* stpcpy() is cool */\n-\t\t\tinet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1);\n-\t\t\tstrcat(buf, \"]\");\n-\n-\t\t\tport = ntohs(sin6_addr->sin6_port);\n-#endif\n-\t\t}\n-\t\tloginfo(\"Connection from %s:%d\", addrbuf, port);\n-\t\tsetenv(\"REMOTE_ADDR\", addrbuf, 1);\n-\t}\n-\telse {\n-\t\tunsetenv(\"REMOTE_ADDR\");\n-\t}\n-\n \talarm(init_timeout ? init_timeout : timeout);\n \tpktlen = packet_read_line(0, line, sizeof(line));\n \talarm(0);\n@@ -676,10 +649,35 @@ static void check_dead_children(void)\n \t\t\tcradle = &blanket->next;\n }\n \n+static char *get_addrstr(int *port, struct sockaddr *addr)\n+{\n+\tstatic char addrbuf[256] = \"\";\n+\tif (addr->sa_family == AF_INET) {\n+\t\tstruct sockaddr_in *sin_addr = (void *) addr;\n+\t\tinet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf));\n+\t\t*port = ntohs(sin_addr->sin_port);\n+#ifndef NO_IPV6\n+\t} else if (addr && addr->sa_family == AF_INET6) {\n+\t\tstruct sockaddr_in6 *sin6_addr = (void *) addr;\n+\n+\t\tchar *buf = addrbuf;\n+\t\t*buf++ = '['; *buf = '\\0'; /* stpcpy() is cool */\n+\t\tinet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1);\n+\t\tstrcat(buf, \"]\");\n+\n+\t\t*port = ntohs(sin6_addr->sin6_port);\n+#endif\n+\t}\n+\treturn addrbuf;\n+}\n+\n char **cld_argv;\n static void handle(int incoming, struct sockaddr *addr, int addrlen)\n {\n \tstruct child_process cld = { 0 };\n+\tchar *addrstr, envbuf[300] = \"REMOTE_ADDR=\";\n+\tchar *env[] = { envbuf, NULL };\n+\tint port = -1;\n \n \tif (max_connections && live_children >= max_connections) {\n \t\tkill_some_child();\n@@ -692,14 +690,21 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)\n \t\t}\n \t}\n \n+\taddrstr = get_addrstr(&port, addr);\n+\tstrcat(envbuf, addrstr);\n+\n+\tcld.env = (const char **)env;\n \tcld.argv = (const char **)cld_argv;\n \tcld.in = incoming;\n \tcld.out = dup(incoming);\n \n \tif (start_command(&cld))\n \t\tlogerror(\"unable to fork\");\n-\telse\n+\telse {\n+\t\tloginfo(\"[%\"PRIuMAX\"] Connection from %s:%d\",\n+\t\t    (uintmax_t)cld.pid, addrstr, port);\n \t\tadd_child(&cld, addr, addrlen);\n+\t}\n \tclose(incoming);\n }\n \n@@ -1164,8 +1169,13 @@ int main(int argc, char **argv)\n \t\tif (inetd_mode && !freopen(\"/dev/null\", \"w\", stderr))\n \t\t\tdie_errno(\"failed to redirect stderr to /dev/null\");\n \n-\t\tif (getpeername(0, peer, &slen))\n-\t\t\tpeer = NULL;\n+\t\tif (!getpeername(0, peer, &slen)) {\n+\t\t\tint port = -1;\n+\t\t\tchar *addrstr = get_addrstr(&port, peer);\n+\t\t\tsetenv(\"REMOTE_ADDR\", addrstr, 1);\n+\t\t\tloginfo(\"[%\"PRIuMAX\"] Connection from %s:%d\",\n+\t\t\t    (uintmax_t)getpid(), addrstr, port);\n+\t\t}\n \n \t\treturn execute(peer);\n \t}\n-- \n1.7.3.1.51.ge462f.dirty\n"},{"id":"153143","messageId":"1286716854-5744-13-git-send-email-kusmabite@gmail.com","threadId":"25410","inReplyTo":"1286716854-5744-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v3 12/14] mingw: import poll-emulation from gnulib","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T13:20:52Z","receivedAt":"2010-10-10T13:20:52Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"lib/poll.c and lib/poll.in.h imported from 0a05120 in\ngit://git.savannah.gnu.org/gnulib.git\n---\n compat/win32/poll.c |  597 +++++++++++++++++++++++++++++++++++++++++++++++++++\n compat/win32/poll.h |   53 +++++\n 2 files changed, 650 insertions(+), 0 deletions(-)\n create mode 100644 compat/win32/poll.c\n create mode 100644 compat/win32/poll.h\n\ndiff --git a/compat/win32/poll.c b/compat/win32/poll.c\nnew file mode 100644\nindex 0000000..7c52cb6\n--- /dev/null\n+++ b/compat/win32/poll.c\n@@ -0,0 +1,597 @@\n+/* Emulation for poll(2)\n+   Contributed by Paolo Bonzini.\n+\n+   Copyright 2001-2003, 2006-2010 Free Software Foundation, Inc.\n+\n+   This file is part of gnulib.\n+\n+   This program is free software; you can redistribute it and/or modify\n+   it under the terms of the GNU General Public License as published by\n+   the Free Software Foundation; either version 2, or (at your option)\n+   any later version.\n+\n+   This program is distributed in the hope that it will be useful,\n+   but WITHOUT ANY WARRANTY; without even the implied warranty of\n+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+   GNU General Public License for more details.\n+\n+   You should have received a copy of the GNU General Public License along\n+   with this program; if not, write to the Free Software Foundation,\n+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */\n+\n+/* Tell gcc not to warn about the (nfd < 0) tests, below.  */\n+#if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__\n+# pragma GCC diagnostic ignored \"-Wtype-limits\"\n+#endif\n+\n+#include <config.h>\n+#include <alloca.h>\n+\n+#include <sys/types.h>\n+#include \"poll.h\"\n+#include <errno.h>\n+#include <limits.h>\n+#include <assert.h>\n+\n+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__\n+# define WIN32_NATIVE\n+# include <winsock2.h>\n+# include <windows.h>\n+# include <io.h>\n+# include <stdio.h>\n+# include <conio.h>\n+#else\n+# include <sys/time.h>\n+# include <sys/socket.h>\n+# include <sys/select.h>\n+# include <unistd.h>\n+#endif\n+\n+#ifdef HAVE_SYS_IOCTL_H\n+# include <sys/ioctl.h>\n+#endif\n+#ifdef HAVE_SYS_FILIO_H\n+# include <sys/filio.h>\n+#endif\n+\n+#include <time.h>\n+\n+#ifndef INFTIM\n+# define INFTIM (-1)\n+#endif\n+\n+/* BeOS does not have MSG_PEEK.  */\n+#ifndef MSG_PEEK\n+# define MSG_PEEK 0\n+#endif\n+\n+#ifdef WIN32_NATIVE\n+\n+#define IsConsoleHandle(h) (((long) (h) & 3) == 3)\n+\n+static BOOL\n+IsSocketHandle (HANDLE h)\n+{\n+  WSANETWORKEVENTS ev;\n+\n+  if (IsConsoleHandle (h))\n+    return FALSE;\n+\n+  /* Under Wine, it seems that getsockopt returns 0 for pipes too.\n+     WSAEnumNetworkEvents instead distinguishes the two correctly.  */\n+  ev.lNetworkEvents = 0xDEADBEEF;\n+  WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);\n+  return ev.lNetworkEvents != 0xDEADBEEF;\n+}\n+\n+/* Declare data structures for ntdll functions.  */\n+typedef struct _FILE_PIPE_LOCAL_INFORMATION {\n+  ULONG NamedPipeType;\n+  ULONG NamedPipeConfiguration;\n+  ULONG MaximumInstances;\n+  ULONG CurrentInstances;\n+  ULONG InboundQuota;\n+  ULONG ReadDataAvailable;\n+  ULONG OutboundQuota;\n+  ULONG WriteQuotaAvailable;\n+  ULONG NamedPipeState;\n+  ULONG NamedPipeEnd;\n+} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;\n+\n+typedef struct _IO_STATUS_BLOCK\n+{\n+  union {\n+    DWORD Status;\n+    PVOID Pointer;\n+  } u;\n+  ULONG_PTR Information;\n+} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;\n+\n+typedef enum _FILE_INFORMATION_CLASS {\n+  FilePipeLocalInformation = 24\n+} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;\n+\n+typedef DWORD (WINAPI *PNtQueryInformationFile)\n+         (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);\n+\n+# ifndef PIPE_BUF\n+#  define PIPE_BUF      512\n+# endif\n+\n+/* Compute revents values for file handle H.  If some events cannot happen\n+   for the handle, eliminate them from *P_SOUGHT.  */\n+\n+static int\n+win32_compute_revents (HANDLE h, int *p_sought)\n+{\n+  int i, ret, happened;\n+  INPUT_RECORD *irbuffer;\n+  DWORD avail, nbuffer;\n+  BOOL bRet;\n+  IO_STATUS_BLOCK iosb;\n+  FILE_PIPE_LOCAL_INFORMATION fpli;\n+  static PNtQueryInformationFile NtQueryInformationFile;\n+  static BOOL once_only;\n+\n+  switch (GetFileType (h))\n+    {\n+    case FILE_TYPE_PIPE:\n+      if (!once_only)\n+        {\n+          NtQueryInformationFile = (PNtQueryInformationFile)\n+            GetProcAddress (GetModuleHandle (\"ntdll.dll\"),\n+                            \"NtQueryInformationFile\");\n+          once_only = TRUE;\n+        }\n+\n+      happened = 0;\n+      if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)\n+        {\n+          if (avail)\n+            happened |= *p_sought & (POLLIN | POLLRDNORM);\n+        }\n+      else if (GetLastError () == ERROR_BROKEN_PIPE)\n+        happened |= POLLHUP;\n+\n+      else\n+        {\n+          /* It was the write-end of the pipe.  Check if it is writable.\n+             If NtQueryInformationFile fails, optimistically assume the pipe is\n+             writable.  This could happen on Win9x, where NtQueryInformationFile\n+             is not available, or if we inherit a pipe that doesn't permit\n+             FILE_READ_ATTRIBUTES access on the write end (I think this should\n+             not happen since WinXP SP2; WINE seems fine too).  Otherwise,\n+             ensure that enough space is available for atomic writes.  */\n+          memset (&iosb, 0, sizeof (iosb));\n+          memset (&fpli, 0, sizeof (fpli));\n+\n+          if (!NtQueryInformationFile\n+              || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),\n+                                         FilePipeLocalInformation)\n+              || fpli.WriteQuotaAvailable >= PIPE_BUF\n+              || (fpli.OutboundQuota < PIPE_BUF &&\n+                  fpli.WriteQuotaAvailable == fpli.OutboundQuota))\n+            happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);\n+        }\n+      return happened;\n+\n+    case FILE_TYPE_CHAR:\n+      ret = WaitForSingleObject (h, 0);\n+      if (!IsConsoleHandle (h))\n+        return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;\n+\n+      nbuffer = avail = 0;\n+      bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);\n+      if (bRet)\n+        {\n+          /* Input buffer.  */\n+          *p_sought &= POLLIN | POLLRDNORM;\n+          if (nbuffer == 0)\n+            return POLLHUP;\n+          if (!*p_sought)\n+            return 0;\n+\n+          irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));\n+          bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);\n+          if (!bRet || avail == 0)\n+            return POLLHUP;\n+\n+          for (i = 0; i < avail; i++)\n+            if (irbuffer[i].EventType == KEY_EVENT)\n+              return *p_sought;\n+          return 0;\n+        }\n+      else\n+        {\n+          /* Screen buffer.  */\n+          *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;\n+          return *p_sought;\n+        }\n+\n+    default:\n+      ret = WaitForSingleObject (h, 0);\n+      if (ret == WAIT_OBJECT_0)\n+        return *p_sought & ~(POLLPRI | POLLRDBAND);\n+\n+      return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);\n+    }\n+}\n+\n+/* Convert fd_sets returned by select into revents values.  */\n+\n+static int\n+win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)\n+{\n+  int happened = 0;\n+\n+  if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)\n+    happened |= (POLLIN | POLLRDNORM) & sought;\n+\n+  else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))\n+    {\n+      int r, error;\n+\n+      char data[64];\n+      WSASetLastError (0);\n+      r = recv (h, data, sizeof (data), MSG_PEEK);\n+      error = WSAGetLastError ();\n+      WSASetLastError (0);\n+\n+      if (r > 0 || error == WSAENOTCONN)\n+        happened |= (POLLIN | POLLRDNORM) & sought;\n+\n+      /* Distinguish hung-up sockets from other errors.  */\n+      else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET\n+               || error == WSAECONNABORTED || error == WSAENETRESET)\n+        happened |= POLLHUP;\n+\n+      else\n+        happened |= POLLERR;\n+    }\n+\n+  if (lNetworkEvents & (FD_WRITE | FD_CONNECT))\n+    happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;\n+\n+  if (lNetworkEvents & FD_OOB)\n+    happened |= (POLLPRI | POLLRDBAND) & sought;\n+\n+  return happened;\n+}\n+\n+#else /* !MinGW */\n+\n+/* Convert select(2) returned fd_sets into poll(2) revents values.  */\n+static int\n+compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)\n+{\n+  int happened = 0;\n+  if (FD_ISSET (fd, rfds))\n+    {\n+      int r;\n+      int socket_errno;\n+\n+# if defined __MACH__ && defined __APPLE__\n+      /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK\n+         for some kinds of descriptors.  Detect if this descriptor is a\n+         connected socket, a server socket, or something else using a\n+         0-byte recv, and use ioctl(2) to detect POLLHUP.  */\n+      r = recv (fd, NULL, 0, MSG_PEEK);\n+      socket_errno = (r < 0) ? errno : 0;\n+      if (r == 0 || socket_errno == ENOTSOCK)\n+        ioctl (fd, FIONREAD, &r);\n+# else\n+      char data[64];\n+      r = recv (fd, data, sizeof (data), MSG_PEEK);\n+      socket_errno = (r < 0) ? errno : 0;\n+# endif\n+      if (r == 0)\n+        happened |= POLLHUP;\n+\n+      /* If the event happened on an unconnected server socket,\n+         that's fine. */\n+      else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))\n+        happened |= (POLLIN | POLLRDNORM) & sought;\n+\n+      /* Distinguish hung-up sockets from other errors.  */\n+      else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET\n+               || socket_errno == ECONNABORTED || socket_errno == ENETRESET)\n+        happened |= POLLHUP;\n+\n+      else\n+        happened |= POLLERR;\n+    }\n+\n+  if (FD_ISSET (fd, wfds))\n+    happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;\n+\n+  if (FD_ISSET (fd, efds))\n+    happened |= (POLLPRI | POLLRDBAND) & sought;\n+\n+  return happened;\n+}\n+#endif /* !MinGW */\n+\n+int\n+poll (pfd, nfd, timeout)\n+     struct pollfd *pfd;\n+     nfds_t nfd;\n+     int timeout;\n+{\n+#ifndef WIN32_NATIVE\n+  fd_set rfds, wfds, efds;\n+  struct timeval tv;\n+  struct timeval *ptv;\n+  int maxfd, rc;\n+  nfds_t i;\n+\n+# ifdef _SC_OPEN_MAX\n+  static int sc_open_max = -1;\n+\n+  if (nfd < 0\n+      || (nfd > sc_open_max\n+          && (sc_open_max != -1\n+              || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))\n+    {\n+      errno = EINVAL;\n+      return -1;\n+    }\n+# else /* !_SC_OPEN_MAX */\n+#  ifdef OPEN_MAX\n+  if (nfd < 0 || nfd > OPEN_MAX)\n+    {\n+      errno = EINVAL;\n+      return -1;\n+    }\n+#  endif /* OPEN_MAX -- else, no check is needed */\n+# endif /* !_SC_OPEN_MAX */\n+\n+  /* EFAULT is not necessary to implement, but let's do it in the\n+     simplest case. */\n+  if (!pfd)\n+    {\n+      errno = EFAULT;\n+      return -1;\n+    }\n+\n+  /* convert timeout number into a timeval structure */\n+  if (timeout == 0)\n+    {\n+      ptv = &tv;\n+      ptv->tv_sec = 0;\n+      ptv->tv_usec = 0;\n+    }\n+  else if (timeout > 0)\n+    {\n+      ptv = &tv;\n+      ptv->tv_sec = timeout / 1000;\n+      ptv->tv_usec = (timeout % 1000) * 1000;\n+    }\n+  else if (timeout == INFTIM)\n+    /* wait forever */\n+    ptv = NULL;\n+  else\n+    {\n+      errno = EINVAL;\n+      return -1;\n+    }\n+\n+  /* create fd sets and determine max fd */\n+  maxfd = -1;\n+  FD_ZERO (&rfds);\n+  FD_ZERO (&wfds);\n+  FD_ZERO (&efds);\n+  for (i = 0; i < nfd; i++)\n+    {\n+      if (pfd[i].fd < 0)\n+        continue;\n+\n+      if (pfd[i].events & (POLLIN | POLLRDNORM))\n+        FD_SET (pfd[i].fd, &rfds);\n+\n+      /* see select(2): \"the only exceptional condition detectable\n+         is out-of-band data received on a socket\", hence we push\n+         POLLWRBAND events onto wfds instead of efds. */\n+      if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))\n+        FD_SET (pfd[i].fd, &wfds);\n+      if (pfd[i].events & (POLLPRI | POLLRDBAND))\n+        FD_SET (pfd[i].fd, &efds);\n+      if (pfd[i].fd >= maxfd\n+          && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI\n+                               | POLLRDNORM | POLLRDBAND\n+                               | POLLWRNORM | POLLWRBAND)))\n+        {\n+          maxfd = pfd[i].fd;\n+          if (maxfd > FD_SETSIZE)\n+            {\n+              errno = EOVERFLOW;\n+              return -1;\n+            }\n+        }\n+    }\n+\n+  /* examine fd sets */\n+  rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);\n+  if (rc < 0)\n+    return rc;\n+\n+  /* establish results */\n+  rc = 0;\n+  for (i = 0; i < nfd; i++)\n+    if (pfd[i].fd < 0)\n+      pfd[i].revents = 0;\n+    else\n+      {\n+        int happened = compute_revents (pfd[i].fd, pfd[i].events,\n+                                        &rfds, &wfds, &efds);\n+        if (happened)\n+          {\n+            pfd[i].revents = happened;\n+            rc++;\n+          }\n+      }\n+\n+  return rc;\n+#else\n+  static struct timeval tv0;\n+  static HANDLE hEvent;\n+  WSANETWORKEVENTS ev;\n+  HANDLE h, handle_array[FD_SETSIZE + 2];\n+  DWORD ret, wait_timeout, nhandles;\n+  fd_set rfds, wfds, xfds;\n+  BOOL poll_again;\n+  MSG msg;\n+  int rc = 0;\n+  nfds_t i;\n+\n+  if (nfd < 0 || timeout < -1)\n+    {\n+      errno = EINVAL;\n+      return -1;\n+    }\n+\n+  if (!hEvent)\n+    hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);\n+\n+  handle_array[0] = hEvent;\n+  nhandles = 1;\n+  FD_ZERO (&rfds);\n+  FD_ZERO (&wfds);\n+  FD_ZERO (&xfds);\n+\n+  /* Classify socket handles and create fd sets. */\n+  for (i = 0; i < nfd; i++)\n+    {\n+      int sought = pfd[i].events;\n+      pfd[i].revents = 0;\n+      if (pfd[i].fd < 0)\n+        continue;\n+      if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND\n+                      | POLLPRI | POLLRDBAND)))\n+        continue;\n+\n+      h = (HANDLE) _get_osfhandle (pfd[i].fd);\n+      assert (h != NULL);\n+      if (IsSocketHandle (h))\n+        {\n+          int requested = FD_CLOSE;\n+\n+          /* see above; socket handles are mapped onto select.  */\n+          if (sought & (POLLIN | POLLRDNORM))\n+            {\n+              requested |= FD_READ | FD_ACCEPT;\n+              FD_SET ((SOCKET) h, &rfds);\n+            }\n+          if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))\n+            {\n+              requested |= FD_WRITE | FD_CONNECT;\n+              FD_SET ((SOCKET) h, &wfds);\n+            }\n+          if (sought & (POLLPRI | POLLRDBAND))\n+            {\n+              requested |= FD_OOB;\n+              FD_SET ((SOCKET) h, &xfds);\n+            }\n+\n+          if (requested)\n+            WSAEventSelect ((SOCKET) h, hEvent, requested);\n+        }\n+      else\n+        {\n+          /* Poll now.  If we get an event, do not poll again.  Also,\n+             screen buffer handles are waitable, and they'll block until\n+             a character is available.  win32_compute_revents eliminates\n+             bits for the \"wrong\" direction. */\n+          pfd[i].revents = win32_compute_revents (h, &sought);\n+          if (sought)\n+            handle_array[nhandles++] = h;\n+          if (pfd[i].revents)\n+            timeout = 0;\n+        }\n+    }\n+\n+  if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)\n+    {\n+      /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but\n+         no need to call select again.  */\n+      poll_again = FALSE;\n+      wait_timeout = 0;\n+    }\n+  else\n+    {\n+      poll_again = TRUE;\n+      if (timeout == INFTIM)\n+        wait_timeout = INFINITE;\n+      else\n+        wait_timeout = timeout;\n+    }\n+\n+  for (;;)\n+    {\n+      ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,\n+                                       wait_timeout, QS_ALLINPUT);\n+\n+      if (ret == WAIT_OBJECT_0 + nhandles)\n+        {\n+          /* new input of some other kind */\n+          BOOL bRet;\n+          while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)\n+            {\n+              TranslateMessage (&msg);\n+              DispatchMessage (&msg);\n+            }\n+        }\n+      else\n+        break;\n+    }\n+\n+  if (poll_again)\n+    select (0, &rfds, &wfds, &xfds, &tv0);\n+\n+  /* Place a sentinel at the end of the array.  */\n+  handle_array[nhandles] = NULL;\n+  nhandles = 1;\n+  for (i = 0; i < nfd; i++)\n+    {\n+      int happened;\n+\n+      if (pfd[i].fd < 0)\n+        continue;\n+      if (!(pfd[i].events & (POLLIN | POLLRDNORM |\n+                             POLLOUT | POLLWRNORM | POLLWRBAND)))\n+        continue;\n+\n+      h = (HANDLE) _get_osfhandle (pfd[i].fd);\n+      if (h != handle_array[nhandles])\n+        {\n+          /* It's a socket.  */\n+          WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);\n+          WSAEventSelect ((SOCKET) h, 0, 0);\n+\n+          /* If we're lucky, WSAEnumNetworkEvents already provided a way\n+             to distinguish FD_READ and FD_ACCEPT; this saves a recv later.  */\n+          if (FD_ISSET ((SOCKET) h, &rfds)\n+              && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))\n+            ev.lNetworkEvents |= FD_READ | FD_ACCEPT;\n+          if (FD_ISSET ((SOCKET) h, &wfds))\n+            ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;\n+          if (FD_ISSET ((SOCKET) h, &xfds))\n+            ev.lNetworkEvents |= FD_OOB;\n+\n+          happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,\n+                                                   ev.lNetworkEvents);\n+        }\n+      else\n+        {\n+          /* Not a socket.  */\n+          int sought = pfd[i].events;\n+          happened = win32_compute_revents (h, &sought);\n+          nhandles++;\n+        }\n+\n+       if ((pfd[i].revents |= happened) != 0)\n+        rc++;\n+    }\n+\n+  return rc;\n+#endif\n+}\ndiff --git a/compat/win32/poll.h b/compat/win32/poll.h\nnew file mode 100644\nindex 0000000..b7aa59d\n--- /dev/null\n+++ b/compat/win32/poll.h\n@@ -0,0 +1,53 @@\n+/* Header for poll(2) emulation\n+   Contributed by Paolo Bonzini.\n+\n+   Copyright 2001, 2002, 2003, 2007, 2009, 2010 Free Software Foundation, Inc.\n+\n+   This file is part of gnulib.\n+\n+   This program is free software; you can redistribute it and/or modify\n+   it under the terms of the GNU General Public License as published by\n+   the Free Software Foundation; either version 2, or (at your option)\n+   any later version.\n+\n+   This program is distributed in the hope that it will be useful,\n+   but WITHOUT ANY WARRANTY; without even the implied warranty of\n+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+   GNU General Public License for more details.\n+\n+   You should have received a copy of the GNU General Public License along\n+   with this program; if not, write to the Free Software Foundation,\n+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */\n+\n+#ifndef _GL_POLL_H\n+#define _GL_POLL_H\n+\n+/* fake a poll(2) environment */\n+#define POLLIN      0x0001      /* any readable data available   */\n+#define POLLPRI     0x0002      /* OOB/Urgent readable data      */\n+#define POLLOUT     0x0004      /* file descriptor is writeable  */\n+#define POLLERR     0x0008      /* some poll error occurred      */\n+#define POLLHUP     0x0010      /* file descriptor was \"hung up\" */\n+#define POLLNVAL    0x0020      /* requested events \"invalid\"    */\n+#define POLLRDNORM  0x0040\n+#define POLLRDBAND  0x0080\n+#define POLLWRNORM  0x0100\n+#define POLLWRBAND  0x0200\n+\n+struct pollfd\n+{\n+  int fd;                       /* which file descriptor to poll */\n+  short events;                 /* events we are interested in   */\n+  short revents;                /* events found on return        */\n+};\n+\n+typedef unsigned long nfds_t;\n+\n+extern int poll (struct pollfd *pfd, nfds_t nfd, int timeout);\n+\n+/* Define INFTIM only if doing so conforms to POSIX.  */\n+#if !defined (_POSIX_C_SOURCE) && !defined (_XOPEN_SOURCE)\n+#define INFTIM (-1)\n+#endif\n+\n+#endif /* _GL_POLL_H */\n-- \n1.7.3.1.51.ge462f.dirty\n"},{"id":"153142","messageId":"1286716854-5744-14-git-send-email-kusmabite@gmail.com","threadId":"25410","inReplyTo":"1286716854-5744-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v3 13/14] mingw: use poll-emulation from gnulib","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T13:20:53Z","receivedAt":"2010-10-10T13:20:53Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n Makefile            |    2 +-\n compat/mingw.c      |   65 ---------------------------------------------------\n compat/mingw.h      |   11 --------\n compat/win32/poll.c |    3 +-\n git-compat-util.h   |    1 +\n 5 files changed, 3 insertions(+), 79 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex ebb51e3..42baa4d 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1131,7 +1131,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tCOMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch -Icompat/win32\n \tCOMPAT_CFLAGS += -DSTRIP_EXTENSION=\\\".exe\\\"\n \tCOMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o \\\n-\t\tcompat/win32/pthread.o\n+\t\tcompat/win32/pthread.o compat/win32/poll.o\n \tEXTLIBS += -lws2_32\n \tPTHREAD_LIBS =\n \tX = .exe\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 32ca664..bbe45d0 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -408,71 +408,6 @@ int pipe(int filedes[2])\n \treturn 0;\n }\n \n-int poll(struct pollfd *ufds, unsigned int nfds, int timeout)\n-{\n-\tint i, pending;\n-\n-\tif (timeout >= 0) {\n-\t\tif (nfds == 0) {\n-\t\t\tSleep(timeout);\n-\t\t\treturn 0;\n-\t\t}\n-\t\treturn errno = EINVAL, error(\"poll timeout not supported\");\n-\t}\n-\n-\t/* When there is only one fd to wait for, then we pretend that\n-\t * input is available and let the actual wait happen when the\n-\t * caller invokes read().\n-\t */\n-\tif (nfds == 1) {\n-\t\tif (!(ufds[0].events & POLLIN))\n-\t\t\treturn errno = EINVAL, error(\"POLLIN not set\");\n-\t\tufds[0].revents = POLLIN;\n-\t\treturn 0;\n-\t}\n-\n-repeat:\n-\tpending = 0;\n-\tfor (i = 0; i < nfds; i++) {\n-\t\tDWORD avail = 0;\n-\t\tHANDLE h = (HANDLE) _get_osfhandle(ufds[i].fd);\n-\t\tif (h == INVALID_HANDLE_VALUE)\n-\t\t\treturn -1;\t/* errno was set */\n-\n-\t\tif (!(ufds[i].events & POLLIN))\n-\t\t\treturn errno = EINVAL, error(\"POLLIN not set\");\n-\n-\t\t/* this emulation works only for pipes */\n-\t\tif (!PeekNamedPipe(h, NULL, 0, NULL, &avail, NULL)) {\n-\t\t\tint err = GetLastError();\n-\t\t\tif (err == ERROR_BROKEN_PIPE) {\n-\t\t\t\tufds[i].revents = POLLHUP;\n-\t\t\t\tpending++;\n-\t\t\t} else {\n-\t\t\t\terrno = EINVAL;\n-\t\t\t\treturn error(\"PeekNamedPipe failed,\"\n-\t\t\t\t\t\" GetLastError: %u\", err);\n-\t\t\t}\n-\t\t} else if (avail) {\n-\t\t\tufds[i].revents = POLLIN;\n-\t\t\tpending++;\n-\t\t} else\n-\t\t\tufds[i].revents = 0;\n-\t}\n-\tif (!pending) {\n-\t\t/* The only times that we spin here is when the process\n-\t\t * that is connected through the pipes is waiting for\n-\t\t * its own input data to become available. But since\n-\t\t * the process (pack-objects) is itself CPU intensive,\n-\t\t * it will happily pick up the time slice that we are\n-\t\t * relinquishing here.\n-\t\t */\n-\t\tSleep(0);\n-\t\tgoto repeat;\n-\t}\n-\treturn 0;\n-}\n-\n struct tm *gmtime_r(const time_t *timep, struct tm *result)\n {\n \t/* gmtime() in MSVCRT.DLL is thread-safe, but not reentrant */\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex 2218043..aed49d8 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -72,16 +72,6 @@ struct passwd {\n \n extern char *getpass(const char *prompt);\n \n-#ifndef POLLIN\n-struct pollfd {\n-\tint fd;           /* file descriptor */\n-\tshort events;     /* requested events */\n-\tshort revents;    /* returned events */\n-};\n-#define POLLIN 1\n-#define POLLHUP 2\n-#endif\n-\n typedef void (__cdecl *sig_handler_t)(int);\n struct sigaction {\n \tsig_handler_t sa_handler;\n@@ -188,7 +178,6 @@ int pipe(int filedes[2]);\n unsigned int sleep (unsigned int seconds);\n int mkstemp(char *template);\n int gettimeofday(struct timeval *tv, void *tz);\n-int poll(struct pollfd *ufds, unsigned int nfds, int timeout);\n struct tm *gmtime_r(const time_t *timep, struct tm *result);\n struct tm *localtime_r(const time_t *timep, struct tm *result);\n int getpagesize(void);\t/* defined in MinGW's libgcc.a */\ndiff --git a/compat/win32/poll.c b/compat/win32/poll.c\nindex 7c52cb6..c1ca0d2 100644\n--- a/compat/win32/poll.c\n+++ b/compat/win32/poll.c\n@@ -24,8 +24,7 @@\n # pragma GCC diagnostic ignored \"-Wtype-limits\"\n #endif\n \n-#include <config.h>\n-#include <alloca.h>\n+#include <malloc.h>\n \n #include <sys/types.h>\n #include \"poll.h\"\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 100197f..f16a092 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -82,6 +82,7 @@\n #define WIN32_LEAN_AND_MEAN  /* stops windows.h including winsock.h */\n #include <winsock2.h>\n #include <windows.h>\n+#include \"compat/win32/poll.h\"\n #endif\n \n #include <unistd.h>\n-- \n1.7.3.1.51.ge462f.dirty\n"},{"id":"153144","messageId":"1286716854-5744-15-git-send-email-kusmabite@gmail.com","threadId":"25410","inReplyTo":"1286716854-5744-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v3 14/14] daemon: only use posix features on posix systems","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T13:20:54Z","receivedAt":"2010-10-10T13:20:54Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Windows does not supply the POSIX-functions fork(), setuuid(), setgid(),\nsetsid() and initgroups(). Disable support for --user, --group and\n--detach on platforms lacking _POSIX_VERSION.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n\nThis might be a bit controversial; does anyone know of any systems that\nimplements fork(), setuuid(), setgid() and setsid() but does not define\n_POSIX_VERSION? Perhaps we should have a separate makefile-switch instead?\n\n Makefile |    8 +++-----\n daemon.c |   43 +++++++++++++++++++++++++++++++------------\n 2 files changed, 34 insertions(+), 17 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 42baa4d..f5992da 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -401,6 +401,7 @@ EXTRA_PROGRAMS =\n # ... and all the rest that could be moved out of bindir to gitexecdir\n PROGRAMS += $(EXTRA_PROGRAMS)\n \n+PROGRAM_OBJS += daemon.o\n PROGRAM_OBJS += fast-import.o\n PROGRAM_OBJS += imap-send.o\n PROGRAM_OBJS += shell.o\n@@ -1064,7 +1065,6 @@ ifeq ($(uname_S),Windows)\n \tNO_SVN_TESTS = YesPlease\n \tNO_PERL_MAKEMAKER = YesPlease\n \tRUNTIME_PREFIX = YesPlease\n-\tNO_POSIX_ONLY_PROGRAMS = YesPlease\n \tNO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease\n \tNO_NSEC = YesPlease\n \tUSE_WIN32_MMAP = YesPlease\n@@ -1117,7 +1117,6 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tNO_SVN_TESTS = YesPlease\n \tNO_PERL_MAKEMAKER = YesPlease\n \tRUNTIME_PREFIX = YesPlease\n-\tNO_POSIX_ONLY_PROGRAMS = YesPlease\n \tNO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease\n \tNO_NSEC = YesPlease\n \tUSE_WIN32_MMAP = YesPlease\n@@ -1128,6 +1127,8 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tNO_PYTHON = YesPlease\n \tBLK_SHA1 = YesPlease\n \tETAGS_TARGET = ETAGS\n+\tNO_INET_PTON = YesPlease\n+\tNO_INET_NTOP = YesPlease\n \tCOMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch -Icompat/win32\n \tCOMPAT_CFLAGS += -DSTRIP_EXTENSION=\\\".exe\\\"\n \tCOMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o \\\n@@ -1246,9 +1247,6 @@ ifdef ZLIB_PATH\n endif\n EXTLIBS += -lz\n \n-ifndef NO_POSIX_ONLY_PROGRAMS\n-\tPROGRAM_OBJS += daemon.o\n-endif\n ifndef NO_OPENSSL\n \tOPENSSL_LIBSSL = -lssl\n \tifdef OPENSSLDIR\ndiff --git a/daemon.c b/daemon.c\nindex 54bbec2..56a9bed 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -23,10 +23,12 @@ static const char daemon_usage[] =\n \"           [--strict-paths] [--base-path=path] [--base-path-relaxed]\\n\"\n \"           [--user-path | --user-path=path]\\n\"\n \"           [--interpolated-path=path]\\n\"\n-\"           [--reuseaddr] [--detach] [--pid-file=file]\\n\"\n+\"           [--reuseaddr] [--pid-file=file]\\n\"\n \"           [--[enable|disable|allow-override|forbid-override]=service]\\n\"\n \"           [--inetd | [--listen=host_or_ipaddr] [--port=n]\\n\"\n-\"                      [--user=user [--group=group]]\\n\"\n+#ifdef _POSIX_VERSION\n+\"           [--detach] [--user=user [--group=group]]\\n\"\n+#endif\n \"           [directory...]\";\n \n /* List of acceptable pathname prefixes */\n@@ -593,7 +595,7 @@ static struct child {\n \tstruct sockaddr_storage address;\n } *firstborn;\n \n-static void add_child(struct child_process *cld, struct sockaddr *addr, int addrlen)\n+static void add_child(struct child_process *cld, struct sockaddr *addr, socklen_t addrlen)\n {\n \tstruct child *newborn, **cradle;\n \n@@ -672,7 +674,7 @@ static char *get_addrstr(int *port, struct sockaddr *addr)\n }\n \n char **cld_argv;\n-static void handle(int incoming, struct sockaddr *addr, int addrlen)\n+static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)\n {\n \tstruct child_process cld = { 0 };\n \tchar *addrstr, envbuf[300] = \"REMOTE_ADDR=\";\n@@ -908,7 +910,7 @@ static int service_loop(struct socketlist *socklist)\n \t\tfor (i = 0; i < socklist->nr; i++) {\n \t\t\tif (pfd[i].revents & POLLIN) {\n \t\t\t\tstruct sockaddr_storage ss;\n-\t\t\t\tunsigned int sslen = sizeof(ss);\n+\t\t\t\tsocklen_t sslen = sizeof(ss);\n \t\t\t\tint incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen);\n \t\t\t\tif (incoming < 0) {\n \t\t\t\t\tswitch (errno) {\n@@ -938,6 +940,7 @@ static void sanitize_stdfds(void)\n \t\tclose(fd);\n }\n \n+#ifdef _POSIX_VERSION\n static void daemonize(void)\n {\n \tswitch (fork()) {\n@@ -955,6 +958,7 @@ static void daemonize(void)\n \tclose(2);\n \tsanitize_stdfds();\n }\n+#endif\n \n static void store_pid(const char *path)\n {\n@@ -965,7 +969,12 @@ static void store_pid(const char *path)\n \t\tdie_errno(\"failed to write pid file '%s'\", path);\n }\n \n-static int serve(struct string_list *listen_addr, int listen_port, struct passwd *pass, gid_t gid)\n+#ifdef _POSIX_VERSION\n+static struct passwd *pass;\n+static gid_t gid;\n+#endif\n+\n+static int serve(struct string_list *listen_addr, int listen_port)\n {\n \tstruct socketlist socklist = { NULL, 0, 0 };\n \n@@ -974,10 +983,12 @@ static int serve(struct string_list *listen_addr, int listen_port, struct passwd\n \t\tdie(\"unable to allocate any listen sockets on port %u\",\n \t\t    listen_port);\n \n+#ifdef _POSIX_VERSION\n \tif (pass && gid &&\n \t    (initgroups(pass->pw_name, gid) || setgid (gid) ||\n \t     setuid(pass->pw_uid)))\n \t\tdie(\"cannot drop privileges\");\n+#endif\n \n \treturn service_loop(&socklist);\n }\n@@ -987,11 +998,11 @@ int main(int argc, char **argv)\n \tint listen_port = 0;\n \tstruct string_list listen_addr = STRING_LIST_INIT_NODUP;\n \tint serve_mode = 0, inetd_mode = 0;\n-\tconst char *pid_file = NULL, *user_name = NULL, *group_name = NULL;\n+\tconst char *pid_file = NULL;\n+#ifdef _POSIX_VERSION\n \tint detach = 0;\n-\tstruct passwd *pass = NULL;\n-\tstruct group *group;\n-\tgid_t gid = 0;\n+\tconst char *user_name = NULL, *group_name = NULL;\n+#endif\n \tint i;\n \n \tgit_extract_argv0_path(argv[0]);\n@@ -1080,6 +1091,7 @@ int main(int argc, char **argv)\n \t\t\tpid_file = arg + 11;\n \t\t\tcontinue;\n \t\t}\n+#ifdef _POSIX_VERSION\n \t\tif (!strcmp(arg, \"--detach\")) {\n \t\t\tdetach = 1;\n \t\t\tlog_syslog = 1;\n@@ -1093,6 +1105,7 @@ int main(int argc, char **argv)\n \t\t\tgroup_name = arg + 8;\n \t\t\tcontinue;\n \t\t}\n+#endif\n \t\tif (!prefixcmp(arg, \"--enable=\")) {\n \t\t\tenable_service(arg + 9, 1);\n \t\t\tcontinue;\n@@ -1127,14 +1140,17 @@ int main(int argc, char **argv)\n \t\t/* avoid splitting a message in the middle */\n \t\tsetvbuf(stderr, NULL, _IOFBF, 4096);\n \n+#ifdef _POSIX_VERSION\n \tif (inetd_mode && (group_name || user_name))\n \t\tdie(\"--user and --group are incompatible with --inetd\");\n+#endif\n \n \tif (inetd_mode && (listen_port || (listen_addr.nr > 0)))\n \t\tdie(\"--listen= and --port= are incompatible with --inetd\");\n \telse if (listen_port == 0)\n \t\tlisten_port = DEFAULT_GIT_PORT;\n \n+#ifdef _POSIX_VERSION\n \tif (group_name && !user_name)\n \t\tdie(\"--group supplied without --user\");\n \n@@ -1146,13 +1162,14 @@ int main(int argc, char **argv)\n \t\tif (!group_name)\n \t\t\tgid = pass->pw_gid;\n \t\telse {\n-\t\t\tgroup = getgrnam(group_name);\n+\t\t\tstruct group *group = getgrnam(group_name);\n \t\t\tif (!group)\n \t\t\t\tdie(\"group not found - %s\", group_name);\n \n \t\t\tgid = group->gr_gid;\n \t\t}\n \t}\n+#endif\n \n \tif (strict_paths && (!ok_paths || !*ok_paths))\n \t\tdie(\"option --strict-paths requires a whitelist\");\n@@ -1180,11 +1197,13 @@ int main(int argc, char **argv)\n \t\treturn execute(peer);\n \t}\n \n+#ifdef _POSIX_VERSION\n \tif (detach) {\n \t\tdaemonize();\n \t\tloginfo(\"Ready to rumble\");\n \t}\n \telse\n+#endif\n \t\tsanitize_stdfds();\n \n \tif (pid_file)\n@@ -1197,5 +1216,5 @@ int main(int argc, char **argv)\n \tcld_argv[argc] = \"--serve\";\n \tcld_argv[argc+1] = NULL;\n \n-\treturn serve(&listen_addr, listen_port, pass, gid);\n+\treturn serve(&listen_addr, listen_port);\n }\n-- \n1.7.3.1.51.ge462f.dirty\n"},{"id":"153145","messageId":"AANLkTim1BZR89M22tAkT0qtfk70QeN0QuyKi5Q2KQQKR@mail.gmail.com","threadId":"25410","inReplyTo":"1286716854-5744-13-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v3 12/14] mingw: import poll-emulation from gnulib","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2010-10-10T14:15:00Z","receivedAt":"2010-10-10T14:15:00Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Sun, Oct 10, 2010 at 13:20, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> lib/poll.c and lib/poll.in.h imported from 0a05120 in\n> git://git.savannah.gnu.org/gnulib.git\n\nHaving fought with importing things from gnulib myself using their\ntools it would be useful to note in the commit message *how* you\nimported this. Did you use the gnulib command with some archane\noptions so it wouldn't touch the build system while it was at it, or\ndid you just copy the relevant files manually?\n"},{"id":"153146","messageId":"AANLkTikR4FMK31oJP24B+9QxLypSbO7PL8G5vEtUp=my@mail.gmail.com","threadId":"25410","inReplyTo":"AANLkTim1BZR89M22tAkT0qtfk70QeN0QuyKi5Q2KQQKR@mail.gmail.com","subject":"Re: [PATCH v3 12/14] mingw: import poll-emulation from gnulib","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T14:28:40Z","receivedAt":"2010-10-10T14:28:40Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sun, Oct 10, 2010 at 4:15 PM, Ævar Arnfjörð Bjarmason\n<avarab@gmail.com> wrote:\n> On Sun, Oct 10, 2010 at 13:20, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n>> lib/poll.c and lib/poll.in.h imported from 0a05120 in\n>> git://git.savannah.gnu.org/gnulib.git\n>\n> Having fought with importing things from gnulib myself using their\n> tools it would be useful to note in the commit message *how* you\n> imported this. Did you use the gnulib command with some archane\n> options so it wouldn't touch the build system while it was at it, or\n> did you just copy the relevant files manually?\n>\n\nSorry if that was unclear - I just copied the files (verbatim).\nPatching to make it compile for us comes in the next patch.\n\nI didn't even know that there was a gnulib tool to extract code, but a\nquick google-search shows that there is. I'll look into using the tool\ninstead for the next round.\n"},{"id":"153156","messageId":"201010102058.16773.j6t@kdbg.org","threadId":"25410","inReplyTo":"1286716854-5744-12-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v3 11/14] daemon: report connection from root-process","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2010-10-10T18:58:16Z","receivedAt":"2010-10-10T18:58:16Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Sonntag, 10. Oktober 2010, Erik Faye-Lund wrote:\n> Report incoming connections from the process that\n> accept() the connection instead of the handling\n> process.\n>\n> This enables \"Connection from\"-reporting on\n> Windows, where getpeername(0, ...) consistently\n> fails.\n\nIs this from the process that you invoke with --serve? then this failure could \nbe due to Winsockets not being initilized. Did you check that?\n\n-- Hannes\n"},{"id":"153158","messageId":"AANLkTinz69u-hh-URqBrpdcrm+84N2BC7Ov4O8xeuW73@mail.gmail.com","threadId":"25410","inReplyTo":"201010102058.16773.j6t@kdbg.org","subject":"Re: [PATCH v3 11/14] daemon: report connection from root-process","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T19:31:02Z","receivedAt":"2010-10-10T19:31:02Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sun, Oct 10, 2010 at 8:58 PM, Johannes Sixt <j6t@kdbg.org> wrote:\n> On Sonntag, 10. Oktober 2010, Erik Faye-Lund wrote:\n>> Report incoming connections from the process that\n>> accept() the connection instead of the handling\n>> process.\n>>\n>> This enables \"Connection from\"-reporting on\n>> Windows, where getpeername(0, ...) consistently\n>> fails.\n>\n> Is this from the process that you invoke with --serve? then this failure could\n> be due to Winsockets not being initilized. Did you check that?\n>\n\nI've tried that, and unfortunately it lack of socket initialization\ndoes not seem to be the reason :(\n"},{"id":"153159","messageId":"AANLkTimxFm+hgJBM2B+Eui6+fStM1JSfkyMsKRoqCXd-@mail.gmail.com","threadId":"25410","inReplyTo":"AANLkTikR4FMK31oJP24B+9QxLypSbO7PL8G5vEtUp=my@mail.gmail.com","subject":"Re: [PATCH v3 12/14] mingw: import poll-emulation from gnulib","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T19:34:15Z","receivedAt":"2010-10-10T19:34:15Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sun, Oct 10, 2010 at 4:28 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> On Sun, Oct 10, 2010 at 4:15 PM, Ævar Arnfjörð Bjarmason\n> <avarab@gmail.com> wrote:\n>> On Sun, Oct 10, 2010 at 13:20, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n>>> lib/poll.c and lib/poll.in.h imported from 0a05120 in\n>>> git://git.savannah.gnu.org/gnulib.git\n>>\n>> Having fought with importing things from gnulib myself using their\n>> tools it would be useful to note in the commit message *how* you\n>> imported this. Did you use the gnulib command with some archane\n>> options so it wouldn't touch the build system while it was at it, or\n>> did you just copy the relevant files manually?\n>>\n>\n> Sorry if that was unclear - I just copied the files (verbatim).\n> Patching to make it compile for us comes in the next patch.\n>\n> I didn't even know that there was a gnulib tool to extract code, but a\n> quick google-search shows that there is. I'll look into using the tool\n> instead for the next round.\n>\n\nI've had a quick look at it, and it really doesn't seem like\ngnulib-tool is suited for us here. It seems to be intended on pure\nautoconf-projects, and starts including all kinds of things that we\ndon't need. We only care about poll-emulation on Windows, and we don't\nneed autoconf to tell us if it should be used or not.\n\nSo I'm not in favor of using gnulib-tool, and going with the current\nmethod of verbatim copy with a separate fix-up commit. But perhaps I\nshould clarify the commit message so other people can easily upgrade\nthe emulation later...\n"},{"id":"153160","messageId":"AANLkTimn3XWDXhqrZm+VS1Ouy8tzmCAVOyMN7KjQ7dFt@mail.gmail.com","threadId":"25410","inReplyTo":"1286716854-5744-15-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v3 14/14] daemon: only use posix features on posix systems","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2010-10-10T19:40:28Z","receivedAt":"2010-10-10T19:40:28Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Sun, Oct 10, 2010 at 13:20, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> Windows does not supply the POSIX-functions fork(), setuuid(), setgid(),\n> setsid() and initgroups(). Disable support for --user, --group and\n> --detach on platforms lacking _POSIX_VERSION.\n\nFWIW I checked if Perl's fork() emulation with threads on Windows\ncould emulate this, but no:\n\n    perl -E '\n    if (my $pid = fork()) {\n      say \"$$: child running as $pid\"\n    } else {\n      sleep 1;\n      say \"$$: running in the background\"\n    }'\n\nOn Unix that would detach the process from the terminal, but on\nWindows with threads the original process only returns after the child\nhas finished.\n\nI didn't expect it to act differently, but I thought I'd note it here\nin case anyone had it in mind to implement --detach on Windows.\n\n> This might be a bit controversial; does anyone know of any systems that\n> implements fork(), setuuid(), setgid() and setsid() but does not define\n> _POSIX_VERSION? Perhaps we should have a separate makefile-switch instead?\n\nEven if it's defined it's more self-documenting to have our own\nHAVE_POSIX_GOODIES (or something like that) instead.\n"},{"id":"153161","messageId":"4CB216C2.1060608@gmail.com","threadId":"25410","inReplyTo":"1286716854-5744-2-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v3 01/14] mingw: add network-wrappers for daemon","fromName":"Eric Sunshine","fromEmail":"ericsunshine@gmail.com","sentAt":"2010-10-10T19:40:50Z","receivedAt":"2010-10-10T19:40:50Z","isPatch":true,"sender":{"key":"ericsunshine@gmail.com","avatar":null},"body":"On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:\n> From: Mike Pape<dotzenlabs@gmail.com>\n>\n> git-daemon requires some socket-functionality that is not yet\n> supported in the Windows-port. This patch adds said functionality,\n> and makes sure WSAStartup gets called by socket(), since it is the\n> first network-call in git-daemon. In addition, a check is added to\n> prevent WSAStartup (and WSACleanup, though atexit) from being\n> called more than once, since git-daemon calls both socket() and\n> gethostbyname().\n>\n> Signed-off-by: Mike Pape<dotzenlabs@gmail.com>\n> Signed-off-by: Erik Faye-Lund<kusmabite@gmail.com>\n> ---\n> diff --git a/compat/mingw.c b/compat/mingw.c\n> index 6590f33..563ef1f 100644\n> --- a/compat/mingw.c\n> +++ b/compat/mingw.c\n> +#undef accept\n> +int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)\n> +{\n> +\tint sockfd2;\n> +\n> +\tSOCKET s1 = (SOCKET)_get_osfhandle(sockfd1);\n> +\tSOCKET s2 = accept(s1, sa, sz);\n> +\n> +\t/* convert into a file descriptor */\n> +\tif ((sockfd2 = _open_osfhandle(s2, O_RDWR|O_BINARY))<  0) {\n> +\t\tclosesocket(s2);\n> +\t\treturn error(\"unable to make a socket file descriptor: %s\",\n> +\t\t\tstrerror(errno));\n\nIs 'errno' from _open_osfhandle() still valid when handed to strerror() \nor has it been clobbered by closesocket()?\n\nCorollary: Does _open_osfhandle() indeed set 'errno', or is it more \nappropriate to call WSAGetLastError()? (The documentation I read for \n_open_osfhandle() did not say anything about how to determine the reason \nfor failure.)\n\n-- ES\n"},{"id":"153162","messageId":"AANLkTinEmrHMfw0z=uwOs9FDRcta3gwcEvc1MBi+_7C-@mail.gmail.com","threadId":"25410","inReplyTo":"AANLkTinz69u-hh-URqBrpdcrm+84N2BC7Ov4O8xeuW73@mail.gmail.com","subject":"Re: [PATCH v3 11/14] daemon: report connection from root-process","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T19:42:26Z","receivedAt":"2010-10-10T19:42:26Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sun, Oct 10, 2010 at 9:31 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> On Sun, Oct 10, 2010 at 8:58 PM, Johannes Sixt <j6t@kdbg.org> wrote:\n>> On Sonntag, 10. Oktober 2010, Erik Faye-Lund wrote:\n>>> Report incoming connections from the process that\n>>> accept() the connection instead of the handling\n>>> process.\n>>>\n>>> This enables \"Connection from\"-reporting on\n>>> Windows, where getpeername(0, ...) consistently\n>>> fails.\n>>\n>> Is this from the process that you invoke with --serve? then this failure could\n>> be due to Winsockets not being initilized. Did you check that?\n>>\n>\n> I've tried that, and unfortunately it lack of socket initialization\n> does not seem to be the reason :(\n>\n\nBut looking at it a bit more, I can do the following code-reduction on\ntop, changing this to a +10 lines to a -2 lines patch ;)\n\ndiff --git a/daemon.c b/daemon.c\nindex 56a9bed..e9a4839 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -518,7 +518,7 @@ static void parse_host_arg(char *extra_args, int buflen)\n }\n\n\n-static int execute(struct sockaddr *addr)\n+static int execute()\n {\n \tstatic char line[1000];\n \tint pktlen, len, i;\n@@ -1179,22 +1179,10 @@ int main(int argc, char **argv)\n \t\t    base_path);\n\n \tif (serve_mode) {\n-\t\tstruct sockaddr_storage ss;\n-\t\tstruct sockaddr *peer = (struct sockaddr *)&ss;\n-\t\tsocklen_t slen = sizeof(ss);\n-\n \t\tif (inetd_mode && !freopen(\"/dev/null\", \"w\", stderr))\n \t\t\tdie_errno(\"failed to redirect stderr to /dev/null\");\n\n-\t\tif (!getpeername(0, peer, &slen)) {\n-\t\t\tint port = -1;\n-\t\t\tchar *addrstr = get_addrstr(&port, peer);\n-\t\t\tsetenv(\"REMOTE_ADDR\", addrstr, 1);\n-\t\t\tloginfo(\"[%\"PRIuMAX\"] Connection from %s:%d\",\n-\t\t\t    (uintmax_t)getpid(), addrstr, port);\n-\t\t}\n-\n-\t\treturn execute(peer);\n+\t\treturn execute();\n \t}\n\n #ifdef _POSIX_VERSION\n"},{"id":"153163","messageId":"4CB2190F.6000908@gmail.com","threadId":"25410","inReplyTo":"1286716854-5744-3-git-send-email-kusmabite@gmail.com","subject":"Re: [msysGit] [PATCH v3 02/14] mingw: implement syslog","fromName":"Eric Sunshine","fromEmail":"ericsunshine@gmail.com","sentAt":"2010-10-10T19:50:39Z","receivedAt":"2010-10-10T19:50:39Z","isPatch":true,"sender":{"key":"ericsunshine@gmail.com","avatar":null},"body":"On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:\n> From: Mike Pape<dotzenlabs@gmail.com>\n>\n> Syslog does not usually exist on Windows, so we implement our own\n> using Window's ReportEvent mechanism.\n>\n> Signed-off-by: Mike Pape<dotzenlabs@gmail.com>\n> Signed-off-by: Erik Faye-Lund<kusmabite@gmail.com>\n> ---\n> +void syslog(int priority, const char *fmt, const char *arg)\n> +{\n> +\tWORD logtype;\n> +\n> +\tif (!ms_eventlog)\n> +\t\treturn;\n> +\n> +\tif (strcmp(fmt, \"%s\")) {\n> +\t\twarning(\"format string of syslog() not implemented\");\n> +\t\treturn;\n> +\t}\n\nIt is not exactly clear what the intention is here. Is this trying to \nsay that no formatting directives are allowed in 'fmt' or what? The \nsimple case it is actually checking (where 'fmt' is solely '%s') could \neasily be handled manually, as could more complex formats.\n\n> +\t/*\n> +\t * ReportEvent() doesn't handle strings containing %n, where n is\n> +\t * an integer. Such events must be reformatted by the caller.\n> +\t */\n> +\tReportEventA(ms_eventlog,\n> +\t    logtype,\n> +\t    0,\n> +\t    0,\n> +\t    NULL,\n> +\t    1,\n> +\t    0,\n> +\t    (const char **)&arg,\n> +\t    NULL);\n\nThe comment about '%n' seems to be warning about a potential problem but \ndoes not actually protect against it. Should this issue be handled?\n\n-- ES\n"},{"id":"153164","messageId":"AANLkTikRetnkmNc07Cd=1EeWZn8jC5PmFk87YffGs9Kx@mail.gmail.com","threadId":"25410","inReplyTo":"AANLkTimxFm+hgJBM2B+Eui6+fStM1JSfkyMsKRoqCXd-@mail.gmail.com","subject":"Re: [PATCH v3 12/14] mingw: import poll-emulation from gnulib","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2010-10-10T19:51:52Z","receivedAt":"2010-10-10T19:51:52Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Sun, Oct 10, 2010 at 19:34, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> On Sun, Oct 10, 2010 at 4:28 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n>> On Sun, Oct 10, 2010 at 4:15 PM, Ævar Arnfjörð Bjarmason\n>> <avarab@gmail.com> wrote:\n>>> On Sun, Oct 10, 2010 at 13:20, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n>>>> lib/poll.c and lib/poll.in.h imported from 0a05120 in\n>>>> git://git.savannah.gnu.org/gnulib.git\n>>>\n>>> Having fought with importing things from gnulib myself using their\n>>> tools it would be useful to note in the commit message *how* you\n>>> imported this. Did you use the gnulib command with some archane\n>>> options so it wouldn't touch the build system while it was at it, or\n>>> did you just copy the relevant files manually?\n>>>\n>>\n>> Sorry if that was unclear - I just copied the files (verbatim).\n>> Patching to make it compile for us comes in the next patch.\n>>\n>> I didn't even know that there was a gnulib tool to extract code, but a\n>> quick google-search shows that there is. I'll look into using the tool\n>> instead for the next round.\n>>\n>\n> I've had a quick look at it, and it really doesn't seem like\n> gnulib-tool is suited for us here. It seems to be intended on pure\n> autoconf-projects, and starts including all kinds of things that we\n> don't need. We only care about poll-emulation on Windows, and we don't\n> need autoconf to tell us if it should be used or not.\n\nThe only reason I asked was that I tried to use gnulib-tool at one\npoint and reached the same conclusion. But in my case I wanted it to\nresolve dependencies (i.e. bring in multiple projects), so not using\nit was its own pain.\n\nI just thought I'd ask in case you'd spent more time on getting it to\nwork.\n\n> So I'm not in favor of using gnulib-tool, and going with the current\n> method of verbatim copy with a separate fix-up commit. But perhaps I\n> should clarify the commit message so other people can easily upgrade\n> the emulation later...\n\nBy all means don't use gnulib, but noting how to upgrade things when\nwe add anything external in compat/ is a good idea.\n"},{"id":"153165","messageId":"4CB219D3.8000801@sunshineco.com","threadId":"25410","inReplyTo":"1286716854-5744-6-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v3 05/14] mingw: use real pid","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2010-10-10T19:53:55Z","receivedAt":"2010-10-10T19:53:55Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:\n> The Windows port so far used process handles as PID. However,\n> this does not work consistently with getpid.\n\nPerhaps this could be elaborated a bit to explain the interaction with \ngetpid() and how it is causing problems for daemon mode. For the casual \nreader, it is not immediately obvious what is failing or why this patch \nis needed.\n\n-- ES\n"},{"id":"153166","messageId":"4CB21A5D.4020408@sunshineco.com","threadId":"25410","inReplyTo":"1286716854-5744-9-git-send-email-kusmabite@gmail.com","subject":"Re: [msysGit] [PATCH v3 08/14] daemon: use run-command api for async serving","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2010-10-10T19:56:13Z","receivedAt":"2010-10-10T19:56:13Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:\n> fork() is only available on POSIX, so to support git-daemon\n> on Windows we have to use something else.\n>\n> Instead we invent the flag --serve, which is a stripped down\n> version of --inetd-mode. We use start_command() to call\n> git-daemon with this flag appended to serve clients.\n>\n> Signed-off-by: Erik Faye-Lund<kusmabite@gmail.com>\n> ---\n> @@ -654,14 +641,14 @@ static void remove_child(pid_t pid)\n>    */\n>   static void kill_some_child(void)\n>   {\n> -\tconst struct child *blanket, *next;\n> +\tstruct child *blanket, *next;\n\nIt is not immediately obvious why 'const' was dropped.\n\n> @@ -671,18 +658,26 @@ static void check_dead_children(void)\n>   \tint status;\n>   \tpid_t pid;\n>\n> -\twhile ((pid = waitpid(-1,&status, WNOHANG))>  0) {\n> -\t\tconst char *dead = \"\";\n> -\t\tremove_child(pid);\n> -\t\tif (!WIFEXITED(status) || (WEXITSTATUS(status)>  0))\n> -\t\t\tdead = \" (with error)\";\n> -\t\tloginfo(\"[%\"PRIuMAX\"] Disconnected%s\", (uintmax_t)pid, dead);\n> -\t}\n> +\tstruct child **cradle, *blanket;\n> +\tfor (cradle =&firstborn; (blanket = *cradle);)\n> +\t\tif ((pid = waitpid(blanket->cld.pid,&status, WNOHANG))>  1) {\n> +\t\t\tconst char *dead = \"\";\n> +\t\t\tif (status)\n> +\t\t\t\tdead = \" (with error)\";\n> +\t\t\tloginfo(\"[%\"PRIuMAX\"] Disconnected%s\", (uintmax_t)pid, dead);\n> +\n> +\t\t\t/* remove the child */\n> +\t\t\t*cradle = blanket->next;\n> +\t\t\tlive_children--;\n> +\t\t\tfree(blanket);\n> +\t\t} else\n> +\t\t\tcradle =&blanket->next;\n>   }\n>\n> +char **cld_argv;\n>   static void handle(int incoming, struct sockaddr *addr, int addrlen)\n>   {\n\nShould 'cld_argv' be declared static?\n\n-- ES\n"},{"id":"153167","messageId":"AANLkTikqJKKSOS-X+d_hx0hyEdFmX3zNZBvZMV4qRMAp@mail.gmail.com","threadId":"25410","inReplyTo":"AANLkTinEmrHMfw0z=uwOs9FDRcta3gwcEvc1MBi+_7C-@mail.gmail.com","subject":"Re: [PATCH v3 11/14] daemon: report connection from root-process","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2010-10-10T20:14:42Z","receivedAt":"2010-10-10T20:14:42Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Sun, Oct 10, 2010 at 19:42, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n\n> -static int execute(struct sockaddr *addr)\n> +static int execute()\n\nIsn't execute(void) more portable?\n"},{"id":"153168","messageId":"AANLkTinP7RKOhLFZs71P5dpmA1p1OsjikSmVv5WkkL1z@mail.gmail.com","threadId":"25410","inReplyTo":"4CB216C2.1060608@gmail.com","subject":"Re: [PATCH v3 01/14] mingw: add network-wrappers for daemon","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T20:20:58Z","receivedAt":"2010-10-10T20:20:58Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sun, Oct 10, 2010 at 9:40 PM, Eric Sunshine <ericsunshine@gmail.com> wrote:\n> On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:\n>>\n>> From: Mike Pape<dotzenlabs@gmail.com>\n>>\n>> git-daemon requires some socket-functionality that is not yet\n>> supported in the Windows-port. This patch adds said functionality,\n>> and makes sure WSAStartup gets called by socket(), since it is the\n>> first network-call in git-daemon. In addition, a check is added to\n>> prevent WSAStartup (and WSACleanup, though atexit) from being\n>> called more than once, since git-daemon calls both socket() and\n>> gethostbyname().\n>>\n>> Signed-off-by: Mike Pape<dotzenlabs@gmail.com>\n>> Signed-off-by: Erik Faye-Lund<kusmabite@gmail.com>\n>> ---\n>> diff --git a/compat/mingw.c b/compat/mingw.c\n>> index 6590f33..563ef1f 100644\n>> --- a/compat/mingw.c\n>> +++ b/compat/mingw.c\n>> +#undef accept\n>> +int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)\n>> +{\n>> +       int sockfd2;\n>> +\n>> +       SOCKET s1 = (SOCKET)_get_osfhandle(sockfd1);\n>> +       SOCKET s2 = accept(s1, sa, sz);\n>> +\n>> +       /* convert into a file descriptor */\n>> +       if ((sockfd2 = _open_osfhandle(s2, O_RDWR|O_BINARY))<  0) {\n>> +               closesocket(s2);\n>> +               return error(\"unable to make a socket file descriptor:\n>> %s\",\n>> +                       strerror(errno));\n>\n> Is 'errno' from _open_osfhandle() still valid when handed to strerror() or\n> has it been clobbered by closesocket()?\n>\n> Corollary: Does _open_osfhandle() indeed set 'errno', or is it more\n> appropriate to call WSAGetLastError()? (The documentation I read for\n> _open_osfhandle() did not say anything about how to determine the reason for\n> failure.)\n>\n\n_open_osfhandle seems to set both errno and the winsock-error.\nclosesocket() sets the winsock-error but not the CRT. I've just tested\nwith a very simple application:\n\n---8<---\n#include <winsock2.h>\n#include <io.h>\n#include <fcntl.h>\n#include <stdio.h>\n\nconst char *win32_strerror(DWORD dw)\n{\n\tstatic char tmp[4096];\n\tFormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw,\n\t    MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),\n\t    tmp, sizeof(tmp), NULL);\n\treturn tmp;\n}\n\nint main()\n{\n\tWSADATA wsa = {0};\n\n\tWSAStartup(MAKEWORD(2, 0), &wsa);\n\tprintf(\"errno: '%s'\\nWSAGetLastError: '%s'\\n\",\n\t    strerror(errno), win32_strerror(WSAGetLastError()));\n\terrno = 0;\n\n\t_open_osfhandle(-1, O_RDWR | O_BINARY);\n\tprintf(\"errno: '%s'\\nWSAGetLastError: '%s'\\n\",\n\t    strerror(errno), win32_strerror(WSAGetLastError()));\n\terrno = 0;\n\n\tclosesocket(-1);\n\tprintf(\"errno: '%s'\\nWSAGetLastError: '%s'\\n\",\n\t    strerror(errno), win32_strerror(WSAGetLastError()));\n\n\treturn 0;\n}\n\n---8<---\n\nThe output is:\n\n---8<---\nerrno: 'Result too large'\nWSAGetLastError: 'The operation completed successfully.\n'\nerrno: 'Bad file descriptor'\nWSAGetLastError: 'The handle is invalid.\n'\nerrno: 'No error'\nWSAGetLastError: 'An operation was attempted on something that is not a socket.\n'\n---8<---\n\nSo, it seems that WSAGetLastError() gets clobbered by closesocket(),\nbut not errno.\n"},{"id":"153173","messageId":"AANLkTinsqAOj7LtACpbcOrVZfeUApDjmQe2uYLH8npBF@mail.gmail.com","threadId":"25410","inReplyTo":"4CB2190F.6000908@gmail.com","subject":"Re: [msysGit] [PATCH v3 02/14] mingw: implement syslog","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T20:37:26Z","receivedAt":"2010-10-10T20:37:26Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sun, Oct 10, 2010 at 9:50 PM, Eric Sunshine <ericsunshine@gmail.com> wrote:\n> On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:\n>>\n>> From: Mike Pape<dotzenlabs@gmail.com>\n>>\n>> Syslog does not usually exist on Windows, so we implement our own\n>> using Window's ReportEvent mechanism.\n>>\n>> Signed-off-by: Mike Pape<dotzenlabs@gmail.com>\n>> Signed-off-by: Erik Faye-Lund<kusmabite@gmail.com>\n>> ---\n>> +void syslog(int priority, const char *fmt, const char *arg)\n>> +{\n>> +       WORD logtype;\n>> +\n>> +       if (!ms_eventlog)\n>> +               return;\n>> +\n>> +       if (strcmp(fmt, \"%s\")) {\n>> +               warning(\"format string of syslog() not implemented\");\n>> +               return;\n>> +       }\n>\n> It is not exactly clear what the intention is here. Is this trying to say\n> that no formatting directives are allowed in 'fmt' or what? The simple case\n> it is actually checking (where 'fmt' is solely '%s') could easily be handled\n> manually, as could more complex formats.\n>\n\nThis is the result of the feed-back in v1, where we tried to implement\nall format strings. But that turned out to be very complex (due to the\nlack of a portable va_copy()) and since we control all call-sites for\nsyslog and already only use \"%s\" as the format, it should be OK.\n\nPerhaps that should be mentioned in the commit message...\n\n>> +       /*\n>> +        * ReportEvent() doesn't handle strings containing %n, where n is\n>> +        * an integer. Such events must be reformatted by the caller.\n>> +        */\n>> +       ReportEventA(ms_eventlog,\n>> +           logtype,\n>> +           0,\n>> +           0,\n>> +           NULL,\n>> +           1,\n>> +           0,\n>> +           (const char **)&arg,\n>> +           NULL);\n>\n> The comment about '%n' seems to be warning about a potential problem but\n> does not actually protect against it. Should this issue be handled?\n>\n\nThis is again an issue that was discussed in the first round.\nReportEvent() CANNOT report a string containing \"%n\" (where n is an\ninteger). And while we could probably try to work around it by\ninserting a space or something, and I don't think we ever were able to\nfind a case where we could report a string containing \"%n\" in the\nfirst place...\n\nAre you suggesting that we report an error when we can't report the\nstring correctly? We could do that, but I'm not sure how the end-user\nwould benefit from that. ReportEvent is used to report errors (unless\nthe --verbose flag has been specified), and reporting that we can't\npresent an error message strike me as a bit confusing... Even the\ncorrupted error message is probably better :P\n"},{"id":"153174","messageId":"AANLkTinZgXF5pxq_HG1veQwO9_=Pmm5Vk2PUHd6=h7yQ@mail.gmail.com","threadId":"25410","inReplyTo":"4CB21A5D.4020408@sunshineco.com","subject":"Re: [PATCH v3 08/14] daemon: use run-command api for async serving","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T20:42:44Z","receivedAt":"2010-10-10T20:42:44Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sun, Oct 10, 2010 at 9:56 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:\n>>\n>> fork() is only available on POSIX, so to support git-daemon\n>> on Windows we have to use something else.\n>>\n>> Instead we invent the flag --serve, which is a stripped down\n>> version of --inetd-mode. We use start_command() to call\n>> git-daemon with this flag appended to serve clients.\n>>\n>> Signed-off-by: Erik Faye-Lund<kusmabite@gmail.com>\n>> ---\n>> @@ -654,14 +641,14 @@ static void remove_child(pid_t pid)\n>>   */\n>>  static void kill_some_child(void)\n>>  {\n>> -       const struct child *blanket, *next;\n>> +       struct child *blanket, *next;\n>\n> It is not immediately obvious why 'const' was dropped.\n>\n\nIt's a left-over hunk from a previous version. Thanks for pointing it out!\n\n>> @@ -671,18 +658,26 @@ static void check_dead_children(void)\n>>        int status;\n>>        pid_t pid;\n>>\n>> -       while ((pid = waitpid(-1,&status, WNOHANG))>  0) {\n>> -               const char *dead = \"\";\n>> -               remove_child(pid);\n>> -               if (!WIFEXITED(status) || (WEXITSTATUS(status)>  0))\n>> -                       dead = \" (with error)\";\n>> -               loginfo(\"[%\"PRIuMAX\"] Disconnected%s\", (uintmax_t)pid,\n>> dead);\n>> -       }\n>> +       struct child **cradle, *blanket;\n>> +       for (cradle =&firstborn; (blanket = *cradle);)\n>> +               if ((pid = waitpid(blanket->cld.pid,&status, WNOHANG))>\n>>  1) {\n>> +                       const char *dead = \"\";\n>> +                       if (status)\n>> +                               dead = \" (with error)\";\n>> +                       loginfo(\"[%\"PRIuMAX\"] Disconnected%s\",\n>> (uintmax_t)pid, dead);\n>> +\n>> +                       /* remove the child */\n>> +                       *cradle = blanket->next;\n>> +                       live_children--;\n>> +                       free(blanket);\n>> +               } else\n>> +                       cradle =&blanket->next;\n>>  }\n>>\n>> +char **cld_argv;\n>>  static void handle(int incoming, struct sockaddr *addr, int addrlen)\n>>  {\n>\n> Should 'cld_argv' be declared static?\n>\n\nYes it should, thanks!\n"},{"id":"153175","messageId":"AANLkTimZFzk6aV7SLZwQ=VP92Z3x_s3Q4dsQexLUSD6j@mail.gmail.com","threadId":"25410","inReplyTo":"AANLkTikqJKKSOS-X+d_hx0hyEdFmX3zNZBvZMV4qRMAp@mail.gmail.com","subject":"Re: [PATCH v3 11/14] daemon: report connection from root-process","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T20:48:39Z","receivedAt":"2010-10-10T20:48:39Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sun, Oct 10, 2010 at 10:14 PM, Ævar Arnfjörð Bjarmason\n<avarab@gmail.com> wrote:\n> On Sun, Oct 10, 2010 at 19:42, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n>\n>> -static int execute(struct sockaddr *addr)\n>> +static int execute()\n>\n> Isn't execute(void) more portable?\n>\n\nYes, it is. Thanks!\n"},{"id":"153176","messageId":"201010102251.27095.j6t@kdbg.org","threadId":"25410","inReplyTo":"AANLkTinsqAOj7LtACpbcOrVZfeUApDjmQe2uYLH8npBF@mail.gmail.com","subject":"Re: [msysGit] [PATCH v3 02/14] mingw: implement syslog","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2010-10-10T20:51:26Z","receivedAt":"2010-10-10T20:51:26Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Sonntag, 10. Oktober 2010, Erik Faye-Lund wrote:\n> On Sun, Oct 10, 2010 at 9:50 PM, Eric Sunshine <ericsunshine@gmail.com> \nwrote:\n> > On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:\n> >> +       /*\n> >> +        * ReportEvent() doesn't handle strings containing %n, where n\n> >> is +        * an integer. Such events must be reformatted by the caller.\n> >> +        */\n> >\n> > The comment about '%n' seems to be warning about a potential problem but\n> > does not actually protect against it. Should this issue be handled?\n>\n> This is again an issue that was discussed in the first round.\n> ReportEvent() CANNOT report a string containing \"%n\" (where n is an\n> integer). And while we could probably try to work around it by\n> inserting a space or something, and I don't think we ever were able to\n> find a case where we could report a string containing \"%n\" in the\n> first place...\n\nI recall that it was mentioned that this could happen for IPv6 addresses?\n\n-- Hannes\n"},{"id":"153177","messageId":"AANLkTinmpzo2-eyPrnx0u=tGBOcMBz03LuFUjZO87dG5@mail.gmail.com","threadId":"25410","inReplyTo":"4CB219D3.8000801@sunshineco.com","subject":"Re: [PATCH v3 05/14] mingw: use real pid","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T20:52:10Z","receivedAt":"2010-10-10T20:52:10Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sun, Oct 10, 2010 at 9:53 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:\n>>\n>> The Windows port so far used process handles as PID. However,\n>> this does not work consistently with getpid.\n>\n> Perhaps this could be elaborated a bit to explain the interaction with\n> getpid() and how it is causing problems for daemon mode. For the casual\n> reader, it is not immediately obvious what is failing or why this patch is\n> needed.\n>\n\nGood point. How about something like this?\n\n\"The Windows port so far used process handles as PID. However, this is\nnot consistent with what getpid returns.\n\nPIDs are system-global identifiers, but process handles are local to a\nprocess. Using PIDs instead of process handles allows for instance a\nuser to kill a hung process with the Task Manager, something that\nwould have been impossible with process handles.\"\n"},{"id":"153180","messageId":"AANLkTimSxk=b=cHSvvnVejy=smwTmGboqya0cW+6YOrF@mail.gmail.com","threadId":"25410","inReplyTo":"201010102251.27095.j6t@kdbg.org","subject":"Re: [msysGit] [PATCH v3 02/14] mingw: implement syslog","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T21:17:30Z","receivedAt":"2010-10-10T21:17:30Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sun, Oct 10, 2010 at 10:51 PM, Johannes Sixt <j6t@kdbg.org> wrote:\n> On Sonntag, 10. Oktober 2010, Erik Faye-Lund wrote:\n>> On Sun, Oct 10, 2010 at 9:50 PM, Eric Sunshine <ericsunshine@gmail.com>\n> wrote:\n>> > On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:\n>> >> +       /*\n>> >> +        * ReportEvent() doesn't handle strings containing %n, where n\n>> >> is +        * an integer. Such events must be reformatted by the caller.\n>> >> +        */\n>> >\n>> > The comment about '%n' seems to be warning about a potential problem but\n>> > does not actually protect against it. Should this issue be handled?\n>>\n>> This is again an issue that was discussed in the first round.\n>> ReportEvent() CANNOT report a string containing \"%n\" (where n is an\n>> integer). And while we could probably try to work around it by\n>> inserting a space or something, and I don't think we ever were able to\n>> find a case where we could report a string containing \"%n\" in the\n>> first place...\n>\n> I recall that it was mentioned that this could happen for IPv6 addresses?\n>\n\nAh, that's right. Microsoft even mentions it in MSDN: \"Note that the\nstring that you log cannot contain %n, where n is an integer value\n(for example, %1) because the event viewer treats it as an insertion\nstring. Because an IPv6 address can contain this character sequence,\nyou cannot log an event message that contains an IPv6 address\".\n\nWhat should we do about it? Error out?\n\nStrangely enough, reporting strings with \"%1\" works fine when I test\nit now. Perhaps this is dependent on the windows-version?\n\nYep, it is. On Vista 64 it seems to work, but on WinXP it does not.\nThe string gets expanded into itself 100 times, and then there's\napparently a recursion test.\n\nAlso, it is only %1 that does not report correctly on WinXP, probably\nbecause of a check against the wNumStrings-parameter. Even strings\nlike %11 does not expand.\n\nFormatMessage has the FORMAT_MESSAGE_IGNORE_INSERTS-flag to avoid this\nkind of expansion, but unfortunately I can't find similar\nfunctionality for ReportEvent :(\n"},{"id":"153181","messageId":"4CB22DCD.8080806@gmail.com","threadId":"25410","inReplyTo":"AANLkTinP7RKOhLFZs71P5dpmA1p1OsjikSmVv5WkkL1z@mail.gmail.com","subject":"Re: [PATCH v3 01/14] mingw: add network-wrappers for daemon","fromName":"Eric Sunshine","fromEmail":"ericsunshine@gmail.com","sentAt":"2010-10-10T21:19:09Z","receivedAt":"2010-10-10T21:19:09Z","isPatch":true,"sender":{"key":"ericsunshine@gmail.com","avatar":null},"body":"On 10/10/2010 4:20 PM, Erik Faye-Lund wrote:\n> On Sun, Oct 10, 2010 at 9:40 PM, Eric Sunshine<ericsunshine@gmail.com>  wrote:\n>> On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:\n>>>\n>>> From: Mike Pape<dotzenlabs@gmail.com>\n>>>\n>>> git-daemon requires some socket-functionality that is not yet\n>>> supported in the Windows-port. This patch adds said functionality,\n>>> and makes sure WSAStartup gets called by socket(), since it is the\n>>> first network-call in git-daemon. In addition, a check is added to\n>>> prevent WSAStartup (and WSACleanup, though atexit) from being\n>>> called more than once, since git-daemon calls both socket() and\n>>> gethostbyname().\n>>>\n>>> Signed-off-by: Mike Pape<dotzenlabs@gmail.com>\n>>> Signed-off-by: Erik Faye-Lund<kusmabite@gmail.com>\n>>> ---\n>>> diff --git a/compat/mingw.c b/compat/mingw.c\n>>> index 6590f33..563ef1f 100644\n>>> --- a/compat/mingw.c\n>>> +++ b/compat/mingw.c\n>>> +#undef accept\n>>> +int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)\n>>> +{\n>>> +       int sockfd2;\n>>> +\n>>> +       SOCKET s1 = (SOCKET)_get_osfhandle(sockfd1);\n>>> +       SOCKET s2 = accept(s1, sa, sz);\n>>> +\n>>> +       /* convert into a file descriptor */\n>>> +       if ((sockfd2 = _open_osfhandle(s2, O_RDWR|O_BINARY))<    0) {\n>>> +               closesocket(s2);\n>>> +               return error(\"unable to make a socket file descriptor:\n>>> %s\",\n>>> +                       strerror(errno));\n>>\n>> Is 'errno' from _open_osfhandle() still valid when handed to strerror() or\n>> has it been clobbered by closesocket()?\n>>\n>> Corollary: Does _open_osfhandle() indeed set 'errno', or is it more\n>> appropriate to call WSAGetLastError()? (The documentation I read for\n>> _open_osfhandle() did not say anything about how to determine the reason for\n>> failure.)\n>>\n>\n> _open_osfhandle seems to set both errno and the winsock-error.\n> closesocket() sets the winsock-error but not the CRT. I've just tested\n> with a very simple application:\n> So, it seems that WSAGetLastError() gets clobbered by closesocket(),\n> but not errno.\n\nThank you for checking. Even if it is not strictly needed in this case, \nfor the sake of clarity (and to avoid having this question repeated in \nthe future), it might be worthwhile to save 'errno' or the result of \nWSAGetLastError() in a temporary before invoking closesocket(), and then \npass the temporary to strerror().\n\n-- ES\n"},{"id":"153183","messageId":"4CB22FF3.5070503@gmail.com","threadId":"25410","inReplyTo":"AANLkTinsqAOj7LtACpbcOrVZfeUApDjmQe2uYLH8npBF@mail.gmail.com","subject":"Re: [msysGit] [PATCH v3 02/14] mingw: implement syslog","fromName":"Eric Sunshine","fromEmail":"ericsunshine@gmail.com","sentAt":"2010-10-10T21:28:19Z","receivedAt":"2010-10-10T21:28:19Z","isPatch":true,"sender":{"key":"ericsunshine@gmail.com","avatar":null},"body":"On 10/10/2010 4:37 PM, Erik Faye-Lund wrote:\n> On Sun, Oct 10, 2010 at 9:50 PM, Eric Sunshine<ericsunshine@gmail.com>  wrote:\n>> On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:\n>>>\n>>> From: Mike Pape<dotzenlabs@gmail.com>\n>>>\n>>> Syslog does not usually exist on Windows, so we implement our own\n>>> using Window's ReportEvent mechanism.\n>>>\n>>> Signed-off-by: Mike Pape<dotzenlabs@gmail.com>\n>>> Signed-off-by: Erik Faye-Lund<kusmabite@gmail.com>\n>>> ---\n>>> +void syslog(int priority, const char *fmt, const char *arg)\n>>> +{\n>>> +       WORD logtype;\n>>> +\n>>> +       if (!ms_eventlog)\n>>> +               return;\n>>> +\n>>> +       if (strcmp(fmt, \"%s\")) {\n>>> +               warning(\"format string of syslog() not implemented\");\n>>> +               return;\n>>> +       }\n>>\n>> It is not exactly clear what the intention is here. Is this trying to say\n>> that no formatting directives are allowed in 'fmt' or what? The simple case\n>> it is actually checking (where 'fmt' is solely '%s') could easily be handled\n>> manually, as could more complex formats.\n>>\n>\n> This is the result of the feed-back in v1, where we tried to implement\n> all format strings.\n\nIn retrospect, when thinking more carefully about the conditional \nexpression, I suppose the code is self-documenting, though perhaps a \ncomment in code or in commit message would help.\n\n> But that turned out to be very complex (due to the\n> lack of a portable va_copy()) and since we control all call-sites for\n> syslog and already only use \"%s\" as the format, it should be OK.\n\nDo you mean vsnprintf() rather than va_copy()?\n\n>>> +       /*\n>>> +        * ReportEvent() doesn't handle strings containing %n, where n is\n>>> +        * an integer. Such events must be reformatted by the caller.\n>>> +        */\n>>> +       ReportEventA(ms_eventlog,\n>>> +           logtype,\n>>> +           0,\n>>> +           0,\n>>> +           NULL,\n>>> +           1,\n>>> +           0,\n>>> +           (const char **)&arg,\n>>> +           NULL);\n>>\n>> The comment about '%n' seems to be warning about a potential problem but\n>> does not actually protect against it. Should this issue be handled?\n>>\n>\n> This is again an issue that was discussed in the first round.\n> ReportEvent() CANNOT report a string containing \"%n\" (where n is an\n> integer). And while we could probably try to work around it by\n> inserting a space or something, and I don't think we ever were able to\n> find a case where we could report a string containing \"%n\" in the\n> first place...\n>\n> Are you suggesting that we report an error when we can't report the\n> string correctly? We could do that, but I'm not sure how the end-user\n> would benefit from that. ReportEvent is used to report errors (unless\n> the --verbose flag has been specified), and reporting that we can't\n> present an error message strike me as a bit confusing... Even the\n> corrupted error message is probably better :P\n\nI am not suggesting reporting an error. As a first-time reader of the \ncode, I was trying to understand the presence of the comment which did \nnot really seem to relate to the code. Perhaps adding a \"FIXME\" to the \ncomment saying that the condition should perhaps be handled in the \nfuture would help to explain the comments presence.\n\n(On the other hand, for the '%s' check above, the code does report a \nwarning and then exits, so it is not inconceivable that a '%n' could \nalso emit a warning.)\n\n-- ES\n"},{"id":"153192","messageId":"4CB23689.7020100@sunshineco.com","threadId":"25410","inReplyTo":"AANLkTinmpzo2-eyPrnx0u=tGBOcMBz03LuFUjZO87dG5@mail.gmail.com","subject":"Re: [PATCH v3 05/14] mingw: use real pid","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2010-10-10T21:56:25Z","receivedAt":"2010-10-10T21:56:25Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On 10/10/2010 4:52 PM, Erik Faye-Lund wrote:\n> On Sun, Oct 10, 2010 at 9:53 PM, Eric Sunshine<sunshine@sunshineco.com>  wrote:\n>> On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:\n>>>\n>>> The Windows port so far used process handles as PID. However,\n>>> this does not work consistently with getpid.\n>>\n>> Perhaps this could be elaborated a bit to explain the interaction with\n>> getpid() and how it is causing problems for daemon mode. For the casual\n>> reader, it is not immediately obvious what is failing or why this patch is\n>> needed.\n>>\n>\n> Good point. How about something like this?\n\nThanks. This sort of explanation could indeed be helpful as part of the \ncommit message.\n\n> \"The Windows port so far used process handles as PID. However, this is\n> not consistent with what getpid returns.\n>\n> PIDs are system-global identifiers, but process handles are local to a\n> process. Using PIDs instead of process handles allows for instance a\n> user to kill a hung process with the Task Manager, something that\n> would have been impossible with process handles.\"\n\nMinor nit: Add commas around 'for instance': \"...handles allows, for \ninstance, a user...\"\n\nThese also could be combined into a single paragraph.\n\n-- ES\n"},{"id":"153197","messageId":"AANLkTinBE14dWCecXvpH=8N1b0H=9j9tc=t07d_MHEFF@mail.gmail.com","threadId":"25410","inReplyTo":"4CB22FF3.5070503@gmail.com","subject":"Re: [msysGit] [PATCH v3 02/14] mingw: implement syslog","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T22:16:56Z","receivedAt":"2010-10-10T22:16:56Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sun, Oct 10, 2010 at 11:28 PM, Eric Sunshine <ericsunshine@gmail.com> wrote:\n> On 10/10/2010 4:37 PM, Erik Faye-Lund wrote:\n>>\n>> On Sun, Oct 10, 2010 at 9:50 PM, Eric Sunshine<ericsunshine@gmail.com>\n>>  wrote:\n>>>\n>>> On 10/10/2010 9:20 AM, Erik Faye-Lund wrote:\n>>>>\n>>>> From: Mike Pape<dotzenlabs@gmail.com>\n>>>>\n>>>> Syslog does not usually exist on Windows, so we implement our own\n>>>> using Window's ReportEvent mechanism.\n>>>>\n>>>> Signed-off-by: Mike Pape<dotzenlabs@gmail.com>\n>>>> Signed-off-by: Erik Faye-Lund<kusmabite@gmail.com>\n>>>> ---\n>>>> +void syslog(int priority, const char *fmt, const char *arg)\n>>>> +{\n>>>> +       WORD logtype;\n>>>> +\n>>>> +       if (!ms_eventlog)\n>>>> +               return;\n>>>> +\n>>>> +       if (strcmp(fmt, \"%s\")) {\n>>>> +               warning(\"format string of syslog() not implemented\");\n>>>> +               return;\n>>>> +       }\n>>>\n>>> It is not exactly clear what the intention is here. Is this trying to say\n>>> that no formatting directives are allowed in 'fmt' or what? The simple\n>>> case\n>>> it is actually checking (where 'fmt' is solely '%s') could easily be\n>>> handled\n>>> manually, as could more complex formats.\n>>>\n>>\n>> This is the result of the feed-back in v1, where we tried to implement\n>> all format strings.\n>\n> In retrospect, when thinking more carefully about the conditional\n> expression, I suppose the code is self-documenting, though perhaps a comment\n> in code or in commit message would help.\n>\n>> But that turned out to be very complex (due to the\n>> lack of a portable va_copy()) and since we control all call-sites for\n>> syslog and already only use \"%s\" as the format, it should be OK.\n>\n> Do you mean vsnprintf() rather than va_copy()?\n>\n\nOK, I had to read some old discussions to figure out what the issue was :)\n\nThe problem was lack of portable va_copy, because I tried to add a\nnon-variadic version of strbuf_addf(), namely strbuf_vaddf() to do the\nwork.\n\nI guess it could be implemented pretty easily with vsnprintf(),\nthough. I was afraid of doing that originally because I know there's\nportability issues with the return value of snprintf. Luckily it seems\nthat we have a fix for that in compat/sprintf.c, and we rely on the\nreturn value being correct in strbuf_addf() so it would probably be\nsafe.\n\nSomething like this (on top)\n\n---8<---\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex bbe45d0..e3f3f92 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1435,17 +1435,24 @@ void openlog(const char *ident, int logopt,\nint facility)\n \t\twarning(\"RegisterEventSource() failed: %lu\", GetLastError());\n }\n\n-void syslog(int priority, const char *fmt, const char *arg)\n+void syslog(int priority, const char *fmt, ...)\n {\n \tWORD logtype;\n+\tchar *str;\n+\tint str_len;\n+\tva_list ap;\n\n \tif (!ms_eventlog)\n \t\treturn;\n\n-\tif (strcmp(fmt, \"%s\")) {\n-\t\twarning(\"format string of syslog() not implemented\");\n-\t\treturn;\n-\t}\n+\tva_start(ap, fmt);\n+\tstr_len = vsnprintf(NULL, 0, fmt, ap);\n+\tva_end(ap);\n+\n+\tstr = malloc(str_len + 1);\n+\tva_start(ap, fmt);\n+\tvsnprintf(str, str_len, fmt, ap);\n+\tva_end(ap);\n\n \tswitch (priority) {\n \tcase LOG_EMERG:\n@@ -1478,8 +1485,9 @@ void syslog(int priority, const char *fmt, const\nchar *arg)\n \t    NULL,\n \t    1,\n \t    0,\n-\t    (const char **)&arg,\n+\t    (const char **)&str,\n \t    NULL);\n+\tfree(str);\n }\n\n #undef signal\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex aed49d8..45a63a0 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -186,7 +186,7 @@ int setitimer(int type, struct itimerval *in,\nstruct itimerval *out);\n int sigaction(int sig, struct sigaction *in, struct sigaction *out);\n int link(const char *oldpath, const char *newpath);\n void openlog(const char *ident, int logopt, int facility);\n-void syslog(int priority, const char *fmt, const char *arg);\n+void syslog(int priority, const char *fmt, ...);\n\n /*\n  * replacements of existing functions\n---8<---\n\n>> Are you suggesting that we report an error when we can't report the\n>> string correctly? We could do that, but I'm not sure how the end-user\n>> would benefit from that. ReportEvent is used to report errors (unless\n>> the --verbose flag has been specified), and reporting that we can't\n>> present an error message strike me as a bit confusing... Even the\n>> corrupted error message is probably better :P\n>\n> I am not suggesting reporting an error. As a first-time reader of the code,\n> I was trying to understand the presence of the comment which did not really\n> seem to relate to the code. Perhaps adding a \"FIXME\" to the comment saying\n> that the condition should perhaps be handled in the future would help to\n> explain the comments presence.\n>\n\nA FIXME would certainly a good idea, if I don't just end up supporting\nvarargs here.\n\n> (On the other hand, for the '%s' check above, the code does report a warning\n> and then exits, so it is not inconceivable that a '%n' could also emit a\n> warning.)\n>\n\nI guess I could add something like this:\n\nif (strstr(arg, \"%1\"))\n\twarning(\"arg contains %1, message might be corrupted\");\n\nI don't want to return in that case, because I think some output is\nbetter than no output, and it seems to work on Vista. In fact, working\non Vista is kind of demotivating me to add such a warning in the first\nplace...\n"},{"id":"153198","messageId":"AANLkTin-P1Q8n-+weSODiLGVfUQYae6m3MzW51Yms68X@mail.gmail.com","threadId":"25410","inReplyTo":"AANLkTinBE14dWCecXvpH=8N1b0H=9j9tc=t07d_MHEFF@mail.gmail.com","subject":"Re: [msysGit] [PATCH v3 02/14] mingw: implement syslog","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-10T22:23:57Z","receivedAt":"2010-10-10T22:23:57Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Mon, Oct 11, 2010 at 12:16 AM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> On Sun, Oct 10, 2010 at 11:28 PM, Eric Sunshine <ericsunshine@gmail.com> wrote:\n>> On 10/10/2010 4:37 PM, Erik Faye-Lund wrote:\n>>> Are you suggesting that we report an error when we can't report the\n>>> string correctly? We could do that, but I'm not sure how the end-user\n>>> would benefit from that. ReportEvent is used to report errors (unless\n>>> the --verbose flag has been specified), and reporting that we can't\n>>> present an error message strike me as a bit confusing... Even the\n>>> corrupted error message is probably better :P\n>>\n>> I am not suggesting reporting an error. As a first-time reader of the code,\n>> I was trying to understand the presence of the comment which did not really\n>> seem to relate to the code. Perhaps adding a \"FIXME\" to the comment saying\n>> that the condition should perhaps be handled in the future would help to\n>> explain the comments presence.\n>>\n>\n> A FIXME would certainly a good idea, if I don't just end up supporting\n> varargs here.\n>\n\nUhm, excuse me for confusing the different comments :P\n\nYes, a FIXME should definitely be added. And I definitely need to seep now! ;)\n"},{"id":"153199","messageId":"4CB24A43.9090501@gmail.com","threadId":"25410","inReplyTo":"AANLkTinBE14dWCecXvpH=8N1b0H=9j9tc=t07d_MHEFF@mail.gmail.com","subject":"Re: [PATCH v3 02/14] mingw: implement syslog","fromName":"Eric Sunshine","fromEmail":"ericsunshine@gmail.com","sentAt":"2010-10-10T23:20:35Z","receivedAt":"2010-10-10T23:20:35Z","isPatch":true,"sender":{"key":"ericsunshine@gmail.com","avatar":null},"body":"On 10/10/2010 6:16 PM, Erik Faye-Lund wrote:\n> On Sun, Oct 10, 2010 at 11:28 PM, Eric Sunshine<ericsunshine@gmail.com>  wrote:\n>> On 10/10/2010 4:37 PM, Erik Faye-Lund wrote:\n>>> This is the result of the feed-back in v1, where we tried to implement\n>>> all format strings. But that turned out to be very complex (due to the\n>>> lack of a portable va_copy()) and since we control all call-sites for\n>>> syslog and already only use \"%s\" as the format, it should be OK.\n>>\n>> Do you mean vsnprintf() rather than va_copy()?\n>\n> The problem was lack of portable va_copy, because I tried to add a\n> non-variadic version of strbuf_addf(), namely strbuf_vaddf() to do the\n> work.\n>\n> I guess it could be implemented pretty easily with vsnprintf(),\n> though. I was afraid of doing that originally because I know there's\n> portability issues with the return value of snprintf. Luckily it seems\n> that we have a fix for that in compat/sprintf.c, and we rely on the\n> return value being correct in strbuf_addf() so it would probably be\n> safe.\n>\n> Something like this (on top)\n>\n> diff --git a/compat/mingw.c b/compat/mingw.c\n> index bbe45d0..e3f3f92 100644\n> --- a/compat/mingw.c\n> +++ b/compat/mingw.c\n> @@ -1435,17 +1435,24 @@ void openlog(const char *ident, int logopt,\n> int facility)\n>   \t\twarning(\"RegisterEventSource() failed: %lu\", GetLastError());\n>   }\n>\n> -void syslog(int priority, const char *fmt, const char *arg)\n> +void syslog(int priority, const char *fmt, ...)\n>   {\n>   \tWORD logtype;\n> +\tchar *str;\n> +\tint str_len;\n> +\tva_list ap;\n>\n>   \tif (!ms_eventlog)\n>   \t\treturn;\n>\n> -\tif (strcmp(fmt, \"%s\")) {\n> -\t\twarning(\"format string of syslog() not implemented\");\n> -\t\treturn;\n> -\t}\n> +\tva_start(ap, fmt);\n> +\tstr_len = vsnprintf(NULL, 0, fmt, ap);\n> +\tva_end(ap);\n\nvsnprintf() can return -1 on error (even the compat/snprintf.c version \ncan do so), so perhaps check for this condition before the subsequent \nmalloc(str_len+1)?\n\n> +\n> +\tstr = malloc(str_len + 1);\n> +\tva_start(ap, fmt);\n> +\tvsnprintf(str, str_len, fmt, ap);\n> +\tva_end(ap);\n>\n>   \tswitch (priority) {\n>   \tcase LOG_EMERG:\n> @@ -1478,8 +1485,9 @@ void syslog(int priority, const char *fmt, const\n> char *arg)\n>   \t    NULL,\n>   \t    1,\n>   \t    0,\n> -\t    (const char **)&arg,\n> +\t    (const char **)&str,\n>   \t    NULL);\n> +\tfree(str);\n>   }\n\nOther than the note about -1 return value, this revision looks fine.\n\n>> (On the other hand, for the '%s' check above, the code does report a warning\n>> and then exits, so it is not inconceivable that a '%n' could also emit a\n>> warning.)\n>\n> I guess I could add something like this:\n>\n> if (strstr(arg, \"%1\"))\n> \twarning(\"arg contains %1, message might be corrupted\");\n>\n> I don't want to return in that case, because I think some output is\n> better than no output, and it seems to work on Vista.\n\nRather than emitting a warning, it might be reasonable to perform a \nsimple transformation on the string if it contains a %1 (or %n \ngenerally) in order to avoid ReportEvent()'s shortcoming. Even something \nas simple as inserting a space between '%' and '1' might be sufficiently \ndefensive.\n\n-- ES\n"},{"id":"153238","messageId":"AANLkTi==sd=jm9LZ6p6NLVBMc4wnU0PrYvJY6ezGWiWt@mail.gmail.com","threadId":"25410","inReplyTo":"4CB24A43.9090501@gmail.com","subject":"Re: [msysGit] [PATCH v3 02/14] mingw: implement syslog","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T15:28:16Z","receivedAt":"2010-10-11T15:28:16Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Mon, Oct 11, 2010 at 1:20 AM, Eric Sunshine <ericsunshine@gmail.com> wrote:\n> On 10/10/2010 6:16 PM, Erik Faye-Lund wrote:\n>>\n>> On Sun, Oct 10, 2010 at 11:28 PM, Eric Sunshine<ericsunshine@gmail.com>\n>>  wrote:\n>>> (On the other hand, for the '%s' check above, the code does report a\n>>> warning\n>>> and then exits, so it is not inconceivable that a '%n' could also emit a\n>>> warning.)\n>>\n>> I guess I could add something like this:\n>>\n>> if (strstr(arg, \"%1\"))\n>>        warning(\"arg contains %1, message might be corrupted\");\n>>\n>> I don't want to return in that case, because I think some output is\n>> better than no output, and it seems to work on Vista.\n>\n> Rather than emitting a warning, it might be reasonable to perform a simple\n> transformation on the string if it contains a %1 (or %n generally) in order\n> to avoid ReportEvent()'s shortcoming. Even something as simple as inserting\n> a space between '%' and '1' might be sufficiently defensive.\n>\n\nYes, but I'm tempted to defer fixing this until we see that it's a\nproblem in reality. The logic to somehow escape such sequences looks a\nbit nasty in my head. But perhaps strbuf_expand() is the right hammer\nfor this use...\n\nThen the logical next question becomes what we should expand it to.\nDoes \"%1\" -> \"% 1\" make sense for IPv6 addresses?\n"},{"id":"153240","messageId":"AANLkTikXMCgC0P-=255SRvqfDSGua7Gcb-jmqS8paUNj@mail.gmail.com","threadId":"25410","inReplyTo":"AANLkTi==sd=jm9LZ6p6NLVBMc4wnU0PrYvJY6ezGWiWt@mail.gmail.com","subject":"Re: [msysGit] [PATCH v3 02/14] mingw: implement syslog","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T15:59:59Z","receivedAt":"2010-10-11T15:59:59Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Mon, Oct 11, 2010 at 5:28 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> On Mon, Oct 11, 2010 at 1:20 AM, Eric Sunshine <ericsunshine@gmail.com> wrote:\n>> On 10/10/2010 6:16 PM, Erik Faye-Lund wrote:\n>>>\n>>> On Sun, Oct 10, 2010 at 11:28 PM, Eric Sunshine<ericsunshine@gmail.com>\n>>>  wrote:\n>>>> (On the other hand, for the '%s' check above, the code does report a\n>>>> warning\n>>>> and then exits, so it is not inconceivable that a '%n' could also emit a\n>>>> warning.)\n>>>\n>>> I guess I could add something like this:\n>>>\n>>> if (strstr(arg, \"%1\"))\n>>>        warning(\"arg contains %1, message might be corrupted\");\n>>>\n>>> I don't want to return in that case, because I think some output is\n>>> better than no output, and it seems to work on Vista.\n>>\n>> Rather than emitting a warning, it might be reasonable to perform a simple\n>> transformation on the string if it contains a %1 (or %n generally) in order\n>> to avoid ReportEvent()'s shortcoming. Even something as simple as inserting\n>> a space between '%' and '1' might be sufficiently defensive.\n>>\n>\n> Yes, but I'm tempted to defer fixing this until we see that it's a\n> problem in reality. The logic to somehow escape such sequences looks a\n> bit nasty in my head. But perhaps strbuf_expand() is the right hammer\n> for this use...\n>\n> Then the logical next question becomes what we should expand it to.\n> Does \"%1\" -> \"% 1\" make sense for IPv6 addresses?\n>\n\nSomething along these lines? (on top of the previous patch, uhm, with\nsome local modifications. Sorry, I'm not at home and do not have the\noriginal version at hand. I'm sure you get the picture, though...)\n\nI also added a +1 that was missing and caused the string to be capped.\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex ae6b448..d1444d2 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1438,6 +1438,11 @@ void openlog(const char *ident, int logopt, int facility)\n\n void syslog(int priority, const char *fmt, ...)\n {\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tstruct strbuf_expand_dict_entry dict[] = {\n+\t\t{\"1\", \"% 1\"},\n+\t\t{NULL, NULL}\n+\t};\n \tWORD logtype;\n \tchar *str;\n \tint str_len;\n@@ -1457,8 +1462,9 @@ void syslog(int priority, const char *fmt, ...)\n\n \tstr = malloc(str_len + 1);\n \tva_start(ap, fmt);\n-\tvsnprintf(str, str_len, fmt, ap);\n+\tvsnprintf(str, str_len + 1, fmt, ap);\n \tva_end(ap);\n+\tstrbuf_expand(&sb, str, strbuf_expand_dict_cb, &dict);\n\n \tswitch (priority) {\n \tcase LOG_EMERG:\n@@ -1480,10 +1486,6 @@ void syslog(int priority, const char *fmt, ...)\n \t\tbreak;\n \t}\n\n-\t/*\n-\t * FIXME: ReportEvent() doesn't handle strings containing \"%1\".\n-\t * Such events must currently be reformatted by the caller.\n-\t */\n \tReportEventA(ms_eventlog,\n \t    logtype,\n \t    0,\n@@ -1491,9 +1493,10 @@ void syslog(int priority, const char *fmt, ...)\n \t    NULL,\n \t    1,\n \t    0,\n-\t    (const char **)&str,\n+\t    (const char **)&sb.buf,\n \t    NULL);\n \tfree(str);\n+\tsb_release(&sb);\n }\n\n #undef signal\ndiff --git a/daemon.c b/daemon.c\n"}]}