Mail Archives: djgpp-workers/1999/09/05/01:22:30
Hi folks,
Today I decided to try and see if I could get DJGPP to understand and generate Win 9X
style long command lines. I didn't take too much work to get things working with my
sample Win32 console programs. I know even if the changes are accepted they won't make
DJGPP 2.03, so I list a first draft of the patch below in case anyone has any comments
and to see if I should bother cleaning them up.
*** dosexec.c.orig Tue Jun 29 11:50:10 1999
--- dosexec.c Sat Sep 4 21:06:22 1999
*************** extern size_t __PROXY_LEN;
*** 148,154 ****
transfer buffer will be overrun! */
static int
direct_exec_tail(const char *program, const char *args,
! char * const envp[], const char *proxy, int lfn)
{
__dpmi_regs r;
unsigned long program_la;
--- 148,155 ----
transfer buffer will be overrun! */
static int
direct_exec_tail(const char *program, const char *args,
! char * const envp[], const char *proxy,
! int lfn, int using_cmdline_var)
{
__dpmi_regs r;
unsigned long program_la;
*************** direct_exec_tail(const char *program, co
*** 206,213 ****
dosmemput(progname, proglen, program_la);
/* The command-line tail. */
! arg_header[0] = strlen(args);
arg_header[1] = '\r';
dosmemput(arg_header, 1, arg_la);
dosmemput(args, strlen(args), arg_la+1);
dosmemput(arg_header+1, 1, arg_la+1+strlen(args));
--- 207,215 ----
dosmemput(progname, proglen, program_la);
/* The command-line tail. */
! arg_header[0] = (!using_cmdline_var) ? strlen(args) : 127;
arg_header[1] = '\r';
+
dosmemput(arg_header, 1, arg_la);
dosmemput(args, strlen(args), arg_la+1);
dosmemput(arg_header+1, 1, arg_la+1+strlen(args));
*************** _dos_exec(const char *program, const cha
*** 369,375 ****
tbuf_beg = tbuf_ptr = __tb;
tbuf_len = _go32_info_block.size_of_transfer_buffer;
tbuf_end = tbuf_beg + tbuf_len - 1;
! return direct_exec_tail(program, args, envp, 0, 2);
}
static char GO32_V2_STRING[] = "go32-v2.exe";
--- 371,377 ----
tbuf_beg = tbuf_ptr = __tb;
tbuf_len = _go32_info_block.size_of_transfer_buffer;
tbuf_end = tbuf_beg + tbuf_len - 1;
! return direct_exec_tail(program, args, envp, 0, 2, 0);
}
static char GO32_V2_STRING[] = "go32-v2.exe";
*************** static int direct_exec(const char *progr
*** 436,441 ****
--- 438,444 ----
char *args, *argp;
int need_quote = !__dosexec_in_system;
int unescape_quote = __dosexec_in_system;
+ int using_cmdline_var = 0;
/* 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
*** 458,464 ****
for (i=1; argv[i]; i++)
arglen += 2*strlen(argv[i]) + 1 + 2;
! args = (char *)alloca(arglen+1);
argp = args;
for (i=1; argv[i]; i++)
{
--- 461,471 ----
for (i=1; argv[i]; i++)
arglen += 2*strlen(argv[i]) + 1 + 2;
! #if 0
! args = (char *)alloca(arglen + 1);
! #else
! args = (char *)alloca((arglen <= CMDLEN_LIMIT) ? (arglen + 1) : (CMDLEN_LIMIT + 1));
! #endif
argp = args;
for (i=1; argv[i]; i++)
{
*************** static int direct_exec(const char *progr
*** 503,514 ****
*argp = 0;
if (argp - args > CMDLEN_LIMIT)
errno = E2BIG;
tbuf_beg = tbuf_ptr = __tb;
tbuf_len = _go32_info_block.size_of_transfer_buffer;
tbuf_end = tbuf_beg + tbuf_len - 1;
! return direct_exec_tail(program, args, envp, 0, 2);
}
static int go32_exec(const char *program, char **argv, char **envp)
--- 510,570 ----
*argp = 0;
if (argp - args > CMDLEN_LIMIT)
+ #if 0
errno = E2BIG;
+ #else
+ {
+ /* The command line is too long to pass directly. Put the entire
+ contents of the command line into the CMDLINE variable and
+ set the command line length to 127 in direct_exec_tail.
+ This method is understood by 32-bit Windows and 4DOS.
+ Others will just get the truncated command line. */
+
+ const char cmdline_str[] = "CMDLINE=";
+ const int cmdline_str_size = sizeof(cmdline_str) - 1;
+
+ char *cmdline = alloca(arglen + 1);
+
+ argp = cmdline;
+ strcpy(cmdline, cmdline_str);
+ argp += cmdline_str_size;
+ strcpy(argp, program);
+ argp += strlen(program);
+
+ /* Build up a command line in a manner very similiar to
+ the method above. */
+ for (i = 1; argv[i]; i++)
+ {
+ int quoted = 0;
+ const char *p = argv[i];
+
+ *argp++ = ' ';
+ if (need_quote && strpbrk(p, " \t") != 0)
+ {
+ *argp++ = '"';
+ quoted = 1;
+ }
+ while (*p)
+ {
+ if (*p == '"' && (quoted || need_quote))
+ *argp++ = '\\';
+ else if (*p == '\\' && p[1] == '\'' && unescape_quote)
+ p++;
+ *argp++ = *p++;
+ }
+ if (quoted)
+ *argp++ = '"';
+ }
+ *argp = 0;
+ putenv(cmdline);
+ using_cmdline_var = 1;
+ }
+ #endif
tbuf_beg = tbuf_ptr = __tb;
tbuf_len = _go32_info_block.size_of_transfer_buffer;
tbuf_end = tbuf_beg + tbuf_len - 1;
! return direct_exec_tail(program, args, envp, 0, 2, using_cmdline_var);
}
static int go32_exec(const char *program, char **argv, char **envp)
*************** static int go32_exec(const char *program
*** 695,701 ****
else
argv[0] = save_argv0;
! retval = direct_exec_tail(rpath, pcmd, envp, pproxy, lfn);
if (proxy_cmdline)
free(proxy_cmdline);
return retval;
--- 751,757 ----
else
argv[0] = save_argv0;
! retval = direct_exec_tail(rpath, pcmd, envp, pproxy, lfn, 0);
if (proxy_cmdline)
free(proxy_cmdline);
return retval;
*************** __dosexec_command_exec(const char *progr
*** 804,810 ****
tbuf_beg = tbuf_ptr = __tb;
tbuf_len = _go32_info_block.size_of_transfer_buffer;
tbuf_end = tbuf_ptr + tbuf_len - 1;
! i = direct_exec_tail(comspec, cmdline, envp, 0, 2);
return i;
}
--- 860,866 ----
tbuf_beg = tbuf_ptr = __tb;
tbuf_len = _go32_info_block.size_of_transfer_buffer;
tbuf_end = tbuf_ptr + tbuf_len - 1;
! i = direct_exec_tail(comspec, cmdline, envp, 0, 2, 0);
return i;
}
*** c1args.c.orig Tue Jun 29 11:49:58 1999
--- c1args.c Sun Sep 5 00:34:38 1999
*************** __crt0_setup_arguments(void)
*** 399,408 ****
{
char doscmd[128];
movedata(_stubinfo->psp_selector, 128, ds, (int)doscmd, 128);
! arglist = parse_bytes(doscmd+1, doscmd[0] & 0x7f,
! (_crt0_startup_flags & _CRT0_FLAG_KEEP_QUOTES) == 0);
}
!
/*
** Check for !proxy.
**
--- 399,436 ----
{
char doscmd[128];
movedata(_stubinfo->psp_selector, 128, ds, (int)doscmd, 128);
! if ((doscmd[0] & 0x7f) != 127)
! arglist = parse_bytes(doscmd + 1, doscmd[0] & 0x7f,
! (_crt0_startup_flags & _CRT0_FLAG_KEEP_QUOTES) == 0);
! else
! {
! /* Command line is in the environment variable CMDLINE. */
! char *cmdline = getenv("CMDLINE");
! if (cmdline)
! {
! char stop_token;
!
! /* Skip over the name of the program. */
! if ((*cmdline == '\"') || (*cmdline == '\''))
! stop_token = *cmdline;
! else
! stop_token = ' ';
!
! while (*cmdline != stop_token)
! ++cmdline;
!
! ++cmdline; /* Skip over the stop token. */
!
! arglist = parse_bytes(cmdline, strlen(cmdline),
! (_crt0_startup_flags & _CRT0_FLAG_KEEP_QUOTES) == 0);
! }
! else
! {
! abort();
! }
! }
}
!
/*
** Check for !proxy.
**
---
Mark Elbrecht, snowball3 AT bigfoot DOT com
http://snowball.frogspace.net/
- Raw text -