981e9673d068c0c867f8bcbcec0b1e107f4487e5
[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
32 extern char *xmalloc ();
33
34 /* **************************************************************** */
35 /*                                                                  */
36 /*       Functions for quoting strings to be re-read as input       */
37 /*                                                                  */
38 /* **************************************************************** */
39
40 /* Return a new string which is the single-quoted version of STRING.
41    Used by alias and trap, among others. */
42 char *
43 sh_single_quote (string)
44      char *string;
45 {
46   register int c;
47   char *result, *r, *s;
48
49   result = xmalloc (3 + (4 * strlen (string)));
50   r = result;
51   *r++ = '\'';
52
53   for (s = string; s && (c = *s); s++)
54     {
55       *r++ = c;
56
57       if (c == '\'')
58         {
59           *r++ = '\\';  /* insert escaped single quote */
60           *r++ = '\'';
61           *r++ = '\'';  /* start new quoted string */
62         }
63     }
64
65   *r++ = '\'';
66   *r = '\0';
67
68   return (result);
69 }
70
71 /* Quote STRING using double quotes.  Return a new string. */
72 char *
73 sh_double_quote (string)
74      char *string;
75 {
76   register int c;
77   char *result, *r, *s;
78
79   result = xmalloc (3 + (2 * strlen (string)));
80   r = result;
81   *r++ = '"';
82
83   for (s = string; s && (c = *s); s++)
84     {
85       if (sh_syntaxtab[c] & CBSDQUOTE)
86         *r++ = '\\';
87
88       *r++ = c;
89     }
90
91   *r++ = '"';
92   *r = '\0';
93
94   return (result);
95 }
96
97 /* Remove backslashes that are quoting characters that are special between
98    double quotes.  Return a new string. */
99 char *
100 sh_un_double_quote (string)
101      char *string;
102 {
103   register int c, pass_next;
104   char *result, *r, *s;
105
106   r = result = xmalloc (strlen (string) + 1);
107
108   for (pass_next = 0, s = string; s && (c = *s); s++)
109     {
110       if (pass_next)
111         {
112           *r++ = c;
113           pass_next = 0;
114           continue;
115         }
116       if (c == '\\' && (sh_syntaxtab[s[1]] & CBSDQUOTE))
117         {
118           pass_next = 1;
119           continue;
120         }
121       *r++ = c;
122     }
123
124   *r = '\0';
125   return result;
126 }
127
128 /* Quote special characters in STRING using backslashes.  Return a new
129    string. */
130 char *
131 sh_backslash_quote (string)
132      char *string;
133 {
134   int c;
135   char *result, *r, *s;
136
137   result = xmalloc (2 * strlen (string) + 1);
138
139   for (r = result, s = string; s && (c = *s); s++)
140     {
141       switch (c)
142         {
143         case ' ': case '\t': case '\n':         /* IFS white space */
144         case '\'': case '"': case '\\':         /* quoting chars */
145         case '|': case '&': case ';':           /* shell metacharacters */
146         case '(': case ')': case '<': case '>':
147         case '!': case '{': case '}':           /* reserved words */
148         case '*': case '[': case '?': case ']': /* globbing chars */
149         case '^':
150         case '$': case '`':                     /* expansion chars */
151           *r++ = '\\';
152           *r++ = c;
153           break;
154 #if 0
155         case '~':                               /* tilde expansion */
156           if (s == string || s[-1] == '=' || s[-1] == ':')
157             *r++ = '\\';
158           *r++ = c;
159           break;
160 #endif
161         case '#':                               /* comment char */
162           if (s == string)
163             *r++ = '\\';
164           /* FALLTHROUGH */
165         default:
166           *r++ = c;
167           break;
168         }
169     }
170
171   *r = '\0';
172   return (result);
173 }
174
175 #if defined (PROMPT_STRING_DECODE)
176 /* Quote characters that get special treatment when in double quotes in STRING
177    using backslashes.  Return a new string. */
178 char *
179 sh_backslash_quote_for_double_quotes (string)
180      char *string;
181 {
182   int c;
183   char *result, *r, *s;
184
185   result = xmalloc (2 * strlen (string) + 1);
186
187   for (r = result, s = string; s && (c = *s); s++)
188     {
189       if (sh_syntaxtab[c] & CBSDQUOTE)
190         *r++ = '\\';
191
192       *r++ = c;
193     }
194
195   *r = '\0';
196   return (result);
197 }
198 #endif /* PROMPT_STRING_DECODE */
199
200 int
201 sh_contains_shell_metas (string)
202      char *string;
203 {
204   char *s;
205
206   for (s = string; s && *s; s++)
207     {
208       switch (*s)
209         {
210         case ' ': case '\t': case '\n':         /* IFS white space */
211         case '\'': case '"': case '\\':         /* quoting chars */
212         case '|': case '&': case ';':           /* shell metacharacters */
213         case '(': case ')': case '<': case '>':
214         case '!': case '{': case '}':           /* reserved words */
215         case '*': case '[': case '?': case ']': /* globbing chars */
216         case '^':
217         case '$': case '`':                     /* expansion chars */
218           return (1);
219         case '~':                               /* tilde expansion */
220           if (s == string || s[-1] == '=' || s[-1] == ':')
221             return (1);
222         case '#':
223           if (s == string)                      /* comment char */
224             return (1);
225           /* FALLTHROUGH */
226         default:
227           break;
228         }
229     }
230
231   return (0);
232 }