Bash-4.3 distribution sources and documentation
[platform/upstream/bash.git] / lib / sh / shquote.c
1 /* shquote - functions to quote and dequote strings */
2
3 /* Copyright (C) 1999 Free Software Foundation, Inc.
4
5    This file is part of GNU Bash, the Bourne Again SHell.
6
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 */
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
32 #include "syntax.h"
33 #include <xmalloc.h>
34
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
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 *
88 sh_single_quote (string)
89      const char *string;
90 {
91   register int c;
92   char *result, *r;
93   const char *s;
94
95   result = (char *)xmalloc (3 + (4 * strlen (string)));
96   r = result;
97
98   if (string[0] == '\'' && string[1] == 0)
99     {
100       *r++ = '\\';
101       *r++ = '\'';
102       *r++ = 0;
103       return result;
104     }
105
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 *
128 sh_double_quote (string)
129      const char *string;
130 {
131   register unsigned char c;
132   char *result, *r;
133   const char *s;
134
135   result = (char *)xmalloc (3 + (2 * strlen (string)));
136   r = result;
137   *r++ = '"';
138
139   for (s = string; s && (c = *s); s++)
140     {
141       /* Backslash-newline disappears within double quotes, so don't add one. */
142       if ((sh_syntaxtab[c] & CBSDQUOTE) && c != '\n')
143         *r++ = '\\';
144       else if (c == CTLESC || c == CTLNUL)
145         *r++ = CTLESC;          /* could be '\\'? */
146
147       *r++ = c;
148     }
149
150   *r++ = '"';
151   *r = '\0';
152
153   return (result);
154 }
155
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
182 /* Remove backslashes that are quoting characters that are special between
183    double quotes.  Return a new string.  XXX - should this handle CTLESC
184    and CTLNUL? */
185 char *
186 sh_un_double_quote (string)
187      char *string;
188 {
189   register int c, pass_next;
190   char *result, *r, *s;
191
192   r = result = (char *)xmalloc (strlen (string) + 1);
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         }
202       if (c == '\\' && (sh_syntaxtab[(unsigned char) s[1]] & CBSDQUOTE))
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
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
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    
223 char *
224 sh_backslash_quote (string, table, flags)
225      char *string;
226      char *table;
227      int flags;
228 {
229   int c;
230   char *result, *r, *s, *backslash_table;
231
232   result = (char *)xmalloc (2 * strlen (string) + 1);
233
234   backslash_table = table ? table : (char *)bstab;
235   for (r = result, s = string; s && (c = *s); s++)
236     {
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;
246     }
247
248   *r = '\0';
249   return (result);
250 }
251
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 {
259   unsigned char c;
260   char *result, *r, *s;
261
262   result = (char *)xmalloc (2 * strlen (string) + 1);
263
264   for (r = result, s = string; s && (c = *s); s++)
265     {
266       if (sh_syntaxtab[c] & CBSDQUOTE)
267         *r++ = '\\';
268       /* I should probably add flags for these to sh_syntaxtab[] */
269       else if (c == CTLESC || c == CTLNUL)
270         *r++ = CTLESC;          /* could be '\\'? */
271
272       *r++ = c;
273     }
274
275   *r = '\0';
276   return (result);
277 }
278 #endif /* PROMPT_STRING_DECODE */
279
280 int
281 sh_contains_shell_metas (string)
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);
302           break;
303         case '#':
304           if (s == string)                      /* comment char */
305             return (1);
306           /* FALLTHROUGH */
307         default:
308           break;
309         }
310     }
311
312   return (0);
313 }