| /* shquote - functions to quote and dequote strings */ |
| |
| /* Copyright (C) 1999 Free Software Foundation, Inc. |
| |
| This file is part of GNU Bash, the Bourne Again SHell. |
| |
| Bash is free software: you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| Bash is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with Bash. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #include <config.h> |
| |
| #if defined (HAVE_UNISTD_H) |
| # ifdef _MINIX |
| # include <sys/types.h> |
| # endif |
| # include <unistd.h> |
| #endif |
| |
| #include <stdio.h> |
| |
| #include "syntax.h" |
| #include <xmalloc.h> |
| |
| /* **************************************************************** */ |
| /* */ |
| /* Functions for quoting strings to be re-read as input */ |
| /* */ |
| /* **************************************************************** */ |
| |
| /* Return a new string which is the single-quoted version of STRING. |
| Used by alias and trap, among others. */ |
| char * |
| sh_single_quote (string) |
| const char *string; |
| { |
| register int c; |
| char *result, *r; |
| const char *s; |
| |
| result = (char *)xmalloc (3 + (4 * strlen (string))); |
| r = result; |
| *r++ = '\''; |
| |
| for (s = string; s && (c = *s); s++) |
| { |
| *r++ = c; |
| |
| if (c == '\'') |
| { |
| *r++ = '\\'; /* insert escaped single quote */ |
| *r++ = '\''; |
| *r++ = '\''; /* start new quoted string */ |
| } |
| } |
| |
| *r++ = '\''; |
| *r = '\0'; |
| |
| return (result); |
| } |
| |
| /* Quote STRING using double quotes. Return a new string. */ |
| char * |
| sh_double_quote (string) |
| const char *string; |
| { |
| register unsigned char c; |
| char *result, *r; |
| const char *s; |
| |
| result = (char *)xmalloc (3 + (2 * strlen (string))); |
| r = result; |
| *r++ = '"'; |
| |
| for (s = string; s && (c = *s); s++) |
| { |
| /* Backslash-newline disappears within double quotes, so don't add one. */ |
| if ((sh_syntaxtab[c] & CBSDQUOTE) && c != '\n') |
| *r++ = '\\'; |
| else if (c == CTLESC || c == CTLNUL) |
| *r++ = CTLESC; /* could be '\\'? */ |
| |
| *r++ = c; |
| } |
| |
| *r++ = '"'; |
| *r = '\0'; |
| |
| return (result); |
| } |
| |
| /* Turn S into a simple double-quoted string. If FLAGS is non-zero, quote |
| double quote characters in S with backslashes. */ |
| char * |
| sh_mkdoublequoted (s, slen, flags) |
| const char *s; |
| int slen, flags; |
| { |
| char *r, *ret; |
| int rlen; |
| |
| rlen = (flags == 0) ? slen + 3 : (2 * slen) + 1; |
| ret = r = (char *)xmalloc (rlen); |
| |
| *r++ = '"'; |
| while (*s) |
| { |
| if (flags && *s == '"') |
| *r++ = '\\'; |
| *r++ = *s++; |
| } |
| *r++ = '"'; |
| *r = '\0'; |
| |
| return ret; |
| } |
| |
| /* Remove backslashes that are quoting characters that are special between |
| double quotes. Return a new string. XXX - should this handle CTLESC |
| and CTLNUL? */ |
| char * |
| sh_un_double_quote (string) |
| char *string; |
| { |
| register int c, pass_next; |
| char *result, *r, *s; |
| |
| r = result = (char *)xmalloc (strlen (string) + 1); |
| |
| for (pass_next = 0, s = string; s && (c = *s); s++) |
| { |
| if (pass_next) |
| { |
| *r++ = c; |
| pass_next = 0; |
| continue; |
| } |
| if (c == '\\' && (sh_syntaxtab[(unsigned char) s[1]] & CBSDQUOTE)) |
| { |
| pass_next = 1; |
| continue; |
| } |
| *r++ = c; |
| } |
| |
| *r = '\0'; |
| return result; |
| } |
| |
| /* Quote special characters in STRING using backslashes. Return a new |
| string. NOTE: if the string is to be further expanded, we need a |
| way to protect the CTLESC and CTLNUL characters. As I write this, |
| the current callers will never cause the string to be expanded without |
| going through the shell parser, which will protect the internal |
| quoting characters. */ |
| char * |
| sh_backslash_quote (string) |
| char *string; |
| { |
| int c; |
| char *result, *r, *s; |
| |
| result = (char *)xmalloc (2 * strlen (string) + 1); |
| |
| for (r = result, s = string; s && (c = *s); s++) |
| { |
| switch (c) |
| { |
| case ' ': case '\t': case '\n': /* IFS white space */ |
| case '\'': case '"': case '\\': /* quoting chars */ |
| case '|': case '&': case ';': /* shell metacharacters */ |
| case '(': case ')': case '<': case '>': |
| case '!': case '{': case '}': /* reserved words */ |
| case '*': case '[': case '?': case ']': /* globbing chars */ |
| case '^': |
| case '$': case '`': /* expansion chars */ |
| case ',': /* brace expansion */ |
| *r++ = '\\'; |
| *r++ = c; |
| break; |
| #if 0 |
| case '~': /* tilde expansion */ |
| if (s == string || s[-1] == '=' || s[-1] == ':') |
| *r++ = '\\'; |
| *r++ = c; |
| break; |
| |
| case CTLESC: case CTLNUL: /* internal quoting characters */ |
| *r++ = CTLESC; /* could be '\\'? */ |
| *r++ = c; |
| break; |
| #endif |
| |
| case '#': /* comment char */ |
| if (s == string) |
| *r++ = '\\'; |
| /* FALLTHROUGH */ |
| default: |
| *r++ = c; |
| break; |
| } |
| } |
| |
| *r = '\0'; |
| return (result); |
| } |
| |
| #if defined (PROMPT_STRING_DECODE) |
| /* Quote characters that get special treatment when in double quotes in STRING |
| using backslashes. Return a new string. */ |
| char * |
| sh_backslash_quote_for_double_quotes (string) |
| char *string; |
| { |
| unsigned char c; |
| char *result, *r, *s; |
| |
| result = (char *)xmalloc (2 * strlen (string) + 1); |
| |
| for (r = result, s = string; s && (c = *s); s++) |
| { |
| if (sh_syntaxtab[c] & CBSDQUOTE) |
| *r++ = '\\'; |
| /* I should probably add flags for these to sh_syntaxtab[] */ |
| else if (c == CTLESC || c == CTLNUL) |
| *r++ = CTLESC; /* could be '\\'? */ |
| |
| *r++ = c; |
| } |
| |
| *r = '\0'; |
| return (result); |
| } |
| #endif /* PROMPT_STRING_DECODE */ |
| |
| int |
| sh_contains_shell_metas (string) |
| char *string; |
| { |
| char *s; |
| |
| for (s = string; s && *s; s++) |
| { |
| switch (*s) |
| { |
| case ' ': case '\t': case '\n': /* IFS white space */ |
| case '\'': case '"': case '\\': /* quoting chars */ |
| case '|': case '&': case ';': /* shell metacharacters */ |
| case '(': case ')': case '<': case '>': |
| case '!': case '{': case '}': /* reserved words */ |
| case '*': case '[': case '?': case ']': /* globbing chars */ |
| case '^': |
| case '$': case '`': /* expansion chars */ |
| return (1); |
| case '~': /* tilde expansion */ |
| if (s == string || s[-1] == '=' || s[-1] == ':') |
| return (1); |
| break; |
| case '#': |
| if (s == string) /* comment char */ |
| return (1); |
| /* FALLTHROUGH */ |
| default: |
| break; |
| } |
| } |
| |
| return (0); |
| } |