summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile79
-rw-r--r--connect.c73
-rw-r--r--daemon.c95
-rwxr-xr-xgit.sh4
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
diff --git a/Makefile b/Makefile
index e943954cf8..8b152dd558 100644
--- 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.
@@ -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:
diff --git a/connect.c b/connect.c
index 825c439acc..b157cf1cc7 100644
--- 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.
*/
diff --git a/daemon.c b/daemon.c
index 65e62d7bb1..8366a33bcb 100644
--- 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 178d0f0c09..ea710aafc1 100755
--- 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]"