size_t
shquote(
const char *arg
, char *buf
, size_t bufsize
)
size_t
shquotev(
int argc
, char * const *argv
, char *buf
, size_t bufsize
)
)
and
shquotev(
)
functions copy strings and transform the copies by adding shell
escape and quoting characters.
They are used to encapsulate
arguments to be included in command strings passed to the
system(
)
and
popen(
)
functions, so that the arguments will have the correct values
after being evaluated by the shell.
The exact method of quoting and escaping may vary, and is intended
to match the conventions of the shell used by
system()
and
popen(
).
It may not match the conventions used by other shells.
In this implementation, the following
transformation is applied to each input string:
'\''
,
and
The
shquote()
function transforms the string specified by its
arg
argument, and places the result into the memory pointed to by
buf
.
The
shquotev()
function transforms each of the
argc
strings specified by the array
argv
independently.
The transformed strings are placed in the memory pointed to by
buf
,
separated by spaces.
It does not modify the pointer array specified by
argv
or the strings pointed to by the pointers in the array.
Both functions write up to
bufsize
- 1 characters of output into the buffer pointed to by
buf
,
then add a
NUL
character to terminate the output string.
If
bufsize
is given as zero, the
buf
parameter is ignored and no output is written.
)
and
shquotev(
)
functions return the number of characters necessary to hold the
result from operating on their input strings,
not including the terminating
NUL
.
That is, they return the length of the string that would have
been written to the output buffer, if it were large enough.
If an error occurs during processing, the value ((size_t)-1)
is returned and
errno
is set appropriately.
)
to construct a command string to be used with
system(
).
The command uses an environment variable (which will be expanded by
the shell) to determine the actual program to run.
Note that the environment variable may be expanded by
the shell into multiple words.
The first word of the expansion will be used by the shell
as the name of the program to run,
and the rest will be passed as arguments to the program.
char **argv, c, *cmd;
size_t cmdlen, len, qlen;
int argc;
...
/*
* Size buffer to hold the command string, and allocate it.
* Buffer of length one given to snprintf() for portability.
*/
cmdlen = snprintf(&c, 1, "${PROG-%s} ", PROG_DEFAULT);
qlen = shquotev(argc, argv, NULL, 0);
if (qlen == (size_t)-1) {
...
}
cmdlen += qlen + 1;
cmd = malloc(cmdlen);
if (cmd == NULL) {
...
}
/* Create the command string. */
len = snprintf(cmd, cmdlen, "${PROG-%s} ", PROG_DEFAULT);
qlen = shquotev(argc, argv, cmd + len, cmdlen - len);
if (qlen == (size_t)-1) {
/* Should not ever happen. */
...
}
len += qlen;
/* "cmd" can now be passed to system(). */
The following example shows how you would implement the same
functionality using the
shquote()
function directly.
char **argv, c, *cmd;
size_t cmdlen, len, qlen;
int argc, i;
...
/*
* Size buffer to hold the command string, and allocate it.
* Buffer of length one given to snprintf() for portability.
*/
cmdlen = snprintf(&c, 1, "${PROG-%s} ", PROG_DEFAULT);
for (i = 0; i < argc; i++) {
qlen = shquote(argv[i], NULL, 0);
if (qlen == (size_t)-1) {
...
}
cmdlen += qlen + 1;
}
cmd = malloc(cmdlen);
if (cmd == NULL) {
...
}
/* Start the command string with the env var reference. */
len = snprintf(cmd, cmdlen, "${PROG-%s} ", PROG_DEFAULT);
/* Quote all of the arguments when copying them. */
for (i = 0; i < argc; i++) {
qlen = shquote(argv[i], cmd + len, cmdlen - len);
if (qlen == (size_t)-1) {
/* Should not ever happen. */
...
}
len += qlen;
cmd[len++] = ' ';
}
cmd[--len] = '\0';
/* "cmd" can now be passed to system(). */
/bin/sh
popen(
)
(the shell used by system(
) and)
must first be fixed to handle multibyte characters.
When that has been done,
these functions can have multibyte character support enabled.