delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1996/09/16/04:53:18

Date: Mon, 16 Sep 1996 11:49:42 +0200 (IST)
From: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
To: djgpp-workers AT delorie DOT com
Subject: Changes for `system' and `dosexec'
Message-Id: <Pine.SUN.3.91.960916114205.21681Q-100000@is>
Mime-Version: 1.0

The changes below take care of a few minor problems:

	- the test for unixy or dos shell is now done in one place, and 
the functions which do that are exported, so these tests are consistent;
	- invoking a v1.x program is always done through !proxy, to 
prevent go32 from printing its copyright line;
	- a couple of executable extensions were added;
	- if the first character if the command line (ater removing the 
redirection constructs) is a left paren `(', the shell is called 
immediately (for the sake of those who use this feature of [4N]DOS);
	- the semi-colon `;' escaping is handled better.

Don't be scared by the size of the diff: most of it is whitespace changes 
(because a block of code was removed, causeing a change in the 
indentation).

------------------------------------------------------------------------
*** src/libc/ansi/stdlib/system.c~8	Sat Sep  7 16:54:38 1996
--- src/libc/ansi/stdlib/system.c	Sun Sep 15 16:38:42 1996
*************** _shell_command (const char *prog, const 
*** 85,178 ****
         the command interpreter and let the user type ``exit''.  */
      return _dos_exec (shell, "", environ);
    }
!   else
    {
!     char *p, *shellbase = shell;
! 
!     for (p = shell; *p; p++)
!       if (*p == ':' || *p == '/' || *p == '\\')
! 	shellbase = p + 1;
  
!     if (!stricmp (shellbase, "command.com")
! 	|| !stricmp (shellbase, "4dos.com")
! 	|| !stricmp (shellbase, "ndos.com"))
      {
!       char *cmd_tail = (char *)alloca (3 + strlen (prog) + 1
! 				       + strlen (cmdline) + 1);
!       const char *s = prog;
!       char *d = cmd_tail + 3;
! 
!       strcpy (cmd_tail, "/c ");
!       while ((*d = *s++) != 0)
!       {
! 	if (*d == '/')
! 	  *d = '\\';
! 	d++;
!       }
  
!       if (*cmdline)
!       {
! 	if (*prog)
! 	  *d++ = ' ';
  
! 	strcpy (d, cmdline);
!       }
  
!       /* [4N]DOS.COM can support upto 255 chars per command line.
! 	 They lose that feature here, because there's no simple
! 	 way to pass long command lines to DOS function 4Bh (Exec)
! 	 which `_dos_exec' summons.  */
!       if (strlen (cmd_tail) > 126)
!       {
! 	errno = E2BIG;
! 	return emiterror ("Command line too long.", 0);
!       }
!       else
! 	return _dos_exec (shell, cmd_tail, environ);
      }
      else
!     {
!       /* Assume this is a `sh' work-alike.  What's below should
! 	 work with `ms_sh'; others should be fine if they support
! 	 the response file method (but I didn't test anything
! 	 except `ms_sh').  */
  
!       FILE *respf;
!       int   e = errno;
!       char *atfile = (char *) alloca (L_tmpnam);
!       char *cmd_tail = (char *)alloca (L_tmpnam + 5);
  
!       errno = 0;
!       respf = fopen (tmpnam (atfile), "wb");
  
!       /* Note that the command line is written to the response file
! 	 as a single (possibly long) line.  The docs of `ms_sh' tells
! 	 that when invoking other programs, it writes each argument
! 	 on a separate line, but the shell itself doesn't seem to
! 	 care when it gets everything as a single line.  */
  
!       if (respf)
!       {
! 	int retval;
  
! 	errno = e;
! 	if (*prog)
! 	{
! 	  fputs (prog, respf);
! 	  fputc (' ', respf);
! 	}
! 	fputs (cmdline, respf);
! 	fputc ('\n', respf);
! 	fclose (respf);
! 	strcpy (cmd_tail, "-c @");
! 	strcat (cmd_tail, atfile);
! 	retval = _dos_exec (shell, cmd_tail, environ);
! 	remove (atfile);
! 	return retval;
        }
!       else
! 	return emiterror ("Cannot open response file for SH", errno);
      }
    }
  }
  
