1 /* -*- mode: C; c-basic-offset: 3; -*- */
3 /*--------------------------------------------------------------------*/
4 /*--- User-mode execve() for #! scripts. m_ume_script.c ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright (C) 2000-2017 Julian Seward
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, see <http://www.gnu.org/licenses/>.
27 The GNU General Public License is contained in the file COPYING.
30 #include "pub_core_basics.h"
31 #include "pub_core_vki.h"
33 #include "pub_core_libcbase.h"
34 #include "pub_core_libcassert.h" // VG_(exit), vg_assert
35 #include "pub_core_libcfile.h" // VG_(close) et al
36 #include "pub_core_libcprint.h"
37 #include "pub_core_clientstate.h" // VG_(args_the_exename)
38 #include "pub_core_mallocfree.h" // VG_(strdup)
39 #include "pub_core_ume.h" // self
43 /* Return true, if the first line begins with #! and contains an
45 Bool
VG_(match_script
)(const void *hdr
, SizeT len
)
47 const HChar
* script
= hdr
;
48 const HChar
* end
= script
+ len
;
49 const HChar
* interp
= script
+ 2;
51 if (len
< 2) return False
;
52 if (0 != VG_(memcmp
)(hdr
, "#!", 2)) return False
;
54 // Find interpreter name, which may be absolute or relative.
55 // First, skip over any space between the #! and the start of the
57 while (interp
< end
&& (*interp
== ' ' || *interp
== '\t')) interp
++;
60 if (interp
>= end
) return False
; // can't find start of interp name
62 // No interpreter found.
63 if (*interp
== '\n') return False
;
65 return True
; // looks like a #! script
69 /* returns: 0 = success, non-0 is failure */
70 Int
VG_(load_script
)(Int fd
, const HChar
* name
, ExeInfo
* info
)
81 // Read the first part of the file.
82 res
= VG_(pread
)(fd
, hdr
, len
, 0);
83 if (sr_isError(res
)) {
90 vg_assert('#' == hdr
[0] && '!' == hdr
[1]);
94 while (interp
< end
&& (*interp
== ' ' || *interp
== '\t'))
97 /* skip over interpreter name */
98 for (cp
= interp
; cp
< end
&& !VG_(isspace
)(*cp
); cp
++)
105 if (!eol
&& cp
< end
) {
106 /* skip space before arg */
107 while (cp
< end
&& VG_(isspace
)(*cp
) && *cp
!= '\n')
110 /* arg is from here to eol */
112 while (cp
< end
&& *cp
!= '\n')
116 VG_(free
)(info
->interp_name
);
117 info
->interp_name
= VG_(strdup
)("ume.ls.1", interp
);
118 vg_assert(NULL
!= info
->interp_name
);
119 if (arg
!= NULL
&& *arg
!= '\0') {
120 info
->interp_args
= VG_(strdup
)("ume.ls.2", arg
);
121 vg_assert(NULL
!= info
->interp_args
);
124 if (info
->argv
&& info
->argv
[0] != NULL
)
125 info
->argv
[0] = name
;
127 VG_(args_the_exename
) = name
;
130 VG_(printf
)("#! script: interp_name=\"%s\" interp_args=\"%s\"\n",
131 info
->interp_name
, info
->interp_args
);
133 return VG_(do_exec_inner
)(interp
, info
);
136 /*--------------------------------------------------------------------*/
138 /*--------------------------------------------------------------------*/