diff --git a/check.t b/check.t index 50fe0c7..75468c8 100644 --- a/check.t +++ b/check.t @@ -1,4 +1,4 @@ -# $MirOS: src/bin/mksh/check.t,v 1.96 2007/04/15 10:58:55 tg Exp $ +# $MirOS: src/bin/mksh/check.t,v 1.97 2007/04/15 12:09:56 tg Exp $ # $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $ @@ -7,7 +7,7 @@ # http://www.research.att.com/~gsf/public/ifs.sh expected-stdout: - @(#)MIRBSD KSH R29 2007/03/14 + @(#)MIRBSD KSH R29 2007/04/15 description: Check version of shell. category: pdksh @@ -3931,6 +3931,7 @@ expected-stdout: name: utf8bom-2 description: Check that we can execute BOM-shebangs + XXX if the OS can already execute them, we lose category: pdksh env-setup: !FOO=BAR! stdin: @@ -3939,8 +3940,6 @@ stdin: print '#!/usr/bin/env perl\nprint "a=$ENV{FOO}\n";' >t3 print '#!/usr/bin/env perl\nprint "a=$ENV{FOO}\n";' >t4 chmod +x t? - EXECSHELL=$0 - export EXECSHELL ./t1 ./t2 ./t3 diff --git a/exec.c b/exec.c index c3f209a..cc6274e 100644 --- a/exec.c +++ b/exec.c @@ -2,7 +2,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.26 2007/03/04 03:04:24 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.27 2007/04/15 12:09:57 tg Exp $"); static int comexec(struct op *, struct tbl *volatile, const char **, int volatile); @@ -674,6 +674,9 @@ static void scriptexec(struct op *tp, const char **ap) { const char *sh; + unsigned char *cp; + char buf[64]; /* 64 == MAXINTERP in MirBSD */ + int fd; union mksh_ccphack args, cap; sh = str_val(global("EXECSHELL")); @@ -683,6 +686,55 @@ scriptexec(struct op *tp, const char **ap) sh = "/bin/sh"; *tp->args-- = tp->str; + + if ((fd = open(tp->str, O_RDONLY)) >= 0) { + /* read first MAXINTERP octets from file */ + if (read(fd, buf, sizeof (buf)) <= 0) + /* read error -> no good */ + buf[0] = '\0'; + close(fd); + /* scan for newline or NUL _before_ end of buffer */ + cp = (unsigned char *)buf; + while ((char *)cp < (buf + sizeof (buf))) + if (*cp == '\0' || *cp == '\n') { + *cp = '\0'; + break; + } else + ++cp; + /* if the shebang line is longer than MAXINTERP, bail out */ + if ((char *)cp >= (buf + sizeof (buf))) + goto noshebang; + /* skip UTF-8 Byte Order Mark, if present */ + cp = (unsigned char *)buf; + if ((cp[0] == 0xEF) && (cp[1] == 0xBB) && (cp[2] == 0xBF)) + cp += 3; + /* bail out if read error (above) or no shebang */ + if ((cp[0] != '#') || (cp[1] != '!')) + goto noshebang; + cp += 2; + /* skip whitespace before shell name */ + while (*cp == ' ' || *cp == '\t') + ++cp; + /* just whitespace on the line? */ + if (*cp == '\0') + goto noshebang; + /* no, we actually found an interpreter name */ + sh = (char *)cp; + /* look for end of shell/interpreter name */ + while (*cp != ' ' && *cp != '\t' && *cp != '\0') + ++cp; + /* any arguments? */ + if (*cp) { + *cp++ = '\0'; + /* skip spaces before arguments */ + while (*cp == ' ' || *cp == '\t') + ++cp; + /* pass it all in ONE argument (historic reasons) */ + if (*cp) + *tp->args-- = (char *)cp; + } + } + noshebang: args.ro = tp->args; *args.ro = sh; diff --git a/sh.h b/sh.h index 5b2a1e7..626d31c 100644 --- a/sh.h +++ b/sh.h @@ -8,8 +8,8 @@ /* $OpenBSD: c_test.h,v 1.4 2004/12/20 11:34:26 otto Exp $ */ /* $OpenBSD: tty.h,v 1.5 2004/12/20 11:34:26 otto Exp $ */ -#define MKSH_SH_H_ID "$MirOS: src/bin/mksh/sh.h,v 1.122 2007/04/15 10:45:59 tg Exp $" -#define MKSH_VERSION "R29 2007/03/14" +#define MKSH_SH_H_ID "$MirOS: src/bin/mksh/sh.h,v 1.123 2007/04/15 12:09:57 tg Exp $" +#define MKSH_VERSION "R29 2007/04/15" #if HAVE_SYS_PARAM_H #include