--- 85,167 ----
         the command interpreter and let the user type ``exit''.  */
      return _dos_exec (shell, "", environ);
    }
!   else if (_is_dos_shell (shell))
    {
!     char *cmd_tail = (char *)alloca (3 + strlen (prog) + 1
! 				     + strlen (cmdline) + 1);
!     const char *s = prog;
!     char *d = cmd_tail + 3;
  
!     strcpy (cmd_tail, "/c ");
!     while ((*d = *s++) != 0)
      {
!       if (*d == '/')
! 	*d = '\\';
!       d++;
!     }
  
!     if (*cmdline)
!     {
!       if (*prog)
! 	*d++ = ' ';
  
!       strcpy (d, cmdline);
!     }
  
!     /* [4N]DOS.COM can support upto 255 chars per command line.
!        They lose that feature here, because there's no simple
!        way to pass long command lines to DOS function 4Bh (Exec)
!        which `_dos_exec' summons.  */
!     if (strlen (cmd_tail) > 126)
!     {
!       errno = E2BIG;
!       return emiterror ("Command line too long.", 0);
      }
      else
!       return _dos_exec (shell, cmd_tail, environ);
!   }
!   else
!   {
!     /* Assume this is a `sh' work-alike.  What's below should
!        work with `ms_sh'; others should be fine if they support
!        the response file method (but I didn't test anything
!        except `ms_sh').  */
  
!     FILE *respf;
!     int   e = errno;
!     char *atfile = (char *) alloca (L_tmpnam);
!     char *cmd_tail = (char *)alloca (L_tmpnam + 5);
  
!     errno = 0;
!     respf = fopen (tmpnam (atfile), "wb");
  
!     /* Note that the command line is written to the response file
!        as a single (possibly long) line.  The docs of `ms_sh' tells
!        that when invoking other programs, it writes each argument
!        on a separate line, but the shell itself doesn't seem to
!        care when it gets everything as a single line.  */
  
!     if (respf)
!     {
!       int retval;
  
!       errno = e;
!       if (*prog)
!       {
! 	fputs (prog, respf);
! 	fputc (' ', respf);
        }
!       fputs (cmdline, respf);
!       fputc ('\n', respf);
!       fclose (respf);
!       strcpy (cmd_tail, "-c @");
!       strcat (cmd_tail, atfile);
!       retval = _dos_exec (shell, cmd_tail, environ);
!       remove (atfile);
!       return retval;
      }
+     else
+       return emiterror ("Cannot open response file for SH", errno);
    }
  }
  
