Re: re-quoting (aka reconstituting a command line)



On Sep 21, 1:37 pm, Marcel Bruinsma <m...@xxxxxxxxxxxxxxxxx> wrote:
Alternative (alnums are probably more frequent),

for (quote = '\0', c = word; *c; c++) {
    if (!isalnum((int)*c)) {
        if (strchr("\"\\$`", (int)*c)) {

Nice idea, applied.

The memory allocated by malloc(3) is not cleared,

        *ptr++ = argv[1] ? ' ' : '\0';
or
        *ptr++ = ' ';  // Add space unconditionally
    }
    *--ptr = '\0';  // Extra space => end of string
    return cmdline;

Thanks. Turns out I had this one right in my "real" code but had lost
it in the sample program.

The following is my - well, I hesitate to say "final" version but I
think it's closing in on being correct:

// gcc -o requote -W -Wall -g requote.c

#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

static char *
requote(char **argv)
{
char *word, *cmdline, *ptr, *c;
int extra_s, extra_d, quote, i;
size_t cmdlen;

// Figure out the worst-case scenario for how much space the
cmdline
// will need and allocate that much.
for (cmdlen = 0, i = 0; argv[i]; i++) {
// If every character is a single-quote and we use single quotes;
// this is a very pessimistic strategy.
cmdlen += (strlen(argv[i]) * 4) + 4;
}
cmdline = malloc(cmdlen);

// There are 4 viable POSIX quoting strategies: (1) use only
// backslashes (no quotes), (2) use double quotes and escape
// as required, (3) use single quotes and special-case
// embedded single quotes, (4) use a hybrid strategy of examining
// the word and choosing the simplest of single, double, or none.
// The following represents the hybrid approach.

for (ptr = cmdline; (word = *argv); argv++) {

// First, figure out what kind of quotes we want if any.
// We need _some_ metric by which to choose quoting style;
// the current one is to assume that the most elegant
// quoting is that which requires the fewest characters.
// Therefore we count the number of extra chars required
// for a single- or double-quoting decision, and choose the
// one which requires the fewest (or no quotes at all if
// they're both zero).
// There are a very few characters which make single-quoting
// preferable; otherwise, if any character is not on the
// list of known inert chars, we play it safe and issue a
// vote for double-quoting. Double-quoting will generally
// win unless there's a preponderance of that smaller set.
for (extra_s = extra_d = 0, c = word; *c; c++) {
if (strchr("$\"\\`", *c)) {
extra_s += 4;
extra_d += 1;
} else if (!isalnum((int)*c)) {
if (!strchr("!%+,-./=:@_", *c)) {
extra_d += 1;
extra_s += 1;
}
}
}
if (extra_s || extra_d) {
quote = (extra_d > extra_s) ? '\'' : '"';
} else {
quote = 0;
}

// Add opening quote if required.
if (quote) {
*ptr++ = quote;
}

// Copy the current word into the output buffer with adjustments.
for (; *word; word++) {
int chr;

switch((chr = *word)) {
case '\b': *ptr++ = '\\'; chr = 'b'; break;
case '\f': *ptr++ = '\\'; chr = 'f'; break;
case '\r': *ptr++ = '\\'; chr = 'r'; break;
case '$':
case '`':
case '"':
if (quote == '"') {
*ptr++ = '\\';
}
break;
case '\'':
if (quote == '\'') {
*ptr++ = '\'';
*ptr++ = '\\';
*ptr++ = '\'';
}
break;
default:
break;
}
*ptr++ = chr;
}

// Add closing quote if required.
if (quote) {
*ptr++ = quote;
}

// Add space if required.
if (argv[1]) {
*ptr++ = ' ';
} else {
*ptr = '\0';
}
}

// Trim to fit
cmdline = realloc(cmdline, strlen(cmdline) + 1);

return cmdline;
}

int
main(int argc, char **argv)
{
char *cmd;
int rc = 0;

argv[0] = "echo";
cmd = requote(argv);

fprintf(stderr, "==[%d]%s==\n", argc, cmd);

rc = system(cmd);

free(cmd);

return rc;
}
.



Relevant Pages

  • Re: re-quoting (aka reconstituting a command line)
    ... static char * ... int quote, argc; ... // embedded single quotes, use a hybrid strategy of examining ...
    (comp.unix.shell)
  • Re: I need HELP!!!
    ... char ch; ... leave context in your post. ... quote what you are replying to ...
    (comp.lang.c)
  • Re: fancier indent string
    ... TP>>> attribution not only breaks that, ... TP>>> instead of only a one character quote attrib char it's at least ... TP> That's always going to be a third less chars as the initials ... TP>> char trailed or followed by space. ...
    (comp.mail.mutt)
  • Re: handling apostrophe
    ... Try changing ur routine such that single quotes are replaced with double ... > will determine tha filter. ... >> quote is the defined and documented way to get a single quote into the ...
    (microsoft.public.sqlserver.programming)
  • Re: Kernel Panic
    ... On Thu, 2004-02-05 at 19:52, Stuart Sears wrote: ... >> They're both just single quotes. ... >> Regards Roger ... I made the assumption that the sed needed a different type of quote mark ...
    (RedHat)