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