Skip to content

Commit e69164d

Browse files
Greg Brockmangitster
Greg Brockman
authored andcommitted
Add interactive mode to git-shell for user-friendliness
Signed-off-by: Greg Brockman <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2dbc887 commit e69164d

File tree

1 file changed

+68
-8
lines changed

1 file changed

+68
-8
lines changed

shell.c

+68-8
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
#include "quote.h"
33
#include "exec_cmd.h"
44
#include "strbuf.h"
5+
#include "run-command.h"
56

67
#define COMMAND_DIR "git-shell-commands"
8+
#define HELP_COMMAND COMMAND_DIR "/help"
79

810
static int do_generic_cmd(const char *me, char *arg)
911
{
@@ -59,6 +61,56 @@ static void cd_to_homedir(void)
5961
die("could not chdir to user's home directory");
6062
}
6163

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+
62114
static struct commands {
63115
const char *name;
64116
int (*exec)(const char *me, char *arg);
@@ -92,15 +144,23 @@ int main(int argc, char **argv)
92144
/*
93145
* Special hack to pretend to be a CVS server
94146
*/
95-
if (argc == 2 && !strcmp(argv[1], "cvs server"))
147+
if (argc == 2 && !strcmp(argv[1], "cvs server")) {
96148
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+
}
104164

105165
prog = xstrdup(argv[2]);
106166
if (!strncmp(prog, "git", 3) && isspace(prog[3]))

0 commit comments

Comments
 (0)