Merge with http://www.kernel.org/pub/scm/git/git.git
authorPeter Anvin <hpa@tazenda.sc.orionmulti.com>
Thu, 29 Sep 2005 06:20:08 +0000 (23:20 -0700)
committerPeter Anvin <hpa@tazenda.sc.orionmulti.com>
Thu, 29 Sep 2005 06:20:08 +0000 (23:20 -0700)
Makefile
connect.c
daemon.c
git.sh
index 9920467d9060a434e96a38136bf3caf56c19ca8d..ff12fbf0993c27362285c48377baf1327335ac22 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -29,6 +29,8 @@
 #
 # Define WITH_OWN_SUBPROCESS_PY if you want to use with python 2.3.
 #
+# Define NO_IPV6 if you lack IPv6 support and getaddrinfo().
+#
 # Define COLLISION_CHECK below if you believe that SHA1's
 # 1461501637330902918203684832716283019655932542976 hashes do not give you
 # sufficient guarantee that no collisions between objects will ever happen.
@@ -97,7 +99,7 @@ SCRIPT_PYTHON = \
 # The ones that do not have to link with lcrypto nor lz.
 SIMPLE_PROGRAMS = \
        git-get-tar-commit-id git-mailinfo git-mailsplit git-stripspace \
-       git-daemon git-var
+       git-var git-daemon
 
 # ... and all the rest
 PROGRAMS = \
@@ -172,6 +174,12 @@ ifeq ($(shell uname -s),SunOS)
        TAR = gtar
        PLATFORM_DEFINES += -D__EXTENSIONS__
 endif
+ifeq ($(shell uname -o),Cygwin)
+       NO_STRCASESTR = YesPlease
+       NEEDS_LIBICONV = YesPlease
+       NO_IPV6 = YesPlease
+       X = .exe
+endif
 ifneq (,$(findstring arm,$(shell uname -m)))
        ARM_SHA1 = YesPlease
 endif
@@ -227,6 +235,9 @@ ifdef NO_STRCASESTR
        DEFINES += -Dstrcasestr=gitstrcasestr
        LIB_OBJS += compat/strcasestr.o
 endif
+ifdef NO_IPV6
+       DEFINES += -DNO_IPV6 -Dsockaddr_storage=sockaddr_in
+endif
 
 ifdef PPC_SHA1
        SHA1_HEADER = "ppc/sha1.h"
@@ -253,10 +264,13 @@ SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
          $(patsubst %.py,%,$(SCRIPT_PYTHON)) \
          gitk
 
+PROGRAMS_X = $(patsubst %,%$(X),$(PROGRAMS))
+SIMPLE_PROGRAMS_X = $(patsubst %,%$(X),$(SIMPLE_PROGRAMS))
+
 export TAR INSTALL DESTDIR SHELL_PATH
 ### Build rules
 
-all: $(PROGRAMS) $(SCRIPTS)
+all: $(PROGRAMS_X) $(SCRIPTS)
 
 all:
        $(MAKE) -C templates
@@ -290,30 +304,30 @@ $(patsubst %.py,%,$(SCRIPT_PYTHON)) : % : %.py
 %.o: %.S
        $(CC) -o $*.o -c $(ALL_CFLAGS) $<
 
-git-%: %.o $(LIB_FILE)
+git-%$(X): %.o $(LIB_FILE)
        $(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIBS)
 
-git-mailinfo : SIMPLE_LIB += $(LIB_4_ICONV)
-$(SIMPLE_PROGRAMS) : $(LIB_FILE)
-$(SIMPLE_PROGRAMS) : git-% : %.o
+git-mailinfo$(X) : SIMPLE_LIB += $(LIB_4_ICONV)
+$(SIMPLE_PROGRAMS_X) : $(LIB_FILE)
+$(SIMPLE_PROGRAMS_X) : git-%$(X) : %.o
        $(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIB_FILE) $(SIMPLE_LIB)
 
