e992a66323134e723dd30a5ceb94853d20323fe6
[platform/upstream/bash.git] / lib / sh / shquote.c
1 /* Copyright (C) 1999 Free Software Foundation, Inc.
2
3    This file is part of GNU Bash, the Bourne Again SHell.
4
5    Bash is free software; you can redistribute it and/or modify it under
6    the terms of the GNU General Public License as published by the Free
7    Software Foundation; either version 2, or (at your option) any later
8    version.
9
10    Bash is distributed in the hope that it will be useful, but WITHOUT ANY
11    WARRANTY; without even the implied warranty of MERCHANTABILITY or
12    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13    for more details.
14    
15    You should have received a copy of the GNU General Public License along
16    with Bash; see the file COPYING.  If not, write to the Free Software
17    Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
18
19 #include <config.h>
20
21 #if defined (HAVE_UNISTD_H)
22 #  ifdef _MINIX
23 #    include <sys/types.h>
24 #  endif
25 #  include <unistd.h>
26 #endif
27
28 #include <stdio.h>
29
30 #include "syntax.h"
31 #include <xmalloc.h>
32
33 /* **************************************************************** */
34 /*                                                                  */
35 /*       Functions for quoting strings to be re-read as input       */
36 /*                                                                  */
37 /* **************************************************************** */
38
39 /* Return a new string which is the single-quoted version of STRING.
40    Used by alias and trap, among others. */
41 char *
42 sh_single_quote (string)
43      char *string;
44 {
45   register int c;
46   char *result, *r, *s;
47
48   result = (char *)xmalloc (3 + (4 * strlen (string)));
49   r = result;
50   *r++ = '\'';
51
52   for (s = string; s && (c = *s); s++)
53     {
54       *r++ = c;
55
56       if (c == '\'')
57         {
58           *r++ = '\\';  /* insert escaped single quote */
59           *r++ = '\'';
60           *r++ = '\'';  /* start new quoted string */
61         }
62     }
63
64   *r++ = '\'';
65   *r = '\0';
66
67   return (result);
68 }
69
70 /* Quote STRING using double quotes.  Return a new string. */
71 char *
72 sh_double_quote (string)
73      char *string;
74 {
75   register unsigned char c;
76   char *result, *r, *s;
77
78   result = (char *)xmalloc (3 + (2 * strlen (string)));
79   r = result;
80   *r++ = '"';
81
82   for (s = string; s && (c = *s); s++)
83     {
84       /* Backslash-newline disappears within double quotes, so don't add one. */
85       if ((sh_syntaxtab[c] & CBSDQUOTE) && c != '\n')
86         *r++ = '\\';
87       else if (c == CTLESC || c == CTLNUL)
88         *r++ = CTLESC;          /* could be '\\'? */
89
90       *r++ = c;
91     }
92
93   *r++ = '"';
94   *r = '\0';
95
96   return (result);
97 }
98
99 /* Turn S into a simple double-quoted string.  If FLAGS is non-zero, quote
100    double quote characters in S with backslashes. */
101 char *
102 sh_mkdoublequoted (s, slen, flags)
103      const char *s;
104      int slen, flags;
105 {
106   char *r, *ret;
107   int rlen;
108
109   rlen = (flags == 0) ? slen + 3 : (2 * slen) + 1;
110   ret = r = (char *)xmalloc (rlen);
111   
112   *r++ = '"';
113   while (*s)
114     {
115       if (flags && *s == '"')
116         *r++ = '\\';
117       *r++ = *s++;
118     }
119   *r++ = '"';
120   *r = '\0';
121
122   return ret;
123 }
124
125 /* Remove backslashes that are quoting characters that are special between
126    double quotes.  Return a new string.  XXX - should this handle CTLESC
127    and CTLNUL? */
128 char *
129 sh_un_double_quote (string)
130      char *string;
131 {
132   register int c, pass_next;
133   char *result, *r, *s;
134
135   r = result = (char *)xmalloc (strlen (string) + 1);
136
137   for (pass_next = 0, s = string; s && (c = *s); s++)
138     {
139       if (pass_next)
140         {
141           *r++ = c;
142           pass_next = 0;
143           continue;
144         }
145       if (c == '\\' && (sh_syntaxtab[(unsigned char) s[1]] & CBSDQUOTE))
146         {
147           pass_next = 1;
148           continue;
149         }
150       *r++ = c;
151     }
152
153   *r = '\0';
154   return result;
155 }
156
157 /* Quote special characters in STRING using backslashes.  Return a new
158    string.  NOTE:  if the string is to be further expanded, we need a
159    way to protect the CTLESC and CTLNUL characters.  As I write this,
160    the current callers will never cause the string to be expanded without
161    going through the shell parser, which will protect the internal
162    quoting characters. */
163 char *
164 sh_backslash_quote (string)
165      char *string;
166 {
167   int c;
168   char *result, *r, *s;
169
170   result = (char *)xmalloc (2 * strlen (string) + 1);
171
172   for (r = result, s = string; s && (c = *s); s++)
173     {
174       switch (c)
175         {
176         case ' ': case '\t': case '\n':         /* IFS white space */
177         case '\'': case '"': case '\\':         /* quoting chars */
178         case '|': case '&': case ';':           /* shell metacharacters */
179         case '(': case ')': case '<': case '>':
180         case '!': case '{': case '}':           /* reserved words */
181         case '*': case '[': case '?': case ']': /* globbing chars */
182         case '^':
183         case '$': case '`':                     /* expansion chars */
184         case ',':                               /* brace expansion */
185           *r++ = '\\';
186           *r++ = c;
187           break;
188 #if 0
189         case '~':                               /* tilde expansion */
190           if (s == string || s[-1] == '=' || s[-1] == ':')
191             *r++ = '\\';
192           *r++ = c;
193           break;
194
195         case CTLESC: case CTLNUL:               /* internal quoting characters */
196           *r++ = CTLESC;                        /* could be '\\'? */
197           *r++ = c;
198           break;
199 #endif
200
201         case '#':                               /* comment char */
202           if (s == string)
203             *r++ = '\\';
204           /* FALLTHROUGH */
205         default:
206           *r++ = c;
207           break;
208         }
209     }
210
211   *r = '\0';
212   return (result);
213 }
214
215 #if defined (PROMPT_STRING_DECODE)
216 /* Quote characters that get special treatment when in double quotes in STRING
217    using backslashes.  Return a new string. */
218 char *
219 sh_backslash_quote_for_double_quotes (string)
220      char *string;
221 {
222   unsigned char c;
223   char *result, *r, *s;
224
225   result = (char *)xmalloc (2 * strlen (string) + 1);
226
227   for (r = result, s = string; s && (c = *s); s++)
228     {
229       if (sh_syntaxtab[c] & CBSDQUOTE)
230         *r++ = '\\';
231       /* I should probably add flags for these to sh_syntaxtab[] */
232       else if (c == CTLESC || c == CTLNUL)
233         *r++ = CTLESC;          /* could be '\\'? */
234
235       *r++ = c;
236     }
237
238   *r = '\0';
239   return (result);
240 }
241 #endif /* PROMPT_STRING_DECODE */
242
243 int
244 sh_contains_shell_metas (string)
245      char *string;
246 {
247   char *s;
248
249   for (s = string; s && *s; s++)
250     {
251       switch (*s)
252         {
253         case ' ': case '\t': case '\n':         /* IFS white space */
254         case '\'': case '"': case '\\':         /* quoting chars */
255         case '|': case '&': case ';':           /* shell metacharacters */
256         case '(': case ')': case '<': case '>':
257         case '!': case '{': case '}':           /* reserved words */
258         case '*': case '[': case '?': case ']': /* globbing chars */
259         case '^':
260         case '$': case '`':                     /* expansion chars */
261           return (1);
262         case '~':                               /* tilde expansion */
263           if (s == string || s[-1] == '=' || s[-1] == ':')
264             return (1);
265           break;
266         case '#':
267           if (s == string)                      /* comment char */
268             return (1);
269           /* FALLTHROUGH */
270         default:
271           break;
272         }
273     }
274
275   return (0);
276 }