git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 1/3] Allow creation of arbitrary git-shell commands

From
Greg Brockman <gdb@mit.edu>
Date
Jul 21, 2010, 15:15 UTC
Message-ID
<1279725355-23016-2-git-send-email-gdb@mit.edu>
In-Reply-To
<1279725355-23016-1-git-send-email-gdb@mit.edu>

This provides a mechanism for the server to expose custom functionality to clients. My particular use case is that I would like a way of discovering all repositories available for cloning. A client that clones via

  git clone user@example.com
can invoke a command by
  ssh user@example.com $command
Signed-off-by: Greg Brockman <gdb@mit.edu>
---
 shell.c |   34 ++++++++++++++++++++++++++++++++--
 1 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/shell.c b/shell.c
index e4864e0..34159c4 100644
--- a/shell.c
+++ b/shell.c
@@ -3,6 +3,8 @@
 #include "exec_cmd.h"
 #include "strbuf.h"
 
+#define COMMAND_DIR "git-shell-commands"
+
 static int do_generic_cmd(const char *me, char *arg)
 {
 	const char *my_argv[4];
@@ -33,6 +35,20 @@ static int do_cvs_cmd(const char *me, char *arg)
 	return execv_git_cmd(cvsserver_argv);
 }
 
+static int is_valid_cmd_name(const char *cmd)
+{
+	/* Test command contains no . or / characters */
+	return cmd[strcspn(cmd, "./")] == '\0';
+}
+
+static char *make_cmd(const char *prog)
+{
+	char *prefix = xmalloc((strlen(prog) + strlen(COMMAND_DIR) + 2));
+	strcpy(prefix, COMMAND_DIR);
+	strcat(prefix, "/");
+	strcat(prefix, prog);
+	return prefix;
+}
 
 static struct commands {
 	const char *name;
@@ -48,6 +64,7 @@ static struct commands {
 int main(int argc, char **argv)
 {
 	char *prog;
+	const char **user_argv;
 	struct commands *cmd;
 	int devnull_fd;
 
@@ -76,7 +93,7 @@ int main(int argc, char **argv)
 	else if (argc != 3 || strcmp(argv[1], "-c"))
 		die("What do you think I am? A shell?");
 
-	prog = argv[2];
+	prog = xstrdup(argv[2]);
 	if (!strncmp(prog, "git", 3) && isspace(prog[3]))
 		/* Accept "git foo" as if the caller said "git-foo". */
 		prog[3] = '-';
@@ -99,5 +116,18 @@ int main(int argc, char **argv)
 		}
 		exit(cmd->exec(cmd->name, arg));
 	}
-	die("unrecognized command '%s'", prog);
+
+	if (split_cmdline(prog, &user_argv) != -1) {
+		if (is_valid_cmd_name(user_argv[0])) {
+			prog = make_cmd(user_argv[0]);
+			user_argv[0] = prog;
+			execv(user_argv[0], (char *const *) user_argv);
+		}
+		free(prog);
+		free(user_argv);
+		die("unrecognized command '%s'", argv[2]);
+	} else {
+		free(prog);
+		die("invalid command format '%s'", argv[2]);
+	}
 }
-- 
1.7.0.4
Previous: Greg BrockmanNext: Greg Brockman
Message 2 of 23 in “[PATCHv3] Updated patch series for providing mechanism to list available repositories”
  1. Greg BrockmanJul 21, 2010
  2. 1/3 Allow creation of arbitrary git-shell commandsGreg Brockman, Jul 21, 2010
  3. 2/3 Add interactive mode to git-shell for user-friendlinessGreg Brockman, Jul 21, 2010
  4. 3/3 Add sample commands for git-shellGreg Brockman, Jul 21, 2010
  5. Greg BrockmanJul 26, 2010
  6. Ævar Arnfjörð BjarmasonJul 26, 2010
  7. Greg BrockmanJul 26, 2010
  8. Jakub NarebskiJul 27, 2010
  9. Jonathan NiederJul 26, 2010
  10. Greg BrockmanJul 27, 2010
  11. Jonathan NiederJul 27, 2010
  12. Johannes SixtJul 27, 2010
  13. Jonathan NiederJul 27, 2010
  14. Greg BrockmanJul 27, 2010
  15. Jonathan NiederJul 28, 2010
  16. Greg BrockmanJul 28, 2010
  17. Jonathan NiederJul 28, 2010
  18. Greg BrockmanJul 28, 2010
  19. Anders KaseorgJul 28, 2010
  20. Jonathan NiederJul 28, 2010
  21. Greg BrockmanJul 29, 2010
  22. Jonathan NiederJul 29, 2010
  23. Jonathan NiederJul 28, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.