1/* Functions to deal with the inferior being executed on GDB or
2   GDBserver.
3
4   Copyright (C) 2019-2020 Free Software Foundation, Inc.
5
6   This file is part of GDB.
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21#include "gdbsupport/common-defs.h"
22#include "gdbsupport/common-inferior.h"
23
24/* See common-inferior.h.  */
25
26bool startup_with_shell = true;
27
28/* See common-inferior.h.  */
29
30std::string
31construct_inferior_arguments (gdb::array_view<char * const> argv)
32{
33  std::string result;
34
35  if (startup_with_shell)
36    {
37#ifdef __MINGW32__
38      /* This holds all the characters considered special to the
39	 Windows shells.  */
40      static const char special[] = "\"!&*|[]{}<>?`~^=;, \t\n";
41      static const char quote = '"';
42#else
43      /* This holds all the characters considered special to the
44	 typical Unix shells.  We include `^' because the SunOS
45	 /bin/sh treats it as a synonym for `|'.  */
46      static const char special[] = "\"!#$&*()\\|[]{}<>?'`~^; \t\n";
47      static const char quote = '\'';
48#endif
49      for (int i = 0; i < argv.size (); ++i)
50	{
51	  if (i > 0)
52	    result += ' ';
53
54	  /* Need to handle empty arguments specially.  */
55	  if (argv[i][0] == '\0')
56	    {
57	      result += quote;
58	      result += quote;
59	    }
60	  else
61	    {
62#ifdef __MINGW32__
63	      bool quoted = false;
64
65	      if (strpbrk (argv[i], special))
66		{
67		  quoted = true;
68		  result += quote;
69		}
70#endif
71	      for (char *cp = argv[i]; *cp; ++cp)
72		{
73		  if (*cp == '\n')
74		    {
75		      /* A newline cannot be quoted with a backslash (it
76			 just disappears), only by putting it inside
77			 quotes.  */
78		      result += quote;
79		      result += '\n';
80		      result += quote;
81		    }
82		  else
83		    {
84#ifdef __MINGW32__
85		      if (*cp == quote)
86#else
87		      if (strchr (special, *cp) != NULL)
88#endif
89			result += '\\';
90		      result += *cp;
91		    }
92		}
93#ifdef __MINGW32__
94	      if (quoted)
95		result += quote;
96#endif
97	    }
98	}
99    }
100  else
101    {
102      /* In this case we can't handle arguments that contain spaces,
103	 tabs, or newlines -- see breakup_args().  */
104      for (char *arg : argv)
105	{
106	  char *cp = strchr (arg, ' ');
107	  if (cp == NULL)
108	    cp = strchr (arg, '\t');
109	  if (cp == NULL)
110	    cp = strchr (arg, '\n');
111	  if (cp != NULL)
112	    error (_("can't handle command-line "
113		     "argument containing whitespace"));
114	}
115
116      for (int i = 0; i < argv.size (); ++i)
117	{
118	  if (i > 0)
119	    result += " ";
120	  result += argv[i];
121	}
122    }
123
124  return result;
125}
126