*************** __unquote (char *to, const char *beg, co
*** 385,391 ****
  	s++;
  	break;
        case '\\':
! 	if (s[1] == '"' || s[1] == '\'')
  	  s++;
  	/* Fall-through.  */
        default:
--- 374,382 ----
  	s++;
  	break;
        case '\\':
! 	if (s[1] == '"' || s[1] == '\''
! 	    || (s[1] == ';'
! 		&& (__system_flags & __system_allow_multiple_cmds)))
  	  s++;
  	/* Fall-through.  */
        default:
*************** get_sym (char *s, char **beg, char **end
*** 456,462 ****
  	--*end;
  	return EOL;
        case '\\':
! 	if (s[1] == '"' || s[1] == '\'')
  	  s++;
  	in_a_word = 1;
  	break;
--- 447,454 ----
  	--*end;
  	return EOL;
        case '\\':
! 	if (s[1] == '"' || s[1] == '\''
! 	    || (s[1] == ';' && (sys_flags & __system_allow_multiple_cmds)))
  	  s++;
  	in_a_word = 1;
  	break;
*************** system (const char *cmdline)
*** 579,584 ****
--- 571,580 ----
  	  if (needcmd)
  	  {
  	    __unquote (prog, t, u); /* unquote and copy to prog */
+ 	    /* We can't grok commands in parentheses, so assume they
+ 	       use a shell that knows about these, like 4DOS or `sh'.  */
+ 	    if (prog[0] == '(')
+ 	      return _shell_command ("", cmdline);
  	    strcpy (s, u);	  /* remove program name from cmdline */
  	    needcmd = 0;
  	  }
*** src/libc/dos/process/dosexec.c~1	Wed Sep  4 18:54:28 1996
--- src/libc/dos/process/dosexec.c	Sun Sep 15 11:53:34 1996
*************** direct_exec_tail(const char *program, co
*** 188,194 ****
    } else
      progname = program;
  
!   if (!check_talloc(proglen + strlen(args) + 3 + sizeof(Execp) + 32))
      return -1;
    program_la = talloc(proglen);
    arg_la     = talloc(strlen(args)+3);
--- 188,194 ----
    } else
      progname = program;
  
!   if (!check_talloc(proglen + strlen(args) + 3 + sizeof(Execp) + 48))
      return -1;
    program_la = talloc(proglen);
    arg_la     = talloc(strlen(args)+3);
*************** direct_exec_tail(const char *program, co
*** 252,259 ****
    parm_la -= tbuf_beg;
    program_la -= tbuf_beg;
  #endif
-   if (!check_talloc(0))
-     return -1;
  
    /* The environment.  Replace the !proxy variable, if there is
       one (for nested programs) if we are called from `system',
--- 252,257 ----
*************** static const char *unix_shells[] = {
*** 388,412 ****
    0
  };
  
  static int direct_exec(const char *program, char **argv, char **envp)
  {
    int i, arglen;
    char *args, *argp;
    int need_quote = !__dosexec_in_system;
    int unescape_quote = __dosexec_in_system;
-   const char *ptail = program;
- 
-   {
-     const char *p = ptail;
- 
-     while (*p)
-     {
-       if (*p == '/' || *p == ':' || *p == '\\')
- 	ptail = p + 1;
-       p++;
-     }
-   }
- 
  
    /* PROGRAM can be a shell which expects a single argument
       (beyond the /c or -c switch) that is the entire command
--- 386,429 ----
    0
  };
  
+ static int
+ list_member (const char *program, const char *program_list[])
+ {
+   const char *p = program, *ptail = program;
+   int i;
+ 
+   while (*p)
+   {
+     if (*p == '/' || *p == ':' || *p == '\\')
+       ptail = p + 1;
+     p++;
+   }
+ 
+   for (i = 0; program_list[i]; i++)
+     if (!stricmp (ptail, program_list[i]))
+       return 1;
+ 
+   return 0;
+ }
+ 
+ int
+ _is_unixy_shell (const char *shellpath)
+ {
+   return list_member (shellpath, unix_shells);
+ }
+ 
+ int
+ _is_dos_shell (const char *shellpath)
+ {
+   return list_member (shellpath, shell_brokets);
+ }
+ 
  static int direct_exec(const char *program, char **argv, char **envp)
  {
    int i, arglen;
    char *args, *argp;
    int need_quote = !__dosexec_in_system;
    int unescape_quote = __dosexec_in_system;
  
    /* PROGRAM can be a shell which expects a single argument
       (beyond the /c or -c switch) that is the entire command
*************** static int direct_exec(const char *progr
*** 416,444 ****
       The hard problem is to know when PROGRAM names a shell
       that doesn't like its command line quoted...  */
  
!   if (need_quote && argv[1] && !strcmp (argv[1], "/c") && argv[2] && !argv[3])
!   {
!     for (i = 0; shell_brokets[i]; i++)
!     {
!       if (!stricmp (ptail, shell_brokets[i]))
!       {
! 	need_quote = 0;
! 	break;
!       }
!     }
!   }
  
!   if (unescape_quote)
!   {
!     for (i = 0; unix_shells[i]; i++)
!     {
!       if (!stricmp (ptail, unix_shells[i]))
!       {
! 	unescape_quote = 0;
! 	break;
!       }
!     }
!   }
  
    arglen = 0;
    for (i=1; argv[i]; i++)
--- 433,446 ----
       The hard problem is to know when PROGRAM names a shell
       that doesn't like its command line quoted...  */
  
!   if (need_quote
!       && argv[1] && !strcmp (argv[1], "/c")
!       && argv[2] && !argv[3]
!       && _is_dos_shell (program))
!     need_quote = 0;
  
!   if (unescape_quote && _is_unixy_shell (program))
!     unescape_quote = 0;
  
    arglen = 0;
    for (i=1; argv[i]; i++)
*************** static int go32_exec(const char *program
*** 631,640 ****
    /* Construct the DOS command tail */
    for (argc=0; argv[argc]; argc++);
  
!   if (__dosexec_in_system)
    {
!     /* If PROGRAM is an un-stubbed COFF, it must be passed in the
!        command tail as well, since we call GO32 to run it.  */
      for (i = (is_stubbed ? 1 : 0); i < argc; i++)
      {
        const char *p = argv[i];
--- 633,642 ----
    /* Construct the DOS command tail */
    for (argc=0; argv[argc]; argc++);
  
!   if (__dosexec_in_system && v2_0)
    {
!     /* If PROGRAM is an un-stubbed COFF, its name must be passed
!        in the command tail as well, since we call GO32 to run it.  */
      for (i = (is_stubbed ? 1 : 0); i < argc; i++)
      {
        const char *p = argv[i];
*************** static int go32_exec(const char *program
*** 660,667 ****
    tbuf_end = tbuf_ptr + tbuf_len - 1;
  
    /* If called from `system' and we have a command line shorter
!      than the DOS limit, we don't need to use !proxy at all.  */
!   if (!__dosexec_in_system || cmdp - cmdline > CMDLEN_LIMIT)
    {
      if (!check_talloc(found_si ?
  		      si.struct_length : 0
--- 662,671 ----
    tbuf_end = tbuf_ptr + tbuf_len - 1;
  
    /* If called from `system' and we have a command line shorter
!      than the DOS limit, we don't need to use !proxy at all.
!      Note that v1.x programs are always run through !proxy,
!      to prevent go32.exe from printing its copyright line. */
!   if (!__dosexec_in_system || !v2_0 || cmdp - cmdline > CMDLEN_LIMIT)
    {
      if (!check_talloc(found_si ?
  		      si.struct_length : 0
*************** static struct {
*** 941,946 ****
--- 945,952 ----
    { ".btm", __dosexec_command_exec },
    { ".sh",  script_exec },  /* for compatibility with ms_sh */
    { ".ksh", script_exec },
+   { ".pl", script_exec },   /* Perl */
+   { ".sed", script_exec },
    { "",     go32_exec },
    { 0,      script_exec },  /* every extension not mentioned above calls it */
    { 0,      0 },
*************** __dosexec_find_on_path(const char *progr
*** 1003,1009 ****
        }
      }
  
!   if (haspath)
      return 0;
    *rp = 0;
  
--- 1009,1015 ----
        }
      }
  
!   if (haspath || !envp)
      return 0;
    *rp = 0;
  
*** include/stdlib.h~2	Fri Aug 30 19:57:42 1996
--- include/stdlib.h	Fri Sep 13 18:27:24 1996
*************** void *		xrealloc(void *ptr, size_t _size
*** 108,114 ****
  
  extern int __system_flags;
  
! extern int _shell_command (const char *_prog, const char *_cmdline);
  
  #endif /* !_POSIX_SOURCE */
  #endif /* !__STRICT_ANSI__ */
--- 108,116 ----
  
  extern int __system_flags;
  
! extern int _shell_command  (const char *_prog, const char *_cmdline);
! extern int _is_unixy_shell (const char *_prog);
! extern int _is_dos_shell   (const char *_prog);
  
  #endif /* !_POSIX_SOURCE */
  #endif /* !__STRICT_ANSI__ */

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019