1.\" $NetBSD: shquote.3,v 1.9 2008/09/07 08:55:46 apb 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 September 7, 2008 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.In stdlib.h 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. 57They are used to encapsulate 58arguments to be included in command strings passed to the 59.Fn system 60and 61.Fn popen 62functions, so that the arguments will have the correct values 63after being evaluated by the shell. 64.Pp 65The exact method of quoting and escaping may vary, and is intended 66to match the conventions of the shell used by 67.Fn system 68and 69.Fn popen . 70It may not match the conventions used by other shells. 71In this implementation, the following 72transformation is applied to each input string: 73.Bl -bullet -width indent 74.It 75it is surrounded by single quotes 76.Pq ' , 77.It 78any single quotes in the input are escaped by replacing them with 79the four-character sequence: 80.Li '\e'' , 81and 82.It 83extraneous pairs of single quotes (caused by multiple adjacent single 84quotes in the input string, or by single quotes at the beginning or 85end of the input string) are elided. 86.El 87.Pp 88The 89.Fn shquote 90function transforms the string specified by its 91.Fa arg 92argument, and places the result into the memory pointed to by 93.Fa buf . 94.Pp 95The 96.Fn shquotev 97function transforms each of the 98.Fa argc 99strings specified by the array 100.Fa argv 101independently. 102The transformed strings are placed in the memory pointed to by 103.Fa buf , 104separated by spaces. 105It does not modify the pointer array specified by 106.Fa argv 107or the strings pointed to by the pointers in the array. 108.Pp 109Both functions write up to 110.Fa bufsize 111- 1 characters of output into the buffer pointed to by 112.Fa buf , 113then add a 114.Li NUL 115character to terminate the output string. 116If 117.Fa bufsize 118is given as zero, the 119.Fa buf 120parameter is ignored and no output is written. 121.Sh RETURN VALUES 122The 123.Fn shquote 124and 125.Fn shquotev 126functions return the number of characters necessary to hold the 127result from operating on their input strings, 128not including the terminating 129.Li NUL . 130That is, they return the length of the string that would have 131been written to the output buffer, if it were large enough. 132If an error occurs during processing, the value ((size_t)\-1) 133is returned and 134.Va errno 135is set appropriately. 136.Sh EXAMPLES 137The following code fragment demonstrates how you might use 138.Fn shquotev 139to construct a command string to be used with 140.Fn system . 141The command uses an environment variable (which will be expanded by 142the shell) to determine the actual program to run. 143Note that the environment variable may be expanded by 144the shell into multiple words. 145The first word of the expansion will be used by the shell 146as the name of the program to run, 147and the rest will be passed as arguments to the program. 148.Bd -literal -offset indent 149char **argv, c, *cmd; 150size_t cmdlen, len, qlen; 151int argc; 152 153\&... 154 155/* 156 * Size buffer to hold the command string, and allocate it. 157 * Buffer of length one given to snprintf() for portability. 158 */ 159cmdlen = snprintf(\*[Am]c, 1, "${PROG-%s} ", PROG_DEFAULT); 160qlen = shquotev(argc, argv, NULL, 0); 161if (qlen == (size_t)-1) { 162 \&... 163} 164cmdlen += qlen + 1; 165cmd = malloc(cmdlen); 166if (cmd == NULL) { 167 \&... 168} 169 170/* Create the command string. */ 171len = snprintf(cmd, cmdlen, "${PROG-%s} ", PROG_DEFAULT); 172qlen = shquotev(argc, argv, cmd + len, cmdlen - len); 173if (qlen == (size_t)-1) { 174 /* Should not ever happen. */ 175 \&... 176} 177len += qlen; 178 179/* "cmd" can now be passed to system(). */ 180.Ed 181.Pp 182The following example shows how you would implement the same 183functionality using the 184.Fn shquote 185function directly. 186.Bd -literal -offset indent 187char **argv, c, *cmd; 188size_t cmdlen, len, qlen; 189int argc, i; 190 191\&... 192 193/* 194 * Size buffer to hold the command string, and allocate it. 195 * Buffer of length one given to snprintf() for portability. 196 */ 197cmdlen = snprintf(\*[Am]c, 1, "${PROG-%s} ", PROG_DEFAULT); 198for (i = 0; i \*[Lt] argc; i++) { 199 qlen = shquote(argv[i], NULL, 0); 200 if (qlen == (size_t)-1) { 201 \&... 202 } 203 cmdlen += qlen + 1; 204} 205cmd = malloc(cmdlen); 206if (cmd == NULL) { 207 \&... 208} 209 210/* Start the command string with the env var reference. */ 211len = snprintf(cmd, cmdlen, "${PROG-%s} ", PROG_DEFAULT); 212 213/* Quote all of the arguments when copying them. */ 214for (i = 0; i \*[Lt] argc; i++) { 215 qlen = shquote(argv[i], cmd + len, cmdlen - len); 216 if (qlen == (size_t)-1) { 217 /* Should not ever happen. */ 218 \&... 219 } 220 len += qlen; 221 cmd[len++] = ' '; 222} 223cmd[--len] = '\e0'; 224 225/* "cmd" can now be passed to system(). */ 226.Ed 227.Sh SEE ALSO 228.Xr sh 1 , 229.Xr popen 3 , 230.Xr system 3 231.Sh BUGS 232This implementation does not currently handle strings containing multibyte 233characters properly. 234To address this issue, 235.Pa /bin/sh 236.Po 237the shell used by 238.Fn system 239and 240.Fn popen 241.Pc 242must first be fixed to handle multibyte characters. 243When that has been done, 244these functions can have multibyte character support enabled. 245