3cf97d4f5dd9e8f7f7c673b17707b8473c4b6536
   1#include "cache.h"
   2#include "quote.h"
   3#include "exec_cmd.h"
   4#include "strbuf.h"
   5#include "builtin.h"
   6
   7static int do_generic_cmd(const char *me, char *arg)
   8{
   9        const char *my_argv[4];
  10
  11        setup_path();
  12        if (!arg || !(arg = sq_dequote(arg)))
  13                die("bad argument");
  14        if (prefixcmp(me, "git-"))
  15                die("bad command");
  16
  17        my_argv[0] = me + 4;
  18        my_argv[1] = arg;
  19        my_argv[2] = NULL;
  20
  21        return execv_git_cmd(my_argv);
  22}
  23
  24static int do_cvs_cmd(const char *me, char *arg)
  25{
  26        const char *cvsserver_argv[3] = {
  27                "cvsserver", "server", NULL
  28        };
  29
  30        if (!arg || strcmp(arg, "server"))
  31                die("git-cvsserver only handles server: %s", arg);
  32
  33        setup_path();
  34        return execv_git_cmd(cvsserver_argv);
  35}
  36
  37
  38static struct commands {
  39        const char *name;
  40        int (*exec)(const char *me, char *arg);
  41} cmd_list[] = {
  42        { "git-receive-pack", do_generic_cmd },
  43        { "git-upload-pack", do_generic_cmd },
  44        { "cvs", do_cvs_cmd },
  45        { NULL },
  46};
  47
  48int cmd_shell(int argc, const char **argv, const char *prefix)
  49{
  50        char *prog;
  51        struct commands *cmd;
  52
  53        /*
  54         * Special hack to pretend to be a CVS server
  55         */
  56        if (argc == 2 && !strcmp(argv[1], "cvs server"))
  57                argv--;
  58
  59        /*
  60         * We do not accept anything but "-c" followed by "cmd arg",
  61         * where "cmd" is a very limited subset of git commands.
  62         */
  63        else if (argc != 3 || strcmp(argv[1], "-c"))
  64                die("What do you think I am? A shell?");
  65
  66        prog = xstrdup(argv[2]);
  67        if (!strncmp(prog, "git", 3) && isspace(prog[3]))
  68                /* Accept "git foo" as if the caller said "git-foo". */
  69                prog[3] = '-';
  70
  71        for (cmd = cmd_list ; cmd->name ; cmd++) {
  72                int len = strlen(cmd->name);
  73                char *arg;
  74                if (strncmp(cmd->name, prog, len))
  75                        continue;
  76                arg = NULL;
  77                switch (prog[len]) {
  78                case '\0':
  79                        arg = NULL;
  80                        break;
  81                case ' ':
  82                        arg = prog + len + 1;
  83                        break;
  84                default:
  85                        continue;
  86                }
  87                exit(cmd->exec(cmd->name, arg));
  88        }
  89        die("unrecognized command '%s'", prog);
  90}