rsh.con commit git-cvsserver: fix disabling service via per-method config (523d12e)
   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        char command[COMMAND_SIZE];
  14        char *posn;
  15        int sizen;
  16        int of;
  17        int i;
  18        pid_t pid;
  19
  20        if (!strcmp(url, "-")) {
  21                *fd_in = 0;
  22                *fd_out = 1;
  23                return 0;
  24        }
  25
  26        host = strstr(url, "//");
  27        if (host) {
  28                host += 2;
  29                path = strchr(host, '/');
  30        } else {
  31                host = url;
  32                path = strchr(host, ':');
  33                if (path)
  34                        *(path++) = '\0';
  35        }
  36        if (!path) {
  37                return error("Bad URL: %s", url);
  38        }
  39        /* $GIT_RSH <host> "env GIT_DIR=<path> <remote_prog> <args...>" */
  40        sizen = COMMAND_SIZE;
  41        posn = command;
  42        of = 0;
  43        of |= add_to_string(&posn, &sizen, "env ", 0);
  44        of |= add_to_string(&posn, &sizen, GIT_DIR_ENVIRONMENT "=", 0);
  45        of |= add_to_string(&posn, &sizen, path, 1);
  46        of |= add_to_string(&posn, &sizen, " ", 0);
  47        of |= add_to_string(&posn, &sizen, remote_prog, 1);
  48
  49        for ( i = 0 ; i < rmt_argc ; i++ ) {
  50                of |= add_to_string(&posn, &sizen, " ", 0);
  51                of |= add_to_string(&posn, &sizen, rmt_argv[i], 1);
  52        }
  53
  54        of |= add_to_string(&posn, &sizen, " -", 0);
  55
  56        if ( of )
  57                return error("Command line too long");
  58
  59        if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv))
  60                return error("Couldn't create socket");
  61
  62        pid = fork();
  63        if (pid < 0)
  64                return error("Couldn't fork");
  65        if (!pid) {
  66                const char *ssh, *ssh_basename;
  67                ssh = getenv("GIT_SSH");
  68                if (!ssh) ssh = "ssh";
  69                ssh_basename = strrchr(ssh, '/');
  70                if (!ssh_basename)
  71                        ssh_basename = ssh;
  72                else
  73                        ssh_basename++;
  74                close(sv[1]);
  75                dup2(sv[0], 0);
  76                dup2(sv[0], 1);
  77                execlp(ssh, ssh_basename, host, command, NULL);
  78        }
  79        close(sv[0]);
  80        *fd_in = sv[1];
  81        *fd_out = sv[1];
  82        return 0;
  83}