Home | History | Annotate | Line # | Download | only in gdbsupport
      1      1.1  christos /* Functions to deal with the inferior being executed on GDB or
      2      1.1  christos    GDBserver.
      3      1.1  christos 
      4  1.1.1.4  christos    Copyright (C) 2019-2025 Free Software Foundation, Inc.
      5      1.1  christos 
      6      1.1  christos    This file is part of GDB.
      7      1.1  christos 
      8      1.1  christos    This program is free software; you can redistribute it and/or modify
      9      1.1  christos    it under the terms of the GNU General Public License as published by
     10      1.1  christos    the Free Software Foundation; either version 3 of the License, or
     11      1.1  christos    (at your option) any later version.
     12      1.1  christos 
     13      1.1  christos    This program is distributed in the hope that it will be useful,
     14      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16      1.1  christos    GNU General Public License for more details.
     17      1.1  christos 
     18      1.1  christos    You should have received a copy of the GNU General Public License
     19      1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     20      1.1  christos 
     21      1.1  christos #include "gdbsupport/common-inferior.h"
     22      1.1  christos 
     23      1.1  christos /* See common-inferior.h.  */
     24      1.1  christos 
     25      1.1  christos bool startup_with_shell = true;
     26      1.1  christos 
     27  1.1.1.4  christos /* Escape characters in ARG and return an updated string.  The string
     28  1.1.1.4  christos    SPECIAL contains the set of characters that must be escaped.  SPECIAL
     29  1.1.1.4  christos    must not be nullptr, and it is assumed that SPECIAL contains the newline
     30  1.1.1.4  christos    '\n' character.  It is assumed that ARG is not nullptr, but ARG can
     31  1.1.1.4  christos    be the empty string.  */
     32      1.1  christos 
     33  1.1.1.4  christos static std::string
     34  1.1.1.4  christos escape_characters (const char *arg, const char *special)
     35      1.1  christos {
     36  1.1.1.4  christos   gdb_assert (special != nullptr);
     37  1.1.1.4  christos   gdb_assert (arg != nullptr);
     38  1.1.1.4  christos 
     39      1.1  christos   std::string result;
     40      1.1  christos 
     41      1.1  christos #ifdef __MINGW32__
     42  1.1.1.4  christos   static const char quote = '"';
     43      1.1  christos #else
     44  1.1.1.4  christos   static const char quote = '\'';
     45      1.1  christos #endif
     46      1.1  christos 
     47  1.1.1.4  christos   /* Need to handle empty arguments specially.  */
     48  1.1.1.4  christos   if (arg[0] == '\0')
     49  1.1.1.4  christos     {
     50  1.1.1.4  christos       result += quote;
     51  1.1.1.4  christos       result += quote;
     52  1.1.1.4  christos     }
     53  1.1.1.4  christos   /* The special character handling code here assumes that if SPECIAL is
     54  1.1.1.4  christos      not nullptr, then SPECIAL will contain '\n'.  This is true for all our
     55  1.1.1.4  christos      current usages, but if this ever changes in the future the following
     56  1.1.1.4  christos      might need reworking.  */
     57  1.1.1.4  christos   else
     58  1.1.1.4  christos     {
     59  1.1.1.4  christos #ifdef __MINGW32__
     60  1.1.1.4  christos       bool quoted = false;
     61  1.1.1.4  christos 
     62  1.1.1.4  christos       if (strpbrk (arg, special) != nullptr)
     63  1.1.1.4  christos 	{
     64  1.1.1.4  christos 	  quoted = true;
     65  1.1.1.4  christos 	  result += quote;
     66  1.1.1.4  christos 	}
     67  1.1.1.4  christos #endif
     68  1.1.1.4  christos       for (const char *cp = arg; *cp; ++cp)
     69  1.1.1.4  christos 	{
     70  1.1.1.4  christos 	  if (*cp == '\n')
     71      1.1  christos 	    {
     72  1.1.1.4  christos 	      /* A newline cannot be quoted with a backslash (it just
     73  1.1.1.4  christos 		 disappears), only by putting it inside quotes.  */
     74      1.1  christos 	      result += quote;
     75  1.1.1.4  christos 	      result += '\n';
     76      1.1  christos 	      result += quote;
     77      1.1  christos 	    }
     78      1.1  christos 	  else
     79      1.1  christos 	    {
     80      1.1  christos #ifdef __MINGW32__
     81  1.1.1.4  christos 	      if (*cp == quote)
     82  1.1.1.4  christos #else
     83  1.1.1.4  christos 		if (strchr (special, *cp) != nullptr)
     84  1.1.1.4  christos #endif
     85  1.1.1.4  christos 		  result += '\\';
     86  1.1.1.4  christos 	      result += *cp;
     87  1.1.1.4  christos 	    }
     88  1.1.1.4  christos 	}
     89  1.1.1.4  christos #ifdef __MINGW32__
     90  1.1.1.4  christos       if (quoted)
     91  1.1.1.4  christos 	result += quote;
     92  1.1.1.4  christos #endif
     93  1.1.1.4  christos     }
     94  1.1.1.4  christos 
     95  1.1.1.4  christos   return result;
     96  1.1.1.4  christos }
     97  1.1.1.4  christos 
     98  1.1.1.4  christos /* Return a version of ARG that has special shell characters escaped.  */
     99      1.1  christos 
    100  1.1.1.4  christos static std::string
    101  1.1.1.4  christos escape_shell_characters (const char *arg)
    102  1.1.1.4  christos {
    103      1.1  christos #ifdef __MINGW32__
    104  1.1.1.4  christos   /* This holds all the characters considered special to the
    105  1.1.1.4  christos      Windows shells.  */
    106  1.1.1.4  christos   static const char special[] = "\"!&*|[]{}<>?`~^=;, \t\n";
    107      1.1  christos #else
    108  1.1.1.4  christos   /* This holds all the characters considered special to the
    109  1.1.1.4  christos      typical Unix shells.  We include `^' because the SunOS
    110  1.1.1.4  christos      /bin/sh treats it as a synonym for `|'.  */
    111  1.1.1.4  christos   static const char special[] = "\"!#$&*()\\|[]{}<>?'`~^; \t\n";
    112      1.1  christos #endif
    113  1.1.1.4  christos 
    114  1.1.1.4  christos   return escape_characters (arg, special);
    115  1.1.1.4  christos }
    116  1.1.1.4  christos 
    117  1.1.1.4  christos /* Return a version of ARG that has quote characters and white space
    118  1.1.1.4  christos    characters escaped.  These are the characters that GDB sees as special
    119  1.1.1.4  christos    when splitting a string into separate arguments.  */
    120  1.1.1.4  christos 
    121  1.1.1.4  christos static std::string
    122  1.1.1.4  christos escape_gdb_characters (const char * arg)
    123  1.1.1.4  christos {
    124      1.1  christos #ifdef __MINGW32__
    125  1.1.1.4  christos   static const char special[] = "\" \t\n";
    126  1.1.1.4  christos #else
    127  1.1.1.4  christos   static const char special[] = "\"' \t\n";
    128      1.1  christos #endif
    129  1.1.1.4  christos 
    130  1.1.1.4  christos   return escape_characters (arg, special);
    131  1.1.1.4  christos }
    132  1.1.1.4  christos 
    133  1.1.1.4  christos /* See common-inferior.h.  */
    134  1.1.1.4  christos 
    135  1.1.1.4  christos std::string
    136  1.1.1.4  christos construct_inferior_arguments (gdb::array_view<char * const> argv,
    137  1.1.1.4  christos 			      bool escape_shell_char)
    138  1.1.1.4  christos {
    139  1.1.1.4  christos   /* Select the desired escape function.  */
    140  1.1.1.4  christos   const auto escape_func = (escape_shell_char
    141  1.1.1.4  christos 			    ? escape_shell_characters
    142  1.1.1.4  christos 			    : escape_gdb_characters);
    143  1.1.1.4  christos 
    144  1.1.1.4  christos   std::string result;
    145  1.1.1.4  christos 
    146  1.1.1.4  christos   for (const char *a : argv)
    147      1.1  christos     {
    148  1.1.1.4  christos       if (!result.empty ())
    149  1.1.1.4  christos 	result += " ";
    150      1.1  christos 
    151  1.1.1.4  christos       result += escape_func (a);
    152      1.1  christos     }
    153      1.1  christos 
    154      1.1  christos   return result;
    155      1.1  christos }
    156