diff options
author | Roland McGrath <roland@gnu.org> | 2000-03-13 07:09:36 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2000-03-13 07:09:36 +0000 |
commit | 5471f96e2f27924f2e55e379f4a6159e45a12a32 (patch) | |
tree | 090fa3938b35627144ba6ae57467de045af5e799 | |
parent | 63c2d86136db34b607ade96974565ed7d70532d6 (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.c | 63 | ||||
-rw-r--r-- | exec/priv.h | 17 |
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, |