blob: 9b875c9ac539a9f514ee05a45745df726b23a1d8 [file] [log] [blame]
njn91772d12009-01-21 02:26:56 +00001
2/*--------------------------------------------------------------------*/
3/*--- User-mode execve() for #! scripts. m_ume_script.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
njn9f207462009-03-10 22:02:09 +000010 Copyright (C) 2000-2009 Julian Seward
njn91772d12009-01-21 02:26:56 +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"
32#include "pub_core_vki.h"
33
34#include "pub_core_libcbase.h"
35#include "pub_core_libcassert.h" // VG_(exit), vg_assert
36#include "pub_core_libcfile.h" // VG_(close) et al
37#include "pub_core_libcprint.h"
38#include "pub_core_mallocfree.h" // VG_(strdup)
39#include "pub_core_ume.h" // self
40
41#include "priv_ume.h" // self
42
43
44#if defined(HAVE_SCRIPT)
45
46Bool VG_(match_script)(Char *hdr, Int len)
47{
48 Char* end = hdr + len;
49 Char* interp = hdr + 2;
50
51 // len < 4: need '#', '!', plus at least a '/' and one more char
52 if (len < 4) return False;
53 if (0 != VG_(memcmp)(hdr, "#!", 2)) return False;
54
55 // Find interpreter name, make sure it's an absolute path (starts with
56 // '/') and has at least one more char. First, skip over any space
57 // between the #! and the start of the interpreter name
58 while (interp < end && VG_(isspace)(*interp)) interp++;
59
60 // overrun?
61 if (interp >= end) return False; // can't find start of interp name
62
63 // interp should now point at the /
64 if (*interp != '/') return False; // absolute path only for interpreter
65
66 // check for something plausible after the /
67 interp++;
68 if (interp >= end) return False;
69 if (VG_(isspace)(*interp)) return False;
70
71 // Here we should get the full interpreter name and check it with
72 // check_executable(). See the "EXEC FAILED" failure when running shell
73 // for an example.
74
75 return True; // looks like a #! script
76}
77
78
79/* returns: 0 = success, non-0 is failure */
80Int VG_(load_script)(Int fd, const HChar* name, ExeInfo* info)
81{
82 Char hdr[4096];
83 Int len = 4096;
84 Int eol;
85 Char* interp;
86 Char* end;
87 Char* cp;
88 Char* arg = NULL;
89 SysRes res;
90
91 // Read the first part of the file.
92 res = VG_(pread)(fd, hdr, len, 0);
njncda2f0f2009-05-18 02:12:08 +000093 if (sr_isError(res)) {
njn91772d12009-01-21 02:26:56 +000094 VG_(close)(fd);
95 return VKI_EACCES;
96 } else {
njncda2f0f2009-05-18 02:12:08 +000097 len = sr_Res(res);
njn91772d12009-01-21 02:26:56 +000098 }
99
100 vg_assert('#' == hdr[0] && '!' == hdr[1]);
101
102 end = hdr + len;
103 interp = hdr + 2;
104 while (interp < end && VG_(isspace)(*interp))
105 interp++;
106
107 vg_assert(*interp == '/'); /* absolute path only for interpreter */
108
109 /* skip over interpreter name */
110 for (cp = interp; cp < end && !VG_(isspace)(*cp); cp++)
111 ;
112
113 eol = (*cp == '\n');
114
115 *cp++ = '\0';
116
117 if (!eol && cp < end) {
118 /* skip space before arg */
119 while (cp < end && VG_(isspace)(*cp) && *cp != '\n')
120 cp++;
121
122 /* arg is from here to eol */
123 arg = cp;
124 while (cp < end && *cp != '\n')
125 cp++;
126 *cp = '\0';
127 }
128
129 info->interp_name = VG_(strdup)("ume.ls.1", interp);
130 vg_assert(NULL != info->interp_name);
131 if (arg != NULL && *arg != '\0') {
132 info->interp_args = VG_(strdup)("ume.ls.2", arg);
133 vg_assert(NULL != info->interp_args);
134 }
135
136 if (info->argv && info->argv[0] != NULL)
137 info->argv[0] = (char *)name;
138
139 if (0)
140 VG_(printf)("#! script: interp_name=\"%s\" interp_args=\"%s\"\n",
141 info->interp_name, info->interp_args);
142
143 return VG_(do_exec_inner)(interp, info);
144}
145
146#endif /* defined(HAVE_SCRIPT) */
147
148/*--------------------------------------------------------------------*/
149/*--- end ---*/
150/*--------------------------------------------------------------------*/