git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "H. Peter Anvin" <hpa@zytor.com>
To: Git Mailing List <git@vger.kernel.org>
Subject: [PATCH] rsh.c env and quoting cleanup, take 2
Date: Thu, 15 Sep 2005 12:33:14 -0700	[thread overview]
Message-ID: <4329CC7A.8010203@zytor.com> (raw)
In-Reply-To: <4329C11A.1040302@zytor.com>

[-- Attachment #1: Type: text/plain, Size: 188 bytes --]

This patch does proper quoting, and uses "env" to be compatible with 
tcsh.  As a side benefit, I believe the code is a lot cleaner to read.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>

[-- Attachment #2: rsh-quoting-fix.patch --]
[-- Type: text/x-patch, Size: 3533 bytes --]

Use env and proper quoting for all command arguments.

---
commit 11a45ccbd6daee37193934a5863ed29a0fe91ec3
tree 23cd21abe0209ced9cd6f1f5c501546e662bc941
parent 19397b4521bcc27eb224413fb71519223b94290f
author Peter Anvin <hpa@tazenda.sc.orionmulti.com> Thu, 15 Sep 2005 12:30:36 -0700
committer Peter Anvin <hpa@tazenda.sc.orionmulti.com> Thu, 15 Sep 2005 12:30:36 -0700

 rsh.c |  105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 89 insertions(+), 16 deletions(-)

diff --git a/rsh.c b/rsh.c
--- a/rsh.c
+++ b/rsh.c
@@ -8,6 +8,71 @@
 
 #define COMMAND_SIZE 4096
 
+/*
+ * Write a shell-quoted version of a string into a buffer, and
+ * return bytes that ought to be output excluding final null.
+ */
+static int shell_quote(char *buf, int nmax, const char *str)
+{
+	char ch;
+	int nq;
+	int oc = 0;
+
+	while ( (ch = *str++) ) {
+		nq = 0;
+		if ( strchr(" !\"#$%&\'()*;<=>?[\\]^`{|}", ch) )
+			nq = 1;
+
+		if ( nq ) {
+			if ( nmax > 1 ) {
+				*buf++ = '\\';
+				nmax--;
+			}
+			oc++;
+		}
+
+		if ( nmax > 1 ) {
+			*buf++ = ch;
+			nmax--;
+		}
+		oc++;
+	}
+
+	if ( nmax )
+		*buf = '\0';
+
+	return oc;
+}
+			
+/*
+ * Append a string to a string buffer, with or without quoting.  Return true
+ * if the buffer overflowed.
+ */
+static int add_to_string(char **ptrp, int *sizep, const char *str, int quote)
+{
+	char *p = *ptrp;
+	int size = *sizep;
+	int oc;
+
+	if ( quote ) {
+		oc = shell_quote(p, size, str);
+	} else {
+		oc = strlen(str);
+		memcpy(p, str, (oc >= size) ? size-1 : oc);
+	}
+
+	if ( oc >= size ) {
+		p[size-1] = '\0';
+		*ptrp += size-1;
+		*sizep = 1;
+		return 1;	/* Overflow, string unusable */
+	}
+
+	*ptrp  += oc;
+	*sizep -= oc;
+	return 0;
+}
+
 int setup_connection(int *fd_in, int *fd_out, const char *remote_prog, 
 		     char *url, int rmt_argc, char **rmt_argv)
 {
@@ -16,6 +81,8 @@ int setup_connection(int *fd_in, int *fd
 	int sv[2];
 	char command[COMMAND_SIZE];
 	char *posn;
+	int sizen;
+	int of;
 	int i;
 
 	if (!strcmp(url, "-")) {
@@ -37,24 +104,30 @@ int setup_connection(int *fd_in, int *fd
 	if (!path) {
 		return error("Bad URL: %s", url);
 	}
-	/* ssh <host> 'cd <path>; stdio-pull <arg...> <commit-id>' */
-	snprintf(command, COMMAND_SIZE, 
-		 "%s='%s' %s",
-		 GIT_DIR_ENVIRONMENT, path, remote_prog);
-	*path = '\0';
-	posn = command + strlen(command);
-	for (i = 0; i < rmt_argc; i++) {
-		*(posn++) = ' ';
-		strncpy(posn, rmt_argv[i], COMMAND_SIZE - (posn - command));
-		posn += strlen(rmt_argv[i]);
-		if (posn - command + 4 >= COMMAND_SIZE) {
-			return error("Command line too long");
-		}
+	/* $GIT_RSH <host> "env GIR_DIR=<path> <remote_prog> <args...>" */
+	sizen = COMMAND_SIZE;
+	posn = command;
+	of = 0;
+	of |= add_to_string(&posn, &sizen, "env ", 0);
+	of |= add_to_string(&posn, &sizen, GIT_DIR_ENVIRONMENT, 0);
+	of |= add_to_string(&posn, &sizen, "=", 0);
+	of |= add_to_string(&posn, &sizen, path, 1);
+	of |= add_to_string(&posn, &sizen, " ", 0);
+	of |= add_to_string(&posn, &sizen, remote_prog, 1);
+
+	for ( i = 0 ; i < rmt_argc ; i++ ) {
+		of |= add_to_string(&posn, &sizen, " ", 0);
+		of |= add_to_string(&posn, &sizen, rmt_argv[i], 1);
 	}
-	strcpy(posn, " -");
-	if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv)) {
+
+	of |= add_to_string(&posn, &sizen, " -", 0);
+
+	if ( of )
+		return error("Command line too long");
+
+	if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv))
 		return error("Couldn't create socket");
-	}
+
 	if (!fork()) {
 		const char *ssh, *ssh_basename;
 		ssh = getenv("GIT_SSH");

      parent reply	other threads:[~2005-09-15 19:33 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-09-15  5:50 [PATCH] Remove shell dependency in env.c H. Peter Anvin
2005-09-15  7:58 ` Junio C Hamano
2005-09-15 16:30   ` H. Peter Anvin
2005-09-15 18:44   ` Shell quoting H. Peter Anvin
2005-09-15 19:01     ` Linus Torvalds
2005-09-15 19:31       ` H. Peter Anvin
2005-09-15 19:50         ` Junio C Hamano
2005-09-15 20:18           ` H. Peter Anvin
2005-09-15 19:35       ` Junio C Hamano
2005-09-15 20:02         ` Linus Torvalds
2005-09-16 19:20       ` Junio C Hamano
2005-09-15 19:33     ` H. Peter Anvin [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4329CC7A.8010203@zytor.com \
    --to=hpa@zytor.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).