]> git.ipfire.org Git - thirdparty/bash.git/blame - lib/sh/shquote.c
bash-4.3-beta overlay
[thirdparty/bash.git] / lib / sh / shquote.c
CommitLineData
2e4498b3
CR
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
2e4498b3
CR
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
ddef12ff
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)
18d2df91 89 const char *string;
bb70624e
JA
90{
91 register int c;
89c77bc7
CR
92 char *result, *r;
93 const char *s;
bb70624e 94
f73dda09 95 result = (char *)xmalloc (3 + (4 * strlen (string)));
bb70624e 96 r = result;
1442f67c
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)
18d2df91 129 const char *string;
bb70624e 130{
f73dda09 131 register unsigned char c;
89c77bc7
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 {
da719982
CR
141 /* Backslash-newline disappears within double quotes, so don't add one. */
142 if ((sh_syntaxtab[c] & CBSDQUOTE) && c != '\n')
28ef6c31 143 *r++ = '\\';
d3a24ed2
CR
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
c3271763
CR
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
d3a24ed2
CR
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
633e5c6d
CR
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
8360b906
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 *
8360b906 224sh_backslash_quote (string, table, flags)
bb70624e 225 char *string;
ddef12ff 226 char *table;
8360b906 227 int flags;
bb70624e
JA
228{
229 int c;
ddef12ff 230 char *result, *r, *s, *backslash_table;
bb70624e 231
f73dda09 232 result = (char *)xmalloc (2 * strlen (string) + 1);
bb70624e 233
f14388d3 234 backslash_table = table ? table : (char *)bstab;
bb70624e
JA
235 for (r = result, s = string; s && (c = *s); s++)
236 {
ddef12ff
CR
237 if (backslash_table[c] == 1)
238 *r++ = '\\';
239 else if (c == '#' && s == string) /* comment char */
240 *r++ = '\\';
8360b906 241 else if ((flags&1) && c == '~' && (s == string || s[-1] == ':' || s[-1] == '='))
863d31ae
CR
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++ = '\\';
ddef12ff 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++ = '\\';
d3a24ed2
CR
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}