blob: d89b6ac2dade5b4b68fafa6f9b22cb9c615dbc98 [file] [log] [blame]
sewardj45f4e7c2005-09-27 19:20:21 +00001
2/*--------------------------------------------------------------------*/
3/*--- Command line handling. m_commandline.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
Elliott Hughesed398002017-06-21 14:41:24 -070010 Copyright (C) 2000-2017 Julian Seward
sewardj45f4e7c2005-09-27 19:20:21 +000011 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
31#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000032#include "pub_core_vki.h"
sewardj45f4e7c2005-09-27 19:20:21 +000033#include "pub_core_libcassert.h"
34#include "pub_core_libcbase.h"
35#include "pub_core_libcfile.h"
36#include "pub_core_libcprint.h"
37#include "pub_core_libcproc.h"
38#include "pub_core_mallocfree.h"
sewardj14c7cc52007-02-25 15:08:24 +000039#include "pub_core_xarray.h"
sewardj45f4e7c2005-09-27 19:20:21 +000040#include "pub_core_clientstate.h"
sewardj14c7cc52007-02-25 15:08:24 +000041#include "pub_core_commandline.h" /* self */
sewardj45f4e7c2005-09-27 19:20:21 +000042
43
44/* Add a string to an expandable array of strings. */
45
sewardj14c7cc52007-02-25 15:08:24 +000046static void add_string ( XArray* /* of HChar* */xa, HChar* str )
sewardj45f4e7c2005-09-27 19:20:21 +000047{
sewardj0f631482007-02-27 16:40:53 +000048 (void) VG_(addToXA)( xa, (void*)(&str) );
sewardj45f4e7c2005-09-27 19:20:21 +000049}
50
51
52/* Read the contents of .valgrindrc in 'dir' into malloc'd memory. */
53// Note that we deliberately don't free the malloc'd memory. See
54// comment at call site.
55
florian6bd9dc12012-11-23 16:17:43 +000056static HChar* read_dot_valgrindrc ( const HChar* dir )
sewardj45f4e7c2005-09-27 19:20:21 +000057{
dirka656f3d2008-11-22 12:03:19 +000058 struct vg_stat stat_buf;
sewardj45f4e7c2005-09-27 19:20:21 +000059 HChar* f_clo = NULL;
florian7d3ae572014-09-27 18:01:19 +000060 const HChar dot_valgrindrc[] = ".valgrindrc";
sewardj45f4e7c2005-09-27 19:20:21 +000061
florian7d3ae572014-09-27 18:01:19 +000062 vg_assert(dir != NULL);
63
64 HChar filename[VG_(strlen)(dir) + 1 + VG_(strlen)(dot_valgrindrc) + 1];
65 VG_(sprintf)(filename, "%s/%s", dir, dot_valgrindrc);
66
Elliott Hughesed398002017-06-21 14:41:24 -070067 SysRes fd = VG_(open)(filename, 0, VKI_S_IRUSR);
njncda2f0f2009-05-18 02:12:08 +000068 if ( !sr_isError(fd) ) {
69 Int res = VG_(fstat)( sr_Res(fd), &stat_buf );
Elliott Hughesed398002017-06-21 14:41:24 -070070 /* Ignore if not owned by the current user, or is not a regular file,
71 or is world writeable (CVE-2008-4865). */
72 if (res == 0
73 && stat_buf.uid == VG_(geteuid)()
74 && VKI_S_ISREG(stat_buf.mode)
75 && !(stat_buf.mode & VKI_S_IWOTH)) {
njn9c20ece2009-05-20 02:02:30 +000076 if ( stat_buf.size > 0 ) {
77 f_clo = VG_(malloc)("commandline.rdv.1", stat_buf.size+1);
Elliott Hughesed398002017-06-21 14:41:24 -070078 Int n = VG_(read)(sr_Res(fd), f_clo, stat_buf.size);
dirka656f3d2008-11-22 12:03:19 +000079 if (n == -1) n = 0;
njn9c20ece2009-05-20 02:02:30 +000080 vg_assert(n >= 0 && n <= stat_buf.size+1);
dirka656f3d2008-11-22 12:03:19 +000081 f_clo[n] = '\0';
82 }
sewardj45f4e7c2005-09-27 19:20:21 +000083 }
dirka656f3d2008-11-22 12:03:19 +000084 else
85 VG_(message)(Vg_UserMsg,
Elliott Hughesed398002017-06-21 14:41:24 -070086 "%s was not read as it is either not a regular file,\n"
87 " or is world writeable, or is not owned by the current user.\n",
88 filename);
dirka656f3d2008-11-22 12:03:19 +000089
njncda2f0f2009-05-18 02:12:08 +000090 VG_(close)(sr_Res(fd));
sewardj45f4e7c2005-09-27 19:20:21 +000091 }
92 return f_clo;
93}
94
95
96// Add args from a string into VG_(args_for_valgrind), splitting the
97// string at whitespace and adding each component as a separate arg.
98
99static void add_args_from_string ( HChar* s )
100{
101 HChar* tmp;
102 HChar* cp = s;
103 vg_assert(cp);
104 while (True) {
105 // We have alternating sequences: blanks, non-blanks, blanks...
106 // copy the non-blanks sequences, and add terminating '\0'
107 while (VG_(isspace)(*cp)) cp++;
108 if (*cp == 0) break;
109 tmp = cp;
110 while ( !VG_(isspace)(*cp) && *cp != 0 ) cp++;
111 if ( *cp != 0 ) *cp++ = '\0'; // terminate if not the last
sewardj14c7cc52007-02-25 15:08:24 +0000112 add_string( VG_(args_for_valgrind), tmp );
sewardj45f4e7c2005-09-27 19:20:21 +0000113 }
114}
115
116
117/* Split up the args presented by the launcher to m_main.main(), and
118 park them in VG_(args_for_client) and VG_(args_for_valgrind).
119
120 The resulting arg list is the concatenation of the following:
121 - contents of ~/.valgrindrc
122 - contents of $VALGRIND_OPTS
123 - contents of ./.valgrindrc
124 - args from the command line
125 in the stated order.
126
127 VG_(args_for_valgrind_noexecpass) is set to be the number of items
Elliott Hughesed398002017-06-21 14:41:24 -0700128 in the first three categories. They are not passed to child invocations
sewardj45f4e7c2005-09-27 19:20:21 +0000129 at exec, whereas the last group is.
130
131 If the last group contains --command-line-only=yes, then the
132 first three groups are left empty.
133
134 Scheme: first examine the last group (the supplied argc/argv).
135 It should look like this.
136
137 args-for-v exe_name args-for-c
138
139 args-for-v are taken until either they don't start with '-' or
140 a "--" is seen.
141
142 The exe name and args-for-c are recorded without further ado.
143 Note that args-for-c[0] is the first real arg for the client, not
144 its executable name.
145
146 args-for-v are then copied into tmp_xarray.
147
148 if args-for-v does not include --command-line-only=yes:
149 contents of ~/.valgrindrc, $VALGRIND_OPTS and ./.valgrindrc
150 are copied into VG_(args_for_valgrind).
151 else
152 VG_(args_for_valgrind) is made empty.
153
154 Finally, tmp_xarray is copied onto the end of VG_(args_for_valgrind).
155*/
156
157void VG_(split_up_argv)( Int argc, HChar** argv )
158{
159 Int i;
160 Bool augment = True;
161 static Bool already_called = False;
162
sewardj14c7cc52007-02-25 15:08:24 +0000163 XArray* /* of HChar* */ tmp_xarray;
sewardj45f4e7c2005-09-27 19:20:21 +0000164
165 /* This function should be called once, at startup, and then never
166 again. */
167 vg_assert(!already_called);
168 already_called = True;
169
sewardj9c606bd2008-09-18 18:12:50 +0000170 tmp_xarray = VG_(newXA)( VG_(malloc), "commandline.sua.1",
171 VG_(free), sizeof(HChar*) );
sewardj14c7cc52007-02-25 15:08:24 +0000172
173 vg_assert( ! VG_(args_for_valgrind) );
174 VG_(args_for_valgrind)
sewardj9c606bd2008-09-18 18:12:50 +0000175 = VG_(newXA)( VG_(malloc), "commandline.sua.2",
176 VG_(free), sizeof(HChar*) );
sewardj14c7cc52007-02-25 15:08:24 +0000177
178 vg_assert( ! VG_(args_for_client) );
179 VG_(args_for_client)
sewardj9c606bd2008-09-18 18:12:50 +0000180 = VG_(newXA)( VG_(malloc), "commandline.sua.3",
181 VG_(free), sizeof(HChar*) );
sewardj14c7cc52007-02-25 15:08:24 +0000182
sewardj45f4e7c2005-09-27 19:20:21 +0000183 /* Collect up the args-for-V. */
184 i = 1; /* skip the exe (stage2) name. */
185 for (; i < argc; i++) {
186 vg_assert(argv[i]);
187 if (0 == VG_(strcmp)(argv[i], "--")) {
188 i++;
189 break;
190 }
191 if (0 == VG_(strcmp)(argv[i], "--command-line-only=yes"))
192 augment = False;
193 if (argv[i][0] != '-')
194 break;
sewardj14c7cc52007-02-25 15:08:24 +0000195 add_string( tmp_xarray, argv[i] );
sewardj45f4e7c2005-09-27 19:20:21 +0000196 }
197
198 /* Should now be looking at the exe name. */
199 if (i < argc) {
200 vg_assert(argv[i]);
201 VG_(args_the_exename) = argv[i];
202 i++;
203 }
204
205 /* The rest are args for the client. */
206 for (; i < argc; i++) {
207 vg_assert(argv[i]);
sewardj14c7cc52007-02-25 15:08:24 +0000208 add_string( VG_(args_for_client), argv[i] );
sewardj45f4e7c2005-09-27 19:20:21 +0000209 }
210
sewardj45f4e7c2005-09-27 19:20:21 +0000211 /* Get extra args from ~/.valgrindrc, $VALGRIND_OPTS and
212 ./.valgrindrc into VG_(args_for_valgrind). */
213 if (augment) {
214 // read_dot_valgrindrc() allocates the return value with
215 // VG_(malloc)(). We do not free f1_clo and f2_clo as they get
216 // put into VG_(args_for_valgrind) and so must persist.
sewardj02ab2772006-12-06 17:38:32 +0000217 HChar* home = VG_(getenv)("HOME");
218 HChar* f1_clo = home ? read_dot_valgrindrc( home ) : NULL;
sewardj9c606bd2008-09-18 18:12:50 +0000219 HChar* env_clo = VG_(strdup)( "commandline.sua.4",
220 VG_(getenv)(VALGRIND_OPTS) );
njn64bd24a2007-03-26 22:05:30 +0000221 HChar* f2_clo = NULL;
222
223 // Don't read ./.valgrindrc if "." is the same as "$HOME", else its
224 // contents will be applied twice. (bug #142488)
Elliott Hughesa0664b92017-04-18 17:46:52 -0700225 // Also don't try to read it if there is no cwd.
njn64bd24a2007-03-26 22:05:30 +0000226 if (home) {
florian29d82f62014-09-27 17:42:07 +0000227 const HChar *cwd = VG_(get_startup_wd)();
Elliott Hughesa0664b92017-04-18 17:46:52 -0700228 f2_clo = ( (cwd == NULL || VG_STREQ(home, cwd))
njn64bd24a2007-03-26 22:05:30 +0000229 ? NULL : read_dot_valgrindrc(".") );
230 }
sewardj45f4e7c2005-09-27 19:20:21 +0000231
232 if (f1_clo) add_args_from_string( f1_clo );
233 if (env_clo) add_args_from_string( env_clo );
234 if (f2_clo) add_args_from_string( f2_clo );
235 }
236
237 /* .. and record how many extras we got. */
sewardj14c7cc52007-02-25 15:08:24 +0000238 VG_(args_for_valgrind_noexecpass)
239 = VG_(sizeXA)( VG_(args_for_valgrind) );
sewardj45f4e7c2005-09-27 19:20:21 +0000240
241 /* Finally, copy tmp_xarray onto the end. */
sewardj14c7cc52007-02-25 15:08:24 +0000242 for (i = 0; i < VG_(sizeXA)( tmp_xarray ); i++)
243 add_string( VG_(args_for_valgrind),
244 * (HChar**)VG_(indexXA)( tmp_xarray, i ) );
sewardj45f4e7c2005-09-27 19:20:21 +0000245
sewardj14c7cc52007-02-25 15:08:24 +0000246 VG_(deleteXA)( tmp_xarray );
sewardj45f4e7c2005-09-27 19:20:21 +0000247}
248
249/*--------------------------------------------------------------------*/
250/*--- end ---*/
251/*--------------------------------------------------------------------*/