kern/50526: Update to #! line termination

Phil Pennock pdp at nl.demon.net
Tue Apr 1 07:10:13 PST 2003


>Number:         50526
>Category:       kern
>Synopsis:       Update to #! line termination
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Apr 01 07:10:11 PST 2003
>Closed-Date:
>Last-Modified:
>Originator:     Phil Pennock
>Release:        FreeBSD 4.7-RELEASE-p6 i386
>Organization:
THUS Plc (Demon Internet Netherlands)
>Environment:
System: FreeBSD samhain.noc.nl.demon.net 4.7-RELEASE-p6 FreeBSD 4.7-RELEASE-p6 #0: Mon Feb 24 13:28:19 GMT 2003 root at samhain.noc.nl.demon.net:/usr/src/sys/compile/SAMHAIN i386
>Description:
With modern scripting languages, \r is treated as insignificant whitespace.
Much grief can be avoided, and Support Dept time saved, by ensuring that this
holds throughout an entire script, including the #! line.

This is the primary purpose of supplying the patch below, with the code in
the "#ifndef IMGACT_SHELL_DISALLOW_TRAILING_CR" section.  \r is treated as
end-of-line for #! interpretation.  Suddenly a lot of issues disappear.  I
don't think that any historical behaviour is negatively impacted by this
(and we've been using this patch for a long time now).

The patch also "fixes" another problem, but that's more contentious and very
possibly something which you'll reject: the #! line shouldn't be split by
whitespace, and it breaks some common idioms, such as "-*- perl -*-" for
Emacs-users.  We've had customers complain that this didn't work, but worked
on other ISPs' webservers, so we modify the FreeBSD kernel to use the
historical behaviour (one complete line); this has been in operation without
problems for a long time (but not as long).  This is the code protected by
the "#ifndef IMGACT_SHELL_SPLIT_BY_WHITESPACE" in the patch below.
>How-To-Repeat:
Write script on platform with MS-DOS semantics, upload to FreeBSD web-server
without any newline translation.
>Fix:
This applies against FreeBSD 4.x.

--- imgact_shell.c.old	Tue Apr 16 16:11:18 2002
+++ imgact_shell.c	Tue Apr 16 19:28:30 2002
@@ -72,7 +72,14 @@
 	/*
 	 * Find end of line; return if the line > MAXSHELLCMDLEN long.
 	 */
-	for (ihp = &image_header[2]; *ihp != '\n' && *ihp != '#'; ++ihp) {
+#ifndef IMGACT_SHELL_DISALLOW_TRAILING_CR
+	for (	ihp = &image_header[2];
+		*ihp != '\n' && *ihp != '\r' && *ihp != '#';
+		++ihp)
+#else
+	for (ihp = &image_header[2]; *ihp != '\n' && *ihp != '#'; ++ihp)
+#endif
+	{
 		if (ihp >= &image_header[MAXSHELLCMDLEN])
 			return(ENAMETOOLONG);
 	}
@@ -94,6 +101,45 @@
 	if (*imgp->interpreter_name == '\0')
 		return(ENOEXEC);
 
+#ifndef IMGACT_SHELL_SPLIT_BY_WHITESPACE
+
+	/*
+	 * Collect the shell argument.  Everything after the shell name is
+	 * passed as ONE argument; that's the correct (historical) behaviour.
+	 * Example breakage: perl -opts -*- perl -*-
+	 *
+	 * Given foo.ext starting:
+	 *  #! /bin/interp foo bar   wibble
+	 * want:
+	 *  argv[0] = "/bin/interp"
+	 *  argv[1] = "foo bar   wibble"
+	 *  argv[2] = "foo.ext" (modified with path invoked by)
+	 *  argv[3] = NULL
+	 */
+	interp = imgp->interpreter_name;
+	while (*interp != '\0') {
+		*imgp->stringp++ = *interp++;
+		imgp->stringspace--;
+	}
+	*imgp->stringp++ = '\0';
+	imgp->stringspace--;
+	imgp->argc++;
+
+	/* Skip leading spaces */
+	while ((ihp < line_endp) && ((*ihp == ' ') || (*ihp == '\t'))) ++ihp;
+
+	if (ihp < line_endp) {
+		while (ihp < line_endp) {
+			*imgp->stringp++ = *ihp++;
+			imgp->stringspace--;
+		}
+		*imgp->stringp++ = 0;
+		imgp->stringspace--;
+		imgp->argc++;
+	}
+
+#else
+
 	/* reset for another pass */
 	ihp = &image_header[2];
 
@@ -108,6 +154,7 @@
 			 *	because this is at the front of the string buffer
 			 *	and the maximum shell command length is tiny.
 			 */
+
 			while ((ihp < line_endp) && (*ihp != ' ') && (*ihp != '\t')) {
 				*imgp->stringp++ = *ihp++;
 				imgp->stringspace--;
@@ -119,6 +166,8 @@
 			imgp->argc++;
 		}
 	}
+
+#endif
 
 	imgp->argv0 = imgp->uap->fname;
 
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list