{"thread":{"id":"25421","subject":"[PATCH v4 00/15] daemon-win32","startedAt":"2010-10-11T21:50:14Z","lastAt":"2010-10-21T23:17:04Z","messageCount":47,"participants":["Erik Faye-Lund","Jonathan Nieder","Eric Sunshine","Pat Thoyts","Junio C Hamano","Andreas Schwab"],"isPatch":true,"patchVersion":4,"patchTotal":15},"messages":[{"id":"153261","messageId":"1286833829-5116-1-git-send-email-kusmabite@gmail.com","threadId":"25421","inReplyTo":null,"subject":"[PATCH v4 00/15] daemon-win32","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T21:50:14Z","receivedAt":"2010-10-11T21:50:14Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"OK, here's v3 of this series. Since the last version, the following\nthings were done:\n* 01/14 has the error-path cleaned up, as suggested by Eric Sunshine\n* 02/14 now supports any vararg input, and escapes \"%1\" to \"% 1\" to\n  avoid a limitation ni ReportEvent(). The code has also been moved\n  to compat/win32/syslog.[ch], since it's fairly self contained and\n  it's not strictly speaking a mingw-specific thing.\n* 05/14 now has an extended commit message, detailing the rationale\n  a bit more\n* 08/14 has been fixed up as suggested by Eric Sunshine\n* 11/14 has been fixed up to remove code left dead by the previous\n  version\n* 12/14 has a better commit message, including an explanation on\n  how to update the code. The sources have also been moved to\n  compat/win32/sys/poll.[ch], which is where git usually looks for\n  the poll-header.\n* 14/14 has been split out into 14/15 and 15/15, because it\n  contained some left-over changes (unsigned int -> socklen_t). The\n  left-over code is 14/15.\n* 15/15 have the _POSIX_VERSION-check replaced with a check for\n  NO_POSIX_GOODIES. It has been changed back to opt-out, since I\n  don't want to have to deal with figuring out what platforms it\n  will work for or not. Currently all platforms except from Windows\n  supports all posix-\"goodies\", but it should be easy to opt-out\n  for a future plaform.\n\nErik Faye-Lund (11):\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: use socklen_t\n  daemon: opt-out on features that require posix\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                |   23 ++-\n compat/inet_ntop.c      |   22 +--\n compat/inet_pton.c      |    8 +-\n compat/mingw.c          |  232 +++++++++++++------\n compat/mingw.h          |   41 ++--\n compat/win32/sys/poll.c |  596 +++++++++++++++++++++++++++++++++++++++++++++++\n compat/win32/sys/poll.h |   53 +++++\n compat/win32/syslog.c   |   72 ++++++\n compat/win32/syslog.h   |   20 ++\n daemon.c                |  199 +++++++++-------\n git-compat-util.h       |   11 +-\n 11 files changed, 1067 insertions(+), 210 deletions(-)\n create mode 100644 compat/win32/sys/poll.c\n create mode 100644 compat/win32/sys/poll.h\n create mode 100644 compat/win32/syslog.c\n create mode 100644 compat/win32/syslog.h\n\n-- \n1.7.3.1.199.g72340\n"},{"id":"153262","messageId":"1286833829-5116-2-git-send-email-kusmabite@gmail.com","threadId":"25421","inReplyTo":"1286833829-5116-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v4 01/15] mingw: add network-wrappers for daemon","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T21:50:15Z","receivedAt":"2010-10-11T21:50:15Z","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.\n\nSigned-off-by: Mike Pape <dotzenlabs@gmail.com>\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n compat/mingw.c |   44 +++++++++++++++++++++++++++++++++++++++++++-\n compat/mingw.h |   16 ++++++++++++++++\n 2 files changed, 59 insertions(+), 1 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 6590f33..701a555 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,45 @@ 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\tint err = errno;\n+\t\tclosesocket(s2);\n+\t\treturn error(\"unable to make a socket file descriptor: %s\",\n+\t\t\tstrerror(err));\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.199.g72340\n"},{"id":"153263","messageId":"1286833829-5116-3-git-send-email-kusmabite@gmail.com","threadId":"25421","inReplyTo":"1286833829-5116-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v4 02/15] mingw: implement syslog","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T21:50:16Z","receivedAt":"2010-10-11T21:50:16Z","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\nStrings containing \"%1\" gets corrupted by ReportEvent, so expand\n\"%1\" to \"% 1\" before reporting.\n\nSigned-off-by: Mike Pape <dotzenlabs@gmail.com>\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n Makefile              |    5 ++-\n compat/win32/syslog.c |   72 +++++++++++++++++++++++++++++++++++++++++++++++++\n compat/win32/syslog.h |   20 +++++++++++++\n daemon.c              |    2 -\n git-compat-util.h     |    1 +\n 5 files changed, 96 insertions(+), 4 deletions(-)\n create mode 100644 compat/win32/syslog.c\n create mode 100644 compat/win32/syslog.h\n\ndiff --git a/Makefile b/Makefile\nindex 1f1ce04..d9d9419 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -496,6 +496,7 @@ LIB_H += compat/bswap.h\n LIB_H += compat/cygwin.h\n LIB_H += compat/mingw.h\n LIB_H += compat/win32/pthread.h\n+LIB_H += compat/win32/syslog.h\n LIB_H += csum-file.h\n LIB_H += decorate.h\n LIB_H += delta.h\n@@ -1081,7 +1082,7 @@ ifeq ($(uname_S),Windows)\n \tAR = compat/vcbuild/scripts/lib.pl\n \tCFLAGS =\n \tBASIC_CFLAGS = -nologo -I. -I../zlib -Icompat/vcbuild -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE\n-\tCOMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o compat/win32/pthread.o\n+\tCOMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o compat/win32/pthread.o compat/win32/syslog.o\n \tCOMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/fnmatch -Icompat/regex -Icompat/fnmatch -Icompat/win32 -DSTRIP_EXTENSION=\\\".exe\\\"\n \tBASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib\n \tEXTLIBS = advapi32.lib shell32.lib wininet.lib ws2_32.lib\n@@ -1131,7 +1132,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/syslog.o\n \tEXTLIBS += -lws2_32\n \tPTHREAD_LIBS =\n \tX = .exe\ndiff --git a/compat/win32/syslog.c b/compat/win32/syslog.c\nnew file mode 100644\nindex 0000000..42b95a9\n--- /dev/null\n+++ b/compat/win32/syslog.c\n@@ -0,0 +1,72 @@\n+#include \"../../git-compat-util.h\"\n+#include \"../../strbuf.h\"\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, ...)\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+\tva_list ap;\n+\n+\tif (!ms_eventlog)\n+\t\treturn;\n+\n+\tva_start(ap, fmt);\n+\tstr_len = vsnprintf(NULL, 0, fmt, ap);\n+\tva_end(ap);\n+\n+\tif (str_len < 0) {\n+\t\twarning(\"vsnprintf failed: '%s'\", strerror(errno));\n+\t\treturn;\n+\t}\n+\n+\tstr = malloc(str_len + 1);\n+\tva_start(ap, fmt);\n+\tvsnprintf(str, str_len + 1, fmt, ap);\n+\tva_end(ap);\n+\tstrbuf_expand(&sb, str, strbuf_expand_dict_cb, &dict);\n+\tfree(str);\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+\tReportEventA(ms_eventlog, logtype, 0, 0, NULL, 1, 0,\n+\t    (const char **)&sb.buf, NULL);\n+\n+\tstrbuf_release(&sb);\n+}\ndiff --git a/compat/win32/syslog.h b/compat/win32/syslog.h\nnew file mode 100644\nindex 0000000..70daa7c\n--- /dev/null\n+++ b/compat/win32/syslog.h\n@@ -0,0 +1,20 @@\n+#ifndef SYSLOG_H\n+#define SYSLOG_H\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+void openlog(const char *ident, int logopt, int facility);\n+void syslog(int priority, const char *fmt, ...);\n+\n+#endif /* SYSLOG_H */\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..e192831 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -104,6 +104,7 @@\n #include <assert.h>\n #include <regex.h>\n #include <utime.h>\n+#include <syslog.h>\n #ifndef __MINGW32__\n #include <sys/wait.h>\n #include <sys/poll.h>\n-- \n1.7.3.1.199.g72340\n"},{"id":"153264","messageId":"1286833829-5116-4-git-send-email-kusmabite@gmail.com","threadId":"25421","inReplyTo":"1286833829-5116-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v4 03/15] compat: add inet_pton and inet_ntop prototypes","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T21:50:17Z","receivedAt":"2010-10-11T21:50:17Z","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 d9d9419..2aa067a 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1398,9 +1398,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 e192831..56dce85 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.199.g72340\n"},{"id":"153265","messageId":"1286833829-5116-5-git-send-email-kusmabite@gmail.com","threadId":"25421","inReplyTo":"1286833829-5116-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v4 04/15] inet_ntop: fix a couple of old-style decls","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T21:50:18Z","receivedAt":"2010-10-11T21:50:18Z","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.199.g72340\n"},{"id":"153266","messageId":"1286833829-5116-6-git-send-email-kusmabite@gmail.com","threadId":"25421","inReplyTo":"1286833829-5116-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v4 05/15] mingw: use real pid","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T21:50:19Z","receivedAt":"2010-10-11T21:50:19Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"The Windows port have so far been using process handles in place\nof PID. However, this is not work consistent with what getpid\nreturns.\n\nPIDs are system-global identifiers, but process handles are local\nto a process. Using PIDs instead of process handles allows, for\ninstance, a user to kill a hung process with the Task Manager,\nsomething that would have been impossible with process handles.\n\nChange the code to use the real PID, and use OpenProcess to get a\nprocess-handle. Store the PID and the process handle in a table\nprotected by a critical section, so we can safely close the\nprocess 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 701a555..e2e3c54 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@@ -1518,6 +1541,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 a5bde82..7c4eeea 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -140,13 +140,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@@ -321,11 +315,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.199.g72340\n"},{"id":"153267","messageId":"1286833829-5116-7-git-send-email-kusmabite@gmail.com","threadId":"25421","inReplyTo":"1286833829-5116-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v4 06/15] mingw: support waitpid with pid > 0 and WNOHANG","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T21:50:20Z","receivedAt":"2010-10-11T21:50:20Z","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 e2e3c54..2e7c644 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1550,6 +1550,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 7c4eeea..379d7bf 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -140,6 +140,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.199.g72340\n"},{"id":"153268","messageId":"1286833829-5116-8-git-send-email-kusmabite@gmail.com","threadId":"25421","inReplyTo":"1286833829-5116-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v4 07/15] mingw: add kill emulation","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T21:50:21Z","receivedAt":"2010-10-11T21:50:21Z","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 2e7c644..21d1c2c 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 379d7bf..51fca2f 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -143,6 +143,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.199.g72340\n"},{"id":"153269","messageId":"1286833829-5116-9-git-send-email-kusmabite@gmail.com","threadId":"25421","inReplyTo":"1286833829-5116-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v4 08/15] daemon: use run-command api for async serving","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T21:50:22Z","receivedAt":"2010-10-11T21:50:22Z","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 |   84 +++++++++++++++++++++++++++++++-------------------------------\n 1 files changed, 42 insertions(+), 42 deletions(-)\n\ndiff --git a/daemon.c b/daemon.c\nindex d594375..c0da052 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@@ -661,7 +648,7 @@ static void kill_some_child(void)\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+static 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.199.g72340\n"},{"id":"153270","messageId":"1286833829-5116-10-git-send-email-kusmabite@gmail.com","threadId":"25421","inReplyTo":"1286833829-5116-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v4 09/15] daemon: use full buffered mode for stderr","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T21:50:23Z","receivedAt":"2010-10-11T21:50:23Z","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 c0da052..8a44fb9 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.199.g72340\n"},{"id":"153271","messageId":"1286833829-5116-11-git-send-email-kusmabite@gmail.com","threadId":"25421","inReplyTo":"1286833829-5116-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v4 10/15] Improve the mingw getaddrinfo stub to handle more use cases","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T21:50:24Z","receivedAt":"2010-10-11T21:50:24Z","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 21d1c2c..d88c0d0 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.199.g72340\n"},{"id":"153272","messageId":"1286833829-5116-12-git-send-email-kusmabite@gmail.com","threadId":"25421","inReplyTo":"1286833829-5116-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v4 11/15] daemon: report connection from root-process","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T21:50:25Z","receivedAt":"2010-10-11T21:50:25Z","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 |   72 ++++++++++++++++++++++++++++++-------------------------------\n 1 files changed, 35 insertions(+), 37 deletions(-)\n\ndiff --git a/daemon.c b/daemon.c\nindex 8a44fb9..1574f75 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -516,38 +516,11 @@ static void parse_host_arg(char *extra_args, int buflen)\n }\n \n \n-static int execute(struct sockaddr *addr)\n+static int execute(void)\n {\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 static 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@@ -1157,17 +1162,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\tpeer = NULL;\n-\n-\t\treturn execute(peer);\n+\t\treturn execute();\n \t}\n \n \tif (detach) {\n-- \n1.7.3.1.199.g72340\n"},{"id":"153273","messageId":"1286833829-5116-13-git-send-email-kusmabite@gmail.com","threadId":"25421","inReplyTo":"1286833829-5116-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v4 12/15] mingw: import poll-emulation from gnulib","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T21:50:26Z","receivedAt":"2010-10-11T21:50:26Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"copy lib/poll.c and lib/poll.in.h verbatim from commit 0a05120 in\ngit://git.savannah.gnu.org/gnulib.git to compat/win32/sys/poll.[ch]\n\nTo upgrade this code in the future, branch out from this commit, copy\nnew versions of the files above on top, and merge back the result.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n compat/win32/sys/poll.c |  597 +++++++++++++++++++++++++++++++++++++++++++++++\n compat/win32/sys/poll.h |   53 +++++\n 2 files changed, 650 insertions(+), 0 deletions(-)\n create mode 100644 compat/win32/sys/poll.c\n create mode 100644 compat/win32/sys/poll.h\n\ndiff --git a/compat/win32/sys/poll.c b/compat/win32/sys/poll.c\nnew file mode 100644\nindex 0000000..7c52cb6\n--- /dev/null\n+++ b/compat/win32/sys/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/sys/poll.h b/compat/win32/sys/poll.h\nnew file mode 100644\nindex 0000000..b7aa59d\n--- /dev/null\n+++ b/compat/win32/sys/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.199.g72340\n"},{"id":"153274","messageId":"1286833829-5116-14-git-send-email-kusmabite@gmail.com","threadId":"25421","inReplyTo":"1286833829-5116-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v4 13/15] mingw: use poll-emulation from gnulib","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T21:50:27Z","receivedAt":"2010-10-11T21:50:27Z","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                |    6 +++-\n compat/mingw.c          |   65 -----------------------------------------------\n compat/mingw.h          |   11 --------\n compat/win32/sys/poll.c |    3 +-\n git-compat-util.h       |    2 +-\n 5 files changed, 6 insertions(+), 81 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 2aa067a..46034bf 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -497,6 +497,7 @@ LIB_H += compat/cygwin.h\n LIB_H += compat/mingw.h\n LIB_H += compat/win32/pthread.h\n LIB_H += compat/win32/syslog.h\n+LIB_H += compat/win32/sys/poll.h\n LIB_H += csum-file.h\n LIB_H += decorate.h\n LIB_H += delta.h\n@@ -1082,7 +1083,7 @@ ifeq ($(uname_S),Windows)\n \tAR = compat/vcbuild/scripts/lib.pl\n \tCFLAGS =\n \tBASIC_CFLAGS = -nologo -I. -I../zlib -Icompat/vcbuild -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE\n-\tCOMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o compat/win32/pthread.o compat/win32/syslog.o\n+\tCOMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o compat/win32/pthread.o compat/win32/syslog.o compat/win32/sys/poll.o\n \tCOMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/fnmatch -Icompat/regex -Icompat/fnmatch -Icompat/win32 -DSTRIP_EXTENSION=\\\".exe\\\"\n \tBASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib\n \tEXTLIBS = advapi32.lib shell32.lib wininet.lib ws2_32.lib\n@@ -1132,7 +1133,8 @@ 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 compat/win32/syslog.o\n+\t\tcompat/win32/pthread.o compat/win32/syslog.o \\\n+\t\tcompat/win32/sys/poll.o\n \tEXTLIBS += -lws2_32\n \tPTHREAD_LIBS =\n \tX = .exe\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex d88c0d0..b780200 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 51fca2f..99a7467 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -59,16 +59,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@@ -175,7 +165,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/sys/poll.c b/compat/win32/sys/poll.c\nindex 7c52cb6..c1ca0d2 100644\n--- a/compat/win32/sys/poll.c\n+++ b/compat/win32/sys/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 56dce85..d0a1e48 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -105,9 +105,9 @@\n #include <regex.h>\n #include <utime.h>\n #include <syslog.h>\n+#include <sys/poll.h>\n #ifndef __MINGW32__\n #include <sys/wait.h>\n-#include <sys/poll.h>\n #include <sys/socket.h>\n #include <sys/ioctl.h>\n #include <termios.h>\n-- \n1.7.3.1.199.g72340\n"},{"id":"153275","messageId":"1286833829-5116-15-git-send-email-kusmabite@gmail.com","threadId":"25421","inReplyTo":"1286833829-5116-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v4 14/15] daemon: use socklen_t","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T21:50:28Z","receivedAt":"2010-10-11T21:50:28Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"---\n daemon.c |    6 +++---\n 1 files changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/daemon.c b/daemon.c\nindex 1574f75..9b97b58 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -593,7 +593,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 +672,7 @@ static char *get_addrstr(int *port, struct sockaddr *addr)\n }\n \n static 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 +908,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-- \n1.7.3.1.199.g72340\n"},{"id":"153276","messageId":"1286833829-5116-16-git-send-email-kusmabite@gmail.com","threadId":"25421","inReplyTo":"1286833829-5116-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v4 15/15] daemon: opt-out on features that require posix","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T21:50:29Z","receivedAt":"2010-10-11T21:50:29Z","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 if the NO_POSIX_GOODIES flag is set.\n\nMinGW doesn't have prototypes and headers for inet_ntop and inet_pton,\nso include our implementation instead. MSVC does have, so avoid doing\nso there.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n Makefile |   14 +++++++++-----\n daemon.c |   37 ++++++++++++++++++++++++++++---------\n 2 files changed, 37 insertions(+), 14 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 46034bf..53986b1 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@@ -1066,7 +1067,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@@ -1077,6 +1077,7 @@ ifeq ($(uname_S),Windows)\n \tNO_CURL = YesPlease\n \tNO_PYTHON = YesPlease\n \tBLK_SHA1 = YesPlease\n+\tNO_POSIX_GOODIES = UnfortunatelyYes\n \tNATIVE_CRLF = YesPlease\n \n \tCC = compat/vcbuild/scripts/clink.pl\n@@ -1119,7 +1120,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@@ -1130,6 +1130,9 @@ 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+\tNO_POSIX_GOODIES = UnfortunatelyYes\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@@ -1249,9 +1252,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\n@@ -1419,6 +1419,10 @@ ifdef NO_DEFLATE_BOUND\n \tBASIC_CFLAGS += -DNO_DEFLATE_BOUND\n endif\n \n+ifdef NO_POSIX_GOODIES\n+\tBASIC_CFLAGS += -DNO_POSIX_GOODIES\n+endif\n+\n ifdef BLK_SHA1\n \tSHA1_HEADER = \"block-sha1/sha1.h\"\n \tLIB_OBJS += block-sha1/sha1.o\ndiff --git a/daemon.c b/daemon.c\nindex 9b97b58..aa580f6 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+#ifndef NO_POSIX_GOODIES\n+\"           [--detach] [--user=user [--group=group]]\\n\"\n+#endif\n \"           [directory...]\";\n \n /* List of acceptable pathname prefixes */\n@@ -938,6 +940,7 @@ static void sanitize_stdfds(void)\n \t\tclose(fd);\n }\n \n+#ifndef NO_POSIX_GOODIES\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+#ifndef NO_POSIX_GOODIES\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+#ifndef NO_POSIX_GOODIES\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+#ifndef NO_POSIX_GOODIES\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+#ifndef NO_POSIX_GOODIES\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+#ifndef NO_POSIX_GOODIES\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+#ifndef NO_POSIX_GOODIES\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@@ -1168,11 +1185,13 @@ int main(int argc, char **argv)\n \t\treturn execute();\n \t}\n \n+#ifndef NO_POSIX_GOODIES\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@@ -1185,5 +1204,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.199.g72340\n"},{"id":"153277","messageId":"20101011220742.GA6277@burratino","threadId":"25421","inReplyTo":"1286833829-5116-2-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v4 01/15] mingw: add network-wrappers for daemon","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-10-11T22:07:42Z","receivedAt":"2010-10-11T22:07:42Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"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.\n\nFor the curious: gethostbyname(), getaddrinfo(), and getnameinfo()\nalready call WSAStartup if it hasn't already been called.  So\nimap-send and the libgit transport code do not suffer from the same\nproblem.  Similarly for git daemon in the !NO_IPV6 case.\n\nIn the NO_IPV6 case, git daemon does not call getaddrinfo() and\n--listen=<hostname> does not work (why?), so we have to hook into\nsocket(), too.\n\nLooks good to my winsock-ignorant eyes.\n"},{"id":"153278","messageId":"20101011221146.GB6277@burratino","threadId":"25421","inReplyTo":"1286833829-5116-3-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v4 02/15] mingw: implement syslog","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-10-11T22:11:46Z","receivedAt":"2010-10-11T22:11:46Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Erik Faye-Lund wrote:\n\n> Strings containing \"%1\" gets corrupted by ReportEvent, so expand\n> \"%1\" to \"% 1\" before reporting.\n\nWhat is the symptom?  Can clients trigger this, and is it worth\npreventing them from doing so?\n"},{"id":"153279","messageId":"AANLkTinkpTavtw3Rmubfht56tzGnHckHXRc0L-C83daE@mail.gmail.com","threadId":"25421","inReplyTo":"20101011221146.GB6277@burratino","subject":"Re: [PATCH v4 02/15] mingw: implement syslog","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-11T22:28:40Z","receivedAt":"2010-10-11T22:28:40Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Tue, Oct 12, 2010 at 12:11 AM, Jonathan Nieder <jrnieder@gmail.com> wrote:\n> Erik Faye-Lund wrote:\n>\n>> Strings containing \"%1\" gets corrupted by ReportEvent, so expand\n>> \"%1\" to \"% 1\" before reporting.\n>\n> What is the symptom?  Can clients trigger this, and is it worth\n> preventing them from doing so?\n>\n\nThe string gets inlined into itself (with a limit of 100 expansions)\nleading to string like \"foo %1 bar\" becoming \"foo foo foo ... foo %1\nbar bar bar ... bar\". With our expansion, it becomes \"foo % 1 bar\"\ninstead.\n"},{"id":"153280","messageId":"20101011223746.GA6637@burratino","threadId":"25421","inReplyTo":"AANLkTinkpTavtw3Rmubfht56tzGnHckHXRc0L-C83daE@mail.gmail.com","subject":"Re: [PATCH v4 02/15] mingw: implement syslog","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-10-11T22:37:46Z","receivedAt":"2010-10-11T22:37:46Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Erik Faye-Lund wrote:\n\n> The string gets inlined into itself (with a limit of 100 expansions)\n> leading to string like \"foo %1 bar\" becoming \"foo foo foo ... foo %1\n> bar bar bar ... bar\". With our expansion, it becomes \"foo % 1 bar\"\n> instead.\n\nAh, ok.  Sounds like there is no need to worry about requests for \"%%1\"\netc.  Thanks for explaining.\n\nMaybe the symptoms and cases not covered (%2, %%1) would be worth\nmentioning in the log message?\n"},{"id":"153400","messageId":"AANLkTinBvZ_L-fq1u4tPX6rNW6X3jeoOO23-yLpdxSu0@mail.gmail.com","threadId":"25421","inReplyTo":"20101011223746.GA6637@burratino","subject":"Re: [PATCH v4 02/15] mingw: implement syslog","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-13T12:36:27Z","receivedAt":"2010-10-13T12:36:27Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Tue, Oct 12, 2010 at 12:37 AM, Jonathan Nieder <jrnieder@gmail.com> wrote:\n> Erik Faye-Lund wrote:\n>\n>> The string gets inlined into itself (with a limit of 100 expansions)\n>> leading to string like \"foo %1 bar\" becoming \"foo foo foo ... foo %1\n>> bar bar bar ... bar\". With our expansion, it becomes \"foo % 1 bar\"\n>> instead.\n>\n> Ah, ok.  Sounds like there is no need to worry about requests for \"%%1\"\n> etc.  Thanks for explaining.\n>\n\nActually, %%1 is a bit of a tricky one. It seems that %%1 is used to\nescape %1 on Windows 7, but not on earlier Windows version. I did test\nthis on Vista an XP earlier, but I'll re-test again later and report\nback, in case my earlier tests were flawed.\n\nCan %%1 occur in an IPv6 address at all? If not, I'm tempted to not\nhandle it (unless it turns out I was wrong about %%1-escaping on Vista\nand XP).\n\n> Maybe the symptoms and cases not covered (%2, %%1) would be worth\n> mentioning in the log message?\n>\n\nSorry for the late reply.\n\nI'm sure it could be added, I'm just a bit worried about making the\nwhole commit message too intimidating.\n\nSomething like this, perhaps?\n\n---8<---\nStrings containing \"%1\" gets expanded into themselves by ReportEvent,\nso let's expand \"%1\" to \"% 1\" before reporting, because such string\ncan occur in IPv6-addresses. \"%2\" and above does not appear to be a\nproblem, probably because ReportEvent checks the number against the\nwNumStrings parameter first. \"%%1\" is still a problem, but we don't\nhave a code-path producing such strings.\n---8<---\n\nThis is (of course), assuming my current findings are correct.\n\nThe lack of documentation on the subject is really annoying.\n"},{"id":"153429","messageId":"4CB60743.2030908@sunshineco.com","threadId":"25421","inReplyTo":"AANLkTinBvZ_L-fq1u4tPX6rNW6X3jeoOO23-yLpdxSu0@mail.gmail.com","subject":"Re: [PATCH v4 02/15] mingw: implement syslog","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2010-10-13T19:23:47Z","receivedAt":"2010-10-13T19:23:47Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On 10/13/2010 08:36 AM, Erik Faye-Lund wrote:\n> On Tue, Oct 12, 2010 at 12:37 AM, Jonathan Nieder<jrnieder@gmail.com>  wrote:\n>> Erik Faye-Lund wrote:\n>>\n>>> The string gets inlined into itself (with a limit of 100 expansions)\n>>> leading to string like \"foo %1 bar\" becoming \"foo foo foo ... foo %1\n>>> bar bar bar ... bar\". With our expansion, it becomes \"foo % 1 bar\"\n>>> instead.\n>>\n>> Ah, ok.  Sounds like there is no need to worry about requests for \"%%1\"\n>> etc.  Thanks for explaining.\n>>\n> Actually, %%1 is a bit of a tricky one. It seems that %%1 is used to\n> escape %1 on Windows 7, but not on earlier Windows version. I did test\n> this on Vista an XP earlier, but I'll re-test again later and report\n> back, in case my earlier tests were flawed.\n\nIf that worked universally, escaping '%1' to '%%1' certainly would be \nnicer than '% 1'. (More generally, escape '%n' to '%%n', where n is a \nnumber.) It also would simplify the log message.\n\n> Can %%1 occur in an IPv6 address at all? If not, I'm tempted to not\n> handle it (unless it turns out I was wrong about %%1-escaping on Vista\n> and XP).\n\nAccording to sources I have studied, %%1 would be unlikely (or perhaps \ninvalid) in IPv6 addresses.\n\nhttp://en.wikipedia.org/wiki/IPv6_address#Link-local_addresses_and_zone_indices\n\n-- ES\n"},{"id":"153444","messageId":"AANLkTinj21hnpsHR49nS0u_FtpwA=2Q7ygNpowufRoDC@mail.gmail.com","threadId":"25421","inReplyTo":"4CB60743.2030908@sunshineco.com","subject":"Re: [msysGit] Re: [PATCH v4 02/15] mingw: implement syslog","fromName":"Pat Thoyts","fromEmail":"patthoyts@gmail.com","sentAt":"2010-10-13T21:17:19Z","receivedAt":"2010-10-13T21:17:19Z","isPatch":true,"sender":{"key":"patthoyts@gmail.com","avatar":"https://gravatar.com/avatar/bee887a777c790bd241f398217723fbe4b854428671db83db32216a28654cb25?d=mp&s=160"},"body":"On 13 October 2010 20:23, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On 10/13/2010 08:36 AM, Erik Faye-Lund wrote:\n>>\n>> On Tue, Oct 12, 2010 at 12:37 AM, Jonathan Nieder<jrnieder@gmail.com>\n>>  wrote:\n>>>\n>>> Erik Faye-Lund wrote:\n>>>\n>>>> The string gets inlined into itself (with a limit of 100 expansions)\n>>>> leading to string like \"foo %1 bar\" becoming \"foo foo foo ... foo %1\n>>>> bar bar bar ... bar\". With our expansion, it becomes \"foo % 1 bar\"\n>>>> instead.\n>>>\n>>> Ah, ok.  Sounds like there is no need to worry about requests for \"%%1\"\n>>> etc.  Thanks for explaining.\n>>>\n>> Actually, %%1 is a bit of a tricky one. It seems that %%1 is used to\n>> escape %1 on Windows 7, but not on earlier Windows version. I did test\n>> this on Vista an XP earlier, but I'll re-test again later and report\n>> back, in case my earlier tests were flawed.\n>\n> If that worked universally, escaping '%1' to '%%1' certainly would be nicer\n> than '% 1'. (More generally, escape '%n' to '%%n', where n is a number.) It\n> also would simplify the log message.\n>\n>> Can %%1 occur in an IPv6 address at all? If not, I'm tempted to not\n>> handle it (unless it turns out I was wrong about %%1-escaping on Vista\n>> and XP).\n>\n> According to sources I have studied, %%1 would be unlikely (or perhaps\n> invalid) in IPv6 addresses.\n>\n> http://en.wikipedia.org/wiki/IPv6_address#Link-local_addresses_and_zone_indices\n\nNot on windows. Try ipconfig:\n   Link-local IPv6 Address . . . . . : fe80::c9fb:7840:66f5:b2e9%13\n   Default Gateway . . . . . . . . . : fe80::20c:76ff:fe1e:e00%11\nand so on. Its an interface fragment or something.\n\nHowever - we really don't care. You can just substitute these to\nspaces and no-one will care. Keep it simple.\n"},{"id":"153465","messageId":"7vpqvdhfra.fsf@alter.siamese.dyndns.org","threadId":"25421","inReplyTo":"1286833829-5116-9-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v4 08/15] daemon: use run-command api for async serving","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-10-13T22:47:21Z","receivedAt":"2010-10-13T22:47:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Erik Faye-Lund <kusmabite@gmail.com> writes:\n\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\nThis is not particularly a good style.  Please make it more clear that we\nfreopen in inetd mode by writing it like this:\n\n\tif (inetd_mode) {\n        \tif (!freopen(...))\n                \tdie_errno(...)\n\t}\n"},{"id":"153468","messageId":"7vlj61hfe7.fsf@alter.siamese.dyndns.org","threadId":"25421","inReplyTo":"1286833829-5116-12-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v4 11/15] daemon: report connection from root-process","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-10-13T22:55:12Z","receivedAt":"2010-10-13T22:55:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Erik Faye-Lund <kusmabite@gmail.com> writes:\n\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> Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n> ---\n>  daemon.c |   72 ++++++++++++++++++++++++++++++-------------------------------\n>  1 files changed, 35 insertions(+), 37 deletions(-)\n>\n> diff --git a/daemon.c b/daemon.c\n> index 8a44fb9..1574f75 100644\n> --- a/daemon.c\n> +++ b/daemon.c\n> @@ -516,38 +516,11 @@ static void parse_host_arg(char *extra_args, int buflen)\n>  }\n>  \n>  \n> -static int execute(struct sockaddr *addr)\n> +static int execute(void)\n>  {\n> -...\n> -\t\t}\n> -\t\tloginfo(\"Connection from %s:%d\", addrbuf, port);\n> -\t\tsetenv(\"REMOTE_ADDR\", addrbuf, 1);\n> ...\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\nHmm, loginfo() calls logreport() and adds the process information as\nnecessary to the output.  Wouldn't this patch give the pid information\ntwice?\n"},{"id":"153470","messageId":"7vhbgphf25.fsf@alter.siamese.dyndns.org","threadId":"25421","inReplyTo":"1286833829-5116-16-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v4 15/15] daemon: opt-out on features that require posix","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-10-13T23:02:26Z","receivedAt":"2010-10-13T23:02:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Erik Faye-Lund <kusmabite@gmail.com> writes:\n\n> Windows does not supply the POSIX-functions fork(), setuuid(), setgid(),\n> setsid() and initgroups(). Disable support for --user, --group and\n> --detach if the NO_POSIX_GOODIES flag is set.\n>\n> MinGW doesn't have prototypes and headers for inet_ntop and inet_pton,\n> so include our implementation instead. MSVC does have, so avoid doing\n> so there.\n>\n> Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n> ---\n> diff --git a/daemon.c b/daemon.c\n> index 9b97b58..aa580f6 100644\n> --- a/daemon.c\n> +++ b/daemon.c\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> +#ifndef NO_POSIX_GOODIES\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\nThis is ugly.  Why did you need to make the arguments file-scope static?\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> +#ifndef NO_POSIX_GOODIES\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\nIt would be cleaner to make a helper (e.g. \"drop-privileges\") that is a\nno-op on NO_POSIX_GOODIES platform, and call that without #ifdef here.\n\nThe same aversion to too many #ifdef's apply to the rest of the patch.\n"},{"id":"153476","messageId":"AANLkTi=C9RqQ-EKFN9fsBSHsSopgSuevTpjBj-R0jWcs@mail.gmail.com","threadId":"25421","inReplyTo":"AANLkTinj21hnpsHR49nS0u_FtpwA=2Q7ygNpowufRoDC@mail.gmail.com","subject":"Re: [msysGit] Re: [PATCH v4 02/15] mingw: implement syslog","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-14T00:47:01Z","receivedAt":"2010-10-14T00:47:01Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Wed, Oct 13, 2010 at 11:17 PM, Pat Thoyts <patthoyts@gmail.com> wrote:\n> On 13 October 2010 20:23, Eric Sunshine <sunshine@sunshineco.com> wrote:\n>> On 10/13/2010 08:36 AM, Erik Faye-Lund wrote:\n>>>\n>>> On Tue, Oct 12, 2010 at 12:37 AM, Jonathan Nieder<jrnieder@gmail.com>\n>>>  wrote:\n>>>>\n>>>> Erik Faye-Lund wrote:\n>>>>\n>>>>> The string gets inlined into itself (with a limit of 100 expansions)\n>>>>> leading to string like \"foo %1 bar\" becoming \"foo foo foo ... foo %1\n>>>>> bar bar bar ... bar\". With our expansion, it becomes \"foo % 1 bar\"\n>>>>> instead.\n>>>>\n>>>> Ah, ok.  Sounds like there is no need to worry about requests for \"%%1\"\n>>>> etc.  Thanks for explaining.\n>>>>\n>>> Actually, %%1 is a bit of a tricky one. It seems that %%1 is used to\n>>> escape %1 on Windows 7, but not on earlier Windows version. I did test\n>>> this on Vista an XP earlier, but I'll re-test again later and report\n>>> back, in case my earlier tests were flawed.\n>>\n\nMeh. Windows XP does not escape %%1 to %1, it has the same\nexpansion-problem as %1 does. In other words, my old assertion is\nstill valid.\n\n>> If that worked universally, escaping '%1' to '%%1' certainly would be nicer\n>> than '% 1'. (More generally, escape '%n' to '%%n', where n is a number.) It\n>> also would simplify the log message.\n>>\n>>> Can %%1 occur in an IPv6 address at all? If not, I'm tempted to not\n>>> handle it (unless it turns out I was wrong about %%1-escaping on Vista\n>>> and XP).\n>>\n>> According to sources I have studied, %%1 would be unlikely (or perhaps\n>> invalid) in IPv6 addresses.\n>>\n>> http://en.wikipedia.org/wiki/IPv6_address#Link-local_addresses_and_zone_indices\n>\n> Not on windows. Try ipconfig:\n>   Link-local IPv6 Address . . . . . : fe80::c9fb:7840:66f5:b2e9%13\n>   Default Gateway . . . . . . . . . : fe80::20c:76ff:fe1e:e00%11\n> and so on. Its an interface fragment or something.\n>\n> However - we really don't care. You can just substitute these to\n> spaces and no-one will care. Keep it simple.\n>\n\nUh, none of these contain a double percent-sign. Am I misunderstanding\nwhat you're replying to?\n"},{"id":"153508","messageId":"AANLkTikyxEB0VRg1jWd-AdR0uyxExw7O9YQfXJzu-f_M@mail.gmail.com","threadId":"25421","inReplyTo":"7vpqvdhfra.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v4 08/15] daemon: use run-command api for async serving","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-14T10:18:21Z","receivedAt":"2010-10-14T10:18:21Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Thu, Oct 14, 2010 at 12:47 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Erik Faye-Lund <kusmabite@gmail.com> writes:\n>\n>> @@ -1017,7 +1005,12 @@ int main(int argc, char **argv)\n>>                               continue;\n>>                       }\n>>               }\n>> +             if (!strcmp(arg, \"--serve\")) {\n>> +                     serve_mode = 1;\n>> +                     continue;\n>> +             }\n>>               if (!strcmp(arg, \"--inetd\")) {\n>> +                     serve_mode = 1;\n>>                       inetd_mode = 1;\n>>                       log_syslog = 1;\n>>                       continue;\n>> @@ -1161,12 +1154,12 @@ int main(int argc, char **argv)\n>>               die(\"base-path '%s' does not exist or is not a directory\",\n>>                   base_path);\n>>\n>> -     if (inetd_mode) {\n>> +     if (serve_mode) {\n>>               struct sockaddr_storage ss;\n>>               struct sockaddr *peer = (struct sockaddr *)&ss;\n>>               socklen_t slen = sizeof(ss);\n>>\n>> -             if (!freopen(\"/dev/null\", \"w\", stderr))\n>> +             if (inetd_mode && !freopen(\"/dev/null\", \"w\", stderr))\n>>                       die_errno(\"failed to redirect stderr to /dev/null\");\n>\n> This is not particularly a good style.  Please make it more clear that we\n> freopen in inetd mode by writing it like this:\n>\n>        if (inetd_mode) {\n>                if (!freopen(...))\n>                        die_errno(...)\n>        }\n>\n>\n\nMuch nicer, yeah. Now I'm tempted to do this also:\n\n---8<---\ndiff --git a/daemon.c b/daemon.c\nindex 7f5d72f..11a5e06 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -1010,7 +1010,6 @@ int main(int argc, char **argv)\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@@ -1159,7 +1158,7 @@ int main(int argc, char **argv)\n \t\t\tdie_errno(\"failed to redirect stderr to /dev/null\");\n \t}\n\n-\tif (serve_mode) {\n+\tif (inetd_mode || serve_mode) {\n \t\tstruct sockaddr_storage ss;\n \t\tstruct sockaddr *peer = (struct sockaddr *)&ss;\n \t\tsocklen_t slen = sizeof(ss);\n---8<---\n"},{"id":"153510","messageId":"AANLkTinXNPWaGj2BUaSOJypzv-Sqts-zEdG886oT2YJB@mail.gmail.com","threadId":"25421","inReplyTo":"7vlj61hfe7.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v4 11/15] daemon: report connection from root-process","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-14T10:50:54Z","receivedAt":"2010-10-14T10:50:54Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Thu, Oct 14, 2010 at 12:55 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Erik Faye-Lund <kusmabite@gmail.com> writes:\n>\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>> Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n>> ---\n>>  daemon.c |   72 ++++++++++++++++++++++++++++++-------------------------------\n>>  1 files changed, 35 insertions(+), 37 deletions(-)\n>>\n>> diff --git a/daemon.c b/daemon.c\n>> index 8a44fb9..1574f75 100644\n>> --- a/daemon.c\n>> +++ b/daemon.c\n>> @@ -516,38 +516,11 @@ static void parse_host_arg(char *extra_args, int buflen)\n>>  }\n>>\n>>\n>> -static int execute(struct sockaddr *addr)\n>> +static int execute(void)\n>>  {\n>> -...\n>> -             }\n>> -             loginfo(\"Connection from %s:%d\", addrbuf, port);\n>> -             setenv(\"REMOTE_ADDR\", addrbuf, 1);\n>> ...\n>> +     else {\n>> +             loginfo(\"[%\"PRIuMAX\"] Connection from %s:%d\",\n>> +                 (uintmax_t)cld.pid, addrstr, port);\n>>               add_child(&cld, addr, addrlen);\n>\n> Hmm, loginfo() calls logreport() and adds the process information as\n> necessary to the output.  Wouldn't this patch give the pid information\n> twice?\n>\n\nClose, but not quite. logreport() reports the current PID, while this\ncall to loginfo reports the PID of the child process. So two\nnon-identical PIDs are reported.\n\nThe output becomes something like this:\n\n[6408] [3868] Connection from [::1]:55801\n[3868] Extended attributes (16 bytes) exist <host=localhost>\n[3868] Request upload-pack for '/some-repo.git'\n[3868] '/some-repo.git' does not appear to be a git repository\n[6408] [1876] Connection from [::1]:57311\n[1876] Extended attributes (16 bytes) exist <host=localhost>\n[1876] Request upload-pack for '/some-repo.git'\n[1876] '/some-repo.git' does not appear to be a git repository\n"},{"id":"153513","messageId":"AANLkTi=N+4QokkiGmN+S17=7=QsgKWUXrsF0vZ_6Zt2H@mail.gmail.com","threadId":"25421","inReplyTo":"7vhbgphf25.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v4 15/15] daemon: opt-out on features that require posix","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-14T11:02:10Z","receivedAt":"2010-10-14T11:02:10Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Thu, Oct 14, 2010 at 1:02 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Erik Faye-Lund <kusmabite@gmail.com> writes:\n>\n>> Windows does not supply the POSIX-functions fork(), setuuid(), setgid(),\n>> setsid() and initgroups(). Disable support for --user, --group and\n>> --detach if the NO_POSIX_GOODIES flag is set.\n>>\n>> MinGW doesn't have prototypes and headers for inet_ntop and inet_pton,\n>> so include our implementation instead. MSVC does have, so avoid doing\n>> so there.\n>>\n>> Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n>> ---\n>> diff --git a/daemon.c b/daemon.c\n>> index 9b97b58..aa580f6 100644\n>> --- a/daemon.c\n>> +++ b/daemon.c\n>> @@ -965,7 +969,12 @@ static void store_pid(const char *path)\n>>               die_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>> +#ifndef NO_POSIX_GOODIES\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>>       struct socketlist socklist = { NULL, 0, 0 };\n>>\n>\n> This is ugly.  Why did you need to make the arguments file-scope static?\n>\n\nTo avoid having different signatures for the serve-function dependent\non NO_POSIX_GOODIES.\n\nDo you have any other suggestions on how to do this? Perhaps I should\njust move the logic in serve() to the end of main()? It's the only\ncall-site for the function, and would remove the need for a function\nprototype all-together...\n\n>> @@ -974,10 +983,12 @@ static int serve(struct string_list *listen_addr, int listen_port, struct passwd\n>>               die(\"unable to allocate any listen sockets on port %u\",\n>>                   listen_port);\n>>\n>> +#ifndef NO_POSIX_GOODIES\n>>       if (pass && gid &&\n>>           (initgroups(pass->pw_name, gid) || setgid (gid) ||\n>>            setuid(pass->pw_uid)))\n>>               die(\"cannot drop privileges\");\n>> +#endif\n>\n> It would be cleaner to make a helper (e.g. \"drop-privileges\") that is a\n> no-op on NO_POSIX_GOODIES platform, and call that without #ifdef here.\n>\n\nSure, makes sense.\n\n> The same aversion to too many #ifdef's apply to the rest of the patch.\n>\n\nI can remove some of them, like keeping the variables in main()\naround, even though they'll be constant. That might cause some\ncompile-time warnings, though.\n"},{"id":"153603","messageId":"7vbp6vduly.fsf@alter.siamese.dyndns.org","threadId":"25421","inReplyTo":"AANLkTi=N+4QokkiGmN+S17=7=QsgKWUXrsF0vZ_6Zt2H@mail.gmail.com","subject":"Re: [PATCH v4 15/15] daemon: opt-out on features that require posix","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-10-15T21:16:57Z","receivedAt":"2010-10-15T21:16:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Erik Faye-Lund <kusmabite@gmail.com> writes:\n\n>>> -static int serve(struct string_list *listen_addr, int listen_port, struct passwd *pass, gid_t gid)\n>>> +#ifndef NO_POSIX_GOODIES\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>>>       struct socketlist socklist = { NULL, 0, 0 };\n>>>\n>>\n>> This is ugly.  Why did you need to make the arguments file-scope static?\n>>\n>\n> To avoid having different signatures for the serve-function dependent\n> on NO_POSIX_GOODIES.\n\nWhy does the signature even have to be different between the two to begin\nwith?  I _think_ you have gid_t over there, although you might not have\n\"struct passwd\", in which case you can just define an empty one that your\nalternate implementation is not going to use anyway.  This is especially\ntrue if you are making the \"drop-privileges\" part a helper function, no?\n"},{"id":"153658","messageId":"7veibp5szg.fsf@alter.siamese.dyndns.org","threadId":"25421","inReplyTo":"AANLkTikyxEB0VRg1jWd-AdR0uyxExw7O9YQfXJzu-f_M@mail.gmail.com","subject":"Re: [PATCH v4 08/15] daemon: use run-command api for async serving","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-10-17T04:43:47Z","receivedAt":"2010-10-17T04:43:47Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Erik Faye-Lund <kusmabite@gmail.com> writes:\n\n> On Thu, Oct 14, 2010 at 12:47 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>> Erik Faye-Lund <kusmabite@gmail.com> writes:\n>> ...\n>>> @@ -1017,7 +1005,12 @@ int main(int argc, char **argv)\n>>> +             if (inetd_mode && !freopen(\"/dev/null\", \"w\", stderr))\n>>>                       die_errno(\"failed to redirect stderr to /dev/null\");\n>>\n>> This is not particularly a good style.  Please make it more clear that we\n>> freopen in inetd mode by writing it like this:\n>>\n>>        if (inetd_mode) {\n>>                if (!freopen(...))\n>>                        die_errno(...)\n>>        }\n>>\n>>\n>\n> Much nicer, yeah. Now I'm tempted to do this also:\n> ...\n\nYeah, that is much much saner.  Thanks.\n\n> ---8<---\n> diff --git a/daemon.c b/daemon.c\n> index 7f5d72f..11a5e06 100644\n> --- a/daemon.c\n> +++ b/daemon.c\n> @@ -1010,7 +1010,6 @@ int main(int argc, char **argv)\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> @@ -1159,7 +1158,7 @@ int main(int argc, char **argv)\n>  \t\t\tdie_errno(\"failed to redirect stderr to /dev/null\");\n>  \t}\n>\n> -\tif (serve_mode) {\n> +\tif (inetd_mode || serve_mode) {\n>  \t\tstruct sockaddr_storage ss;\n>  \t\tstruct sockaddr *peer = (struct sockaddr *)&ss;\n>  \t\tsocklen_t slen = sizeof(ss);\n> ---8<---\n"},{"id":"153659","messageId":"7v8w1x5sz7.fsf@alter.siamese.dyndns.org","threadId":"25421","inReplyTo":"AANLkTinXNPWaGj2BUaSOJypzv-Sqts-zEdG886oT2YJB@mail.gmail.com","subject":"Re: [PATCH v4 11/15] daemon: report connection from root-process","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-10-17T04:43:56Z","receivedAt":"2010-10-17T04:43:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Erik Faye-Lund <kusmabite@gmail.com> writes:\n\n>> Hmm, loginfo() calls logreport() and adds the process information as\n>> necessary to the output.  Wouldn't this patch give the pid information\n>> twice?\n>>\n>\n> Close, but not quite. logreport() reports the current PID, while this\n> call to loginfo reports the PID of the child process. So two\n> non-identical PIDs are reported.\n\nI know that; I was questioning if that change to the log output is really\nwhat we want.  I do not deeply care myself, but people with scripts that\nread logs might.\n\n>\n> The output becomes something like this:\n>\n> [6408] [3868] Connection from [::1]:55801\n> [3868] Extended attributes (16 bytes) exist <host=localhost>\n> [3868] Request upload-pack for '/some-repo.git'\n> [3868] '/some-repo.git' does not appear to be a git repository\n> [6408] [1876] Connection from [::1]:57311\n> [1876] Extended attributes (16 bytes) exist <host=localhost>\n> [1876] Request upload-pack for '/some-repo.git'\n> [1876] '/some-repo.git' does not appear to be a git repository\n"},{"id":"153664","messageId":"AANLkTin9cCW0c43kPGu9nBOO092+LEHR+XfY_KFeSyk6@mail.gmail.com","threadId":"25421","inReplyTo":"7v8w1x5sz7.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v4 11/15] daemon: report connection from root-process","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-17T10:18:54Z","receivedAt":"2010-10-17T10:18:54Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sun, Oct 17, 2010 at 6:43 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Erik Faye-Lund <kusmabite@gmail.com> writes:\n>\n>>> Hmm, loginfo() calls logreport() and adds the process information as\n>>> necessary to the output.  Wouldn't this patch give the pid information\n>>> twice?\n>>>\n>>\n>> Close, but not quite. logreport() reports the current PID, while this\n>> call to loginfo reports the PID of the child process. So two\n>> non-identical PIDs are reported.\n>\n> I know that; I was questioning if that change to the log output is really\n> what we want.  I do not deeply care myself, but people with scripts that\n> read logs might.\n>\n\nI could do something like this, but then we lose the port information.\nPerhaps I could add a REMOTE_PORT environment variable to solve that?\n\ndiff --git a/daemon.c b/daemon.c\nindex 589bd04..3d18899 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -522,6 +522,10 @@ static int execute(void)\n {\n \tstatic char line[1000];\n \tint pktlen, len, i;\n+\tchar *addr = getenv(\"REMOTE_ADDR\");\n+\n+\tif (addr)\n+\t\tloginfo(\"Connection from %s\", addr);\n\n \talarm(init_timeout ? init_timeout : timeout);\n \tpktlen = packet_read_line(0, line, sizeof(line));\n@@ -702,11 +706,8 @@ static void handle(int incoming, struct sockaddr\n*addr, socklen_t addrlen)\n\n \tif (start_command(&cld))\n \t\tlogerror(\"unable to fork\");\n-\telse {\n-\t\tloginfo(\"[%\"PRIuMAX\"] Connection from %s:%d\",\n-\t\t    (uintmax_t)cld.pid, addrstr, port);\n+\telse\n \t\tadd_child(&cld, addr, addrlen);\n-\t}\n \tclose(incoming);\n }\n"},{"id":"153713","messageId":"AANLkTim0KeW3eDHAsxrxMCvBUD_15R3VSrHSzOFq38A1@mail.gmail.com","threadId":"25421","inReplyTo":"7vbp6vduly.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v4 15/15] daemon: opt-out on features that require posix","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-18T12:05:09Z","receivedAt":"2010-10-18T12:05:09Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Fri, Oct 15, 2010 at 11:16 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Erik Faye-Lund <kusmabite@gmail.com> writes:\n>\n>>>> -static int serve(struct string_list *listen_addr, int listen_port, struct passwd *pass, gid_t gid)\n>>>> +#ifndef NO_POSIX_GOODIES\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>>>>       struct socketlist socklist = { NULL, 0, 0 };\n>>>>\n>>>\n>>> This is ugly.  Why did you need to make the arguments file-scope static?\n>>>\n>>\n>> To avoid having different signatures for the serve-function dependent\n>> on NO_POSIX_GOODIES.\n>\n> Why does the signature even have to be different between the two to begin\n> with? I _think_ you have gid_t over there\n\nWe don't, so this is the primary reason. But also avoiding\ncompilation-warnings is a secondary motivation.\n\n> although you might not have\n> \"struct passwd\", in which case you can just define an empty one that your\n> alternate implementation is not going to use anyway.\n\nWe do, so this becomes a bit of a hypothetical question. But would you\nseriously consider pretending to have a posix-feature less ugly than\ninlining a function that is only used once?\n\n(I'm going a little off-topic here, I hope that's OK)\nI'm not too happy with some of the\npretend-really-hard-to-be-posix-magic around in the Windows-port. In\nfact, I have some patches to reduce posixness in some areas, while\ngetting rid of some code in mingw.c. Would such patches be welcome, or\nis pretend-to-be-posix the governing portability approach? In some\ncases, this comes at the expense of some performance (and quite a bit\nof added cludge), which is a bit contradictory to the Git design IMO.\n\n> This is especially\n> true if you are making the \"drop-privileges\" part a helper function, no?\n\nI don't follow this part. What exactly becomes more true by having a\ndrop-privileges function?\n\nAnyway, I'm pretty pleased with how this turned out after inlining\nserve() into main(), what do you think about this? I've also moved the\nreordering of usage-string into a new patch that makes inetd_mode and\ndetach incompatible (they already are, it's just not checked for or\ndocumented).\n\ndiff --git a/Makefile b/Makefile\nindex 46034bf..53986b1 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@@ -1066,7 +1067,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@@ -1077,6 +1077,7 @@ ifeq ($(uname_S),Windows)\n \tNO_CURL = YesPlease\n \tNO_PYTHON = YesPlease\n \tBLK_SHA1 = YesPlease\n+\tNO_POSIX_GOODIES = UnfortunatelyYes\n \tNATIVE_CRLF = YesPlease\n\n \tCC = compat/vcbuild/scripts/clink.pl\n@@ -1119,7 +1120,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@@ -1130,6 +1130,9 @@ 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+\tNO_POSIX_GOODIES = UnfortunatelyYes\n \tCOMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat\n-Icompat/fnmatch -Icompat/win32\n \tCOMPAT_CFLAGS += -DSTRIP_EXTENSION=\\\".exe\\\"\n \tCOMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o \\\n@@ -1249,9 +1252,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\n@@ -1419,6 +1419,10 @@ ifdef NO_DEFLATE_BOUND\n \tBASIC_CFLAGS += -DNO_DEFLATE_BOUND\n endif\n\n+ifdef NO_POSIX_GOODIES\n+\tBASIC_CFLAGS += -DNO_POSIX_GOODIES\n+endif\n+\n ifdef BLK_SHA1\n \tSHA1_HEADER = \"block-sha1/sha1.h\"\n \tLIB_OBJS += block-sha1/sha1.o\ndiff --git a/daemon.c b/daemon.c\nindex b7f3874..589bd04 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -26,7 +26,9 @@ static const char daemon_usage[] =\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+#ifndef NO_POSIX_GOODIES\n \"                      [--detach] [--user=user [--group=group]]\\n\"\n+#endif\n \"           [directory...]\";\n\n /* List of acceptable pathname prefixes */\n@@ -938,6 +940,14 @@ static void sanitize_stdfds(void)\n \t\tclose(fd);\n }\n\n+#ifndef NO_POSIX_GOODIES\n+static void drop_privileges(struct passwd *pass, gid_t gid)\n+{\n+\tif (initgroups(pass->pw_name, gid) || setgid (gid) ||\n+\t     setuid(pass->pw_uid))\n+\t\tdie(\"cannot drop privileges\");\n+}\n+\n static void daemonize(void)\n {\n \tswitch (fork()) {\n@@ -955,6 +965,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,33 +976,19 @@ 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,\nstruct passwd *pass, gid_t gid)\n-{\n-\tstruct socketlist socklist = { NULL, 0, 0 };\n-\n-\tsocksetup(listen_addr, listen_port, &socklist);\n-\tif (socklist.nr == 0)\n-\t\tdie(\"unable to allocate any listen sockets on port %u\",\n-\t\t    listen_port);\n-\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-\n-\treturn service_loop(&socklist);\n-}\n-\n int main(int argc, char **argv)\n {\n \tint listen_port = 0;\n \tstruct string_list listen_addr = STRING_LIST_INIT_NODUP;\n+\tstruct socketlist socklist = { NULL, 0, 0 };\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+#ifndef NO_POSIX_GOODIES\n+\tconst char *user_name = NULL, *group_name = NULL;\n \tint detach = 0;\n \tstruct passwd *pass = NULL;\n-\tstruct group *group;\n \tgid_t gid = 0;\n+#endif\n \tint i;\n\n \tgit_extract_argv0_path(argv[0]);\n@@ -1079,6 +1076,7 @@ int main(int argc, char **argv)\n \t\t\tpid_file = arg + 11;\n \t\t\tcontinue;\n \t\t}\n+#ifndef NO_POSIX_GOODIES\n \t\tif (!strcmp(arg, \"--detach\")) {\n \t\t\tdetach = 1;\n \t\t\tlog_syslog = 1;\n@@ -1092,6 +1090,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@@ -1126,14 +1125,15 @@ 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-\tif (inetd_mode && (detach || group_name || user_name))\n-\t\tdie(\"--detach, --user and --group are incompatible with --inetd\");\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+#ifndef NO_POSIX_GOODIES\n+\tif (inetd_mode && (detach || group_name || user_name))\n+\t\tdie(\"--detach, --user and --group are incompatible with --inetd\");\n+\n \tif (group_name && !user_name)\n \t\tdie(\"--group supplied without --user\");\n\n@@ -1145,13 +1145,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@@ -1168,11 +1169,13 @@ int main(int argc, char **argv)\n \tif (inetd_mode || serve_mode)\n \t\treturn execute();\n\n+#ifndef NO_POSIX_GOODIES\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@@ -1185,5 +1188,15 @@ 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+\tsocksetup(&listen_addr, listen_port, &socklist);\n+\tif (socklist.nr == 0)\n+\t\tdie(\"unable to allocate any listen sockets on port %u\",\n+\t\t    listen_port);\n+\n+#ifndef NO_POSIX_GOODIES\n+\tif (pass && gid)\n+\t\tdrop_privileges(pass, gid);\n+#endif\n+\n+\treturn service_loop(&socklist);\n }\n"},{"id":"153721","messageId":"20101018163134.GA6343@burratino","threadId":"25421","inReplyTo":"AANLkTim0KeW3eDHAsxrxMCvBUD_15R3VSrHSzOFq38A1@mail.gmail.com","subject":"Re: [PATCH v4 15/15] daemon: opt-out on features that require posix","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-10-18T16:31:34Z","receivedAt":"2010-10-18T16:31:34Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Hi,\n\nA response to the general questions.\n\nErik Faye-Lund wrote:\n> On Fri, Oct 15, 2010 at 11:16 PM, Junio C Hamano <gitster@pobox.com> wrote:\n\n>> Why does the signature even have to be different between the two to begin\n>> with? I _think_ you have gid_t over there\n>\n> We don't, so this is the primary reason.\n\nJust to throw an idea out: you can also do something like\n\n#ifndef NO_POSIX_GOODIES\nstruct credentials {\n};\n#else\nstruct credentials {\n\tstruct passwd *pass;\n\tgid_t gid;\n}\n#endif\n\nand pass a pointer to credentials around.\n\n> But also avoiding\n> compilation-warnings is a secondary motivation.\n\n(void) gid;\n\nworks for this.\n\n> We do, so this becomes a bit of a hypothetical question. But would you\n> seriously consider pretending to have a posix-feature less ugly than\n> inlining a function that is only used once?\n\nIn general, yes.\n\nLong functions can make code much, much more difficult to read.  A\nfake posix feature just requires some suspension of disbelief.\n\nIn this case (#ifdef-heavy main() vs opaque struct passwd), both\nstrike me as ugly.\n\n> (I'm going a little off-topic here, I hope that's OK)\n> I'm not too happy with some of the\n> pretend-really-hard-to-be-posix-magic around in the Windows-port. In\n> fact, I have some patches to reduce posixness in some areas, while\n> getting rid of some code in mingw.c. Would such patches be welcome, or\n> is pretend-to-be-posix the governing portability approach? In some\n> cases, this comes at the expense of some performance (and quite a bit\n> of added cludge), which is a bit contradictory to the Git design IMO.\n\nSometimes the best abstraction is the posix one and sometimes not.  I\ndon't think this would contradict with your planned patches, unless\nthey introduce #ifdefs all over the place.\n\n>> This is especially\n>> true if you are making the \"drop-privileges\" part a helper function, no?\n>\n> I don't follow this part. What exactly becomes more true by having a\n> drop-privileges function?\n\n(See linux-2.6.git:Documentation/SubmittingPatches, section \"#ifdefs\nare ugly\".)\n\nThe ideal: never an #ifdef within a function.  (Well, the ideal is\nno #ifdef-s in .c files, but that's harder to take seriously.)\n\n#ifndef HAVE_POSIX_GOODIES\nstatic int drop_privileges(...)\n{\n\treturn error(\"--user and --group not supported on this platform\");\n}\n#endif\nstatic int drop_privileges(...)\n{\n\t...\n\tdo\n\tsomething\n\t...\n}\n#endif\n\nwould make serve() look like\n\nstatic int serve(...)\n{\n\tint socknum, *socklist;\n\n\t... setup socket ...\n\n\tif (want to drop privileges) {\n\t\tif (drop_privileges(...))\n\t\t\treturn -1;\n\t}\n\n\treturn service_loop(socknum, socklist);\n}\n\nwhich should be quite readable even to a person only interested in the\n!HAVE_POSIX_GOODIES case imho.  With some code rearrangement it could\nbe made nicer.  Now compare:\n\nstatic int serve(...)\n{\n\tint socknum, *socklist;\n\n\t... setup socket ...\n\n#ifdef HAVE_POSIX_GOODIES\n\t...\n\tdo\n\tthings\n\t...\n#endif\n\n\treturn service_loop(socknum, socklist);\n}\n\nJust my two cents.  Sorry I do not have something more substantive to\nsay.\n"},{"id":"153735","messageId":"m2y69vl67b.fsf@igel.home","threadId":"25421","inReplyTo":"20101018163134.GA6343@burratino","subject":"Re: [PATCH v4 15/15] daemon: opt-out on features that require posix","fromName":"Andreas Schwab","fromEmail":"schwab@linux-m68k.org","sentAt":"2010-10-18T18:13:44Z","receivedAt":"2010-10-18T18:13:44Z","isPatch":true,"sender":{"key":"schwab@linux-m68k.org","avatar":"https://avatars.githubusercontent.com/u/2175493?v=4"},"body":"Jonathan Nieder <jrnieder@gmail.com> writes:\n\n> Just to throw an idea out: you can also do something like\n>\n> #ifndef NO_POSIX_GOODIES\n> struct credentials {\n> };\n> #else\n> struct credentials {\n> \tstruct passwd *pass;\n> \tgid_t gid;\n> }\n> #endif\n>\n> and pass a pointer to credentials around.\n\nEmpty structures are not standard C.  But if you only ever use a pointer\nto the struct you can leave it undefined (ie. just forward-declare it).\n\nAndreas.\n\n-- \nAndreas Schwab, schwab@linux-m68k.org\nGPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5\n\"And now for something completely different.\"\n"},{"id":"153741","messageId":"20101018184209.GD6877@burratino","threadId":"25421","inReplyTo":"m2y69vl67b.fsf@igel.home","subject":"empty structs","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-10-18T18:42:09Z","receivedAt":"2010-10-18T18:42:09Z","isPatch":false,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Andreas Schwab wrote:\n> Jonathan Nieder <jrnieder@gmail.com> writes:\n\n>> Just to throw an idea out: you can also do something like\n>>\n>> #ifndef NO_POSIX_GOODIES\n>> struct credentials {\n>> };\n>> #else\n[...]\n> Empty structures are not standard C.\n\n(For those following at home:\n\n\t\"A structure type describes a sequentially allocated\n\t nonempty set of member objects (and, in certain\n\t circumstances, an incomplete array), each of which\n\t has an optionally specified name and possibly\n\t distinct type.\")\n\nSo I guess future patches following the pattern of v1.7.3-rc0~33^2~13\ngit wrapper: introduce startup_info struct, 2010-08-05) should be\nwritten like\n\n\tstruct startup_info {\n\t\tchar dummy;\n\t};\n\nYuck.  Thanks for the pointer.\n"},{"id":"153743","messageId":"7vaamb480p.fsf@alter.siamese.dyndns.org","threadId":"25421","inReplyTo":"AANLkTim0KeW3eDHAsxrxMCvBUD_15R3VSrHSzOFq38A1@mail.gmail.com","subject":"Re: [PATCH v4 15/15] daemon: opt-out on features that require posix","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-10-18T19:26:30Z","receivedAt":"2010-10-18T19:26:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Erik Faye-Lund <kusmabite@gmail.com> writes:\n\n> (I'm going a little off-topic here, I hope that's OK)\n> I'm not too happy with some of the pretend-really-hard-to-be-posix-magic\n> around in the Windows-port. In fact, I have some patches to reduce\n> posixness in some areas, while getting rid of some code in\n> mingw.c. Would such patches be welcome, or is pretend-to-be-posix the\n> governing portability approach? In some cases, this comes at the expense\n> of some performance (and quite a bit of added cludge), which is a bit\n> contradictory to the Git design IMO.\n\nIf the part of the codepath you need to make conditional can be better\nhelped by abstraction that is higher-level than POSIX, that would be a\nvery acceptable approach.  The \"struct credential\" idea Jonathan gave you\nis an example of such.  The goal is not to force POSIX on Windows or make\nPOSIX emulation on Windows more complete---that is not git's job.  Just\nthat in most of the case the level of abstraction POSIX gives has been\nadequate for our codebase.\n\n>> This is especially\n>> true if you are making the \"drop-privileges\" part a helper function, no?\n>\n> I don't follow this part. What exactly becomes more true by having a\n> drop-privileges function?\n\nBy using a bit higher level abstraction than POSIX primitives give you\n(e.g. initgroups(), setgid(), etc.) that does not have to depend on\nparticular POSIX implementation details (e.g. \"struct passwd\", gid_t,\netc.), you can make the main codepath cleaner and free of ifdefs.\n"},{"id":"154019","messageId":"AANLkTikJXaqDH6vJzPna7txssMO67SxmVy_Nvu2SW46W@mail.gmail.com","threadId":"25421","inReplyTo":"1286833829-5116-16-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v4 15/15] daemon: opt-out on features that require posix","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-21T20:37:44Z","receivedAt":"2010-10-21T20:37:44Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Mon, Oct 11, 2010 at 11:50 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> @@ -1168,11 +1185,13 @@ int main(int argc, char **argv)\n>                return execute();\n>        }\n>\n> +#ifndef NO_POSIX_GOODIES\n>        if (detach) {\n>                daemonize();\n>                loginfo(\"Ready to rumble\");\n>        }\n>        else\n> +#endif\n>                sanitize_stdfds();\n>\n\nDoes anyone know what the call to sanitize_stdfds() is good for? I\ntried searching the mailing list, but the discussion on the patch that\nintroduced it seems to only discuss how to implement\nsanitize_stdfds(), not why...\n\nI understand that it might be beneficial in the --detach code-path,\nbut how can stdint, stdout or stderr be closed in this code-path?\n\n(CC'ed Matthias, who wrote the code)\n"},{"id":"154021","messageId":"20101021203926.GB12685@burratino","threadId":"25421","inReplyTo":"AANLkTikJXaqDH6vJzPna7txssMO67SxmVy_Nvu2SW46W@mail.gmail.com","subject":"Re: [PATCH v4 15/15] daemon: opt-out on features that require posix","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-10-21T20:39:26Z","receivedAt":"2010-10-21T20:39:26Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Erik Faye-Lund wrote:\n\n> I understand that it might be beneficial in the --detach code-path,\n> but how can stdint, stdout or stderr be closed in this code-path?\n\nMaybe \"git daemon >&- 2>&-\"?\n\nIn some situations involving setuid programs, this kind of thing\ncan be a security problem (since fd 1 is not taken, the first open()\nuses that fd, so output intended for stdout goes to that file).\n"},{"id":"154025","messageId":"AANLkTi=dAAsk8LMB=xnFtpyT7yuY2v76OOgJY5KdeD3D@mail.gmail.com","threadId":"25421","inReplyTo":"20101021203926.GB12685@burratino","subject":"Re: [PATCH v4 15/15] daemon: opt-out on features that require posix","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-21T20:54:33Z","receivedAt":"2010-10-21T20:54:33Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Thu, Oct 21, 2010 at 10:39 PM, Jonathan Nieder <jrnieder@gmail.com> wrote:\n> Erik Faye-Lund wrote:\n>\n>> I understand that it might be beneficial in the --detach code-path,\n>> but how can stdint, stdout or stderr be closed in this code-path?\n>\n> Maybe \"git daemon >&- 2>&-\"?\n>\n> In some situations involving setuid programs, this kind of thing\n> can be a security problem (since fd 1 is not taken, the first open()\n> uses that fd, so output intended for stdout goes to that file).\n>\n\nThis is beyond my shell-fu, but if this is supposed to not open\nstdin/out/err then I'm a bit puzzled. K&R explicitly states that\nstdin, stdout and stderr should be opened at startup in Appendix B:\n\"When a program begins execution, the tree streams stdin, stdou and\nstderr are already open\". There's also section 7.5, which lists\nredirection to files and pipes as exceptions, but not keeping them\nclosed.\n\nPerhaps I'm interpreting K&R a little too literary?\n"},{"id":"154030","messageId":"AANLkTik3Di=dcC=CxW+Lou515E2wXq8_OaR99mghC+vF@mail.gmail.com","threadId":"25421","inReplyTo":"20101018163134.GA6343@burratino","subject":"Re: [PATCH v4 15/15] daemon: opt-out on features that require posix","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-21T21:16:57Z","receivedAt":"2010-10-21T21:16:57Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Mon, Oct 18, 2010 at 6:31 PM, Jonathan Nieder <jrnieder@gmail.com> wrote:\n> A response to the general questions.\n\nThanks!\n\n> Erik Faye-Lund wrote:\n>> On Fri, Oct 15, 2010 at 11:16 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>\n>>> Why does the signature even have to be different between the two to begin\n>>> with? I _think_ you have gid_t over there\n>>\n>> We don't, so this is the primary reason.\n>\n> Just to throw an idea out: you can also do something like\n>\n> #ifndef NO_POSIX_GOODIES\n> struct credentials {\n> };\n> #else\n> struct credentials {\n>        struct passwd *pass;\n>        gid_t gid;\n> }\n> #endif\n>\n> and pass a pointer to credentials around.\n>\n\nYes, but that structure still needs to be filled somehow. I'm not sure\nhow this solves anything, really. Isn't it essentially another way of\nwrapping an ifdef around the parameters inside main() (at least when\nI've inlined serve() into main())?\n\n>>> This is especially\n>>> true if you are making the \"drop-privileges\" part a helper function, no?\n>>\n>> I don't follow this part. What exactly becomes more true by having a\n>> drop-privileges function?\n>\n> (See linux-2.6.git:Documentation/SubmittingPatches, section \"#ifdefs\n> are ugly\".)\n>\n> The ideal: never an #ifdef within a function.  (Well, the ideal is\n> no #ifdef-s in .c files, but that's harder to take seriously.)\n>\n> #ifndef HAVE_POSIX_GOODIES\n> static int drop_privileges(...)\n> {\n>        return error(\"--user and --group not supported on this platform\");\n> }\n> #endif\n> static int drop_privileges(...)\n> {\n>        ...\n>        do\n>        something\n>        ...\n> }\n> #endif\n>\n> would make serve() look like\n>\n> static int serve(...)\n> {\n>        int socknum, *socklist;\n>\n>        ... setup socket ...\n>\n>        if (want to drop privileges) {\n>                if (drop_privileges(...))\n>                        return -1;\n>        }\n>\n>        return service_loop(socknum, socklist);\n> }\n>\n> which should be quite readable even to a person only interested in the\n> !HAVE_POSIX_GOODIES case imho.  With some code rearrangement it could\n> be made nicer.  Now compare:\n>\n> static int serve(...)\n> {\n>        int socknum, *socklist;\n>\n>        ... setup socket ...\n>\n> #ifdef HAVE_POSIX_GOODIES\n>        ...\n>        do\n>        things\n>        ...\n> #endif\n>\n>        return service_loop(socknum, socklist);\n> }\n>\n> Just my two cents.  Sorry I do not have something more substantive to\n> say.\n>\n\nYou're leaving out the troublesome part, namely the glue between \"if\n(user_name)\" in main(), and the \"want to drop privileges\"-stuff in\nserve().\n\nI could do a \"struct credentials *cred = NULL;\"  in main(), and assign\nthat inside \"if (user_name)\". But that'd leave a warning about\nunreachable code in drop_privileges(), no?\n\nI'm also getting the feeling that I'm being hinted at to implement\nproper credential-dropping (ie filling out the windows-versions of the\ncode with something that makes sense for windows), but this isn't how\nthese things work on Windows. Daemons run as services on Windows, and\nwhat user to run a service under is a system-administrator setting. In\nfact, you can't even impersonate another user without having it's\npassword.\n\nTurning git-daemon into a service is something that can be done later.\nI've looked into it, and what seems to make the most sense is to have\na separate mode on git-daemon (or even another program), that starts\ngit-daemon as a subprocess. This is because of the way Windows\ncommunicates with the service, requiring a message-loop that can be\nterminated.\n"},{"id":"154034","messageId":"AANLkTi=ydzrvy6_PbFLpA_qcHzF-8s3xbu3XvU5GnQ_k@mail.gmail.com","threadId":"25421","inReplyTo":"AANLkTik3Di=dcC=CxW+Lou515E2wXq8_OaR99mghC+vF@mail.gmail.com","subject":"Re: [PATCH v4 15/15] daemon: opt-out on features that require posix","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-21T22:00:53Z","receivedAt":"2010-10-21T22:00:53Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Thu, Oct 21, 2010 at 11:16 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> On Mon, Oct 18, 2010 at 6:31 PM, Jonathan Nieder <jrnieder@gmail.com> wrote:\n>> Just to throw an idea out: you can also do something like\n>>\n>> #ifndef NO_POSIX_GOODIES\n>> struct credentials {\n>> };\n>> #else\n>> struct credentials {\n>>        struct passwd *pass;\n>>        gid_t gid;\n>> }\n>> #endif\n>>\n>> and pass a pointer to credentials around.\n>>\n>\n> Yes, but that structure still needs to be filled somehow. I'm not sure\n> how this solves anything, really. Isn't it essentially another way of\n> wrapping an ifdef around the parameters inside main() (at least when\n> I've inlined serve() into main())?\n>\n>> #ifndef HAVE_POSIX_GOODIES\n>> static int drop_privileges(...)\n>> {\n>>        return error(\"--user and --group not supported on this platform\");\n>> }\n>> #endif\n>> static int drop_privileges(...)\n>> {\n>>        ...\n>>        do\n>>        something\n>>        ...\n>> }\n>> #endif\n>>\n>> would make serve() look like\n>>\n>> static int serve(...)\n>> {\n>>        int socknum, *socklist;\n>>\n>>        ... setup socket ...\n>>\n>>        if (want to drop privileges) {\n>>                if (drop_privileges(...))\n>>                        return -1;\n>>        }\n>>\n>>        return service_loop(socknum, socklist);\n>> }\n>>\n>> which should be quite readable even to a person only interested in the\n>> !HAVE_POSIX_GOODIES case imho.  With some code rearrangement it could\n>> be made nicer.  Now compare:\n>>\n>> static int serve(...)\n>> {\n>>        int socknum, *socklist;\n>>\n>>        ... setup socket ...\n>>\n>> #ifdef HAVE_POSIX_GOODIES\n>>        ...\n>>        do\n>>        things\n>>        ...\n>> #endif\n>>\n>>        return service_loop(socknum, socklist);\n>> }\n>>\n>> Just my two cents.  Sorry I do not have something more substantive to\n>> say.\n>>\n>\n> You're leaving out the troublesome part, namely the glue between \"if\n> (user_name)\" in main(), and the \"want to drop privileges\"-stuff in\n> serve().\n>\n> I could do a \"struct credentials *cred = NULL;\"  in main(), and assign\n> that inside \"if (user_name)\". But that'd leave a warning about\n> unreachable code in drop_privileges(), no?\n>\n\nOK, I did another stab at this, and this is the best I could come up\nwith right now, what do you think?\n\ndiff --git a/Makefile b/Makefile\nindex 46034bf..53986b1 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@@ -1066,7 +1067,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@@ -1077,6 +1077,7 @@ ifeq ($(uname_S),Windows)\n \tNO_CURL = YesPlease\n \tNO_PYTHON = YesPlease\n \tBLK_SHA1 = YesPlease\n+\tNO_POSIX_GOODIES = UnfortunatelyYes\n \tNATIVE_CRLF = YesPlease\n\n \tCC = compat/vcbuild/scripts/clink.pl\n@@ -1119,7 +1120,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@@ -1130,6 +1130,9 @@ 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+\tNO_POSIX_GOODIES = UnfortunatelyYes\n \tCOMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat\n-Icompat/fnmatch -Icompat/win32\n \tCOMPAT_CFLAGS += -DSTRIP_EXTENSION=\\\".exe\\\"\n \tCOMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o \\\n@@ -1249,9 +1252,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\n@@ -1419,6 +1419,10 @@ ifdef NO_DEFLATE_BOUND\n \tBASIC_CFLAGS += -DNO_DEFLATE_BOUND\n endif\n\n+ifdef NO_POSIX_GOODIES\n+\tBASIC_CFLAGS += -DNO_POSIX_GOODIES\n+endif\n+\n ifdef BLK_SHA1\n \tSHA1_HEADER = \"block-sha1/sha1.h\"\n \tLIB_OBJS += block-sha1/sha1.o\ndiff --git a/daemon.c b/daemon.c\nindex b7f3874..20ae9b4 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -26,7 +26,9 @@ static const char daemon_usage[] =\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+#ifndef NO_POSIX_GOODIES\n \"                      [--detach] [--user=user [--group=group]]\\n\"\n+#endif\n \"           [directory...]\";\n\n /* List of acceptable pathname prefixes */\n@@ -938,6 +940,33 @@ static void sanitize_stdfds(void)\n \t\tclose(fd);\n }\n\n+#ifdef NO_POSIX_GOODIES\n+\n+struct credentials;\n+static void drop_privileges(struct credentials *cred)\n+{\n+\t/* nothing */\n+}\n+\n+static void daemonize(void)\n+{\n+\tdie(\"--detach not supported on this platform\");\n+}\n+\n+#else\n+\n+struct credentials {\n+\tstruct passwd *pass;\n+\tgid_t gid;\n+};\n+\n+static void drop_privileges(struct credentials *cred)\n+{\n+\tif (cred && initgroups(cred->pass->pw_name, cred->gid) ||\n+\t    setgid (cred->gid) || setuid(cred->pass->pw_uid))\n+\t\tdie(\"cannot drop privileges\");\n+}\n+\n static void daemonize(void)\n {\n \tswitch (fork()) {\n@@ -955,6 +984,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 +995,7 @@ 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,\nstruct passwd *pass, gid_t gid)\n+static int serve(struct string_list *listen_addr, int listen_port,\nstruct credentials *cred)\n {\n \tstruct socketlist socklist = { NULL, 0, 0 };\n\n@@ -974,10 +1004,7 @@ static int serve(struct string_list\n*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-\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+\tdrop_privileges(cred);\n\n \treturn service_loop(&socklist);\n }\n@@ -989,9 +1016,7 @@ int main(int argc, char **argv)\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-\tstruct group *group;\n-\tgid_t gid = 0;\n+\tstruct credentials *cred = NULL;\n \tint i;\n\n \tgit_extract_argv0_path(argv[0]);\n@@ -1079,6 +1104,7 @@ int main(int argc, char **argv)\n \t\t\tpid_file = arg + 11;\n \t\t\tcontinue;\n \t\t}\n+#ifndef NO_POSIX_GOODIES\n \t\tif (!strcmp(arg, \"--detach\")) {\n \t\t\tdetach = 1;\n \t\t\tlog_syslog = 1;\n@@ -1092,6 +1118,12 @@ int main(int argc, char **argv)\n \t\t\tgroup_name = arg + 8;\n \t\t\tcontinue;\n \t\t}\n+#else\n+\t\t/* avoid warnings */\n+\t\t(void)user_name;\n+\t\t(void)group_name;\n+\t\t(void)detach;\n+#endif\n \t\tif (!prefixcmp(arg, \"--enable=\")) {\n \t\t\tenable_service(arg + 9, 1);\n \t\t\tcontinue;\n@@ -1126,32 +1158,37 @@ 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-\tif (inetd_mode && (detach || group_name || user_name))\n-\t\tdie(\"--detach, --user and --group are incompatible with --inetd\");\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+#ifndef NO_POSIX_GOODIES\n+\tif (inetd_mode && (detach || group_name || user_name))\n+\t\tdie(\"--detach, --user and --group are incompatible with --inetd\");\n+\n \tif (group_name && !user_name)\n \t\tdie(\"--group supplied without --user\");\n\n \tif (user_name) {\n-\t\tpass = getpwnam(user_name);\n-\t\tif (!pass)\n+\t\tstruct credentials c;\n+\t\tcred = &c;\n+\n+\t\tc->pass = getpwnam(user_name);\n+\t\tif (!c->pass)\n \t\t\tdie(\"user not found - %s\", user_name);\n\n \t\tif (!group_name)\n-\t\t\tgid = pass->pw_gid;\n+\t\t\tc->gid = 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\tc->gid = 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@@ -1185,5 +1222,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, cred);\n }\n"},{"id":"154036","messageId":"20101021220305.GA13142@burratino","threadId":"25421","inReplyTo":"AANLkTi=ydzrvy6_PbFLpA_qcHzF-8s3xbu3XvU5GnQ_k@mail.gmail.com","subject":"Re: [PATCH v4 15/15] daemon: opt-out on features that require posix","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-10-21T22:03:05Z","receivedAt":"2010-10-21T22:03:05Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Hi Erik,\n\nErik Faye-Lund wrote:\n\n> OK, I did another stab at this, and this is the best I could come up\n> with right now, what do you think?\n\nMuch clearer; thanks.\n"},{"id":"154035","messageId":"AANLkTinsKoYupt=yO9eVkpufzNDnke865UfMLKWSS6J1@mail.gmail.com","threadId":"25421","inReplyTo":"AANLkTi=ydzrvy6_PbFLpA_qcHzF-8s3xbu3XvU5GnQ_k@mail.gmail.com","subject":"Re: [PATCH v4 15/15] daemon: opt-out on features that require posix","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-10-21T22:04:32Z","receivedAt":"2010-10-21T22:04:32Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Fri, Oct 22, 2010 at 12:00 AM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n>        if (user_name) {\n> -               pass = getpwnam(user_name);\n> -               if (!pass)\n> +               struct credentials c;\n> +               cred = &c;\n> +\n> +               c->pass = getpwnam(user_name);\n> +               if (!c->pass)\n>                        die(\"user not found - %s\", user_name);\n>\n>                if (!group_name)\n> -                       gid = pass->pw_gid;\n> +                       c->gid = pass->pw_gid;\n>                else {\n> -                       group = getgrnam(group_name);\n> +                       struct group *group = getgrnam(group_name);\n>                        if (!group)\n>                                die(\"group not found - %s\", group_name);\n>\n> -                       gid = group->gr_gid;\n> +                       c->gid = group->gr_gid;\n>                }\n>        }\n\nSorry for the noise, but this is clearly incorrect and won't compile.\nI guess replacing \"c->\" with \"c.\" should do the trick :)\n\nIf I got this way, I'll obviously make sure it compiles! ;)\n"},{"id":"154044","messageId":"7veibjrv9r.fsf@alter.siamese.dyndns.org","threadId":"25421","inReplyTo":"AANLkTi=ydzrvy6_PbFLpA_qcHzF-8s3xbu3XvU5GnQ_k@mail.gmail.com","subject":"Re: [PATCH v4 15/15] daemon: opt-out on features that require posix","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-10-21T23:17:04Z","receivedAt":"2010-10-21T23:17:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Erik Faye-Lund <kusmabite@gmail.com> writes:\n\n> OK, I did another stab at this, and this is the best I could come up\n> with right now, what do you think?\n\nGetting warmer ;-)\n\nSimilarly to drop_privileges() you can create prepare_credential that\ntakes \"struct cred *, const char *username, const char *groupname\" as\nanother helper, and make its implementation on the NO_POSIX side barf/die\nwhen called, saying that switching credentials is not supported in\nNO_POSIX implementation.  That way, you can keep the main clean without\nany conditionals.  Command line argument parser can (and probably should)\nstay the same between implementations.\n\nThanks.\n"}]}