From: Junio C Hamano Date: Tue, 30 Nov 2010 01:52:34 +0000 (-0800) Subject: Merge branch 'md/interix' X-Git-Tag: v1.7.4-rc0~105 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/ec3f7d5d0f3676aa9634ee30f8c9e55893a8c505?ds=inline;hp=-c Merge branch 'md/interix' * md/interix: Interix: add configure checks add support for the SUA layer (interix; windows) Conflicts: git-compat-util.h --- ec3f7d5d0f3676aa9634ee30f8c9e55893a8c505 diff --combined Makefile index 919ed2b7ec,c9d8c9e1fe..1d42413465 --- a/Makefile +++ b/Makefile @@@ -401,7 -401,6 +401,7 @@@ EXTRA_PROGRAMS # ... and all the rest that could be moved out of bindir to gitexecdir PROGRAMS += $(EXTRA_PROGRAMS) +PROGRAM_OBJS += daemon.o PROGRAM_OBJS += fast-import.o PROGRAM_OBJS += imap-send.o PROGRAM_OBJS += shell.o @@@ -497,8 -496,6 +497,8 @@@ LIB_H += compat/bswap. LIB_H += compat/cygwin.h LIB_H += compat/mingw.h LIB_H += compat/win32/pthread.h +LIB_H += compat/win32/syslog.h +LIB_H += compat/win32/sys/poll.h LIB_H += csum-file.h LIB_H += decorate.h LIB_H += delta.h @@@ -1067,6 -1064,7 +1067,6 @@@ ifeq ($(uname_S),Windows NO_SVN_TESTS = YesPlease NO_PERL_MAKEMAKER = YesPlease RUNTIME_PREFIX = YesPlease - NO_POSIX_ONLY_PROGRAMS = YesPlease NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease NO_NSEC = YesPlease USE_WIN32_MMAP = YesPlease @@@ -1077,14 -1075,13 +1077,14 @@@ NO_CURL = YesPlease NO_PYTHON = YesPlease BLK_SHA1 = YesPlease + NO_POSIX_GOODIES = UnfortunatelyYes NATIVE_CRLF = YesPlease CC = compat/vcbuild/scripts/clink.pl AR = compat/vcbuild/scripts/lib.pl CFLAGS = BASIC_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 - COMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o compat/win32/pthread.o + COMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o compat/win32/pthread.o compat/win32/syslog.o compat/win32/sys/poll.o COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/fnmatch -Icompat/regex -Icompat/fnmatch -Icompat/win32 -DSTRIP_EXTENSION=\".exe\" BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib EXTLIBS = advapi32.lib shell32.lib wininet.lib ws2_32.lib @@@ -1099,6 -1096,25 +1099,25 @@@ els endif X = .exe endif + ifeq ($(uname_S),Interix) + NO_SYS_POLL_H = YesPlease + NO_INTTYPES_H = YesPlease + NO_INITGROUPS = YesPlease + NO_IPV6 = YesPlease + NO_MEMMEM = YesPlease + NO_MKDTEMP = YesPlease + NO_STRTOUMAX = YesPlease + NO_NSEC = YesPlease + NO_MKSTEMPS = YesPlease + ifeq ($(uname_R),3.5) + NO_INET_NTOP = YesPlease + NO_INET_PTON = YesPlease + endif + ifeq ($(uname_R),5.2) + NO_INET_NTOP = YesPlease + NO_INET_PTON = YesPlease + endif + endif ifneq (,$(findstring MINGW,$(uname_S))) pathsep = ; NO_PREAD = YesPlease @@@ -1120,6 -1136,7 +1139,6 @@@ NO_SVN_TESTS = YesPlease NO_PERL_MAKEMAKER = YesPlease RUNTIME_PREFIX = YesPlease - NO_POSIX_ONLY_PROGRAMS = YesPlease NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease NO_NSEC = YesPlease USE_WIN32_MMAP = YesPlease @@@ -1130,14 -1147,10 +1149,14 @@@ NO_PYTHON = YesPlease BLK_SHA1 = YesPlease ETAGS_TARGET = ETAGS + NO_INET_PTON = YesPlease + NO_INET_NTOP = YesPlease + NO_POSIX_GOODIES = UnfortunatelyYes COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch -Icompat/win32 COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\" COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o \ - compat/win32/pthread.o + compat/win32/pthread.o compat/win32/syslog.o \ + compat/win32/sys/poll.o EXTLIBS += -lws2_32 PTHREAD_LIBS = X = .exe @@@ -1252,6 -1265,9 +1271,6 @@@ ifdef ZLIB_PAT endif EXTLIBS += -lz -ifndef NO_POSIX_ONLY_PROGRAMS - PROGRAM_OBJS += daemon.o -endif ifndef NO_OPENSSL OPENSSL_LIBSSL = -lssl ifdef OPENSSLDIR @@@ -1363,6 -1379,15 +1382,15 @@@ endi ifdef NO_SYS_SELECT_H BASIC_CFLAGS += -DNO_SYS_SELECT_H endif + ifdef NO_SYS_POLL_H + BASIC_CFLAGS += -DNO_SYS_POLL_H + endif + ifdef NO_INTTYPES_H + BASIC_CFLAGS += -DNO_INTTYPES_H + endif + ifdef NO_INITGROUPS + BASIC_CFLAGS += -DNO_INITGROUPS + endif ifdef NO_MMAP COMPAT_CFLAGS += -DNO_MMAP COMPAT_OBJS += compat/mmap.o @@@ -1400,11 -1425,9 +1428,11 @@@ endi endif ifdef NO_INET_NTOP LIB_OBJS += compat/inet_ntop.o + BASIC_CFLAGS += -DNO_INET_NTOP endif ifdef NO_INET_PTON LIB_OBJS += compat/inet_pton.o + BASIC_CFLAGS += -DNO_INET_PTON endif ifdef NO_ICONV @@@ -1419,10 -1442,6 +1447,10 @@@ ifdef NO_DEFLATE_BOUN BASIC_CFLAGS += -DNO_DEFLATE_BOUND endif +ifdef NO_POSIX_GOODIES + BASIC_CFLAGS += -DNO_POSIX_GOODIES +endif + ifdef BLK_SHA1 SHA1_HEADER = "block-sha1/sha1.h" LIB_OBJS += block-sha1/sha1.o @@@ -1936,7 -1955,7 +1964,7 @@@ git-%$X: %.o $(GITLIBS git-imap-send$X: imap-send.o $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ - $(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL) + $(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL) $(LIB_4_CRYPTO) git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ diff --combined daemon.c index 13435b4667,de59f5d139..d2a4e023e8 --- a/daemon.c +++ b/daemon.c @@@ -5,6 -5,8 +5,6 @@@ #include "strbuf.h" #include "string-list.h" -#include - #ifndef HOST_NAME_MAX #define HOST_NAME_MAX 256 #endif @@@ -13,6 -15,10 +13,10 @@@ #define NI_MAXSERV 32 #endif + #ifdef NO_INITGROUPS + #define initgroups(x, y) (0) /* nothing */ + #endif + static int log_syslog; static int verbose; static int reuseaddr; @@@ -23,10 -29,10 +27,10 @@@ static const char daemon_usage[] " [--strict-paths] [--base-path=] [--base-path-relaxed]\n" " [--user-path | --user-path=]\n" " [--interpolated-path=]\n" -" [--reuseaddr] [--detach] [--pid-file=]\n" +" [--reuseaddr] [--pid-file=]\n" " [--(enable|disable|allow-override|forbid-override)=]\n" " [--inetd | [--listen=] [--port=]\n" -" [--user= [--group=]]\n" +" [--detach] [--user= [--group=]]\n" " [...]"; /* List of acceptable pathname prefixes */ @@@ -67,14 -73,12 +71,14 @@@ static void logreport(int priority, con syslog(priority, "%s", buf); } else { /* - * Since stderr is set to linebuffered mode, the + * Since stderr is set to buffered mode, the * logging of different processes will not overlap + * unless they overflow the (rather big) buffers. */ fprintf(stderr, "[%"PRIuMAX"] ", (uintmax_t)getpid()); vfprintf(stderr, err, params); fputc('\n', stderr); + fflush(stderr); } } @@@ -516,14 -520,37 +520,14 @@@ static void parse_host_arg(char *extra_ } -static int execute(struct sockaddr *addr) +static int execute(void) { static char line[1000]; int pktlen, len, i; + char *addr = getenv("REMOTE_ADDR"), *port = getenv("REMOTE_PORT"); - if (addr) { - char addrbuf[256] = ""; - int port = -1; - - if (addr->sa_family == AF_INET) { - struct sockaddr_in *sin_addr = (void *) addr; - inet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf)); - port = ntohs(sin_addr->sin_port); -#ifndef NO_IPV6 - } else if (addr && addr->sa_family == AF_INET6) { - struct sockaddr_in6 *sin6_addr = (void *) addr; - - char *buf = addrbuf; - *buf++ = '['; *buf = '\0'; /* stpcpy() is cool */ - inet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1); - strcat(buf, "]"); - - port = ntohs(sin6_addr->sin6_port); -#endif - } - loginfo("Connection from %s:%d", addrbuf, port); - setenv("REMOTE_ADDR", addrbuf, 1); - } - else { - unsetenv("REMOTE_ADDR"); - } + if (addr) + loginfo("Connection from %s:%s", addr, port); alarm(init_timeout ? init_timeout : timeout); pktlen = packet_read_line(0, line, sizeof(line)); @@@ -593,17 -620,17 +597,17 @@@ static unsigned int live_children static struct child { struct child *next; - pid_t pid; + struct child_process cld; struct sockaddr_storage address; } *firstborn; -static void add_child(pid_t pid, struct sockaddr *addr, int addrlen) +static void add_child(struct child_process *cld, struct sockaddr *addr, socklen_t addrlen) { struct child *newborn, **cradle; newborn = xcalloc(1, sizeof(*newborn)); live_children++; - newborn->pid = pid; + memcpy(&newborn->cld, cld, sizeof(*cld)); memcpy(&newborn->address, addr, addrlen); for (cradle = &firstborn; *cradle; cradle = &(*cradle)->next) if (!addrcmp(&(*cradle)->address, &newborn->address)) @@@ -612,6 -639,19 +616,6 @@@ *cradle = newborn; } -static void remove_child(pid_t pid) -{ - struct child **cradle, *blanket; - - for (cradle = &firstborn; (blanket = *cradle); cradle = &blanket->next) - if (blanket->pid == pid) { - *cradle = blanket->next; - live_children--; - free(blanket); - break; - } -} - /* * This gets called if the number of connections grows * past "max_connections". @@@ -627,7 -667,7 +631,7 @@@ static void kill_some_child(void for (; (next = blanket->next); blanket = next) if (!addrcmp(&blanket->address, &next->address)) { - kill(blanket->pid, SIGTERM); + kill(blanket->cld.pid, SIGTERM); break; } } @@@ -637,28 -677,18 +641,28 @@@ static void check_dead_children(void int status; pid_t pid; - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { - const char *dead = ""; - remove_child(pid); - if (!WIFEXITED(status) || (WEXITSTATUS(status) > 0)) - dead = " (with error)"; - loginfo("[%"PRIuMAX"] Disconnected%s", (uintmax_t)pid, dead); - } + struct child **cradle, *blanket; + for (cradle = &firstborn; (blanket = *cradle);) + if ((pid = waitpid(blanket->cld.pid, &status, WNOHANG)) > 1) { + const char *dead = ""; + if (status) + dead = " (with error)"; + loginfo("[%"PRIuMAX"] Disconnected%s", (uintmax_t)pid, dead); + + /* remove the child */ + *cradle = blanket->next; + live_children--; + free(blanket); + } else + cradle = &blanket->next; } -static void handle(int incoming, struct sockaddr *addr, int addrlen) +static char **cld_argv; +static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen) { - pid_t pid; + struct child_process cld = { 0 }; + char addrbuf[300] = "REMOTE_ADDR=", portbuf[300]; + char *env[] = { addrbuf, portbuf, NULL }; if (max_connections && live_children >= max_connections) { kill_some_child(); @@@ -671,37 -701,22 +675,37 @@@ } } - if ((pid = fork())) { - close(incoming); - if (pid < 0) { - logerror("Couldn't fork %s", strerror(errno)); - return; - } + if (addr->sa_family == AF_INET) { + struct sockaddr_in *sin_addr = (void *) addr; + inet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf + 12, + sizeof(addrbuf) - 12); + snprintf(portbuf, sizeof(portbuf), "REMOTE_PORT=%d", + ntohs(sin_addr->sin_port)); +#ifndef NO_IPV6 + } else if (addr && addr->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6_addr = (void *) addr; - add_child(pid, addr, addrlen); - return; + char *buf = addrbuf + 12; + *buf++ = '['; *buf = '\0'; /* stpcpy() is cool */ + inet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, + sizeof(addrbuf) - 13); + strcat(buf, "]"); + + snprintf(portbuf, sizeof(portbuf), "REMOTE_PORT=%d", + ntohs(sin6_addr->sin6_port)); +#endif } - dup2(incoming, 0); - dup2(incoming, 1); - close(incoming); + cld.env = (const char **)env; + cld.argv = (const char **)cld_argv; + cld.in = incoming; + cld.out = dup(incoming); - exit(execute(addr)); + if (start_command(&cld)) + logerror("unable to fork"); + else + add_child(&cld, addr, addrlen); + close(incoming); } static void child_handler(int signo) @@@ -903,15 -918,9 +907,15 @@@ static int service_loop(struct socketli for (i = 0; i < socklist->nr; i++) { if (pfd[i].revents & POLLIN) { - struct sockaddr_storage ss; - unsigned int sslen = sizeof(ss); - int incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen); + union { + struct sockaddr sa; + struct sockaddr_in sai; +#ifndef NO_IPV6 + struct sockaddr_in6 sai6; +#endif + } ss; + socklen_t sslen = sizeof(ss); + int incoming = accept(pfd[i].fd, &ss.sa, &sslen); if (incoming < 0) { switch (errno) { case EAGAIN: @@@ -922,7 -931,7 +926,7 @@@ die_errno("accept returned"); } } - handle(incoming, (struct sockaddr *)&ss, sslen); + handle(incoming, &ss.sa, sslen); } } } @@@ -940,62 -949,6 +944,62 @@@ static void sanitize_stdfds(void close(fd); } +#ifdef NO_POSIX_GOODIES + +struct credentials; + +static void drop_privileges(struct credentials *cred) +{ + /* nothing */ +} + +static void daemonize(void) +{ + die("--detach not supported on this platform"); +} + +static struct credentials *prepare_credentials(const char *user_name, + const char *group_name) +{ + die("--user not supported on this platform"); +} + +#else + +struct credentials { + struct passwd *pass; + gid_t gid; +}; + +static void drop_privileges(struct credentials *cred) +{ + if (cred && (initgroups(cred->pass->pw_name, cred->gid) || + setgid (cred->gid) || setuid(cred->pass->pw_uid))) + die("cannot drop privileges"); +} + +static struct credentials *prepare_credentials(const char *user_name, + const char *group_name) +{ + static struct credentials c; + + c.pass = getpwnam(user_name); + if (!c.pass) + die("user not found - %s", user_name); + + if (!group_name) + c.gid = c.pass->pw_gid; + else { + struct group *group = getgrnam(group_name); + if (!group) + die("group not found - %s", group_name); + + c.gid = group->gr_gid; + } + + return &c; +} + static void daemonize(void) { switch (fork()) { @@@ -1013,7 -966,6 +1017,7 @@@ close(2); sanitize_stdfds(); } +#endif static void store_pid(const char *path) { @@@ -1024,8 -976,7 +1028,8 @@@ die_errno("failed to write pid file '%s'", path); } -static int serve(struct string_list *listen_addr, int listen_port, struct passwd *pass, gid_t gid) +static int serve(struct string_list *listen_addr, int listen_port, + struct credentials *cred) { struct socketlist socklist = { NULL, 0, 0 }; @@@ -1034,7 -985,10 +1038,7 @@@ die("unable to allocate any listen sockets on port %u", listen_port); - if (pass && gid && - (initgroups(pass->pw_name, gid) || setgid (gid) || - setuid(pass->pw_uid))) - die("cannot drop privileges"); + drop_privileges(cred); return service_loop(&socklist); } @@@ -1043,10 -997,12 +1047,10 @@@ int main(int argc, char **argv { int listen_port = 0; struct string_list listen_addr = STRING_LIST_INIT_NODUP; - int inetd_mode = 0; + int serve_mode = 0, inetd_mode = 0; const char *pid_file = NULL, *user_name = NULL, *group_name = NULL; int detach = 0; - struct passwd *pass = NULL; - struct group *group; - gid_t gid = 0; + struct credentials *cred = NULL; int i; git_extract_argv0_path(argv[0]); @@@ -1067,10 -1023,6 +1071,10 @@@ continue; } } + if (!strcmp(arg, "--serve")) { + serve_mode = 1; + continue; + } if (!strcmp(arg, "--inetd")) { inetd_mode = 1; log_syslog = 1; @@@ -1179,10 -1131,10 +1183,10 @@@ set_die_routine(daemon_die); } else /* avoid splitting a message in the middle */ - setvbuf(stderr, NULL, _IOLBF, 0); + setvbuf(stderr, NULL, _IOFBF, 4096); - if (inetd_mode && (group_name || user_name)) - die("--user and --group are incompatible with --inetd"); + if (inetd_mode && (detach || group_name || user_name)) + die("--detach, --user and --group are incompatible with --inetd"); if (inetd_mode && (listen_port || (listen_addr.nr > 0))) die("--listen= and --port= are incompatible with --inetd"); @@@ -1192,8 -1144,21 +1196,8 @@@ if (group_name && !user_name) die("--group supplied without --user"); - if (user_name) { - pass = getpwnam(user_name); - if (!pass) - die("user not found - %s", user_name); - - if (!group_name) - gid = pass->pw_gid; - else { - group = getgrnam(group_name); - if (!group) - die("group not found - %s", group_name); - - gid = group->gr_gid; - } - } + if (user_name) + cred = prepare_credentials(user_name, group_name); if (strict_paths && (!ok_paths || !*ok_paths)) die("option --strict-paths requires a whitelist"); @@@ -1203,13 -1168,19 +1207,13 @@@ base_path); if (inetd_mode) { - struct sockaddr_storage ss; - struct sockaddr *peer = (struct sockaddr *)&ss; - socklen_t slen = sizeof(ss); - if (!freopen("/dev/null", "w", stderr)) die_errno("failed to redirect stderr to /dev/null"); - - if (getpeername(0, peer, &slen)) - peer = NULL; - - return execute(peer); } + if (inetd_mode || serve_mode) + return execute(); + if (detach) { daemonize(); loginfo("Ready to rumble"); @@@ -1220,12 -1191,5 +1224,12 @@@ if (pid_file) store_pid(pid_file); - return serve(&listen_addr, listen_port, pass, gid); + /* prepare argv for serving-processes */ + cld_argv = xmalloc(sizeof (char *) * (argc + 2)); + for (i = 0; i < argc; ++i) + cld_argv[i] = argv[i]; + cld_argv[argc] = "--serve"; + cld_argv[argc+1] = NULL; + + return serve(&listen_addr, listen_port, cred); } diff --combined git-compat-util.h index d0a1e480b6,625b2e4f14..490f969744 --- a/git-compat-util.h +++ b/git-compat-util.h @@@ -104,10 -104,13 +104,14 @@@ #include #include #include -#ifndef __MINGW32__ -#include +#include + #ifndef NO_SYS_POLL_H #include + #else + #include + #endif +#ifndef __MINGW32__ +#include #include #include #include @@@ -119,7 -122,11 +123,11 @@@ #include #include #include + #ifndef NO_INTTYPES_H #include + #else + #include + #endif #if defined(__CYGWIN__) #undef _XOPEN_SOURCE #include @@@ -387,14 -394,6 +395,14 @@@ static inline void *gitmempcpy(void *de } #endif +#ifdef NO_INET_PTON +int inet_pton(int af, const char *src, void *dst); +#endif + +#ifdef NO_INET_NTOP +const char *inet_ntop(int af, const void *src, char *dst, size_t size); +#endif + extern void release_pack_memory(size_t, int); typedef void (*try_to_free_t)(size_t);