NAME
shquote
, shquotev
— quote argument strings for use
with the shell
LIBRARY
library “libc”
SYNOPSIS
#include
<stdlib.h>
size_t
shquote
(const
char *arg, char
*buf, size_t
bufsize);
size_t
shquotev
(int
argc, char * const
*argv, char *buf,
size_t bufsize);
DESCRIPTION
Theshquote
()
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:
- it is surrounded by single quotes ('),
- any single quotes in the input are escaped by replacing them with the
four-character sequence:
'\''
, and - extraneous pairs of single quotes (caused by multiple adjacent single quotes in the input string, or by single quotes at the beginning or end of the input string) are elided.
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.
RETURN VALUES
The shquote
() 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.
EXAMPLES
The following code fragment demonstrates how you might use
shquotev
() 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(). */
SEE ALSO
BUGS
This implementation does not currently handle strings containing
multibyte characters properly. To address this issue,
/bin/sh (the shell used by
system
() and popen
()) must
first be fixed to handle multibyte characters. When that has been done,
these functions can have multibyte character support enabled.