rsh.con commit git-svnimport: support for partial imports (ec1e468)
   1#include <string.h>
   2#include <sys/types.h>
   3#include <sys/socket.h>
   4
   5#include "rsh.h"
   6#include "quote.h"
   7#include "cache.h"
   8
   9#define COMMAND_SIZE 4096
  10
  11int setup_connection(int *fd_in, int *fd_out, const char *remote_prog,
  12                     char *url, int rmt_argc, char **rmt_argv)
  13{
  14        char *host;
  15        char *path;
  16        int sv[2];
  17        char command[COMMAND_SIZE];
  18        char *posn;
  19        int sizen;
  20        int of;
  21        int i;
  22        pid_t pid;
  23
  24        if (!strcmp(url, "-")) {
  25                *fd_in = 0;
  26                *fd_out = 1;
  27                return 0;
  28        }
  29
  30        host = strstr(url, "//");
  31        if (host) {
  32                host += 2;
  33                path = strchr(host, '/');
  34        } else {
  35                host = url;
  36                path = strchr(host, ':');
  37                if (path)
  38                        *(path++) = '\0';
  39        }
  40        if (!path) {
  41                return error("Bad URL: %s", url);
  42        }
  43        /* $GIT_RSH <host> "env GIT_DIR=<path> <remote_prog> <args...>" */
  44        sizen = COMMAND_SIZE;
  45        posn = command;
  46        of = 0;
  47        of |= add_to_string(&posn, &sizen, "env ", 0);
  48        of |= add_to_string(&posn, &sizen, GIT_DIR_ENVIRONMENT "=", 0);
  49        of |= add_to_string(&posn, &sizen, path, 1);
  50        of |= add_to_string(&posn, &sizen, " ", 0);
  51        of |= add_to_string(&posn, &sizen, remote_prog, 1);
  52
  53        for ( i = 0 ; i < rmt_argc ; i++ ) {
  54                of |= add_to_string(&posn, &sizen, " ", 0);
  55                of |= add_to_string(&posn, &sizen, rmt_argv[i], 1);
  56        }
  57
  58        of |= add_to_string(&posn, &sizen, " -", 0);
  59
  60        if ( of )
  61                return error("Command line too long");
  62
  63        if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv))
  64                return error("Couldn't create socket");
  65
  66        pid = fork();
  67        if (pid < 0)
  68                return error("Couldn't fork");
  69        if (!pid) {
  70                const char *ssh, *ssh_basename;
  71                ssh = getenv("GIT_SSH");
  72                if (!ssh) ssh = "ssh";
  73                ssh_basename = strrchr(ssh, '/');
  74                if (!ssh_basename)
  75                        ssh_basename = ssh;
  76                else
  77                        ssh_basename++;
  78                close(sv[1]);
  79                dup2(sv[0], 0);
  80                dup2(sv[0], 1);
  81                execlp(ssh, ssh_basename, host, command, NULL);
  82        }
  83        close(sv[0]);
  84        *fd_in = sv[1];
  85        *fd_out = sv[1];
  86        return 0;
  87}