xref: /netbsd/lib/libc/gen/shquote.3 (revision bf9ec67e)
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