Subject: The #! shell script patch to winsup
From: [email-masked] (Geoffrey Noer)

28 Jan 1997 01:21:56 -0800
Approved: [email-masked]
Distribution: cygnus
Message-ID: <[email-masked]>
Content-Type: text
Original-To: [email-masked]
X-Mailer: ELM [version 2.4 PL23]
Content-Length: 4297      
Original-Sender: [email-masked]

Here's the patch to spawn.cc that makes #!/usr/local/bin/perl and
other such things work in shell scripts in gnu-win32 since several
people asked for it:

Index: spawn.cc
===================================================================
RCS file: /cvs/cvsfiles/devo/winsup/spawn.cc,v
retrieving revision 1.38
retrieving revision 1.39
diff -c -r1.38 -r1.39
*** spawn.cc	1996/12/03 21:45:49	1.38
--- spawn.cc	1996/12/16 22:54:43	1.39
***************
*** 331,336 ****
--- 331,338 ----
       Perhaps make exec_p a set of flags (e.g. EXEC_SCRIPT, etc.).
       That may simplify some of the following.  */
  
+ check_again:
+ 
    char real_path[MAX_PATH];
    int exec_p;
    if (symlink_follow (prog_arg, real_path, &exec_p) == -1)
***************
*** 368,392 ****
        __seterrno ();
        return;
      }
-   CloseHandle (hnd);
  
-   /* FIXME: Change this to look for #! and invoke the requested shell.  */
    if (done >= 2 && magic[0] != 'M' && magic[1] != 'Z')
      {
!       /* This is a script.. so we'll run bash on it */
        debug_printf ("spawn_guts: %s is a script\n", prog_arg);
  
!       char *sh_path_buf = (char *) alloca (MAX_PATH);
!       char *sh_path = (char *) find_exec ("sh", sh_path_buf);
!       char *f = (char *) alloca (strlen (copy) + strlen (sh_path) + 2);
!       strcpy (f, sh_path);
        strcat (f, " ");
        strcat (f, copy);
        copy = f;
  
        debug_printf ("spawn_guts: copy is now %s\n", copy);
!       prog = sh_path;
!     }
  
    PROCESS_INFORMATION pi = {0};
  
--- 370,450 ----
        __seterrno ();
        return;
      }
  
    if (done >= 2 && magic[0] != 'M' && magic[1] != 'Z')
      {
!       char new_path[MAX_PATH];
!       char *ptr = new_path;
! 
!       /* Check if this is a script.. so we'll run shell on it */
! 
!       if(magic[0] != '#' || magic[1] != '!')
!         /* shell script without magic */
!         strcpy(new_path, "sh");
!       else {
!         /* read name and arguments of desired shell */
!         if (! ReadFile (hnd, new_path, sizeof (new_path), &done, 0)) {
!           CloseHandle (hnd);
!           __seterrno ();
!           return;
!         }
!         CloseHandle (hnd);
!       }
        debug_printf ("spawn_guts: %s is a script\n", prog_arg);
  
!       while(*ptr && *ptr != '\r' && *ptr != '\n')
!         ptr++;
!       *ptr = '\0';
!       /* desired shell may be symlink or contain extra arguments,
!        * so do some magic work...
!        */
!       prog_arg = (char *) alloca (MAX_PATH);
!       char *ptr2 = new_path;
!       while(*ptr2 == ' ' || *ptr2 == '\t')
!         ptr2++;
!       char *ptr1 = ptr2;
!       while(*ptr1 && *ptr1 != ' ' && *ptr1 != '\t')
!         ptr1++;
!       *ptr1 = '\0';
!       /* pointers:
!        * ptr  - end of shell string;
!        * ptr1 - end of shell name;
!        * ptr2 - start of shell name;
!        */ 
!       find_exec(ptr2, (char *) prog_arg);
!       char *f = (char *) alloca(strlen(copy) + strlen(prog_arg) +
!                                 strlen(real_path) + (ptr-ptr1) + 3);
!       strcpy (f, prog_arg);
!       if(ptr1 != ptr) {
!         strcat(f, " ");
!         strcat(f, ptr1+1);
!       }
        strcat (f, " ");
+       /* If script had absolute path, add it to script name now!
+        * This is necessary if script has been found in via PATH.
+        * For example, /usr/local/bin/tkman started as "tkman":
+        * #!/usr/local/bin/wish -f
+        * ...
+        * We should run /usr/local/bin/wish -f /usr/local/bin/tkman,
+        * but not /usr/local/bin/wish -f tkman!
+        * We don't modify anything, if script has qulified path.
+        */
+       for(ptr=f; *ptr; ptr++)
+         ;
+       if(real_path[0] == '/' && copy[0] != '/') {
+         debug_printf ("spawn_guts: getting path of %s\n", real_path);
+         split_path(real_path, ptr, (char *) new_path);
+         debug_printf ("spawn_guts: path is %s\n", ptr);
+         strcat (f, "/");
+       }
        strcat (f, copy);
        copy = f;
  
+       debug_printf ("spawn_guts: prog_arg is %s\n", prog_arg);
        debug_printf ("spawn_guts: copy is now %s\n", copy);
!       goto check_again;
!     } else
!         CloseHandle (hnd);
  
    PROCESS_INFORMATION pi = {0};

-- 
Geoffrey Noer
[email-masked]
-
For help on using this list, send a message to
"[email-masked]" with one line of text: "help".