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>