Patch-ID: bash40-030
[bash.git] / lib / sh / shquote.c
bloba267d3800b51ee040f810194b1b1ad2fd6d9f5bc
1 /* shquote - functions to quote and dequote strings */
3 /* Copyright (C) 1999 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
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.
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.
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/>.
21 #include <config.h>
23 #if defined (HAVE_UNISTD_H)
24 # ifdef _MINIX
25 # include <sys/types.h>
26 # endif
27 # include <unistd.h>
28 #endif
30 #include <stdio.h>
32 #include "syntax.h"
33 #include <xmalloc.h>
35 /* **************************************************************** */
36 /* */
37 /* Functions for quoting strings to be re-read as input */
38 /* */
39 /* **************************************************************** */
41 /* Return a new string which is the single-quoted version of STRING.
42 Used by alias and trap, among others. */
43 char *
44 sh_single_quote (string)
45 char *string;
47 register int c;
48 char *result, *r, *s;
50 result = (char *)xmalloc (3 + (4 * strlen (string)));
51 r = result;
52 *r++ = '\'';
54 for (s = string; s && (c = *s); s++)
56 *r++ = c;
58 if (c == '\'')
60 *r++ = '\\'; /* insert escaped single quote */
61 *r++ = '\'';
62 *r++ = '\''; /* start new quoted string */
66 *r++ = '\'';
67 *r = '\0';
69 return (result);
72 /* Quote STRING using double quotes. Return a new string. */
73 char *
74 sh_double_quote (string)
75 char *string;
77 register unsigned char c;
78 char *result, *r, *s;
80 result = (char *)xmalloc (3 + (2 * strlen (string)));
81 r = result;
82 *r++ = '"';
84 for (s = string; s && (c = *s); s++)
86 /* Backslash-newline disappears within double quotes, so don't add one. */
87 if ((sh_syntaxtab[c] & CBSDQUOTE) && c != '\n')
88 *r++ = '\\';
89 else if (c == CTLESC || c == CTLNUL)
90 *r++ = CTLESC; /* could be '\\'? */
92 *r++ = c;
95 *r++ = '"';
96 *r = '\0';
98 return (result);
101 /* Turn S into a simple double-quoted string. If FLAGS is non-zero, quote
102 double quote characters in S with backslashes. */
103 char *
104 sh_mkdoublequoted (s, slen, flags)
105 const char *s;
106 int slen, flags;
108 char *r, *ret;
109 int rlen;
111 rlen = (flags == 0) ? slen + 3 : (2 * slen) + 1;
112 ret = r = (char *)xmalloc (rlen);
114 *r++ = '"';
115 while (*s)
117 if (flags && *s == '"')
118 *r++ = '\\';
119 *r++ = *s++;
121 *r++ = '"';
122 *r = '\0';
124 return ret;
127 /* Remove backslashes that are quoting characters that are special between
128 double quotes. Return a new string. XXX - should this handle CTLESC
129 and CTLNUL? */
130 char *
131 sh_un_double_quote (string)
132 char *string;
134 register int c, pass_next;
135 char *result, *r, *s;
137 r = result = (char *)xmalloc (strlen (string) + 1);
139 for (pass_next = 0, s = string; s && (c = *s); s++)
141 if (pass_next)
143 *r++ = c;
144 pass_next = 0;
145 continue;
147 if (c == '\\' && (sh_syntaxtab[(unsigned char) s[1]] & CBSDQUOTE))
149 pass_next = 1;
150 continue;
152 *r++ = c;
155 *r = '\0';
156 return result;
159 /* Quote special characters in STRING using backslashes. Return a new
160 string. NOTE: if the string is to be further expanded, we need a
161 way to protect the CTLESC and CTLNUL characters. As I write this,
162 the current callers will never cause the string to be expanded without
163 going through the shell parser, which will protect the internal
164 quoting characters. */
165 char *
166 sh_backslash_quote (string)
167 char *string;
169 int c;
170 char *result, *r, *s;
172 result = (char *)xmalloc (2 * strlen (string) + 1);
174 for (r = result, s = string; s && (c = *s); s++)
176 switch (c)
178 case ' ': case '\t': case '\n': /* IFS white space */
179 case '\'': case '"': case '\\': /* quoting chars */
180 case '|': case '&': case ';': /* shell metacharacters */
181 case '(': case ')': case '<': case '>':
182 case '!': case '{': case '}': /* reserved words */
183 case '*': case '[': case '?': case ']': /* globbing chars */
184 case '^':
185 case '$': case '`': /* expansion chars */
186 case ',': /* brace expansion */
187 *r++ = '\\';
188 *r++ = c;
189 break;
190 #if 0
191 case '~': /* tilde expansion */
192 if (s == string || s[-1] == '=' || s[-1] == ':')
193 *r++ = '\\';
194 *r++ = c;
195 break;
197 case CTLESC: case CTLNUL: /* internal quoting characters */
198 *r++ = CTLESC; /* could be '\\'? */
199 *r++ = c;
200 break;
201 #endif
203 case '#': /* comment char */
204 if (s == string)
205 *r++ = '\\';
206 /* FALLTHROUGH */
207 default:
208 *r++ = c;
209 break;
213 *r = '\0';
214 return (result);
217 #if defined (PROMPT_STRING_DECODE)
218 /* Quote characters that get special treatment when in double quotes in STRING
219 using backslashes. Return a new string. */
220 char *
221 sh_backslash_quote_for_double_quotes (string)
222 char *string;
224 unsigned char c;
225 char *result, *r, *s;
227 result = (char *)xmalloc (2 * strlen (string) + 1);
229 for (r = result, s = string; s && (c = *s); s++)
231 if (sh_syntaxtab[c] & CBSDQUOTE)
232 *r++ = '\\';
233 /* I should probably add flags for these to sh_syntaxtab[] */
234 else if (c == CTLESC || c == CTLNUL)
235 *r++ = CTLESC; /* could be '\\'? */
237 *r++ = c;
240 *r = '\0';
241 return (result);
243 #endif /* PROMPT_STRING_DECODE */
246 sh_contains_shell_metas (string)
247 char *string;
249 char *s;
251 for (s = string; s && *s; s++)
253 switch (*s)
255 case ' ': case '\t': case '\n': /* IFS white space */
256 case '\'': case '"': case '\\': /* quoting chars */
257 case '|': case '&': case ';': /* shell metacharacters */
258 case '(': case ')': case '<': case '>':
259 case '!': case '{': case '}': /* reserved words */
260 case '*': case '[': case '?': case ']': /* globbing chars */
261 case '^':
262 case '$': case '`': /* expansion chars */
263 return (1);
264 case '~': /* tilde expansion */
265 if (s == string || s[-1] == '=' || s[-1] == ':')
266 return (1);
267 break;
268 case '#':
269 if (s == string) /* comment char */
270 return (1);
271 /* FALLTHROUGH */
272 default:
273 break;
277 return (0);