-git-http-fetch: fetch.o
-git-local-fetch: fetch.o
-git-ssh-fetch: rsh.o fetch.o
-git-ssh-upload: rsh.o
-git-ssh-pull: rsh.o fetch.o
-git-ssh-push: rsh.o
+git-http-fetch$(X): fetch.o
+git-local-fetch$(X): fetch.o
+git-ssh-fetch$(X): rsh.o fetch.o
+git-ssh-upload$(X): rsh.o
+git-ssh-pull$(X): rsh.o fetch.o
+git-ssh-push$(X): rsh.o
 
-git-http-fetch: LIBS += $(CURL_LIBCURL)
-git-rev-list: LIBS += $(OPENSSL_LIBSSL)
+git-http-fetch$(X): LIBS += $(CURL_LIBCURL)
+git-rev-list$(X): LIBS += $(OPENSSL_LIBSSL)
 
 init-db.o: init-db.c
        $(CC) -c $(ALL_CFLAGS) \
                -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir)"' $*.c
 
 $(LIB_OBJS): $(LIB_H)
-$(patsubst git-%,%.o,$(PROGRAMS)): $(LIB_H)
+$(patsubst git-%$(X),%.o,$(PROGRAMS_X)): $(LIB_H)
 $(DIFF_OBJS): diffcore.h
 
 $(LIB_FILE): $(LIB_OBJS)
@@ -328,10 +342,10 @@ doc:
 test: all
        $(MAKE) -C t/ all
 
-test-date: test-date.c date.o
+test-date$(X): test-date.c date.o
        $(CC) $(ALL_CFLAGS) -o $@ test-date.c date.o
 
-test-delta: test-delta.c diff-delta.o patch-delta.o
+test-delta$(X): test-delta.c diff-delta.o patch-delta.o
        $(CC) $(ALL_CFLAGS) -o $@ $^
 
 check:
@@ -341,9 +355,9 @@ check:
 
 ### Installation rules
 
-install: $(PROGRAMS) $(SCRIPTS)
+install: $(PROGRAMS_X) $(SCRIPTS)
        $(INSTALL) -d -m755 $(DESTDIR)$(bindir)
-       $(INSTALL) $(PROGRAMS) $(SCRIPTS) $(DESTDIR)$(bindir)
+       $(INSTALL) $(PROGRAMS_X) $(SCRIPTS) $(DESTDIR)$(bindir)
        $(INSTALL) git-revert $(DESTDIR)$(bindir)/git-cherry-pick
        $(MAKE) -C templates install
        $(INSTALL) -d -m755 $(DESTDIR)$(GIT_PYTHON_DIR)
@@ -381,7 +395,7 @@ deb: dist
 ### Cleaning rules
 
 clean:
