|
2 | 2 | #include "quote.h"
|
3 | 3 | #include "exec_cmd.h"
|
4 | 4 | #include "strbuf.h"
|
| 5 | +#include "run-command.h" |
5 | 6 |
|
6 | 7 | #define COMMAND_DIR "git-shell-commands"
|
| 8 | +#define HELP_COMMAND COMMAND_DIR "/help" |
7 | 9 |
|
8 | 10 | static int do_generic_cmd(const char *me, char *arg)
|
9 | 11 | {
|
@@ -59,6 +61,56 @@ static void cd_to_homedir(void)
|
59 | 61 | die("could not chdir to user's home directory");
|
60 | 62 | }
|
61 | 63 |
|
| 64 | +static void run_shell(void) |
| 65 | +{ |
| 66 | + int done = 0; |
| 67 | + static const char *help_argv[] = { HELP_COMMAND, NULL }; |
| 68 | + /* Print help if enabled */ |
| 69 | + run_command_v_opt(help_argv, RUN_SILENT_EXEC_FAILURE); |
| 70 | + |
| 71 | + do { |
| 72 | + struct strbuf line = STRBUF_INIT; |
| 73 | + const char *prog; |
| 74 | + char *full_cmd; |
| 75 | + char *rawargs; |
| 76 | + const char **argv; |
| 77 | + int code; |
| 78 | + |
| 79 | + fprintf(stderr, "git> "); |
| 80 | + if (strbuf_getline(&line, stdin, '\n') == EOF) { |
| 81 | + fprintf(stderr, "\n"); |
| 82 | + strbuf_release(&line); |
| 83 | + break; |
| 84 | + } |
| 85 | + strbuf_trim(&line); |
| 86 | + rawargs = strbuf_detach(&line, NULL); |
| 87 | + if (split_cmdline(rawargs, &argv) == -1) { |
| 88 | + free(rawargs); |
| 89 | + continue; |
| 90 | + } |
| 91 | + |
| 92 | + prog = argv[0]; |
| 93 | + if (!strcmp(prog, "")) { |
| 94 | + } else if (!strcmp(prog, "quit") || !strcmp(prog, "logout") || |
| 95 | + !strcmp(prog, "exit") || !strcmp(prog, "bye")) { |
| 96 | + done = 1; |
| 97 | + } else if (is_valid_cmd_name(prog)) { |
| 98 | + full_cmd = make_cmd(prog); |
| 99 | + argv[0] = full_cmd; |
| 100 | + code = run_command_v_opt(argv, RUN_SILENT_EXEC_FAILURE); |
| 101 | + if (code == -1 && errno == ENOENT) { |
| 102 | + fprintf(stderr, "unrecognized command '%s'\n", prog); |
| 103 | + } |
| 104 | + free(full_cmd); |
| 105 | + } else { |
| 106 | + fprintf(stderr, "invalid command format '%s'\n", prog); |
| 107 | + } |
| 108 | + |
| 109 | + free(argv); |
| 110 | + free(rawargs); |
| 111 | + } while (!done); |
| 112 | +} |
| 113 | + |
62 | 114 | static struct commands {
|
63 | 115 | const char *name;
|
64 | 116 | int (*exec)(const char *me, char *arg);
|
@@ -92,15 +144,23 @@ int main(int argc, char **argv)
|
92 | 144 | /*
|
93 | 145 | * Special hack to pretend to be a CVS server
|
94 | 146 | */
|
95 |
| - if (argc == 2 && !strcmp(argv[1], "cvs server")) |
| 147 | + if (argc == 2 && !strcmp(argv[1], "cvs server")) { |
96 | 148 | argv--;
|
97 |
| - |
98 |
| - /* |
99 |
| - * We do not accept anything but "-c" followed by "cmd arg", |
100 |
| - * where "cmd" is a very limited subset of git commands. |
101 |
| - */ |
102 |
| - else if (argc != 3 || strcmp(argv[1], "-c")) |
103 |
| - die("What do you think I am? A shell?"); |
| 149 | + } else if (argc == 1) { |
| 150 | + /* Allow the user to run an interactive shell */ |
| 151 | + cd_to_homedir(); |
| 152 | + if (access(COMMAND_DIR, R_OK | X_OK) == -1) |
| 153 | + die("Sorry, the interactive git-shell is not enabled"); |
| 154 | + run_shell(); |
| 155 | + exit(0); |
| 156 | + } else if (argc != 3 || strcmp(argv[1], "-c")) { |
| 157 | + /* |
| 158 | + * We do not accept any other modes except "-c" followed by |
| 159 | + * "cmd arg", where "cmd" is a very limited subset of git |
| 160 | + * commands or a command in the COMMAND_DIR |
| 161 | + */ |
| 162 | + die("Run with no arguments or with -c cmd"); |
| 163 | + } |
104 | 164 |
|
105 | 165 | prog = xstrdup(argv[2]);
|
106 | 166 | if (!strncmp(prog, "git", 3) && isspace(prog[3]))
|
|
0 commit comments