Imported from ../bash-4.0-rc1.tar.gz.
[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 /* **************************************************************** */
36 /*                                                                  */
37 /*       Functions for quoting strings to be re-read as input       */
38 /*                                                                  */
39 /* **************************************************************** */
40
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;
46 {
47   register int c;
48   char *result, *r, *s;
49
50   result = (char *)xmalloc (3 + (4 * strlen (string)));
51   r = result;
52   *r++ = '\'';
53
54   for (s = string; s && (c = *s); s++)
55     {
56       *r++ = c;
57
58       if (c == '\'')
59         {
60           *r++ = '\\';  /* insert escaped single quote */
61           *r++ = '\'';
62           *r++ = '\'';  /* start new quoted string */
63         }
64     }
65
66   *r++ = '\'';
67   *r = '\0';
68
69   return (result);
70 }
71
72 /* Quote STRING using double quotes.  Return a new string. */
73 char *
74 sh_double_quote (string)
75      char *string;
76 {
77   register unsigned char c;
78   char *result, *r, *s;
79
80   result = (char *)xmalloc (3 + (2 * strlen (string)));
81   r = result;
82   *r++ = '"';
83
84   for (s = string; s && (c = *s); s++)
85     {
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 '\\'? */
91
92       *r++ = c;
93     }
94
95   *r++ = '"';
96   *r = '\0';
97
98   return (result);
99 }
100
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;
107 {
108   char *r, *ret;
109   int rlen;
110
111   rlen = (flags == 0) ? slen + 3 : (2 * slen) + 1;
112   ret = r = (char *)xmalloc (rlen);
113   
114   *r++ = '"';
115   while (*s)
116     {
117       if (flags && *s == '"')
118         *r++ = '\\';
119       *r++ = *s++;
120     }
121   *r++ = '"';
122   *r = '\0';
123
124   return ret;
125 }
126
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;
133 {
134   register int c, pass_next;
135   char *result, *r, *s;
136
137   r = result = (char *)xmalloc (strlen (string) + 1);
138
139   for (pass_next = 0, s = string; s && (c = *s); s++)
140     {
141       if (pass_next)
142         {
143           *r++ = c;
144           pass_next = 0;
145           continue;
146         }
147       if (c == '\\' && (sh_syntaxtab[(unsigned char) s[1]] & CBSDQUOTE))
148         {
149           pass_next = 1;
150           continue;
151         }
152       *r++ = c;
153     }
154
155   *r = '\0';
156   return result;
157 }
158
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;
168 {
169   int c;
170   char *result, *r, *s;
171
172   result = (char *)xmalloc (2 * strlen (string) + 1);
173
174   for (r = result, s = string; s && (c = *s); s++)
175     {
176       switch (c)
177         {
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;
196
197         case CTLESC: case CTLNUL:               /* internal quoting characters */
198           *r++ = CTLESC;                        /* could be '\\'? */
199           *r++ = c;
200           break;
201 #endif
202
203         case '#':                               /* comment char */
204           if (s == string)
205             *r++ = '\\';
206           /* FALLTHROUGH */
207         default:
208           *r++ = c;
209           break;
210         }
211     }
212
213   *r = '\0';
214   return (result);
215 }
216
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;
223 {
224   unsigned char c;
225   char *result, *r, *s;
226
227   result = (char *)xmalloc (2 * strlen (string) + 1);
228
229   for (r = result, s = string; s && (c = *s); s++)
230     {
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 '\\'? */
236
237       *r++ = c;
238     }
239
240   *r = '\0';
241   return (result);
242 }
243 #endif /* PROMPT_STRING_DECODE */
244
245 int
246 sh_contains_shell_metas (string)
247      char *string;
248 {
249   char *s;
250
251   for (s = string; s && *s; s++)
252     {
253       switch (*s)
254         {
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;
274         }
275     }
276
277   return (0);
278 }