connect.con commit Factor out the ssh connection stuff from send-pack.c (f719259)
   1#include "cache.h"
   2#include <sys/wait.h>
   3
   4/*
   5 * First, make it shell-safe.  We do this by just disallowing any
   6 * special characters. Somebody who cares can do escaping and let
   7 * through the rest. But since we're doing to feed this to ssh as
   8 * a command line, we're going to be pretty damn anal for now.
   9 */
  10static char *shell_safe(char *url)
  11{
  12        char *n = url;
  13        unsigned char c;
  14        static const char flags[256] = {
  15                ['0'...'9'] = 1,
  16                ['a'...'z'] = 1,
  17                ['A'...'Z'] = 1,
  18                ['.'] = 1, ['/'] = 1,
  19                ['-'] = 1, ['+'] = 1,
  20                [':'] = 1
  21        };
  22
  23        while ((c = *n++) != 0) {
  24                if (flags[c] != 1)
  25                        die("I don't like '%c'. Sue me.", c);
  26        }
  27        return url;
  28}
  29
  30/*
  31 * Yeah, yeah, fixme. Need to pass in the heads etc.
  32 */
  33int git_connect(int fd[2], char *url, const char *prog)
  34{
  35        char command[1024];
  36        const char *host, *path;
  37        char *colon;
  38        int pipefd[2][2];
  39        pid_t pid;
  40
  41        url = shell_safe(url);
  42        host = NULL;
  43        path = url;
  44        colon = strchr(url, ':');
  45        if (colon) {
  46                *colon = 0;
  47                host = url;
  48                path = colon+1;
  49        }
  50        snprintf(command, sizeof(command), "%s %s", prog, path);
  51        if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0)
  52                die("unable to create pipe pair for communication");
  53        pid = fork();
  54        if (!pid) {
  55                dup2(pipefd[1][0], 0);
  56                dup2(pipefd[0][1], 1);
  57                close(pipefd[0][0]);
  58                close(pipefd[0][1]);
  59                close(pipefd[1][0]);
  60                close(pipefd[1][1]);
  61                if (host)
  62                        execlp("ssh", "ssh", host, command, NULL);
  63                else
  64                        execlp("sh", "sh", "-c", command, NULL);
  65                die("exec failed");
  66        }               
  67        fd[0] = pipefd[0][0];
  68        fd[1] = pipefd[1][1];
  69        close(pipefd[0][1]);
  70        close(pipefd[1][0]);
  71        return pid;
  72}
  73
  74int finish_connect(pid_t pid)
  75{
  76        int ret;
  77
  78        for (;;) {
  79                ret = waitpid(pid, NULL, 0);
  80                if (!ret)
  81                        break;
  82                if (errno != EINTR)
  83                        break;
  84        }
  85        return ret;
  86}