280 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			280 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* 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);
 | 
						|
}
 |