3d4b31d3405a4bb61f81a03fc1103ba2bea68411
   1#include "cache.h"
   2#include "pkt-line.h"
   3#include <sys/wait.h>
   4
   5int get_ack(int fd, unsigned char *result_sha1)
   6{
   7        static char line[1000];
   8        int len = packet_read_line(fd, line, sizeof(line));
   9
  10        if (!len)
  11                die("git-fetch-pack: expected ACK/NAK, got EOF");
  12        if (line[len-1] == '\n')
  13                line[--len] = 0;
  14        if (!strcmp(line, "NAK"))
  15                return 0;
  16        if (!strncmp(line, "ACK ", 3)) {
  17                if (!get_sha1_hex(line+4, result_sha1))
  18                        return 1;
  19        }
  20        die("git-fetch_pack: expected ACK/NAK, got '%s'", line);
  21}
  22
  23int path_match(const char *path, int nr, char **match)
  24{
  25        int i;
  26        int pathlen = strlen(path);
  27
  28        for (i = 0; i < nr; i++) {
  29                char *s = match[i];
  30                int len = strlen(s);
  31
  32                if (!len || len > pathlen)
  33                        continue;
  34                if (memcmp(path + pathlen - len, s, len))
  35                        continue;
  36                if (pathlen > len && path[pathlen - len - 1] != '/')
  37                        continue;
  38                *s = 0;
  39                return 1;
  40        }
  41        return 0;
  42}
  43
  44/*
  45 * First, make it shell-safe.  We do this by just disallowing any
  46 * special characters. Somebody who cares can do escaping and let
  47 * through the rest. But since we're doing to feed this to ssh as
  48 * a command line, we're going to be pretty damn anal for now.
  49 */
  50static char *shell_safe(char *url)
  51{
  52        char *n = url;
  53        unsigned char c;
  54        static const char flags[256] = {
  55                ['0'...'9'] = 1,
  56                ['a'...'z'] = 1,
  57                ['A'...'Z'] = 1,
  58                ['.'] = 1, ['/'] = 1,
  59                ['-'] = 1, ['+'] = 1,
  60                [':'] = 1, ['_'] = 1,
  61                ['@'] = 1, [','] = 1,
  62                ['~'] = 1, ['^'] = 1,
  63        };
  64
  65        while ((c = *n++) != 0) {
  66                if (flags[c] != 1)
  67                        die("I don't like '%c'. Sue me.", c);
  68        }
  69        return url;
  70}
  71
  72/*
  73 * Yeah, yeah, fixme. Need to pass in the heads etc.
  74 */
  75int git_connect(int fd[2], char *url, const char *prog)
  76{
  77        char command[1024];
  78        const char *host, *path;
  79        char *colon;
  80        int pipefd[2][2];
  81        pid_t pid;
  82
  83        url = shell_safe(url);
  84        host = NULL;
  85        path = url;
  86        colon = strchr(url, ':');
  87        if (colon) {
  88                *colon = 0;
  89                host = url;
  90                path = colon+1;
  91        }
  92        snprintf(command, sizeof(command), "%s %s", prog, path);
  93        if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0)
  94                die("unable to create pipe pair for communication");
  95        pid = fork();
  96        if (!pid) {
  97                dup2(pipefd[1][0], 0);
  98                dup2(pipefd[0][1], 1);
  99                close(pipefd[0][0]);
 100                close(pipefd[0][1]);
 101                close(pipefd[1][0]);
 102                close(pipefd[1][1]);
 103                if (host)
 104                        execlp("ssh", "ssh", host, command, NULL);
 105                else
 106                        execlp("sh", "sh", "-c", command, NULL);
 107                die("exec failed");
 108        }               
 109        fd[0] = pipefd[0][0];
 110        fd[1] = pipefd[1][1];
 111        close(pipefd[0][1]);
 112        close(pipefd[1][0]);
 113        return pid;
 114}
 115
 116int finish_connect(pid_t pid)
 117{
 118        int ret;
 119
 120        for (;;) {
 121                ret = waitpid(pid, NULL, 0);
 122                if (!ret)
 123                        break;
 124                if (errno != EINTR)
 125                        break;
 126        }
 127        return ret;
 128}