[PATCH/RFC 4/4] Add interactive mode to git-shell for user-friendliness
From: Greg Brockman <hidden>
Date: 2016-06-15 22:49:07
Subsystem:
the rest · Maintainer:
Linus Torvalds
Signed-off-by: Greg Brockman <redacted> --- shell.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 48 insertions(+), 2 deletions(-)
diff --git a/shell.c b/shell.c
index 3fee0ed..9f80226 100644
--- a/shell.c
+++ b/shell.c@@ -1,8 +1,11 @@ +#include <stdio.h> + #include "cache.h" #include "quote.h" #include "exec_cmd.h" #include "strbuf.h" +#define MAX_LINE_LEN 128 #define COMMAND_DIR "git-shell-commands" static int do_generic_cmd(const char *me, char *arg)
@@ -41,6 +44,26 @@ static int is_valid_cmd_name(const char *cmd) return cmd[strcspn(cmd, "./")] == '\0'; } +static int run(const char *prog) +{ + pid_t pid, res; + int w; + pid = fork(); + if (pid == -1) { + perror("fork"); + exit(-1); + } else if ( pid == 0 ) { + execl(prog, prog, (char *) NULL); + if (prog[0] != '\0') + fprintf(stderr, "unrecognized command '%s'\n", prog); + exit(127); + } else { + do { + res = waitpid (pid, &w, 0); + } while (res == -1 && errno == EINTR); + } +} + static struct commands { const char *name;
@@ -56,6 +79,7 @@ static struct commands { int main(int argc, char **argv) { char *prog; + char line[MAX_LINE_LEN]; struct commands *cmd; int devnull_fd;
@@ -81,8 +105,30 @@ int main(int argc, char **argv) * We do not accept anything but "-c" followed by "cmd arg", * where "cmd" is a very limited subset of git commands. */ - else if (argc != 3 || strcmp(argv[1], "-c")) - die("What do you think I am? A shell?"); + else if (argc != 3 || strcmp(argv[1], "-c")) { + if (chdir(COMMAND_DIR)) + die("Sorry, the interactive git-shell is not enabled"); + for (;;) { + printf("git> "); + if (fgets(line, MAX_LINE_LEN, stdin) == NULL) { + printf("\n"); + exit(0); + } + + if (line[strlen(line) - 1] == '\n') + line[strlen(line) - 1] = '\0'; + + if (!strcmp(line, "quit") || !strcmp(line, "logout") || + !strcmp(line, "exit")) { + exit(0); + } else if (!strcmp(line, "")) { + } else if (is_valid_cmd_name(line)) { + run(line); + } else { + fprintf(stderr, "invalid command format '%s'\n", line); + } + }; + } prog = argv[2]; if (!strncmp(prog, "git", 3) && isspace(prog[3]))
--
1.7.0.4