aac2d3494721c9a0642e7ef7e33f5f90e126f2b9
[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       if (sh_syntaxtab[c] & CBSDQUOTE)
85         *r++ = '\\';
86       else if (c == CTLESC || c == CTLNUL)
87         *r++ = CTLESC;          /* could be '\\'? */
88
89       *r++ = c;
90     }
91
92   *r++ = '"';
93   *r = '\0';
94
95   return (result);
96 }
97
98 /* Remove backslashes that are quoting characters that are special between
99    double quotes.  Return a new string.  XXX - should this handle CTLESC
100    and CTLNUL? */
101 char *
102 sh_un_double_quote (string)
103      char *string;
104 {
105   register int c, pass_next;
106   char *result, *r, *s;
107
108   r = result = (char *)xmalloc (strlen (string) + 1);
109
110   for (pass_next = 0, s = string; s && (c = *s); s++)
111     {
112       if (pass_next)
113         {
114           *r++ = c;
115           pass_next = 0;
116           continue;
117         }
118       if (c == '\\' && (sh_syntaxtab[(unsigned char) s[1]] & CBSDQUOTE))
119         {
120           pass_next = 1;
121           continue;
122         }
123       *r++ = c;
124     }
125
126   *r = '\0';
127   return result;
128 }
129
130 /* Quote special characters in STRING using backslashes.  Return a new
131    string. */
132 char *
133 sh_backslash_quote (string)
134      char *string;
135 {
136   int c;
137   char *result, *r, *s;
138
139   result = (char *)xmalloc (2 * strlen (string) + 1);
140
141   for (r = result, s = string; s && (c = *s); s++)
142     {
143       switch (c)
144         {
145         case ' ': case '\t': case '\n':         /* IFS white space */
146         case '\'': case '"': case '\\':         /* quoting chars */
147         case '|': case '&': case ';':           /* shell metacharacters */
148         case '(': case ')': case '<': case '>':
149         case '!': case '{': case '}':           /* reserved words */
150         case '*': case '[': case '?': case ']': /* globbing chars */
151         case '^':
152         case '$': case '`':                     /* expansion chars */
153         case ',':                               /* brace expansion */
154           *r++ = '\\';
155           *r++ = c;
156           break;
157 #if 0
158         case '~':                               /* tilde expansion */
159           if (s == string || s[-1] == '=' || s[-1] == ':')
160             *r++ = '\\';
161           *r++ = c;
162           break;
163 #endif
164         case CTLESC: case CTLNUL:               /* internal quoting characters */
165           *r++ = CTLESC;                        /* could be '\\'? */
166           *r++ = c;
167           break;
168
169         case '#':                               /* comment char */
170           if (s == string)
171             *r++ = '\\';
172           /* FALLTHROUGH */
173         default:
174           *r++ = c;
175           break;
176         }
177     }
178
179   *r = '\0';
180   return (result);
181 }
182
183 #if defined (PROMPT_STRING_DECODE)
184 /* Quote characters that get special treatment when in double quotes in STRING
185    using backslashes.  Return a new string. */
186 char *
187 sh_backslash_quote_for_double_quotes (string)
188      char *string;
189 {
190   unsigned char c;
191   char *result, *r, *s;
192
193   result = (char *)xmalloc (2 * strlen (string) + 1);
194
195   for (r = result, s = string; s && (c = *s); s++)
196     {
197       if (sh_syntaxtab[c] & CBSDQUOTE)
198         *r++ = '\\';
199       /* I should probably add flags for these to sh_syntaxtab[] */
200       else if (c == CTLESC || c == CTLNUL)
201         *r++ = CTLESC;          /* could be '\\'? */
202
203       *r++ = c;
204     }
205
206   *r = '\0';
207   return (result);
208 }
209 #endif /* PROMPT_STRING_DECODE */
210
211 int
212 sh_contains_shell_metas (string)
213      char *string;
214 {
215   char *s;
216
217   for (s = string; s && *s; s++)
218     {
219       switch (*s)
220         {
221         case ' ': case '\t': case '\n':         /* IFS white space */
222         case '\'': case '"': case '\\':         /* quoting chars */
223         case '|': case '&': case ';':           /* shell metacharacters */
224         case '(': case ')': case '<': case '>':
225         case '!': case '{': case '}':           /* reserved words */
226         case '*': case '[': case '?': case ']': /* globbing chars */
227         case '^':
228         case '$': case '`':                     /* expansion chars */
229           return (1);
230         case '~':                               /* tilde expansion */
231           if (s == string || s[-1] == '=' || s[-1] == ':')
232             return (1);
233           break;
234         case '#':
235           if (s == string)                      /* comment char */
236             return (1);
237           /* FALLTHROUGH */
238         default:
239           break;
240         }
241     }
242
243   return (0);
244 }