blob: 0a2f48956f86cdacdf008ebeb45273dd42ad07c4 [file] [log] [blame]
florian512f27e2015-07-21 21:37:23 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
njn91772d12009-01-21 02:26:56 +00002
3/*--------------------------------------------------------------------*/
4/*--- User-mode execve() for #! scripts. m_ume_script.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10
Elliott Hughesed398002017-06-21 14:41:24 -070011 Copyright (C) 2000-2017 Julian Seward
njn91772d12009-01-21 02:26:56 +000012 jseward@acm.org
13
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.
18
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.
23
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
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30*/
31
32#include "pub_core_basics.h"
33#include "pub_core_vki.h"
34
35#include "pub_core_libcbase.h"
njn5ec1a172009-05-19 05:52:29 +000036#include "pub_core_libcassert.h" // VG_(exit), vg_assert
njn91772d12009-01-21 02:26:56 +000037#include "pub_core_libcfile.h" // VG_(close) et al
38#include "pub_core_libcprint.h"
florianff4a0842015-04-08 19:01:15 +000039#include "pub_core_clientstate.h" // VG_(args_the_exename)
njn91772d12009-01-21 02:26:56 +000040#include "pub_core_mallocfree.h" // VG_(strdup)
41#include "pub_core_ume.h" // self
42
njn5ec1a172009-05-19 05:52:29 +000043#include "priv_ume.h"
njn91772d12009-01-21 02:26:56 +000044
florian512f27e2015-07-21 21:37:23 +000045/* Return true, if the first line begins with #! and contains an
46 interpreter. */
florianff4a0842015-04-08 19:01:15 +000047Bool VG_(match_script)(const void *hdr, SizeT len)
njn91772d12009-01-21 02:26:56 +000048{
florian0af78ad2012-11-03 18:28:20 +000049 const HChar* script = hdr;
50 const HChar* end = script + len;
51 const HChar* interp = script + 2;
njn91772d12009-01-21 02:26:56 +000052
florian512f27e2015-07-21 21:37:23 +000053 if (len < 2) return False;
njn91772d12009-01-21 02:26:56 +000054 if (0 != VG_(memcmp)(hdr, "#!", 2)) return False;
55
florian512f27e2015-07-21 21:37:23 +000056 // Find interpreter name, which may be absolute or relative.
57 // First, skip over any space between the #! and the start of the
58 // interpreter name
floriane4a4c572015-04-02 16:07:41 +000059 while (interp < end && (*interp == ' ' || *interp == '\t')) interp++;
njn91772d12009-01-21 02:26:56 +000060
61 // overrun?
62 if (interp >= end) return False; // can't find start of interp name
63
florian512f27e2015-07-21 21:37:23 +000064 // No interpreter found.
65 if (*interp == '\n') return False;
njn91772d12009-01-21 02:26:56 +000066
67 return True; // looks like a #! script
68}
69
70
71/* returns: 0 = success, non-0 is failure */
72Int VG_(load_script)(Int fd, const HChar* name, ExeInfo* info)
73{
florian0af78ad2012-11-03 18:28:20 +000074 HChar hdr[4096];
florianff4a0842015-04-08 19:01:15 +000075 Int len = sizeof hdr;
florian0af78ad2012-11-03 18:28:20 +000076 Int eol;
77 HChar* interp;
78 HChar* end;
79 HChar* cp;
80 HChar* arg = NULL;
njn91772d12009-01-21 02:26:56 +000081 SysRes res;
82
83 // Read the first part of the file.
84 res = VG_(pread)(fd, hdr, len, 0);
njncda2f0f2009-05-18 02:12:08 +000085 if (sr_isError(res)) {
njn91772d12009-01-21 02:26:56 +000086 VG_(close)(fd);
87 return VKI_EACCES;
88 } else {
njncda2f0f2009-05-18 02:12:08 +000089 len = sr_Res(res);
njn91772d12009-01-21 02:26:56 +000090 }
91
92 vg_assert('#' == hdr[0] && '!' == hdr[1]);
93
94 end = hdr + len;
95 interp = hdr + 2;
florianff4a0842015-04-08 19:01:15 +000096 while (interp < end && (*interp == ' ' || *interp == '\t'))
njn91772d12009-01-21 02:26:56 +000097 interp++;
98
njn91772d12009-01-21 02:26:56 +000099 /* skip over interpreter name */
100 for (cp = interp; cp < end && !VG_(isspace)(*cp); cp++)
101 ;
102
103 eol = (*cp == '\n');
104
105 *cp++ = '\0';
106
107 if (!eol && cp < end) {
108 /* skip space before arg */
109 while (cp < end && VG_(isspace)(*cp) && *cp != '\n')
110 cp++;
111
112 /* arg is from here to eol */
113 arg = cp;
114 while (cp < end && *cp != '\n')
115 cp++;
116 *cp = '\0';
117 }
Elliott Hughesa0664b92017-04-18 17:46:52 -0700118 VG_(free)(info->interp_name);
njn91772d12009-01-21 02:26:56 +0000119 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);
124 }
125
126 if (info->argv && info->argv[0] != NULL)
florian3e798632012-11-24 19:41:54 +0000127 info->argv[0] = name;
njn91772d12009-01-21 02:26:56 +0000128
tom892af322010-05-25 08:45:44 +0000129 VG_(args_the_exename) = name;
130
njn91772d12009-01-21 02:26:56 +0000131 if (0)
132 VG_(printf)("#! script: interp_name=\"%s\" interp_args=\"%s\"\n",
133 info->interp_name, info->interp_args);
134
135 return VG_(do_exec_inner)(interp, info);
136}
137
njn91772d12009-01-21 02:26:56 +0000138/*--------------------------------------------------------------------*/
139/*--- end ---*/
140/*--------------------------------------------------------------------*/