Date: Mon, 31 Jan 2005 23:09:19 -0500 From: Garance A Drosihn <drosih@rpi.edu> To: "David G. Lawrence" <dg@dglawrence.com> Cc: freebsd-current@freebsd.org Subject: Re: Bug in #! processing (long reply) Message-ID: <p0620076ebe2490ccdc00@[128.113.24.47]> In-Reply-To: <20041002233542.GL714@nexus.dglawrence.com> References: <200410020349.i923nG8v021675@northstar.hetzel.org> <20041002052856.GE17792@nexus.dglawrence.com> <p0611041fbd848f6aa55d@[128.113.24.47]> <20041002233542.GL714@nexus.dglawrence.com>
next in thread | previous in thread | raw e-mail | index | archive | help
Way back on Oct 02, 2004, David G. Lawrence wrote: >Garance wrote: > > In fact, it seems to be the '--' which is causing the rest of the >> line to be ignored, not the '#'. >> >> The PR is correct in that this feature is documented by perl books, >> but the right way to support the feature is to change /bin/sh and >> not the command interpreter. The PR includes a followup reply from >> Ahmon Dancy <dancy@dancysoft.com> with some additional proof that >> the change to the command interpreter was the wrong way to fix this. >> >> Since this perl feature is documented in many places (including the >> famous "Camel" book from O'Reilly), we can not just drop the support >> in the command interpreter. But if we first fix /bin/sh then I >> believe we can drop it. > > Err, your terminology is a bit off (/bin/sh is the "command >interpreter"); what we're talking about is the behavior of the >execve() system call in the kernel, specifically the imgact_shell >image activation module. When the system sees that a file needs to >be interpreted by something (e.g. sh, perl, python, or some other >language interpreter) it parses the interpreter line specified at >the top of the file (#!/bin/sh) and sets up to invoke that with >the original file as the argument. > > ...but I see what you're saying and I agree with the thought. >The interpreter should decide if the # is a comment, not the kernel. Since the above message, the execve() system call was fixed, but we never changed the behavior of /bin/sh to match. I recently noticed that some of my scripts broke due to this combination, and today one of my friends also mentioned that some of their scripts were broken after they upgraded to the latest 5.3-stable. I remember someone saying that they were going to fix /bin/sh, but I don't remember who, and it looks like I didn't save that email. So I wrote up the following update, and hope to commit it sometime soon. It seems to work fine, but I want to test it a bit after doing some buildworlds on three different platforms. Index: options.c =================================================================== RCS file: /home/ncvs/src/bin/sh/options.c,v retrieving revision 1.21 diff -u -r1.21 options.c --- options.c 6 Apr 2004 20:06:51 -0000 1.21 +++ options.c 1 Feb 2005 01:53:52 -0000 @@ -67,6 +67,7 @@ char *optptr; /* used by nextopt */ char *minusc; /* argument to -c option */ +STATIC int found_eoo; /* found '-' or '--' in the option list */ STATIC void options(int); @@ -82,6 +83,7 @@ void procargs(int argc, char **argv) { + char *ap; int i; argptr = argv; @@ -91,6 +93,23 @@ optlist[i].val = 2; privileged = (getuid() != geteuid() || getgid() != getegid()); options(1); + /* + * If an end-of-options marker ('-' or '--') is followed by an arg + * of '#', then skip over all args after the marker. Some scripting + * languages (e.g.: perl) document that /bin/sh will implement this + * behavior, and they recommend that users take advantage of it to + * solve certain issues that can come up when writing a perl script. + * Yes, this feature is in /bin/sh to help users write perl scripts. + */ + if (found_eoo) { + ap = *argptr; + if (ap != NULL && ap[0] == '#' && ap[1] == '\0') { + while (*argptr != NULL) + argptr++; + /* We need to keep the final argument */ + argptr--; + } + } if (*argptr == NULL && minusc == NULL) sflag = 1; if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1)) @@ -142,6 +161,7 @@ int val; int c; + found_eoo = 0; if (cmdline) minusc = NULL; while ((p = *argptr) != NULL) { @@ -149,6 +169,7 @@ if ((c = *p++) == '-') { val = 1; if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) { + found_eoo = 1; if (!cmdline) { /* "-" means turn off -x and -v */ if (p[0] == '\0') -- Garance Alistair Drosehn = gad@gilead.netel.rpi.edu Senior Systems Programmer or gad@freebsd.org Rensselaer Polytechnic Institute or drosih@rpi.edu
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?p0620076ebe2490ccdc00>