113 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			113 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
#include <string.h>
 | 
						|
#include <sys/types.h>
 | 
						|
#include <sys/socket.h>
 | 
						|
 | 
						|
#include "rsh.h"
 | 
						|
#include "quote.h"
 | 
						|
#include "cache.h"
 | 
						|
 | 
						|
#define COMMAND_SIZE 4096
 | 
						|
 | 
						|
/*
 | 
						|
 * Append a string to a string buffer, with or without shell quoting.
 | 
						|
 * Return true if the buffer overflowed.
 | 
						|
 */
 | 
						|
static int add_to_string(char **ptrp, int *sizep, const char *str, int quote)
 | 
						|
{
 | 
						|
	char *p = *ptrp;
 | 
						|
	int size = *sizep;
 | 
						|
	int oc;
 | 
						|
	int err = 0;
 | 
						|
 | 
						|
	if ( quote ) {
 | 
						|
		oc = sq_quote_buf(p, size, str);
 | 
						|
	} else {
 | 
						|
		oc = strlen(str);
 | 
						|
		memcpy(p, str, (oc >= size) ? size-1 : oc);
 | 
						|
	}
 | 
						|
 | 
						|
	if ( oc >= size ) {
 | 
						|
		err = 1;
 | 
						|
		oc = size-1;
 | 
						|
	}
 | 
						|
 | 
						|
	*ptrp  += oc;
 | 
						|
	**ptrp  = '\0';
 | 
						|
	*sizep -= oc;
 | 
						|
	return err;
 | 
						|
}
 | 
						|
 | 
						|
int setup_connection(int *fd_in, int *fd_out, const char *remote_prog, 
 | 
						|
		     char *url, int rmt_argc, char **rmt_argv)
 | 
						|
{
 | 
						|
	char *host;
 | 
						|
	char *path;
 | 
						|
	int sv[2];
 | 
						|
	char command[COMMAND_SIZE];
 | 
						|
	char *posn;
 | 
						|
	int sizen;
 | 
						|
	int of;
 | 
						|
	int i;
 | 
						|
 | 
						|
	if (!strcmp(url, "-")) {
 | 
						|
		*fd_in = 0;
 | 
						|
		*fd_out = 1;
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	host = strstr(url, "//");
 | 
						|
	if (host) {
 | 
						|
		host += 2;
 | 
						|
		path = strchr(host, '/');
 | 
						|
	} else {
 | 
						|
		host = url;
 | 
						|
		path = strchr(host, ':');
 | 
						|
		if (path)
 | 
						|
			*(path++) = '\0';
 | 
						|
	}
 | 
						|
	if (!path) {
 | 
						|
		return error("Bad URL: %s", url);
 | 
						|
	}
 | 
						|
	/* $GIT_RSH <host> "env GIT_DIR=<path> <remote_prog> <args...>" */
 | 
						|
	sizen = COMMAND_SIZE;
 | 
						|
	posn = command;
 | 
						|
	of = 0;
 | 
						|
	of |= add_to_string(&posn, &sizen, "env ", 0);
 | 
						|
	of |= add_to_string(&posn, &sizen, GIT_DIR_ENVIRONMENT "=", 0);
 | 
						|
	of |= add_to_string(&posn, &sizen, path, 1);
 | 
						|
	of |= add_to_string(&posn, &sizen, " ", 0);
 | 
						|
	of |= add_to_string(&posn, &sizen, remote_prog, 1);
 | 
						|
 | 
						|
	for ( i = 0 ; i < rmt_argc ; i++ ) {
 | 
						|
		of |= add_to_string(&posn, &sizen, " ", 0);
 | 
						|
		of |= add_to_string(&posn, &sizen, rmt_argv[i], 1);
 | 
						|
	}
 | 
						|
 | 
						|
	of |= add_to_string(&posn, &sizen, " -", 0);
 | 
						|
 | 
						|
	if ( of )
 | 
						|
		return error("Command line too long");
 | 
						|
 | 
						|
	if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv))
 | 
						|
		return error("Couldn't create socket");
 | 
						|
 | 
						|
	if (!fork()) {
 | 
						|
		const char *ssh, *ssh_basename;
 | 
						|
		ssh = getenv("GIT_SSH");
 | 
						|
		if (!ssh) ssh = "ssh";
 | 
						|
		ssh_basename = strrchr(ssh, '/');
 | 
						|
		if (!ssh_basename)
 | 
						|
			ssh_basename = ssh;
 | 
						|
		else
 | 
						|
			ssh_basename++;
 | 
						|
		close(sv[1]);
 | 
						|
		dup2(sv[0], 0);
 | 
						|
		dup2(sv[0], 1);
 | 
						|
		execlp(ssh, ssh_basename, host, command, NULL);
 | 
						|
	}
 | 
						|
	close(sv[0]);
 | 
						|
	*fd_in = sv[1];
 | 
						|
	*fd_out = sv[1];
 | 
						|
	return 0;
 | 
						|
}
 |