blob: 6d5871af824588e0b5b89c0c1ba0fe394172a818 [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
sewardj03f8d3f2012-08-05 15:46:46 +000010 Copyright (C) 2000-2012 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{
58 Int n;
59 SysRes fd;
dirka656f3d2008-11-22 12:03:19 +000060 struct vg_stat stat_buf;
sewardj45f4e7c2005-09-27 19:20:21 +000061 HChar* f_clo = NULL;
62 HChar filename[VKI_PATH_MAX];
63
64 VG_(snprintf)(filename, VKI_PATH_MAX, "%s/.valgrindrc",
65 ( NULL == dir ? "" : dir ) );
66 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
njncda2f0f2009-05-18 02:12:08 +000067 if ( !sr_isError(fd) ) {
68 Int res = VG_(fstat)( sr_Res(fd), &stat_buf );
dirka656f3d2008-11-22 12:03:19 +000069 // Ignore if not owned by current user or world writeable (CVE-2008-4865)
njn9c20ece2009-05-20 02:02:30 +000070 if (!res && stat_buf.uid == VG_(geteuid)()
71 && (!(stat_buf.mode & VKI_S_IWOTH))) {
72 if ( stat_buf.size > 0 ) {
73 f_clo = VG_(malloc)("commandline.rdv.1", stat_buf.size+1);
dirka656f3d2008-11-22 12:03:19 +000074 vg_assert(f_clo);
njn9c20ece2009-05-20 02:02:30 +000075 n = VG_(read)(sr_Res(fd), f_clo, stat_buf.size);
dirka656f3d2008-11-22 12:03:19 +000076 if (n == -1) n = 0;
njn9c20ece2009-05-20 02:02:30 +000077 vg_assert(n >= 0 && n <= stat_buf.size+1);
dirka656f3d2008-11-22 12:03:19 +000078 f_clo[n] = '\0';
79 }
sewardj45f4e7c2005-09-27 19:20:21 +000080 }
dirka656f3d2008-11-22 12:03:19 +000081 else
82 VG_(message)(Vg_UserMsg,
83 "%s was not read as it is world writeable or not owned by the "
sewardj738856f2009-07-15 14:48:32 +000084 "current user\n", filename);
dirka656f3d2008-11-22 12:03:19 +000085
njncda2f0f2009-05-18 02:12:08 +000086 VG_(close)(sr_Res(fd));
sewardj45f4e7c2005-09-27 19:20:21 +000087 }
88 return f_clo;
89}
90
91
92// Add args from a string into VG_(args_for_valgrind), splitting the
93// string at whitespace and adding each component as a separate arg.
94
95static void add_args_from_string ( HChar* s )
96{
97 HChar* tmp;
98 HChar* cp = s;
99 vg_assert(cp);
100 while (True) {
101 // We have alternating sequences: blanks, non-blanks, blanks...
102 // copy the non-blanks sequences, and add terminating '\0'
103 while (VG_(isspace)(*cp)) cp++;
104 if (*cp == 0) break;
105 tmp = cp;
106 while ( !VG_(isspace)(*cp) && *cp != 0 ) cp++;
107 if ( *cp != 0 ) *cp++ = '\0'; // terminate if not the last
sewardj14c7cc52007-02-25 15:08:24 +0000108 add_string( VG_(args_for_valgrind), tmp );
sewardj45f4e7c2005-09-27 19:20:21 +0000109 }
110}
111
112
113/* Split up the args presented by the launcher to m_main.main(), and
114 park them in VG_(args_for_client) and VG_(args_for_valgrind).
115
116 The resulting arg list is the concatenation of the following:
117 - contents of ~/.valgrindrc
118 - contents of $VALGRIND_OPTS
119 - contents of ./.valgrindrc
120 - args from the command line
121 in the stated order.
122
123 VG_(args_for_valgrind_noexecpass) is set to be the number of items
124 in the first three categories. They are not passed to child invokations
125 at exec, whereas the last group is.
126
127 If the last group contains --command-line-only=yes, then the
128 first three groups are left empty.
129
130 Scheme: first examine the last group (the supplied argc/argv).
131 It should look like this.
132
133 args-for-v exe_name args-for-c
134
135 args-for-v are taken until either they don't start with '-' or
136 a "--" is seen.
137
138 The exe name and args-for-c are recorded without further ado.
139 Note that args-for-c[0] is the first real arg for the client, not
140 its executable name.
141
142 args-for-v are then copied into tmp_xarray.
143
144 if args-for-v does not include --command-line-only=yes:
145 contents of ~/.valgrindrc, $VALGRIND_OPTS and ./.valgrindrc
146 are copied into VG_(args_for_valgrind).
147 else
148 VG_(args_for_valgrind) is made empty.
149
150 Finally, tmp_xarray is copied onto the end of VG_(args_for_valgrind).
151*/
152
153void VG_(split_up_argv)( Int argc, HChar** argv )
154{
155 Int i;
156 Bool augment = True;
157 static Bool already_called = False;
158
sewardj14c7cc52007-02-25 15:08:24 +0000159 XArray* /* of HChar* */ tmp_xarray;
sewardj45f4e7c2005-09-27 19:20:21 +0000160
161 /* This function should be called once, at startup, and then never
162 again. */
163 vg_assert(!already_called);
164 already_called = True;
165
sewardj9c606bd2008-09-18 18:12:50 +0000166 tmp_xarray = VG_(newXA)( VG_(malloc), "commandline.sua.1",
167 VG_(free), sizeof(HChar*) );
sewardj14c7cc52007-02-25 15:08:24 +0000168 vg_assert(tmp_xarray);
169
170 vg_assert( ! VG_(args_for_valgrind) );
171 VG_(args_for_valgrind)
sewardj9c606bd2008-09-18 18:12:50 +0000172 = VG_(newXA)( VG_(malloc), "commandline.sua.2",
173 VG_(free), sizeof(HChar*) );
sewardj14c7cc52007-02-25 15:08:24 +0000174 vg_assert( VG_(args_for_valgrind) );
175
176 vg_assert( ! VG_(args_for_client) );
177 VG_(args_for_client)
sewardj9c606bd2008-09-18 18:12:50 +0000178 = VG_(newXA)( VG_(malloc), "commandline.sua.3",
179 VG_(free), sizeof(HChar*) );
sewardj14c7cc52007-02-25 15:08:24 +0000180 vg_assert( VG_(args_for_client) );
181
sewardj45f4e7c2005-09-27 19:20:21 +0000182 /* Collect up the args-for-V. */
183 i = 1; /* skip the exe (stage2) name. */
184 for (; i < argc; i++) {
185 vg_assert(argv[i]);
186 if (0 == VG_(strcmp)(argv[i], "--")) {
187 i++;
188 break;
189 }
190 if (0 == VG_(strcmp)(argv[i], "--command-line-only=yes"))
191 augment = False;
192 if (argv[i][0] != '-')
193 break;
sewardj14c7cc52007-02-25 15:08:24 +0000194 add_string( tmp_xarray, argv[i] );
sewardj45f4e7c2005-09-27 19:20:21 +0000195 }
196
197 /* Should now be looking at the exe name. */
198 if (i < argc) {
199 vg_assert(argv[i]);
200 VG_(args_the_exename) = argv[i];
201 i++;
202 }
203
204 /* The rest are args for the client. */
205 for (; i < argc; i++) {
206 vg_assert(argv[i]);
sewardj14c7cc52007-02-25 15:08:24 +0000207 add_string( VG_(args_for_client), argv[i] );
sewardj45f4e7c2005-09-27 19:20:21 +0000208 }
209
sewardj45f4e7c2005-09-27 19:20:21 +0000210 /* Get extra args from ~/.valgrindrc, $VALGRIND_OPTS and
211 ./.valgrindrc into VG_(args_for_valgrind). */
212 if (augment) {
213 // read_dot_valgrindrc() allocates the return value with
214 // VG_(malloc)(). We do not free f1_clo and f2_clo as they get
215 // put into VG_(args_for_valgrind) and so must persist.
sewardj02ab2772006-12-06 17:38:32 +0000216 HChar* home = VG_(getenv)("HOME");
217 HChar* f1_clo = home ? read_dot_valgrindrc( home ) : NULL;
sewardj9c606bd2008-09-18 18:12:50 +0000218 HChar* env_clo = VG_(strdup)( "commandline.sua.4",
219 VG_(getenv)(VALGRIND_OPTS) );
njn64bd24a2007-03-26 22:05:30 +0000220 HChar* f2_clo = NULL;
221
222 // Don't read ./.valgrindrc if "." is the same as "$HOME", else its
223 // contents will be applied twice. (bug #142488)
224 if (home) {
225 HChar cwd[VKI_PATH_MAX+1];
sewardj198f34f2007-07-09 23:13:07 +0000226 Bool cwd_ok = VG_(get_startup_wd)(cwd, VKI_PATH_MAX);
njn64bd24a2007-03-26 22:05:30 +0000227 f2_clo = ( (cwd_ok && VG_STREQ(home, cwd))
228 ? NULL : read_dot_valgrindrc(".") );
229 }
sewardj45f4e7c2005-09-27 19:20:21 +0000230
231 if (f1_clo) add_args_from_string( f1_clo );
232 if (env_clo) add_args_from_string( env_clo );
233 if (f2_clo) add_args_from_string( f2_clo );
234 }
235
236 /* .. and record how many extras we got. */
sewardj14c7cc52007-02-25 15:08:24 +0000237 VG_(args_for_valgrind_noexecpass)
238 = VG_(sizeXA)( VG_(args_for_valgrind) );
sewardj45f4e7c2005-09-27 19:20:21 +0000239
240 /* Finally, copy tmp_xarray onto the end. */
sewardj14c7cc52007-02-25 15:08:24 +0000241 for (i = 0; i < VG_(sizeXA)( tmp_xarray ); i++)
242 add_string( VG_(args_for_valgrind),
243 * (HChar**)VG_(indexXA)( tmp_xarray, i ) );
sewardj45f4e7c2005-09-27 19:20:21 +0000244
sewardj14c7cc52007-02-25 15:08:24 +0000245 VG_(deleteXA)( tmp_xarray );
sewardj45f4e7c2005-09-27 19:20:21 +0000246}
247
248/*--------------------------------------------------------------------*/
249/*--- end ---*/
250/*--------------------------------------------------------------------*/