Subject: Re: a suggestion for improving shell behaviour....
To: NetBSD Userlevel Technical Discussion List <tech-userlevel@netbsd.org>
From: Greg A. Woods <woods@most.weird.com>
List: tech-userlevel
Date: 02/18/1999 23:45:54
[ On Thursday, February 18, 1999 at 13:46:38 (-0800), Erik E. Fair wrote: ]
> Subject: Re: a suggestion for improving shell behaviour....
>
> Given this state of affairs, the code in each shell to recognize scripts
> should be excised, and they should simply execve(2) commands, as originally
> intended. Scripts without the interpreter magic will fail, the kernel will
> not exec binaries for the wrong architectures, and all will be well.
I was half way through writing this myself but I relented for reasons
that I don't really have an explanation for (I guess I'm still dreaming
about those days before csh came along and made my life difficult! ;-).
As greywolf points out, BSD's csh has included a patch (that the source
claims is from Casper Dik) ever since at least 4.3net2 which does mostly
what Erik suggests, though it still does a simple-minded test to be sure
that the file doesn't appear to be a script that was simply missing the
"#!" magic.
I think I'd be happy enough with having a similar test in sh and ksh.
Looking at src/bin/sh/exec.c, which leads back to src/bin/sh/main.c, I
see quite a mess to clean up if one's to get our /bin/sh to do this.
Something like Casper's patch for csh applies to the NetBSD /bin/ksh
fairly easily though (and yes, I even tested this change!):
Index: exec.c
===================================================================
RCS file: /cvs/NetBSD/src/bin/ksh/exec.c,v
retrieving revision 1.1.1.2
diff -c -r1.1.1.2 exec.c
*** exec.c 1998/11/16 19:19:10 1.1.1.2
--- exec.c 1999/02/19 04:43:41
***************
*** 419,428 ****
restoresigs();
cleanup_proc_env();
ksh_execve(t->str, t->args, ap);
! if (errno == ENOEXEC)
scriptexec(t, ap);
! else
! errorf("%s: %s", s, strerror(errno));
}
Break:
exstat = rv;
--- 419,448 ----
restoresigs();
cleanup_proc_env();
ksh_execve(t->str, t->args, ap);
! if (errno == ENOEXEC) {
! int err = errno;
! int fd;
! char c;
!
! if ((fd = open(t->str, O_RDONLY)) == -1) {
! errorf("%s: cannot open %s: %s", s, t->str, strerror(errno));
! break;
! }
! if (read(fd, (char *) &c, 1) != 1) {
! (void) close(fd);
! errorf("%s: cannot read %s: %s", s, t->str, strerror(errno));
! break;
! }
! (void) close(fd);
! errno = err;
! if (!isprint(c) && c != '\n' && c != '\t') {
! errorf("%s: %s: %s", s, t->str, strerror(errno));
! break;
! }
scriptexec(t, ap);
! } else
! errorf("%s: %s: %s", s, t->str, strerror(errno));
! break;
}
Break:
exstat = rv;
--
Greg A. Woods
+1 416 218-0098 VE3TCP <gwoods@acm.org> <robohack!woods>
Planix, Inc. <woods@planix.com>; Secrets of the Weird <woods@weird.com>