summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2000-03-13 07:09:36 +0000
committerRoland McGrath <roland@gnu.org>2000-03-13 07:09:36 +0000
commit5471f96e2f27924f2e55e379f4a6159e45a12a32 (patch)
tree090fa3938b35627144ba6ae57467de045af5e799
parent63c2d86136db34b607ade96974565ed7d70532d6 (diff)
2000-03-13 Roland McGrath <roland@baalperazim.frob.com>
* exec.c (map): Made global. * priv.h: Declare it. (map_fsize, map_vsize): New macros for accessing state set up by map. * hashexec.c (check_hashbang): Use map and copying operations rather than stdio to extract the first line from the file. Move finish call to immediately after reading the line.
-rw-r--r--exec/hashexec.c63
-rw-r--r--exec/priv.h17
2 files changed, 50 insertions, 30 deletions
diff --git a/exec/hashexec.c b/exec/hashexec.c
index 15d67f51..96677088 100644
--- a/exec/hashexec.c
+++ b/exec/hashexec.c
@@ -22,6 +22,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <hurd/sigpreempt.h>
#include <unistd.h>
#include <envz.h>
+#include <sys/param.h>
/* This is called to check E for a #! interpreter specification. E has
already been prepared (successfully) and checked (unsuccessfully). If
@@ -42,13 +43,10 @@ check_hashbang (struct execdata *e,
mach_port_t *deallocnames, u_int ndeallocnames,
mach_port_t *destroynames, u_int ndestroynames)
{
- char *ibuf = NULL;
- size_t ibufsiz = 0;
char *p;
char *interp, *arg; /* Interpreter file name, and first argument */
size_t interp_len, len;
file_t interp_file; /* Port open on the interpreter file. */
- FILE *f = &e->stream;
char *new_argv;
size_t new_argvlen;
mach_port_t *new_dtable = NULL;
@@ -126,41 +124,56 @@ check_hashbang (struct execdata *e,
name, flags, 0, result);
}
- rewind (f);
+ const char *page = map (e, 0, 2);
+ char interp_buf[vm_page_size - 2 + 1];
- /* Check for our ``magic number''--"#!". */
+ if (!page)
+ {
+ e->error = errno;
+ return;
+ }
- errno = 0;
- if (getc (f) != '#' || getc (f) != '!')
+ /* Check for our ``magic number''--"#!". */
+ if (page[0] != '#' || page[1] != '!')
{
- /* No `#!' here. If there was a read error (not including EOF),
- return that error indication. Otherwise return ENOEXEC to
- say it's not a file we know how to execute. */
- e->error = ferror (f) ? errno : ENOEXEC;
+ /* These are not the droids we're looking for. */
+ e->error = ENOEXEC;
return;
}
- /* Read the rest of the first line of the file. */
+ /* Read the rest of the first line of the file.
+ We in fact impose an arbitrary limit of about a page on this. */
- interp_len = getline (&ibuf, &ibufsiz, f);
- if (ferror (f))
+ p = memccpy (interp_buf, page + 2, '\n',
+ MIN (map_fsize (e) - 2, sizeof interp_buf));
+ if (p == NULL)
{
- e->error = errno ?: EIO;
- return;
+ /* The first line went on for more than sizeof INTERP_BUF! */
+ interp_len = sizeof interp_buf - 1;
+ interp_buf[interp_len] = '\0';
+ }
+ else
+ {
+ *--p = '\0'; /* Kill the newline. */
+ interp_len = p - interp_buf;
}
- if (ibuf[interp_len - 1] == '\n')
- ibuf[--interp_len] = '\0';
+
+ /* We are now done reading the script file. */
+ finish (e, 0);
+
/* Find the name of the interpreter. */
- p = ibuf + strspn (ibuf, " \t");
+ p = interp_buf;
+ p += strspn (p, " \t");
interp = strsep (&p, " \t");
if (p)
{
/* Skip remaining blanks, and the rest of the line is the argument. */
- p += strspn (p, " \t");
- arg = p;
- len = interp_len - (arg - ibuf);
+
+ arg = p + strspn (p, " \t");
+ len = interp_len - (arg - interp_buf);
+ interp_len = p - interp;
if (len == 0)
arg = NULL;
@@ -180,8 +193,6 @@ check_hashbang (struct execdata *e,
len = 0;
}
- interp_len = strlen (interp) + 1;
-
user_crdir = user_cwdir = MACH_PORT_NULL;
rwlock_reader_lock (&std_lock);
@@ -380,10 +391,6 @@ check_hashbang (struct execdata *e,
&setup_args, &fault_handler);
}
- /* We are now done reading the script file. */
- finish (e, 0);
- free (ibuf);
-
rwlock_reader_unlock (&std_lock);
if (user_crdir != MACH_PORT_NULL)
diff --git a/exec/priv.h b/exec/priv.h
index f6889b32..75a350f1 100644
--- a/exec/priv.h
+++ b/exec/priv.h
@@ -1,5 +1,5 @@
/* GNU Hurd standard exec server, private declarations.
- Copyright (C) 1992, 1993, 1994, 1995, 1996, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1992,93,94,95,96,99,2000 Free Software Foundation, Inc.
Written by Roland McGrath.
This file is part of the GNU Hurd.
@@ -85,12 +85,19 @@ struct execdata
/* Set by check. */
vm_address_t entry;
- FILE stream;
file_t file;
+#ifdef _STDIO_USES_IOSTREAM
+#else
+ FILE stream;
+#define map_fsize(e) ((e)->stream.__get_limit - (e)->stream.__buffer)
+#define map_vsize(e) ((e)->stream.__bufsize)
+#endif
+
#ifdef BFD
bfd *bfd;
#endif
+
union /* Interpreter section giving name of file. */
{
asection *section;
@@ -128,6 +135,12 @@ error_t elf_machine_matches_host (Elf32_Half e_machine);
void finish (struct execdata *, int dealloc_file_port);
+/* Make sure our mapping window (or read buffer) covers
+ LEN bytes of the file starting at POSN. */
+void *map (struct execdata *e, off_t posn, size_t len);
+
+
+
void check_hashbang (struct execdata *e,
file_t file,
task_t oldtask,