From: "Mark E." To: djgpp-workers AT delorie DOT com Date: Fri, 29 Jun 2001 00:19:58 -0400 MIME-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Subject: Re: v2loadimage and proxy Message-ID: <3B3BC9AE.12.3CD099@localhost> In-reply-to: <1659-Thu28Jun2001205110+0300-eliz@is.elta.co.il> References: <3B39E3C5 DOT 6290 DOT 765DBB AT localhost> (snowball3 AT bigfoot DOT com) X-mailer: Pegasus Mail for Win32 (v3.12c) Reply-To: djgpp-workers AT delorie DOT com Errors-To: nobody AT delorie DOT com X-Mailing-List: djgpp-workers AT delorie DOT com X-Unsubscribes-To: listserv AT delorie DOT com Precedence: bulk > Thanks. I think this is a very good design, but there are a few > boring details which we need to get right. I've incorporated your info into this revision: Index: v2load.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/debug/common/v2load.c,v retrieving revision 1.6 diff -c -p -r1.6 v2load.c *** v2load.c 2001/06/21 17:13:50 1.6 --- v2load.c 2001/06/29 04:12:54 *************** *** 1,3 **** --- 1,4 ---- + /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ *************** *** 20,25 **** --- 21,27 ---- #include #include #include + #include #define SIMAGIC "go32stub" #define __tb_size _go32_info_block.size_of_transfer_buffer *************** static int read_section(int pf, unsigned *** 53,58 **** --- 55,176 ---- return 0; } + static inline int + is_quote(const char ch) + { + return (ch == '"' || ch == '\''); + } + + static + const char *get_arg(const char *ptr, const char **beg, const char **end) + { + char in_quotes; + while (*ptr && isspace(*ptr)) + ++ptr; + + *beg = ptr; + in_quotes = 0; + + while (1) + { + if (*ptr == '\r') + break; + if (!in_quotes && isspace(*ptr)) + break; + if (*ptr == '\\' && is_quote(ptr[1])) + ++ptr; + if (is_quote(*ptr)) + { + if (!in_quotes) + in_quotes = *ptr; + else if (*ptr == in_quotes) + in_quotes = 0; + } + ++ptr; + } + + *end = ptr; + return ptr; + } + + static char proxy_string[] = " !proxy"; + + static int + make_proxy_var(const char *program, const char *cmdline, + unsigned long tbuf, size_t tb_len, + size_t *proxy_argc, size_t *tb_space) + { + size_t argc; + const char *beg, *end; + char proxy[48]; + + /* Include the program name, a null terminator, and offset pointer + in the argument count. */ + argc = 1; + *tb_space = strlen(program) + 1 + sizeof(short); + + /* Got arguments? */ + while (*cmdline != '\r' && (*tb_space <= tb_len)) + { + cmdline = get_arg(cmdline, &beg, &end); + /* Add in the space needed for the command, a null terminator + and offset pointer. */ + *tb_space += (end - beg) + 1 + sizeof(short); + ++argc; + } + /* If the last arg would cause an overrun, don't include it. */ + if (*tb_space > tb_len) + { + --argc; + *tb_space -= (end - beg) - 1 - sizeof(short); + } + + if (*tb_space > 126) + { + sprintf(proxy, "%s=%04x %04lx %04lx", proxy_string, (unsigned int)argc, + tbuf / 16, tbuf & 0x0f); + putenv(proxy); + } + + *proxy_argc = argc; + + return (*tb_space > 126); + } + + static void + make_proxy_buffer(const char *prog, const char *cmdline, size_t argc, + unsigned long tbuf, size_t tb_len) + { + const char *ptr, *beg, *end; + unsigned long argv_ptr; + unsigned long tbuf_end; + int i; + size_t arg_len; + + tbuf_end = tbuf + tb_len; + argv_ptr = tbuf + (argc + 1) * sizeof(short); + ptr = cmdline; + + /* Insert the program name into argv[0]. */ + arg_len = strlen(prog) + 1; + dosmemput(prog, arg_len, argv_ptr); + _farpokew(_dos_ds, tbuf + 0, (argv_ptr - tbuf) & 0xffff); + argv_ptr += arg_len; + + /* Now insert the command line into argv[]. */ + i = 1; + while (i < argc) + { + ptr = get_arg(ptr, &beg, &end); + arg_len = end - beg; + dosmemput(beg, arg_len, argv_ptr); + _farpokeb(_dos_ds, argv_ptr + arg_len, 0); + _farpokew(_dos_ds, tbuf + i * sizeof(short), (argv_ptr - tbuf) & 0xffff); + argv_ptr += arg_len + 1; + ++i; + } + } + int v2loadimage(const char *program, const char *cmdline, jmp_buf load_state) { unsigned short header[5]; *************** int v2loadimage(const char *program, con *** 66,71 **** --- 184,192 ---- __dpmi_meminfo memblock; unsigned new_env_selector; char true_name[FILENAME_MAX]; + size_t proxy_argc, proxy_space; + int proxy_made; + char proxy_cmdline[128]; _truename(program, true_name); *************** int v2loadimage(const char *program, con *** 137,142 **** --- 258,277 ---- si.initial_size += 0xffff; si.initial_size &= 0xffff0000U; + /* Create the proxy variable now so the child's environment + has the correct size. */ + proxy_made = make_proxy_var(program, cmdline + 1, __tb, __tb_size, + &proxy_argc, &proxy_space); + if (proxy_made) + { + /* When the command line is long enough to justify a proxy variable, + set the command tail accordingly. */ + memcpy(proxy_cmdline, cmdline, 128); + proxy_cmdline[0] = 126; + proxy_cmdline[127] = '\r'; + cmdline = (const char *)proxy_cmdline; + } + si.env_size = 0; for (i=0; environ[i]; i++) si.env_size += strlen(environ[i])+1; *************** int v2loadimage(const char *program, con *** 159,164 **** --- 294,308 ---- _farpokeb(new_env_selector, envp++, 0); movedata(_my_ds(), (unsigned)true_name, new_env_selector, envp, strlen(true_name)+1); + /* Now that the proxy variable is in the child's environment, + remove it from the parent's environment. */ + if (proxy_made) + { + char proxy[32]; + sprintf(proxy, "%s=", proxy_string); + putenv(proxy); + } + /* Allocate the dos memory for the transfer buffer. This nukes si.cs_selector, but that's OK since we set it next. */ i = __dpmi_allocate_dos_memory((si.minkeep + 256) / 16, (int *)&si.psp_selector); *************** int v2loadimage(const char *program, con *** 258,263 **** --- 402,412 ---- /* copy command arguments into debug process */ movedata(my_ds, (unsigned)cmdline, si.psp_selector, 128, 128); + + /* Setup the buffer with proxy arguments. */ + if (proxy_made) + make_proxy_buffer(program, cmdline, proxy_argc, __tb, __tb_size); + /* copy si we built into debug process */ movedata(my_ds, (unsigned)&si, si.ds_selector, 0, sizeof(si)); load_state->__ds = client_ds;