]> git.ipfire.org Git - thirdparty/bash.git/blame - lib/sh/shquote.c
Bash-4.3 patch 10
[thirdparty/bash.git] / lib / sh / shquote.c
CommitLineData
3185942a
JA
1/* shquote - functions to quote and dequote strings */
2
bb70624e
JA
3/* Copyright (C) 1999 Free Software Foundation, Inc.
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
3185942a
JA
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19*/
bb70624e
JA
20
21#include <config.h>
22
23#if defined (HAVE_UNISTD_H)
24# ifdef _MINIX
25# include <sys/types.h>
26# endif
27# include <unistd.h>
28#endif
29
30#include <stdio.h>
31
28ef6c31 32#include "syntax.h"
f73dda09 33#include <xmalloc.h>
bb70624e 34
ac50fbac
CR
35/* Default set of characters that should be backslash-quoted in strings */
36static const char bstab[256] =
37 {
38 0, 0, 0, 0, 0, 0, 0, 0,
39 0, 1, 1, 0, 0, 0, 0, 0, /* TAB, NL */
40 0, 0, 0, 0, 0, 0, 0, 0,
41 0, 0, 0, 0, 0, 0, 0, 0,
42
43 1, 1, 1, 0, 1, 0, 1, 1, /* SPACE, !, DQUOTE, DOL, AMP, SQUOTE */
44 1, 1, 1, 0, 1, 0, 0, 0, /* LPAR, RPAR, STAR, COMMA */
45 0, 0, 0, 0, 0, 0, 0, 0,
46 0, 0, 0, 1, 1, 0, 1, 1, /* SEMI, LESSTHAN, GREATERTHAN, QUEST */
47
48 0, 0, 0, 0, 0, 0, 0, 0,
49 0, 0, 0, 0, 0, 0, 0, 0,
50 0, 0, 0, 0, 0, 0, 0, 0,
51 0, 0, 0, 1, 1, 1, 1, 0, /* LBRACK, BS, RBRACK, CARAT */
52
53 1, 0, 0, 0, 0, 0, 0, 0, /* BACKQ */
54 0, 0, 0, 0, 0, 0, 0, 0,
55 0, 0, 0, 0, 0, 0, 0, 0,
56 0, 0, 0, 1, 1, 1, 0, 0, /* LBRACE, BAR, RBRACE */
57
58 0, 0, 0, 0, 0, 0, 0, 0,
59 0, 0, 0, 0, 0, 0, 0, 0,
60 0, 0, 0, 0, 0, 0, 0, 0,
61 0, 0, 0, 0, 0, 0, 0, 0,
62
63 0, 0, 0, 0, 0, 0, 0, 0,
64 0, 0, 0, 0, 0, 0, 0, 0,
65 0, 0, 0, 0, 0, 0, 0, 0,
66 0, 0, 0, 0, 0, 0, 0, 0,
67
68 0, 0, 0, 0, 0, 0, 0, 0,
69 0, 0, 0, 0, 0, 0, 0, 0,
70 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0, 0, 0, 0,
72
73 0, 0, 0, 0, 0, 0, 0, 0,
74 0, 0, 0, 0, 0, 0, 0, 0,
75 0, 0, 0, 0, 0, 0, 0, 0,
76 0, 0, 0, 0, 0, 0, 0, 0,
77 };
78
bb70624e
JA
79/* **************************************************************** */
80/* */
81/* Functions for quoting strings to be re-read as input */
82/* */
83/* **************************************************************** */
84
85/* Return a new string which is the single-quoted version of STRING.
86 Used by alias and trap, among others. */
87char *
28ef6c31 88sh_single_quote (string)
495aee44 89 const char *string;
bb70624e
JA
90{
91 register int c;
495aee44
CR
92 char *result, *r;
93 const char *s;
bb70624e 94
f73dda09 95 result = (char *)xmalloc (3 + (4 * strlen (string)));
bb70624e 96 r = result;
ac50fbac
CR
97
98 if (string[0] == '\'' && string[1] == 0)
99 {
100 *r++ = '\\';
101 *r++ = '\'';
102 *r++ = 0;
103 return result;
104 }
105
bb70624e
JA
106 *r++ = '\'';
107
108 for (s = string; s && (c = *s); s++)
109 {
110 *r++ = c;
111
112 if (c == '\'')
113 {
114 *r++ = '\\'; /* insert escaped single quote */
115 *r++ = '\'';
116 *r++ = '\''; /* start new quoted string */
117 }
118 }
119
120 *r++ = '\'';
121 *r = '\0';
122
123 return (result);
124}
125
126/* Quote STRING using double quotes. Return a new string. */
127char *
28ef6c31 128sh_double_quote (string)
495aee44 129 const char *string;
bb70624e 130{
f73dda09 131 register unsigned char c;
495aee44
CR
132 char *result, *r;
133 const char *s;
bb70624e 134
f73dda09 135 result = (char *)xmalloc (3 + (2 * strlen (string)));
bb70624e
JA
136 r = result;
137 *r++ = '"';
138
139 for (s = string; s && (c = *s); s++)
140 {
95732b49
JA
141 /* Backslash-newline disappears within double quotes, so don't add one. */
142 if ((sh_syntaxtab[c] & CBSDQUOTE) && c != '\n')
28ef6c31 143 *r++ = '\\';
b80f6443
JA
144 else if (c == CTLESC || c == CTLNUL)
145 *r++ = CTLESC; /* could be '\\'? */
28ef6c31
JA
146
147 *r++ = c;
bb70624e
JA
148 }
149
150 *r++ = '"';
151 *r = '\0';
152
153 return (result);
154}
155
95732b49
JA
156/* Turn S into a simple double-quoted string. If FLAGS is non-zero, quote
157 double quote characters in S with backslashes. */
158char *
159sh_mkdoublequoted (s, slen, flags)
160 const char *s;
161 int slen, flags;
162{
163 char *r, *ret;
164 int rlen;
165
166 rlen = (flags == 0) ? slen + 3 : (2 * slen) + 1;
167 ret = r = (char *)xmalloc (rlen);
168
169 *r++ = '"';
170 while (*s)
171 {
172 if (flags && *s == '"')
173 *r++ = '\\';
174 *r++ = *s++;
175 }
176 *r++ = '"';
177 *r = '\0';
178
179 return ret;
180}
181
bb70624e 182/* Remove backslashes that are quoting characters that are special between
b80f6443
JA
183 double quotes. Return a new string. XXX - should this handle CTLESC
184 and CTLNUL? */
bb70624e 185char *
28ef6c31 186sh_un_double_quote (string)
bb70624e
JA
187 char *string;
188{
189 register int c, pass_next;
190 char *result, *r, *s;
191
f73dda09 192 r = result = (char *)xmalloc (strlen (string) + 1);
bb70624e
JA
193
194 for (pass_next = 0, s = string; s && (c = *s); s++)
195 {
196 if (pass_next)
197 {
198 *r++ = c;
199 pass_next = 0;
200 continue;
201 }
f73dda09 202 if (c == '\\' && (sh_syntaxtab[(unsigned char) s[1]] & CBSDQUOTE))
bb70624e
JA
203 {
204 pass_next = 1;
205 continue;
206 }
207 *r++ = c;
208 }
209
210 *r = '\0';
211 return result;
212}
213
214/* Quote special characters in STRING using backslashes. Return a new
95732b49
JA
215 string. NOTE: if the string is to be further expanded, we need a
216 way to protect the CTLESC and CTLNUL characters. As I write this,
217 the current callers will never cause the string to be expanded without
218 going through the shell parser, which will protect the internal
ac50fbac
CR
219 quoting characters. TABLE, if set, points to a map of the ascii code
220 set with char needing to be backslash-quoted if table[char]==1. FLAGS,
221 if 1, causes tildes to be quoted as well. */
222
bb70624e 223char *
ac50fbac 224sh_backslash_quote (string, table, flags)
bb70624e 225 char *string;
ac50fbac
CR
226 char *table;
227 int flags;
bb70624e
JA
228{
229 int c;
ac50fbac 230 char *result, *r, *s, *backslash_table;
bb70624e 231
f73dda09 232 result = (char *)xmalloc (2 * strlen (string) + 1);
bb70624e 233
ac50fbac 234 backslash_table = table ? table : (char *)bstab;
bb70624e
JA
235 for (r = result, s = string; s && (c = *s); s++)
236 {
ac50fbac
CR
237 if (backslash_table[c] == 1)
238 *r++ = '\\';
239 else if (c == '#' && s == string) /* comment char */
240 *r++ = '\\';
241 else if ((flags&1) && c == '~' && (s == string || s[-1] == ':' || s[-1] == '='))
242 /* Tildes are special at the start of a word or after a `:' or `='
243 (technically unquoted, but it doesn't make a difference in practice) */
244 *r++ = '\\';
245 *r++ = c;
bb70624e
JA
246 }
247
248 *r = '\0';
249 return (result);
250}
251
28ef6c31
JA
252#if defined (PROMPT_STRING_DECODE)
253/* Quote characters that get special treatment when in double quotes in STRING
254 using backslashes. Return a new string. */
255char *
256sh_backslash_quote_for_double_quotes (string)
257 char *string;
258{
f73dda09 259 unsigned char c;
28ef6c31
JA
260 char *result, *r, *s;
261
f73dda09 262 result = (char *)xmalloc (2 * strlen (string) + 1);
28ef6c31
JA
263
264 for (r = result, s = string; s && (c = *s); s++)
265 {
266 if (sh_syntaxtab[c] & CBSDQUOTE)
267 *r++ = '\\';
b80f6443
JA
268 /* I should probably add flags for these to sh_syntaxtab[] */
269 else if (c == CTLESC || c == CTLNUL)
270 *r++ = CTLESC; /* could be '\\'? */
28ef6c31
JA
271
272 *r++ = c;
273 }
274
275 *r = '\0';
276 return (result);
277}
278#endif /* PROMPT_STRING_DECODE */
279
bb70624e 280int
28ef6c31 281sh_contains_shell_metas (string)
bb70624e
JA
282 char *string;
283{
284 char *s;
285
286 for (s = string; s && *s; s++)
287 {
288 switch (*s)
289 {
290 case ' ': case '\t': case '\n': /* IFS white space */
291 case '\'': case '"': case '\\': /* quoting chars */
292 case '|': case '&': case ';': /* shell metacharacters */
293 case '(': case ')': case '<': case '>':
294 case '!': case '{': case '}': /* reserved words */
295 case '*': case '[': case '?': case ']': /* globbing chars */
296 case '^':
297 case '$': case '`': /* expansion chars */
298 return (1);
299 case '~': /* tilde expansion */
300 if (s == string || s[-1] == '=' || s[-1] == ':')
301 return (1);
f73dda09 302 break;
bb70624e
JA
303 case '#':
304 if (s == string) /* comment char */
305 return (1);
306 /* FALLTHROUGH */
307 default:
308 break;
309 }
310 }
311
312 return (0);
313}
2b76266c
CR
314
315int
316sh_contains_quotes (string)
317 char *string;
318{
319 char *s;
320
321 for (s = string; s && *s; s++)
322 {
323 if (*s == '\'' || *s == '"' || *s == '\\')
324 return 1;
325 }
326 return 0;
327}