diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 79 | ||||
-rw-r--r-- | connect.c | 73 | ||||
-rw-r--r-- | daemon.c | 95 | ||||
-rwxr-xr-x | git.sh | 4 |
5 files changed, 197 insertions, 55 deletions
diff --git a/.gitignore b/.gitignore index c3eb9543ff..b99a37e9ba 100644 --- a/.gitignore +++ b/.gitignore @@ -100,3 +100,4 @@ git-core-*/?* *.dsc *.deb git-core.spec +*.exe @@ -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. @@ -96,31 +98,29 @@ 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-get-tar-commit-id$(X) git-mailinfo$(X) git-mailsplit$(X) \ + git-stripspace$(X) git-var$(X) git-daemon$(X) # ... and all the rest PROGRAMS = \ - git-apply git-cat-file \ - git-checkout-index git-clone-pack git-commit-tree \ - git-convert-objects git-diff-files \ - git-diff-index git-diff-stages \ - git-diff-tree git-fetch-pack git-fsck-objects \ - git-hash-object git-init-db \ - git-local-fetch git-ls-files git-ls-tree git-merge-base \ - git-merge-index git-mktag git-pack-objects git-patch-id \ - git-peek-remote git-prune-packed git-read-tree \ - git-receive-pack git-rev-list git-rev-parse \ - git-send-pack git-show-branch \ - git-show-index git-ssh-fetch \ - git-ssh-upload git-tar-tree git-unpack-file \ - git-unpack-objects git-update-index git-update-server-info \ - git-upload-pack git-verify-pack git-write-tree \ - git-update-ref \ - $(SIMPLE_PROGRAMS) + git-apply$(X) git-cat-file$(X) git-checkout-index$(X) \ + git-clone-pack$(X) git-commit-tree$(X) git-convert-objects$(X) \ + git-diff-files$(X) git-diff-index$(X) git-diff-stages$(X) \ + git-diff-tree$(X) git-fetch-pack$(X) git-fsck-objects$(X) \ + git-hash-object$(X) git-init-db$(X) git-local-fetch$(X) \ + git-ls-files$(X) git-ls-tree$(X) git-merge-base$(X) \ + git-merge-index$(X) git-mktag$(X) git-pack-objects$(X) \ + git-patch-id$(X) git-peek-remote$(X) git-prune-packed$(X) \ + git-read-tree$(X) git-receive-pack$(X) git-rev-list$(X) \ + git-rev-parse$(X) git-send-pack$(X) git-show-branch$(X) \ + git-show-index$(X) git-ssh-fetch$(X) git-ssh-upload$(X) \ + git-tar-tree$(X) git-unpack-file$(X) git-unpack-objects$(X) \ + git-update-index$(X) git-update-server-info$(X) \ + git-upload-pack$(X) git-verify-pack$(X) git-write-tree$(X) \ + git-update-ref$(X) $(SIMPLE_PROGRAMS) # Backward compatibility -- to be removed after 1.0 -PROGRAMS += git-ssh-pull git-ssh-push +PROGRAMS += git-ssh-pull$(X) git-ssh-push$(X) PYMODULES = \ gitMergeCommon.py @@ -172,6 +172,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 @@ -184,7 +190,7 @@ ifndef NO_CURL else CURL_LIBCURL = -lcurl endif - PROGRAMS += git-http-fetch + PROGRAMS += git-http-fetch$(X) endif ifndef SHELL_PATH @@ -227,6 +233,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" @@ -290,30 +299,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) +git-mailinfo$(X) : SIMPLE_LIB += $(LIB_4_ICONV) $(SIMPLE_PROGRAMS) : $(LIB_FILE) -$(SIMPLE_PROGRAMS) : git-% : %.o +$(SIMPLE_PROGRAMS) : 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)): $(LIB_H) $(DIFF_OBJS): diffcore.h $(LIB_FILE): $(LIB_OBJS) @@ -328,10 +337,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: @@ -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. */ @@ -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); } @@ -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]" |