]>
Commit | Line | Data |
---|---|---|
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 */ |
36 | static 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. */ | |
87 | char * | |
28ef6c31 | 88 | sh_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. */ | |
127 | char * | |
28ef6c31 | 128 | sh_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. */ | |
158 | char * | |
159 | sh_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 | 185 | char * |
28ef6c31 | 186 | sh_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 | 223 | char * |
8360b906 | 224 | sh_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. */ | |
255 | char * | |
256 | sh_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 | 280 | int |
28ef6c31 | 281 | sh_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 | } |