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