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, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29 The GNU General Public License is contained in the file COPYING.
32 #include "pub_core_basics.h"
33 #include "pub_core_vki.h"
35 #include "pub_core_libcbase.h"
36 #include "pub_core_libcassert.h" // VG_(exit), vg_assert
37 #include "pub_core_libcfile.h" // VG_(close) et al
38 #include "pub_core_libcprint.h"
39 #include "pub_core_clientstate.h" // VG_(args_the_exename)
40 #include "pub_core_mallocfree.h" // VG_(strdup)
41 #include "pub_core_ume.h" // self
45 /* Return true, if the first line begins with #! and contains an
47 Bool
VG_(match_script
)(const void *hdr
, SizeT len
)
49 const HChar
* script
= hdr
;
50 const HChar
* end
= script
+ len
;
51 const HChar
* interp
= script
+ 2;
53 if (len
< 2) return False
;
54 if (0 != VG_(memcmp
)(hdr
, "#!", 2)) return False
;
56 // Find interpreter name, which may be absolute or relative.
57 // First, skip over any space between the #! and the start of the
59 while (interp
< end
&& (*interp
== ' ' || *interp
== '\t')) interp
++;
62 if (interp
>= end
) return False
; // can't find start of interp name
64 // No interpreter found.
65 if (*interp
== '\n') return False
;
67 return True
; // looks like a #! script
71 /* returns: 0 = success, non-0 is failure */
72 Int
VG_(load_script
)(Int fd
, const HChar
* name
, ExeInfo
* info
)
83 // Read the first part of the file.
84 res
= VG_(pread
)(fd
, hdr
, len
, 0);
85 if (sr_isError(res
)) {
92 vg_assert('#' == hdr
[0] && '!' == hdr
[1]);
96 while (interp
< end
&& (*interp
== ' ' || *interp
== '\t'))
99 /* skip over interpreter name */
100 for (cp
= interp
; cp
< end
&& !VG_(isspace
)(*cp
); cp
++)
107 if (!eol
&& cp
< end
) {
108 /* skip space before arg */
109 while (cp
< end
&& VG_(isspace
)(*cp
) && *cp
!= '\n')
112 /* arg is from here to eol */
114 while (cp
< end
&& *cp
!= '\n')
118 VG_(free
)(info
->interp_name
);
119 info
->interp_name
= VG_(strdup
)("ume.ls.1", interp
);
120 vg_assert(NULL
!= info
->interp_name
);
121 if (arg
!= NULL
&& *arg
!= '\0') {
122 info
->interp_args
= VG_(strdup
)("ume.ls.2", arg
);
123 vg_assert(NULL
!= info
->interp_args
);
126 if (info
->argv
&& info
->argv
[0] != NULL
)
127 info
->argv
[0] = name
;
129 VG_(args_the_exename
) = name
;
132 VG_(printf
)("#! script: interp_name=\"%s\" interp_args=\"%s\"\n",
133 info
->interp_name
, info
->interp_args
);
135 return VG_(do_exec_inner
)(interp
, info
);
138 /*--------------------------------------------------------------------*/
140 /*--------------------------------------------------------------------*/