Date: Tue, 24 Sep 1996 14:22:05 +0200 (IST) From: Eli Zaretskii To: djgpp-workers AT delorie DOT com Subject: `system' and unixy shells Message-Id: Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII The following changes cause `system' to immediately call the shell if $SHELL or $COMSPEC point to a program whose name is known to be a unixy shell. They also change the way such shells are called (the previous method broke the ``here document'' feature of the shell). *** src/libc/ansi/stdlib/system.c~9 Sun Sep 15 16:38:42 1996 --- src/libc/ansi/stdlib/system.c Sun Sep 22 14:14:28 1996 *************** *** 122,146 **** } 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; --- 122,143 ---- } else { ! /* Assume this is a `sh' work-alike which can be invoked like ! this: ! sh file + where `file' holds the entire command line. + + (Another possibility is a response file, but that breaks the + ``here document'' feature of the shell.) */ FILE *respf; int e = errno; char *atfile = (char *) alloca (L_tmpnam); ! char *cmd_tail = (char *)alloca (L_tmpnam + 1); errno = 0; respf = fopen (tmpnam (atfile), "wb"); if (respf) { int retval; *************** *** 154,167 **** 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); } } --- 151,164 ---- fputs (cmdline, respf); fputc ('\n', respf); fclose (respf); ! strcpy (cmd_tail, " "); strcat (cmd_tail, atfile); retval = _dos_exec (shell, cmd_tail, environ); remove (atfile); return retval; } else ! return emiterror ("Cannot open script file for $SHELL", errno); } } *************** *** 485,502 **** { /* Set the feature bits for this run: either from the environment or from global variable. */ ! const char *p = getenv ("DJSYSFLAGS"); sys_flags = __system_flags; ! if (p && *p) { char *stop; ! long flags = strtol (p, &stop, 0); if (*stop == '\0') sys_flags = flags; } /* Special case: NULL means just exec the command interpreter. */ if (cmdline == 0) cmdline = ""; --- 482,506 ---- { /* Set the feature bits for this run: either from the environment or from global variable. */ ! const char *envflags = getenv ("DJSYSFLAGS"); ! const char *comspec = getenv ("COMSPEC"); ! const char *shell = 0; sys_flags = __system_flags; ! if (envflags && *envflags) { char *stop; ! long flags = strtol (envflags, &stop, 0); if (*stop == '\0') sys_flags = flags; } + if (sys_flags & __system_use_shell) + shell = getenv ("SHELL"); + if (!shell) + shell = comspec; + /* Special case: NULL means just exec the command interpreter. */ if (cmdline == 0) cmdline = ""; *************** *** 506,513 **** while (isspace(*cmdline)) cmdline++; ! /* If they want to always do it via command processor, comply. */ ! if (!*cmdline || (sys_flags & __system_call_cmdproc)) return _shell_command ("", cmdline); else { --- 510,525 ---- while (isspace(*cmdline)) cmdline++; ! /* Call the shell if: ! ! the command line is empty ! or ! they want to always do it via command processor ! or ! $SHELL or $COMSPEC point to a unixy shell */ ! if (!*cmdline ! || (sys_flags & __system_call_cmdproc) ! || (!(sys_flags & __system_emulate_command) && _is_unixy_shell (shell))) return _shell_command ("", cmdline); else { *************** *** 572,578 **** { __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 */ --- 584,593 ---- { __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'. ! ! FIXME: if the parenthesized group is NOT the first command ! in a pipe, the commands that preceed it will be run twice. */ if (prog[0] == '(') return _shell_command ("", cmdline); strcpy (s, u); /* remove program name from cmdline */ *** include/stdlib.h~3 Fri Sep 13 18:27:24 1996 --- include/stdlib.h Sun Sep 22 11:53:56 1996 *************** *** 102,107 **** --- 102,108 ---- #define __system_use_shell 0x0004 /* use $SHELL if set */ #define __system_allow_multiple_cmds 0x0008 /* allow `cmd1; cmd2; ...' */ #define __system_allow_long_cmds 0x0010 /* handle commands > 126 chars */ + #define __system_emulate_command 0x0020 /* try to emulate the shell */ #define __system_handle_null_commands 0x1000 /* ignore cmds with no effect */ #define __system_ignore_chdir 0x2000 /* make `cd' be a null command */ #define __system_emulate_chdir 0x4000 /* handle `cd' internally */ *** src/libc/ansi/stdlib/system.t~2 Sat Aug 31 18:56:10 1996 --- src/libc/ansi/stdlib/system.txh Mon Sep 23 18:06:08 1996 *************** *** 86,91 **** --- 86,99 ---- detect early that the command line is longer than 126 characters and refuse to run it. + @item __system_emulate_command + If reset (the default), @code{system} will pass the entire command line + to the shell if its name is one of the following: @file{sh.exe}, + @file{sh16.exe}, @file{sh32.exe}, @file{bash.exe}, @file{tcsh.exe}. + When set, @code{system} will attempt to emulate redirection and pipes + internally, even if @samp{COMSPEC} or @samp{SHELL} point to a Unix-style + shell. + @item __system_handle_null_commands When set (the default), commands internal to @file{COMMAND.COM} and compatible shells which have no effect in the context of @code{system},