1.\" $NetBSD: shquote.3,v 1.4 2002/02/07 09:24:04 ross Exp $ 2.\" 3.\" Copyright (c) 2001 Christopher G. Demetriou 4.\" All rights reserved. 5.\" 6.\" Redistribution and use in source and binary forms, with or without 7.\" modification, are permitted provided that the following conditions 8.\" are met: 9.\" 1. Redistributions of source code must retain the above copyright 10.\" notice, this list of conditions and the following disclaimer. 11.\" 2. Redistributions in binary form must reproduce the above copyright 12.\" notice, this list of conditions and the following disclaimer in the 13.\" documentation and/or other materials provided with the distribution. 14.\" 3. All advertising materials mentioning features or use of this software 15.\" must display the following acknowledgement: 16.\" This product includes software developed for the 17.\" NetBSD Project. See http://www.netbsd.org/ for 18.\" information about NetBSD. 19.\" 4. The name of the author may not be used to endorse or promote products 20.\" derived from this software without specific prior written permission. 21.\" 22.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32.\" 33.\" <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>> 34.\" 35.Dd March 1, 2001 36.Dt SHQUOTE 3 37.Os 38.Sh NAME 39.Nm shquote , 40.Nm shquotev 41.Nd quote argument strings for use with the shell 42.Sh LIBRARY 43.Lb libc 44.Sh SYNOPSIS 45.Fd #include \*[Lt]stdlib.h\*[Gt] 46.Ft size_t 47.Fn shquote "const char *arg" "char *buf" "size_t bufsize" 48.Ft size_t 49.Fn shquotev "int argc" "char * const *argv" "char *buf" "size_t bufsize" 50.Sh DESCRIPTION 51The 52.Fn shquote 53and 54.Fn shquotev 55functions copy strings and transform the copies by adding shell 56escape and quoting characters. They are used to encapsulate 57arguments to be included in command strings passed to the 58.Fn system 59and 60.Fn popen 61functions, so that the arguments will have the correct values 62after being evaluated by the shell. 63.Pp 64The exact method of quoting and escaping may vary, and is intended 65to match the conventions of the shell used by 66.Fn system 67and 68.Fn popen . 69It may not match the conventions used by other shells. 70In this implementation, the following 71transformation is applied to each input string: 72.Bl -bullet -width indent 73.It 74it is surrounded by single quotes 75.Pq ' , 76.It 77any single quotes in the input are escaped by replacing them with 78the four-character sequence: 79.Li '\e'' , 80and 81.It 82extraneous pairs of single quotes (caused by multiple adjacent single 83quotes in the input string, or by single quotes at the beginning or 84end of the input string) are elided. 85.El 86.Pp 87The 88.Fn shquote 89function transforms the string specified by its 90.Fa arg 91argument, and places the result into the memory pointed to by 92.Fa buf . 93.Pp 94The 95.Fn shquotev 96function transforms each of the 97.Fa argc 98strings specified by the array 99.Fa argv 100independently. The transformed strings are 101placed in the memory pointed to by 102.Fa buf , 103separated by spaces. It does not modify the pointer array 104specified by 105.Fa argv 106or the strings pointed to by the pointers in the arrary. 107.Pp 108Both functions write up to 109.Fa bufsize 110- 1 characters of output into the buffer pointed to by 111.Fa buf , 112then add a 113.Li NUL 114character to terminate the output string. If 115.Fa bufsize 116is given as zero, the 117.Fa buf 118parameter is ignored and no output is written. 119.Sh RETURN VALUES 120The 121.Fn shquote 122and 123.Fn shquotev 124functions return the number of characters necessary to hold the 125result from operating on their input strings, 126not including the terminating 127.Li NUL . 128That is, they return the length of the string that would have 129been written to the output buffer, if it were large enough. 130If an error occurs during processing, the value ((size_t)\-1) 131is returned and 132.Va errno 133is set appropriately. 134.Sh EXAMPLES 135The following code fragment demonstrates how you might use 136.Fn shquotev 137to construct a command string to be used with 138.Fn system . 139The command uses an environment variable (which will be expanded by 140the shell) to determine the actual program to run. Note that 141the environment variable may be expanded by the shell into multiple 142words. The first word of the expansion will be used by the shell 143as the name of the program to run, 144and the rest will be passed as arguments to the program. 145.Bd -literal -offset indent 146char **argv, c, *cmd; 147size_t cmdlen, len, qlen; 148int argc; 149 150\&... 151 152/* 153 * Size buffer to hold the command string, and allocate it. 154 * Buffer of length one given to snprintf() for portability. 155 */ 156cmdlen = snprintf(\*[Am]c, 1, "${PROG-%s} ", PROG_DEFAULT); 157qlen = shquotev(argc, argv, NULL, 0) + 1; 158if (qlen == (size_t)-1) { 159 \&... 160} 161cmdlen += qlen; 162cmd = malloc(cmdlen); 163if (cmd == NULL) { 164 \&... 165} 166 167/* Create the command string. */ 168len = snprintf(cmd, cmdlen, "${PROG-%s} ", PROG_DEFAULT); 169qlen = shquotev(argc, argv, cmd + len, cmdlen - len); 170if (qlen == (size_t)-1) { 171 /* Should not ever happen. */ 172 \&... 173} 174len += qlen; 175 176/* "cmd" can now be passed to system(). */ 177.Ed 178.Pp 179The following example shows how you would implement the same 180functionality using the 181.Fn shquote 182function directly. 183.Bd -literal -offset indent 184char **argv, c, *cmd; 185size_t cmdlen, len, qlen; 186int argc, i; 187 188\&... 189 190/* 191 * Size buffer to hold the command string, and allocate it. 192 * Buffer of length one given to snprintf() for portability. 193 */ 194cmdlen = snprintf(\*[Am]c, 1, "${PROG-%s} ", PROG_DEFAULT); 195for (i = 0; i \*[Lt] argc; i++) { 196 qlen = shquote(argv[i], NULL, 0) + 1; 197 if (qlen == (size_t)-1) { 198 \&... 199 } 200 cmdlen += qlen; 201} 202cmd = malloc(cmdlen); 203if (cmd == NULL) { 204 \&... 205} 206 207/* Start the command string with the env var reference. */ 208len = snprintf(cmd, cmdlen, "${PROG-%s} ", PROG_DEFAULT); 209 210/* Quote all of the arguments when copying them. */ 211for (i = 0; i \*[Lt] argc; i++) { 212 qlen = shquote(argv[i], cmd + len, cmdlen - len); 213 if (qlen == (size_t)-1) { 214 /* Should not ever happen. */ 215 \&... 216 } 217 len += qlen; 218 cmd[len++] = ' '; 219} 220cmd[--len] = '\0'; 221 222/* "cmd" can now be passed to system(). */ 223.Ed 224.Sh SEE ALSO 225.Xr sh 1 , 226.Xr popen 3 , 227.Xr system 3 228.Sh BUGS 229This implementation does not currently handle strings containing multibyte 230characters properly. To address this issue, 231.Pa /bin/sh 232.Po 233the shell used by 234.Fn system 235and 236.Fn popen 237.Pc 238must first be fixed to handle multibyte characters. When that has been 239done, these functions can have multibyte character support enabled. 240