blob: fff4f817aa77eac97ff277faa208294fe0a1b9f5 [file] [log] [blame]
Jari Aalto31859422009-01-12 13:36:28 +00001/* shquote - functions to quote and dequote strings */
2
Jari Aaltobb706242000-03-17 21:46:59 +00003/* Copyright (C) 1999 Free Software Foundation, Inc.
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
Jari Aalto31859422009-01-12 13:36:28 +00007 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.
Jari Aaltobb706242000-03-17 21:46:59 +000011
Jari Aalto31859422009-01-12 13:36:28 +000012 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*/
Jari Aaltobb706242000-03-17 21:46:59 +000020
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
Jari Aalto28ef6c32001-04-06 19:14:31 +000032#include "syntax.h"
Jari Aaltof73dda02001-11-13 17:56:06 +000033#include <xmalloc.h>
Jari Aaltobb706242000-03-17 21:46:59 +000034
Chet Rameyac50fba2014-02-26 09:36:43 -050035/* 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
Jari Aaltobb706242000-03-17 21:46:59 +000079/* **************************************************************** */
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 *
Jari Aalto28ef6c32001-04-06 19:14:31 +000088sh_single_quote (string)
Chet Ramey495aee42011-11-22 19:11:26 -050089 const char *string;
Jari Aaltobb706242000-03-17 21:46:59 +000090{
91 register int c;
Chet Ramey495aee42011-11-22 19:11:26 -050092 char *result, *r;
93 const char *s;
Jari Aaltobb706242000-03-17 21:46:59 +000094
Jari Aaltof73dda02001-11-13 17:56:06 +000095 result = (char *)xmalloc (3 + (4 * strlen (string)));
Jari Aaltobb706242000-03-17 21:46:59 +000096 r = result;
Chet Rameyac50fba2014-02-26 09:36:43 -050097
98 if (string[0] == '\'' && string[1] == 0)
99 {
100 *r++ = '\\';
101 *r++ = '\'';
102 *r++ = 0;
103 return result;
104 }
105
Jari Aaltobb706242000-03-17 21:46:59 +0000106 *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 *
Jari Aalto28ef6c32001-04-06 19:14:31 +0000128sh_double_quote (string)
Chet Ramey495aee42011-11-22 19:11:26 -0500129 const char *string;
Jari Aaltobb706242000-03-17 21:46:59 +0000130{
Jari Aaltof73dda02001-11-13 17:56:06 +0000131 register unsigned char c;
Chet Ramey495aee42011-11-22 19:11:26 -0500132 char *result, *r;
133 const char *s;
Jari Aaltobb706242000-03-17 21:46:59 +0000134
Jari Aaltof73dda02001-11-13 17:56:06 +0000135 result = (char *)xmalloc (3 + (2 * strlen (string)));
Jari Aaltobb706242000-03-17 21:46:59 +0000136 r = result;
137 *r++ = '"';
138
139 for (s = string; s && (c = *s); s++)
140 {
Jari Aalto95732b42005-12-07 14:08:12 +0000141 /* Backslash-newline disappears within double quotes, so don't add one. */
142 if ((sh_syntaxtab[c] & CBSDQUOTE) && c != '\n')
Jari Aalto28ef6c32001-04-06 19:14:31 +0000143 *r++ = '\\';
Jari Aaltob80f6442004-07-27 13:29:18 +0000144 else if (c == CTLESC || c == CTLNUL)
145 *r++ = CTLESC; /* could be '\\'? */
Jari Aalto28ef6c32001-04-06 19:14:31 +0000146
147 *r++ = c;
Jari Aaltobb706242000-03-17 21:46:59 +0000148 }
149
150 *r++ = '"';
151 *r = '\0';
152
153 return (result);
154}
155
Jari Aalto95732b42005-12-07 14:08:12 +0000156/* 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
Jari Aaltobb706242000-03-17 21:46:59 +0000182/* Remove backslashes that are quoting characters that are special between
Jari Aaltob80f6442004-07-27 13:29:18 +0000183 double quotes. Return a new string. XXX - should this handle CTLESC
184 and CTLNUL? */
Jari Aaltobb706242000-03-17 21:46:59 +0000185char *
Jari Aalto28ef6c32001-04-06 19:14:31 +0000186sh_un_double_quote (string)
Jari Aaltobb706242000-03-17 21:46:59 +0000187 char *string;
188{
189 register int c, pass_next;
190 char *result, *r, *s;
191
Jari Aaltof73dda02001-11-13 17:56:06 +0000192 r = result = (char *)xmalloc (strlen (string) + 1);
Jari Aaltobb706242000-03-17 21:46:59 +0000193
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 }
Jari Aaltof73dda02001-11-13 17:56:06 +0000202 if (c == '\\' && (sh_syntaxtab[(unsigned char) s[1]] & CBSDQUOTE))
Jari Aaltobb706242000-03-17 21:46:59 +0000203 {
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
Jari Aalto95732b42005-12-07 14:08:12 +0000215 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
Chet Rameyac50fba2014-02-26 09:36:43 -0500219 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
Jari Aaltobb706242000-03-17 21:46:59 +0000223char *
Chet Rameyac50fba2014-02-26 09:36:43 -0500224sh_backslash_quote (string, table, flags)
Jari Aaltobb706242000-03-17 21:46:59 +0000225 char *string;
Chet Rameyac50fba2014-02-26 09:36:43 -0500226 char *table;
227 int flags;
Jari Aaltobb706242000-03-17 21:46:59 +0000228{
229 int c;
Chet Rameyac50fba2014-02-26 09:36:43 -0500230 char *result, *r, *s, *backslash_table;
Jari Aaltobb706242000-03-17 21:46:59 +0000231
Jari Aaltof73dda02001-11-13 17:56:06 +0000232 result = (char *)xmalloc (2 * strlen (string) + 1);
Jari Aaltobb706242000-03-17 21:46:59 +0000233
Chet Rameyac50fba2014-02-26 09:36:43 -0500234 backslash_table = table ? table : (char *)bstab;
Jari Aaltobb706242000-03-17 21:46:59 +0000235 for (r = result, s = string; s && (c = *s); s++)
236 {
Chet Rameyac50fba2014-02-26 09:36:43 -0500237 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;
Jari Aaltobb706242000-03-17 21:46:59 +0000246 }
247
248 *r = '\0';
249 return (result);
250}
251
Jari Aalto28ef6c32001-04-06 19:14:31 +0000252#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{
Jari Aaltof73dda02001-11-13 17:56:06 +0000259 unsigned char c;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000260 char *result, *r, *s;
261
Jari Aaltof73dda02001-11-13 17:56:06 +0000262 result = (char *)xmalloc (2 * strlen (string) + 1);
Jari Aalto28ef6c32001-04-06 19:14:31 +0000263
264 for (r = result, s = string; s && (c = *s); s++)
265 {
266 if (sh_syntaxtab[c] & CBSDQUOTE)
267 *r++ = '\\';
Jari Aaltob80f6442004-07-27 13:29:18 +0000268 /* I should probably add flags for these to sh_syntaxtab[] */
269 else if (c == CTLESC || c == CTLNUL)
270 *r++ = CTLESC; /* could be '\\'? */
Jari Aalto28ef6c32001-04-06 19:14:31 +0000271
272 *r++ = c;
273 }
274
275 *r = '\0';
276 return (result);
277}
278#endif /* PROMPT_STRING_DECODE */
279
Jari Aaltobb706242000-03-17 21:46:59 +0000280int
Jari Aalto28ef6c32001-04-06 19:14:31 +0000281sh_contains_shell_metas (string)
Jari Aaltobb706242000-03-17 21:46:59 +0000282 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);
Jari Aaltof73dda02001-11-13 17:56:06 +0000302 break;
Jari Aaltobb706242000-03-17 21:46:59 +0000303 case '#':
304 if (s == string) /* comment char */
305 return (1);
306 /* FALLTHROUGH */
307 default:
308 break;
309 }
310 }
311
312 return (0);
313}
Chet Ramey2b762662014-04-11 11:05:05 -0400314
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}