Add first cut at "git protocol" connect logic.
Useful for pulling stuff off a dedicated server. Instead of connecting with ssh or just starting a local pipeline, we connect over TCP to the other side and try to see if there's a git server listening. Of course, since I haven't written the git server yet, that will never happen. But the server really just needs to listen on a port, and execute a "git-upload-pack" when somebody connects. (It should read one packet-line, which should be of the format "git-upload-pack directoryname\n" and eventually we migth have other commands the server might accept).maint
							parent
							
								
									2408cff9f7
								
							
						
					
					
						commit
						2386d65822
					
				
							
								
								
									
										10
									
								
								cache.h
								
								
								
								
							
							
						
						
									
										10
									
								
								cache.h
								
								
								
								
							|  | @ -40,6 +40,16 @@ | ||||||
| #define NORETURN | #define NORETURN | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Intensive research over the course of many years has shown that | ||||||
|  |  * port 9418 is totally unused by anything else. Or | ||||||
|  |  * | ||||||
|  |  *	Your search - "port 9418" - did not match any documents. | ||||||
|  |  * | ||||||
|  |  * as www.google.com puts it. | ||||||
|  |  */ | ||||||
|  | #define DEFAULT_GIT_PORT 9418 | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Environment variables transition. |  * Environment variables transition. | ||||||
|  * We accept older names for now but warn. |  * We accept older names for now but warn. | ||||||
|  |  | ||||||
							
								
								
									
										83
									
								
								connect.c
								
								
								
								
							
							
						
						
									
										83
									
								
								connect.c
								
								
								
								
							|  | @ -2,6 +2,10 @@ | ||||||
| #include "pkt-line.h" | #include "pkt-line.h" | ||||||
| #include "quote.h" | #include "quote.h" | ||||||
| #include <sys/wait.h> | #include <sys/wait.h> | ||||||
|  | #include <sys/socket.h> | ||||||
|  | #include <netinet/in.h> | ||||||
|  | #include <arpa/inet.h> | ||||||
|  | #include <netdb.h> | ||||||
|  |  | ||||||
| int get_ack(int fd, unsigned char *result_sha1) | int get_ack(int fd, unsigned char *result_sha1) | ||||||
| { | { | ||||||
|  | @ -42,25 +46,100 @@ int path_match(const char *path, int nr, char **match) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | enum protocol { | ||||||
|  | 	PROTO_LOCAL = 1, | ||||||
|  | 	PROTO_SSH, | ||||||
|  | 	PROTO_GIT, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static enum protocol get_protocol(const char *name) | ||||||
|  | { | ||||||
|  | 	if (!strcmp(name, "ssh")) | ||||||
|  | 		return PROTO_SSH; | ||||||
|  | 	if (!strcmp(name, "git")) | ||||||
|  | 		return PROTO_GIT; | ||||||
|  | 	die("I don't handle protocol '%s'", name); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void lookup_host(const char *host, struct sockaddr *in) | ||||||
|  | { | ||||||
|  | 	struct addrinfo *res; | ||||||
|  | 	int ret; | ||||||
|  |  | ||||||
|  | 	ret = getaddrinfo(host, NULL, NULL, &res); | ||||||
|  | 	if (ret) | ||||||
|  | 		die("Unable to look up %s (%s)", host, gai_strerror(ret)); | ||||||
|  | 	*in = *res->ai_addr; | ||||||
|  | 	freeaddrinfo(res); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path) | ||||||
|  | { | ||||||
|  | 	struct sockaddr addr; | ||||||
|  | 	int port = DEFAULT_GIT_PORT, sockfd; | ||||||
|  | 	char *colon; | ||||||
|  |  | ||||||
|  | 	colon = strchr(host, ':'); | ||||||
|  | 	if (colon) { | ||||||
|  | 		char *end; | ||||||
|  | 		unsigned long n = strtoul(colon+1, &end, 0); | ||||||
|  | 		if (colon[1] && !*end) { | ||||||
|  | 			*colon = 0; | ||||||
|  | 			port = n; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	lookup_host(host, &addr); | ||||||
|  | 	((struct sockaddr_in *)&addr)->sin_port = htons(port); | ||||||
|  |  | ||||||
|  | 	sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_IP); | ||||||
|  | 	if (sockfd < 0) | ||||||
|  | 		die("unable to create socket (%s)", strerror(errno)); | ||||||
|  | 	if (connect(sockfd, (void *)&addr, sizeof(addr)) < 0) | ||||||
|  | 		die("unable to connect (%s)", strerror(errno)); | ||||||
|  | 	fd[0] = sockfd; | ||||||
|  | 	fd[1] = sockfd; | ||||||
|  | 	packet_write(sockfd, "%s %s\n", prog, path); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Yeah, yeah, fixme. Need to pass in the heads etc. |  * Yeah, yeah, fixme. Need to pass in the heads etc. | ||||||
|  */ |  */ | ||||||
| int git_connect(int fd[2], char *url, const char *prog) | int git_connect(int fd[2], char *url, const char *prog) | ||||||
| { | { | ||||||
| 	char command[1024]; | 	char command[1024]; | ||||||
| 	const char *host, *path; | 	char *host, *path; | ||||||
| 	char *colon; | 	char *colon; | ||||||
| 	int pipefd[2][2]; | 	int pipefd[2][2]; | ||||||
| 	pid_t pid; | 	pid_t pid; | ||||||
|  | 	enum protocol protocol; | ||||||
|  |  | ||||||
| 	host = NULL; | 	host = NULL; | ||||||
| 	path = url; | 	path = url; | ||||||
| 	colon = strchr(url, ':'); | 	colon = strchr(url, ':'); | ||||||
|  | 	protocol = PROTO_LOCAL; | ||||||
| 	if (colon) { | 	if (colon) { | ||||||
| 		*colon = 0; | 		*colon = 0; | ||||||
| 		host = url; | 		host = url; | ||||||
| 		path = colon+1; | 		path = colon+1; | ||||||
|  | 		protocol = PROTO_SSH; | ||||||
|  | 		if (!memcmp(path, "//", 2)) { | ||||||
|  | 			char *slash = strchr(path + 2, '/'); | ||||||
|  | 			if (slash) { | ||||||
|  | 				int nr = slash - path - 2; | ||||||
|  | 				memmove(path, path+2, nr); | ||||||
|  | 				path[nr] = 0; | ||||||
|  | 				protocol = get_protocol(url); | ||||||
|  | 				host = path; | ||||||
|  | 				path = slash; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if (protocol == PROTO_GIT) | ||||||
|  | 		return git_tcp_connect(fd, prog, host, path); | ||||||
|  |  | ||||||
| 	if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0) | 	if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0) | ||||||
| 		die("unable to create pipe pair for communication"); | 		die("unable to create pipe pair for communication"); | ||||||
| 	pid = fork(); | 	pid = fork(); | ||||||
|  | @ -73,7 +152,7 @@ int git_connect(int fd[2], char *url, const char *prog) | ||||||
| 		close(pipefd[0][1]); | 		close(pipefd[0][1]); | ||||||
| 		close(pipefd[1][0]); | 		close(pipefd[1][0]); | ||||||
| 		close(pipefd[1][1]); | 		close(pipefd[1][1]); | ||||||
| 		if (host) | 		if (protocol == PROTO_SSH) | ||||||
| 			execlp("ssh", "ssh", host, command, NULL); | 			execlp("ssh", "ssh", host, command, NULL); | ||||||
| 		else | 		else | ||||||
| 			execlp("sh", "sh", "-c", command, NULL); | 			execlp("sh", "sh", "-c", command, NULL); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Linus Torvalds
						Linus Torvalds