-       rm -f *.o mozilla-sha1/*.o ppc/*.o compat/*.o $(PROGRAMS) $(LIB_FILE)
+       rm -f *.o mozilla-sha1/*.o ppc/*.o compat/*.o $(PROGRAMS_X) $(LIB_FILE)
        rm -f $(filter-out gitk,$(SCRIPTS))
        rm -f git-core.spec *.pyc *.pyo
        rm -rf $(GIT_TARNAME)
index 825c439accfbb4be4daa21a4d8b33addca0cd8b2..b157cf1cc718bbd7b8f4598b2dcb3a7ba92bb8e3 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -290,6 +290,8 @@ static enum protocol get_protocol(const char *name)
 #define STR_(s)        # s
 #define STR(s) STR_(s)
 
+#ifndef NO_IPV6
+
 static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path)
 {
        int sockfd = -1;
@@ -346,6 +348,77 @@ static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path)
        return 0;
 }
 
+#else /* NO_IPV6 */
+
+static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path)
+{
+       int sockfd = -1;
+       char *colon, *end;
+       char *port = STR(DEFAULT_GIT_PORT), *ep;
+       struct hostent *he;
+       struct sockaddr_in sa;
+       char **ap;
+       unsigned int nport;
+
+       if (host[0] == '[') {
+               end = strchr(host + 1, ']');
+               if (end) {
+                       *end = 0;
+                       end++;
+                       host++;
+               } else
+                       end = host;
+       } else
+               end = host;
+       colon = strchr(end, ':');
+
+       if (colon) {
+               *colon = 0;
+               port = colon + 1;
+       }
+
+
+       he = gethostbyname(host);
+       if (!he)
+               die("Unable to look up %s (%s)", host, hstrerror(h_errno));
+       nport = strtoul(port, &ep, 10);
+       if ( ep == port || *ep ) {
+               /* Not numeric */
+               struct servent *se = getservbyname(port,"tcp");
+               if ( !se )
+                       die("Unknown port %s\n", port);
+               nport = se->s_port;
+       }
+
+       for (ap = he->h_addr_list; *ap; ap++) {
+               sockfd = socket(he->h_addrtype, SOCK_STREAM, 0);
+               if (sockfd < 0)
+                       continue;
+
+               memset(&sa, 0, sizeof sa);
+               sa.sin_family = he->h_addrtype;
+               sa.sin_port = htons(nport);
+               memcpy(&sa.sin_addr, ap, he->h_length);
+
+               if (connect(sockfd, (struct sockaddr *)&sa, sizeof sa) < 0) {
+                       close(sockfd);
+                       sockfd = -1;
+                       continue;
+               }
+               break;
+       }
+
+       if (sockfd < 0)
+               die("unable to connect a socket (%s)", strerror(errno));
+
+       fd[0] = sockfd;
+       fd[1] = sockfd;
+       packet_write(sockfd, "%s %s\n", prog, path);
+       return 0;
+}
+
+#endif /* NO_IPV6 */
+
 /*
  * Yeah, yeah, fixme. Need to pass in the heads etc.
  */
index a369ce527eb4bd36528ce53da1048618d2373341..526ac782cf73cf42eb52e7db803500a13bfa3714 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -1,9 +1,11 @@
 #include "cache.h"
 #include "pkt-line.h"
+#include <alloca.h>
 #include <signal.h>
 #include <sys/wait.h>
 #include <sys/socket.h>
 #include <sys/time.h>
+#include <sys/poll.h>
 #include <netdb.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
@@ -328,6 +330,7 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)
                inet_ntop(AF_INET, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf));
                port = sin_addr->sin_port;
 
+#ifndef NO_IPV6
        } else if (addr->sa_family == AF_INET6) {
                struct sockaddr_in6 *sin6_addr = (void *) addr;
 
@@ -337,6 +340,7 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)
                strcat(buf, "]");
 
                port = sin6_addr->sin6_port;
+#endif
        }
        loginfo("Connection from %s:%d", addrbuf, port);
 
@@ -369,16 +373,16 @@ static void child_handler(int signo)
        }
 }
 
-static int serve(int port)
+#ifndef NO_IPV6
+
+static int socksetup(int port, int **socklist_p)
 {
-       struct addrinfo hints, *ai0, *ai;
-       int gai;
        int socknum = 0, *socklist = NULL;
        int maxfd = -1;
-       fd_set fds_init, fds;
        char pbuf[NI_MAXSERV];
 
-       signal(SIGCHLD, child_handler);
+       struct addrinfo hints, *ai0, *ai;
+       int gai;
 
        sprintf(pbuf, "%d", port);
        memset(&hints, 0, sizeof(hints));
@@ -391,8 +395,6 @@ static int serve(int port)
        if (gai)
                die("getaddrinfo() failed: %s\n", gai_strerror(gai));
 
-       FD_ZERO(&fds_init);
-
        for (ai = ai0; ai; ai = ai->ai_next) {
                int sockfd;
                int *newlist;
@@ -431,23 +433,65 @@ static int serve(int port)
                socklist = newlist;
                socklist[socknum++] = sockfd;
 
-               FD_SET(sockfd, &fds_init);
                if (maxfd < sockfd)
                        maxfd = sockfd;
        }
 
        freeaddrinfo(ai0);
 
-       if (socknum == 0)
-               die("unable to allocate any listen sockets on port %u", port);
+       *socklist_p = socklist;
+       return socknum;
+}
+
+#else /* NO_IPV6 */
+
+static int socksetup(int port, int **socklist_p)
+{
+       struct sockaddr_in sin;
+       int sockfd;
+
+       sockfd = socket(AF_INET, SOCK_STREAM, 0);
+       if (sockfd < 0)
+               return 0;
+
+       memset(&sin, 0, sizeof sin);
+       sin.sin_family = AF_INET;
+       sin.sin_addr.s_addr = htonl(INADDR_ANY);
+       sin.sin_port = htons(port);
+
+       if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) {
+               close(sockfd);
+               return 0;
+       }
 
