🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

1 total messages Started by ian Mon, 01 Jan 1990 14:15
Make 3.57 doesn't always execute shell scripts correctly.
#1684
Author: ian
Date: Mon, 01 Jan 1990 14:15
256 lines
7507 bytes
When make attempts to execute a command and it fails with ENOEXEC
(bad magic number) it assumes the command is a shell script and
invokes the shell to intreprete it. Suppose "foo" is a shell script,
and the make file has

blah:
	foo blah

If the shell script doesn't begin with "#!", or is on a system where
"#!" is not supported, then make looks down the path and finds foo
and execs '/usr/local/bin/foo blah'. This fails with ENOEXEC, and
make then tries to exec '/bin/sh -c foo blah'. This is not the right
thing to do.

The -c switch to "/bin/sh" means that the next *string* is interpreted
as the whole command (including arguments). More correct would be to
exec '/bin/sh -c "foo blah"'. This us clumsy to do though because all
the argv[i] have to be concatenated with intervening spaces and
correctly quoting all special characters is a not trivial exercise.
It is better is to drop the "-c". The only problem is that the full
pathname of the script has to be specified. That is, make should exec
'/bin/sh /usr/local/bin/foo blah'. Fortunately the look up of foo in
the path has already been performed. I have rearranged the functional
breakdown of "exec_command" and "child_execute_job" and added a new
function "search_exec_path". The differences follow

*** ../make-3.57-dist/job.c	Wed Oct 25 11:38:09 1989
--- job.c	Tue Jan  2 00:34:33 1990
***************
*** 757,762 ****
--- 757,763 ----
       char **argv, **envp;
  {
    char *path;
+   char *program, *buffer, *search_exec_path();
  
    if (stdin_fd != 0)
      (void) dup2 (stdin_fd, 0);
***************
*** 777,786 ****
    path = allocated_variable_expand_for_file ("$(PATH)", file);
  
    /* Run the command.  */
-   exec_command (argv, envp, path);
  
-   /* If exec_command returned, then we should use the shell.  */
    {
      int argc;
      char **shell_argv;
  
--- 778,810 ----
    path = allocated_variable_expand_for_file ("$(PATH)", file);
  
    /* Run the command.  */
  
    {
+     int len;
+     len = strlen (argv[0]) + 1;
+     buffer = (char *) alloca (strlen (path) + 1 + len);
+   }
+ 
+   if ((program = search_exec_path(argv[0], path, buffer)) == NULL)
+     {
+       error ("%s: Command not found", argv[0]);
+       _exit (127);
+     }
+ 
+   /* Make might be installed set-gid kmem so that the load average
+      code works, so we want to make sure we use the real gid.  */
+   (void) setgid (getgid ());
+ 
+   execve (program, argv, envp);
+ 
+   if (errno != ENOEXEC)
+     {
+       perror_with_name ("execve: ", program);
+       _exit (127);
+     }
+ 
+   /* If execve returned, then we should use the shell.  */
+   {
      int argc;
      char **shell_argv;
  
***************
*** 787,798 ****
      argc = 0;
      while (argv[argc] != 0)
        ++argc;
!     shell_argv = (char **) alloca ((2 + argc + 1) * sizeof (char *));
      shell_argv[0] = variable_expand_for_file ("$(SHELL)", file);
!     shell_argv[1] = "-c";
      do
!       shell_argv[2 + argc] = argv[argc];
!     while (argc-- > 0);
      exec_command (shell_argv, envp, path);
  
      /* If that returned, die.  */
--- 811,822 ----
      argc = 0;
      while (argv[argc] != 0)
        ++argc;
!     shell_argv = (char **) alloca ((1 + argc + 1) * sizeof (char *));
      shell_argv[0] = variable_expand_for_file ("$(SHELL)", file);
!     shell_argv[1] = program;
      do
!       shell_argv[1 + argc] = argv[argc];
!     while (argc-- > 1);
      exec_command (shell_argv, envp, path);
  
      /* If that returned, die.  */
***************
*** 800,818 ****
    }
  }
  
! /* Replace the current process with one running the command
!    in ARGV, with environment ENVP.  The program named in ARGV[0]
!    is searched for in PATH.  This function does not return.  */
  
! void
! exec_command (argv, envp, path)
!      char **argv, **envp;
!      char *path;
  {
    char *program;
  
!   if (*path == '\0' || index (argv[0], '/') != 0)
!     program = argv[0];
    else
      {
        unsigned int len;
--- 824,841 ----
    }
  }
  
! /* Search the PATH for an executable file and return the full path name
!  * for that file. Buffer better be big enough to take the full path name.
!  */
  
! char *
! search_exec_path (command, path, buffer)
!      char *command, *path, *buffer;
  {
    char *program;
  
!   if (*path == '\0' || index (command, '/') != 0)
!     program = command;
    else
      {
        unsigned int len;
***************
*** 825,832 ****
  	ngroups = getgroups (NGROUPS, groups);
  #endif	/* Not USG.  */
  
!       len = strlen (argv[0]) + 1;
!       program = (char *) alloca (strlen (path) + 1 + len);
        do
  	{
  	  struct stat st;
--- 848,855 ----
  	ngroups = getgroups (NGROUPS, groups);
  #endif	/* Not USG.  */
  
!       len = strlen(command) + 1;
!       program = buffer;
        do
  	{
  	  struct stat st;
***************
*** 838,849 ****
  	    p = path + strlen (path);
  
  	  if (p == path)
! 	    bcopy (argv[0], program, len);
  	  else
  	    {
  	      bcopy (path, program, p - path);
  	      program[p - path] = '/';
! 	      bcopy (argv[0], program + (p - path) + 1, len);
  	    }
  
  	  if (stat (program, &st) == 0
--- 861,872 ----
  	    p = path + strlen (path);
  
  	  if (p == path)
! 	    bcopy (command, program, len);
  	  else
  	    {
  	      bcopy (path, program, p - path);
  	      program[p - path] = '/';
! 	      bcopy (command, program + (p - path) + 1, len);
  	    }
  
  	  if (stat (program, &st) == 0
***************
*** 868,884 ****
  		}
  
  	      if (perm != 0)
! 		goto run;
  	    }
  
  	  path = p + 1;
  	} while (*path != '\0');
  
        error ("%s: Command not found", argv[0]);
        _exit (127);
      }
  
-  run:;
    /* Make might be installed set-gid kmem so that the load average
       code works, so we want to make sure we use the real gid.  */
    (void) setgid (getgid ());
--- 891,929 ----
  		}
  
  	      if (perm != 0)
! 		return program;
  	    }
  
  	  path = p + 1;
  	} while (*path != '\0');
+       return NULL;
+     }
+   return program;
+ }
+ 
+ /* Replace the current process with one running the command
+    in ARGV, with environment ENVP.  The program named in ARGV[0]
+    is searched for in PATH.  This function does not return.  */
+ 
+ void
+ exec_command (argv, envp, path)
+      char **argv, **envp;
+      char *path;
+ {
+   char *program, *buffer;
  
+   {
+     int len;
+     len = strlen (argv[0]) + 1;
+     buffer = (char *) alloca (strlen (path) + 1 + len);
+   }
+ 
+   if ((program = search_exec_path(argv[0], path, buffer)) == NULL)
+     {
        error ("%s: Command not found", argv[0]);
        _exit (127);
      }
  
    /* Make might be installed set-gid kmem so that the load average
       code works, so we want to make sure we use the real gid.  */
    (void) setgid (getgid ());
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads