From: Pierre Habouzit <madcoder@debian.org>
To: Junio C Hamano <gitster@pobox.com>, git@vger.kernel.org
Subject: [SUPERSEDES PATCH 4/7] sq_quote_argv and add_to_string rework with strbuf's.
Date: Thu, 20 Sep 2007 10:44:41 +0200 [thread overview]
Message-ID: <20070920084441.GC2053@artemis.corp> (raw)
In-Reply-To: <20070920082701.GA2053@artemis.corp>
[-- Attachment #1: Type: text/plain, Size: 7902 bytes --]
* sq_quote_buf is made public, and works on a strbuf.
* sq_quote_argv also works on a strbuf.
* make sq_quote_argv take a "maxlen" argument to check the buffer won't grow
too big.
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
---
connect.c | 21 ++++++--------
git.c | 16 +++-------
quote.c | 94 +++++++++++++++---------------------------------------------
quote.h | 9 ++----
trace.c | 25 +++++++---------
5 files changed, 52 insertions(+), 113 deletions(-)
diff --git a/connect.c b/connect.c
index 1653a0e..06d279e 100644
--- a/connect.c
+++ b/connect.c
@@ -577,16 +577,13 @@ pid_t git_connect(int fd[2], char *url, const char *prog, int flags)
if (pid < 0)
die("unable to fork");
if (!pid) {
- char command[MAX_CMD_LEN];
- char *posn = command;
- int size = MAX_CMD_LEN;
- int of = 0;
+ struct strbuf cmd;
- of |= add_to_string(&posn, &size, prog, 0);
- of |= add_to_string(&posn, &size, " ", 0);
- of |= add_to_string(&posn, &size, path, 1);
-
- if (of)
+ strbuf_init(&cmd, MAX_CMD_LEN);
+ strbuf_addstr(&cmd, prog);
+ strbuf_addch(&cmd, ' ');
+ sq_quote_buf(&cmd, path);
+ if (cmd.len >= MAX_CMD_LEN)
die("command line too long");
dup2(pipefd[1][0], 0);
@@ -606,10 +603,10 @@ pid_t git_connect(int fd[2], char *url, const char *prog, int flags)
ssh_basename++;
if (!port)
- execlp(ssh, ssh_basename, host, command, NULL);
+ execlp(ssh, ssh_basename, host, cmd.buf, NULL);
else
execlp(ssh, ssh_basename, "-p", port, host,
- command, NULL);
+ cmd.buf, NULL);
}
else {
unsetenv(ALTERNATE_DB_ENVIRONMENT);
@@ -618,7 +615,7 @@ pid_t git_connect(int fd[2], char *url, const char *prog, int flags)
unsetenv(GIT_WORK_TREE_ENVIRONMENT);
unsetenv(GRAFT_ENVIRONMENT);
unsetenv(INDEX_ENVIRONMENT);
- execlp("sh", "sh", "-c", command, NULL);
+ execlp("sh", "sh", "-c", cmd.buf, NULL);
}
die("exec failed");
}
diff --git a/git.c b/git.c
index 6773c12..d7c6bca 100644
--- a/git.c
+++ b/git.c
@@ -187,19 +187,13 @@ static int handle_alias(int *argcp, const char ***argv)
if (alias_string) {
if (alias_string[0] == '!') {
if (*argcp > 1) {
- int i, sz = PATH_MAX;
- char *s = xmalloc(sz), *new_alias = s;
+ struct strbuf buf;
- add_to_string(&s, &sz, alias_string, 0);
+ strbuf_init(&buf, PATH_MAX);
+ strbuf_addstr(&buf, alias_string);
+ sq_quote_argv(&buf, (*argv) + 1, *argcp - 1, PATH_MAX);
free(alias_string);
- alias_string = new_alias;
- for (i = 1; i < *argcp &&
- !add_to_string(&s, &sz, " ", 0) &&
- !add_to_string(&s, &sz, (*argv)[i], 1)
- ; i++)
- ; /* do nothing */
- if (!sz)
- die("Too many or long arguments");
+ alias_string = buf.buf;
}
trace_printf("trace: alias to shell cmd: %s => %s\n",
alias_command, alias_string + 1);
diff --git a/quote.c b/quote.c
index d88bf75..edd1a09 100644
--- a/quote.c
+++ b/quote.c
@@ -12,37 +12,31 @@
* a'b ==> a'\''b ==> 'a'\''b'
* a!b ==> a'\!'b ==> 'a'\!'b'
*/
-#undef EMIT
-#define EMIT(x) do { if (++len < n) *bp++ = (x); } while(0)
-
static inline int need_bs_quote(char c)
{
return (c == '\'' || c == '!');
}
-static size_t sq_quote_buf(char *dst, size_t n, const char *src)
+void sq_quote_buf(struct strbuf *dst, const char *src)
{
- char c;
- char *bp = dst;
- size_t len = 0;
-
- EMIT('\'');
- while ((c = *src++)) {
- if (need_bs_quote(c)) {
- EMIT('\'');
- EMIT('\\');
- EMIT(c);
- EMIT('\'');
- } else {
- EMIT(c);
+ char *to_free = NULL;
+
+ if (dst->buf == src)
+ to_free = strbuf_detach(dst);
+
+ strbuf_addch(dst, '\'');
+ while (*src) {
+ size_t len = strcspn(src, "'\\");
+ strbuf_add(dst, src, len);
+ src += len;
+ while (need_bs_quote(*src)) {
+ strbuf_addstr(dst, "'\\");
+ strbuf_addch(dst, *src++);
+ strbuf_addch(dst, '\'');
}
}
- EMIT('\'');
-
- if ( n )
- *bp = 0;
-
- return len;
+ strbuf_addch(dst, '\'');
+ free(to_free);
}
void sq_quote_print(FILE *stream, const char *src)
@@ -62,11 +56,10 @@ void sq_quote_print(FILE *stream, const char *src)
fputc('\'', stream);
}
-char *sq_quote_argv(const char** argv, int count)
+void sq_quote_argv(struct strbuf *dst, const char** argv, int count,
+ size_t maxlen)
{
- char *buf, *to;
int i;
- size_t len = 0;
/* Count argv if needed. */
if (count < 0) {
@@ -74,53 +67,14 @@ char *sq_quote_argv(const char** argv, int count)
; /* just counting */
}
- /* Special case: no argv. */
- if (!count)
- return xcalloc(1,1);
-
- /* Get destination buffer length. */
- for (i = 0; i < count; i++)
- len += sq_quote_buf(NULL, 0, argv[i]) + 1;
-
- /* Alloc destination buffer. */
- to = buf = xmalloc(len + 1);
-
/* Copy into destination buffer. */
+ strbuf_grow(dst, 32 * count);
for (i = 0; i < count; ++i) {
- *to++ = ' ';
- to += sq_quote_buf(to, len, argv[i]);
+ strbuf_addch(dst, ' ');
+ sq_quote_buf(dst, argv[i]);
+ if (maxlen && dst->len > maxlen)
+ die("Too many or long arguments");
}
-
- return buf;
-}
-
-/*
- * Append a string to a string buffer, with or without shell quoting.
- * Return true if the buffer overflowed.
- */
-int add_to_string(char **ptrp, int *sizep, const char *str, int quote)
-{
- char *p = *ptrp;
- int size = *sizep;
- int oc;
- int err = 0;
-
- if (quote)
- oc = sq_quote_buf(p, size, str);
- else {
- oc = strlen(str);
- memcpy(p, str, (size <= oc) ? size - 1 : oc);
- }
-
- if (size <= oc) {
- err = 1;
- oc = size - 1;
- }
-
- *ptrp += oc;
- **ptrp = '\0';
- *sizep -= oc;
- return err;
}
char *sq_dequote(char *arg)
diff --git a/quote.h b/quote.h
index 8a59cc5..78e8d3e 100644
--- a/quote.h
+++ b/quote.h
@@ -29,13 +29,10 @@
*/
extern void sq_quote_print(FILE *stream, const char *src);
-extern char *sq_quote_argv(const char** argv, int count);
-/*
- * Append a string to a string buffer, with or without shell quoting.
- * Return true if the buffer overflowed.
- */
-extern int add_to_string(char **ptrp, int *sizep, const char *str, int quote);
+extern void sq_quote_buf(struct strbuf *, const char *src);
+extern void sq_quote_argv(struct strbuf *, const char **argv, int count,
+ size_t maxlen);
/* This unwraps what sq_quote() produces in place, but returns
* NULL if the input does not look like what sq_quote would have
diff --git a/trace.c b/trace.c
index 91548a5..efc656b 100644
--- a/trace.c
+++ b/trace.c
@@ -85,32 +85,29 @@ void trace_printf(const char *fmt, ...)
void trace_argv_printf(const char **argv, int count, const char *fmt, ...)
{
- char buf[8192];
va_list ap;
- char *argv_str;
- size_t argv_len;
+ struct strbuf trace;
int fd, len, need_close = 0;
fd = get_trace_fd(&need_close);
if (!fd)
return;
+ strbuf_init(&trace, 0);
+ strbuf_grow(&trace, 8192);
+
va_start(ap, fmt);
- len = vsnprintf(buf, sizeof(buf), fmt, ap);
+ len = vsnprintf(trace.buf, strbuf_avail(&trace) + 1, fmt, ap);
va_end(ap);
- if (len >= sizeof(buf))
+ if (len >= strbuf_avail(&trace))
die("unreasonnable trace length");
+ strbuf_setlen(&trace, len);
- /* Get the argv string. */
- argv_str = sq_quote_argv(argv, count);
- argv_len = strlen(argv_str);
-
- write_or_whine_pipe(fd, buf, len, err_msg);
- write_or_whine_pipe(fd, argv_str, argv_len, err_msg);
- write_or_whine_pipe(fd, "\n", 1, err_msg);
-
- free(argv_str);
+ sq_quote_argv(&trace, argv, count, 0);
+ strbuf_addch(&trace, '\n');
+ write_or_whine_pipe(fd, trace.buf, trace.len, err_msg);
+ strbuf_release(&trace);
if (need_close)
close(fd);
}
--
1.5.3.2.1036.gca8d2
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
next prev parent reply other threads:[~2007-09-20 8:44 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-19 22:42 quote/strbuf series, take 3 Pierre Habouzit
[not found] ` <1190241736-30449-2-git-send-email-madcoder@debian.org>
[not found] ` <1190241736-30449-3-git-send-email-madcoder@debian.org>
2007-09-20 4:27 ` [PATCH 2/7] nfv?asprintf are broken without va_copy, workaround them Junio C Hamano
2007-09-20 4:53 ` Christian Couder
2007-09-20 8:27 ` Pierre Habouzit
2007-09-20 8:43 ` [SUPERSEDES PATCH " Pierre Habouzit
2007-09-21 6:17 ` Junio C Hamano
2007-09-21 7:02 ` Pierre Habouzit
2007-09-20 8:44 ` Pierre Habouzit [this message]
[not found] ` <1190241736-30449-4-git-send-email-madcoder@debian.org>
[not found] ` <1190241736-30449-5-git-send-email-madcoder@debian.org>
[not found] ` <1190241736-30449-6-git-send-email-madcoder@debian.org>
[not found] ` <1190241736-30449-7-git-send-email-madcoder@debian.org>
[not found] ` <1190241736-30449-8-git-send-email-madcoder@debian.org>
2007-09-20 22:05 ` [PATCH 7/7] Avoid duplicating memory, and use xmemdupz instead of xstrdup Pierre Habouzit
2007-09-21 7:03 ` Pierre Habouzit
2007-09-21 7:39 ` [DON'T MERGE PATCH 7/7] Pierre Habouzit
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
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070920084441.GC2053@artemis.corp \
--to=madcoder@debian.org \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
/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.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
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 read-only IMAP folder(s) and NNTP newsgroup(s).