+       *socklist_p = malloc(sizeof(int));
+       if ( !*socklist_p )
+               die("memory allocation failed: %s", strerror(errno));
+       **socklist_p = sockfd;
+}
+
+#endif
+
+static int service_loop(int socknum, int *socklist)
+{
+       struct pollfd *pfd;
+       int i;
+
+       pfd = calloc(socknum, sizeof(struct pollfd));
+       if (!pfd)
+               die("memory allocation failed: %s", strerror(errno));
+
+       for (i = 0; i < socknum; i++) {
+               pfd[i].fd = socklist[i];
+               pfd[i].events = POLLIN;
+       }
+       
        for (;;) {
                int i;
-               fds = fds_init;
-               
-               if (select(maxfd + 1, &fds, NULL, NULL, NULL) < 0) {
+
+               if (poll(pfd, socknum, 0) < 0) {
                        if (errno != EINTR) {
-                               error("select failed, resuming: %s",
+                               error("poll failed, resuming: %s",
                                      strerror(errno));
                                sleep(1);
                        }
@@ -455,12 +499,10 @@ static int serve(int port)
                }
 
                for (i = 0; i < socknum; i++) {
-                       int sockfd = socklist[i];
-
-                       if (FD_ISSET(sockfd, &fds)) {
+                       if (pfd[i].revents & POLLIN) {
                                struct sockaddr_storage ss;
                                int sslen = sizeof(ss);
-                               int incoming = accept(sockfd, (struct sockaddr *)&ss, &sslen);
+                               int incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen);
                                if (incoming < 0) {
                                        switch (errno) {
                                        case EAGAIN:
@@ -477,6 +519,19 @@ static int serve(int port)
        }
 }
 
+static int serve(int port)
+{
+       int socknum, *socklist;
+       
+       signal(SIGCHLD, child_handler);
+       
+       socknum = socksetup(port, &socklist);
+       if (socknum == 0)
+               die("unable to allocate any listen sockets on port %u", port);
+       
+       return service_loop(socknum, socklist);
+}      
+
 int main(int argc, char **argv)
 {
        int port = DEFAULT_GIT_PORT;
@@ -526,7 +581,7 @@ int main(int argc, char **argv)
        if (inetd_mode) {
                fclose(stderr); //FIXME: workaround
                return execute();
+       } else {
+               return serve(port);
        }
-
-       return serve(port);
 }
diff --git a/git.sh b/git.sh
index 178d0f0c09cad4859656dd4480ad9c096032f545..ea710aafc130afb5b4adabcaab4ec996662cdc34 100755 (executable)
--- a/git.sh
+++ b/git.sh
@@ -11,7 +11,11 @@ case "$#" in
                echo "git version @@GIT_VERSION@@"
                exit 0 ;;
        esac
+
        test -x $path/git-$cmd && exec $path/git-$cmd "$@" ;;
+
+       # In case we're running on Cygwin...
+       test -x $path/git-$cmd.exe && exec $path/git-$cmd.exe "$@" ;;
 esac
 
 echo "Usage: git COMMAND [OPTIONS] [TARGET]"