From: JRSON@NetZero.Net (John R Hanson)
To: cygwin@sourceware.cygnus.com, cgf@cygnus.com
Subject: cygwin->msvcrt argv expansion algorithems
Date: Sun, 12 Dec 1999 12:33:00 -0000 [thread overview]
Message-ID: <3853f8e4.51785625@smtp.netzero.net> (raw)
Hi Chris
You would know better than I where these need to be slotted
into the cygwin .dll.
--- Cut Here ----------------------------------------------------------
/* this is an example program for encoding and decoding
command lines to be used when starting a subprocess
via CreateProcess
compile with
gcc -oCreateP CreateP.c
*/
#include <windows.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#ifdef __CYGWIN__
#define _flushall() fflush(NULL)
#endif
static char *
basename (const char *name){
const char *base = name;
while (*name)
if ((*name++ == '/')||(name[-1] == '\\')||(name[-1] == ':'))
base = name;
return (char *) base;
}
#define CHR(c) { \
if (buf) { \
if (size + 1 > buf_size) \
return -1; \
buf[size] = (char)c; \
} \
size++; \
}
#define CHRS(c,n) { \
if (buf) { \
if (size + (n) > buf_size) \
return -1; \
memset (buf + size, c, n); \
} \
size += n; \
}
#define STR(s,n) { \
if (buf) { \
if (size + (n) > buf_size) \
return -1; \
memcpy (buf + size, s, n); \
} \
size += n; \
}
/*
· Arguments are delimited by white space, which is either a space or a tab.
· A string surrounded by double quotation marks is interpreted as a
single argument, regardless of white space contained within. A quoted
string can be embedded in an argument. Note that the caret (^) is not
recognized as an escape character or delimiter.
· A double quotation mark preceded by a backslash, \", is interpreted as
a literal double quotation mark (").
· Backslashes are interpreted literally, unless they immediately precede
a double quotation mark.
· If an even number of backslashes is followed by a double quotation
mark, then one backslash (\) is placed in the argv array for every pair
of backslashes (\\), and the double quotation mark (") is interpreted as
a string delimiter.
· If an odd number of backslashes is followed by a double quotation
mark, then one backslash (\) is placed in the argv array for every pair
of backslashes (\\) and the double quotation mark is interpreted as an
escape sequence by the remaining backslash, causing a literal double
quotation mark (") to be placed in argv.
*/
static size_t
decode_args (
char *buf,
size_t buf_size,
char *CommandLine,
char **argv,
int *argc) {
int bs;
int copy;
char *p;
int quote;
size_t size = 0;
*argc = 1;
p = CommandLine;
if (argv) *argv++ = buf;
if (*p++ == '\"'){
while (*p && *p != '\"') {
CHR(*p);
p++;
}
if (*p == '\"') p++;
}
else{
CHR(p[-1]);
while (*p && *p != ' ' && *p != '\t'){
CHR(*p);
p++;
}
}
CHR('\0');
quote = FALSE;
for(;;) {
if (*p) while (*p == ' ' || *p == '\t') p++;
if (!*p) break;
if (argv) *argv++ = &buf[size];
++*argc;
for (;;) {
copy = TRUE;
bs = 0;
while (*p == '\\') {
p++; bs++;
}
if (*p == '\"') {
if (!(bs % 2)) {
if (quote) {
if (p[1] == '\"') p++;
else copy = FALSE;
}
else copy = FALSE;
quote = !quote;
}
bs >>= bs;
}
CHRS('\\', bs);
if (!*p || (!quote && (*p == ' ' || *p == '\t'))) break;
if (copy) CHR(*p);
p++;
}
CHR('\0');
}
if (argv) *argv++ = NULL;
return size;
}
static size_t
encode_args (
char *buf,
size_t buf_size,
char **argv,
int argc,
const char *prog_name) {
size_t size = 0;
const char *src, *p, *base;
int quote, bs, shell = 0;
/* assume MS or cyg runtime */
base = basename(prog_name);
if (!strncasecmp(base, "cmd", 3) && (base[3] == '.' || base[3] == '\0'))
shell = 1;
else /* .com extension is required */
if (!strcasecmp (base, "command.com"))
shell = 2;
src = *argv++;
if (argc) {
STR (src, strlen (src));
src = *argv++;
}
for (;argc > 1;argc--) {
CHR (' ');
quote = FALSE;
if (!*src) quote = TRUE;
if (!quote)
for (p = src;*p;p++)
if (shell < 2)
if (*p == ' ' || *p == '\t' || *p == '&' || (*p == '"' && shell == 1)) {
quote = TRUE;
break;
}
if (quote) CHR ('"');
bs = 0;
while (*src) {
if (*src == '"' && !shell) {
CHRS ('\\', bs + 1);
bs = 0;
}
else
if (*src == '\\' && !shell)
bs++;
else
bs = 0;
CHR (*src);
src++;
}
if (quote) {
CHRS ('\\', bs);
bs = 0;
CHR ('"');
}
src = *argv++;
}
CHR ('\0');
return size;
}
#undef CHR
#undef CHRS
#undef STR
void
get_args(){
/* Most of this would be in mainCRTStartup normally */
char fname[MAX_PATH], *buf, **argv, *CommandLine = GetCommandLine();
int buf_size, argc;
if (!*CommandLine){
GetModuleFileName(NULL, fname, MAX_PATH);
CommandLine = fname;
}
printf("%s\n", CommandLine);
if ((buf_size = decode_args(NULL, 0, CommandLine, (char **)NULL, &argc)) < 0) abort();
if (!(buf = (char *)argv = (char **)alloca(((argc + 1) * sizeof(char *)) + buf_size))) abort();
buf += ((argc + 1) * sizeof(char *));
if ((buf_size = decode_args(buf, buf_size, CommandLine, argv, &argc)) < 0) abort();
while (*argv) printf("%s ", *argv++);
printf("\n");
/* main(argc, argv, __environ) */
exit(0);
}
HANDLE
exec_it(char **argv, char *fname){
STARTUPINFO si;
PROCESS_INFORMATION pi;
size_t buf_size;
char *p, *path_exec;
void *buf;
int WinErr;
char out_path[1024] = "PATH=";
int argc = strlen((char *)argv);
buf_size = encode_args (NULL, 0, argv, argc, fname);
if ((buf_size < 0)||(buf_size > 1024 * 32)){
errno = E2BIG;
return (HANDLE)-1;
}
buf = alloca (buf_size);
if (buf == NULL) {
errno = ENOMEM;
return (HANDLE)-1;
}
buf_size = encode_args (buf, buf_size, argv, argc, fname);
if ((buf_size < 0)||(buf_size > 1024 * 32)){
errno = E2BIG;
return (HANDLE)-1;
}
/* path must be all '\\' */
if ((p = path_exec = strdup((const char *)getenv("PATH")))){
while (*p) if (*p++ == '/') p[-1] = '\\';
putenv(strcat(out_path, path_exec));
free(path_exec);
}
if (fname == (p = basename(fname))) {
/* force .exe && search if needed */
if (!strncasecmp(fname, argv[0], strlen(fname)))
fname = NULL;
}
else {
p = fname;
while (*p) if (*p++ == '/') p[-1] = '\\';
}
/* console only */
memset(&si, 0, sizeof (STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = (HANDLE)_get_osfhandle(0);
si.hStdOutput = (HANDLE)_get_osfhandle(1);
si.hStdError = (HANDLE)_get_osfhandle(2);
_flushall();
if (!CreateProcess(fname, buf, NULL, NULL, TRUE, GetPriorityClass ((HANDLE)-1), NULL, NULL, &si, &pi)){
if (((WinErr = GetLastError()) > 187) && (WinErr < 203))
errno = ENOEXEC;
else{ /* ? */
errno = GetLastError();
perror("in CreateP");
}
}
else {
CloseHandle(pi.hThread);
return pi.hProcess;
}
return (HANDLE)-1;
}
int
main(int argc, char **argv){
HANDLE waitfor;
char *command_args[] = {"command.com", "/c", "echo \"this\""};
char *cmd_args[] = {"cmd", "/c", "echo \"this\""};
char *cmd2_args[] = {"cmd", "/c", "echo.&&echo."};
/* non cygwin */
char *sh_args[] = {"sh", "-c", "echo \\\\\\\"this\\\\\\\""};
char *sh1_args[] = {"\"sh\"", "-c", "echo \\\\\\\"this\\\\\\\""};
/* cygwin */
char *bash_args[] = {"bash", "-c", "echo \\\\\\\"this\\\\\\\""};
if (argc == 1) {
waitfor = exec_it(command_args, "CreateP.exe");
WaitForSingleObject(waitfor, 0x5000);
waitfor = exec_it(command_args, "command.com");
WaitForSingleObject(waitfor, 0x5000);
exec_it(cmd_args, "CreateP.exe");
WaitForSingleObject(waitfor, 0x5000);
exec_it(cmd_args, "cmd");
WaitForSingleObject(waitfor, 0x5000);
exec_it(cmd2_args, "CreateP.exe");
WaitForSingleObject(waitfor, 0x5000);
exec_it(cmd2_args, "cmd");
WaitForSingleObject(waitfor, 0x5000);
/* cygwin */
exec_it(bash_args, "CreateP.exe");
WaitForSingleObject(waitfor, 0x5000);
exec_it(bash_args, "d:\\bin\\bash.exe");
WaitForSingleObject(waitfor, 0x5000);
/* non cygwin */
exec_it(sh_args, "CreateP.exe");
WaitForSingleObject(waitfor, 0x5000);
exec_it(sh_args, "d:\\bin\\sh.exe");
WaitForSingleObject(waitfor, 0x5000);
exec_it(sh1_args, "CreateP.exe");
WaitForSingleObject(waitfor, 0x5000);
exec_it(sh1_args, "d:\\bin\\sh.exe");
WaitForSingleObject(waitfor, 0x5000);
}
else{
get_args();
}
return 0;
}
__________________________________________
NetZero - Defenders of the Free World
Get your FREE Internet Access and Email at
http://www.netzero.net/download/index.html
--
Want to unsubscribe from this list?
Send a message to cygwin-unsubscribe@sourceware.cygnus.com
WARNING: multiple messages have this Message-ID
From: JRSON@NetZero.Net (John R Hanson)
To: cygwin@sourceware.cygnus.com, cgf@cygnus.com
Subject: cygwin->msvcrt argv expansion algorithems
Date: Fri, 31 Dec 1999 13:28:00 -0000 [thread overview]
Message-ID: <3853f8e4.51785625@smtp.netzero.net> (raw)
Message-ID: <19991231132800.VjrEzmF6b3a_Mz9rIt-_uJbOHWET_qAHcL-6lsLFqvk@z> (raw)
Hi Chris
You would know better than I where these need to be slotted
into the cygwin .dll.
--- Cut Here ----------------------------------------------------------
/* this is an example program for encoding and decoding
command lines to be used when starting a subprocess
via CreateProcess
compile with
gcc -oCreateP CreateP.c
*/
#include <windows.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#ifdef __CYGWIN__
#define _flushall() fflush(NULL)
#endif
static char *
basename (const char *name){
const char *base = name;
while (*name)
if ((*name++ == '/')||(name[-1] == '\\')||(name[-1] == ':'))
base = name;
return (char *) base;
}
#define CHR(c) { \
if (buf) { \
if (size + 1 > buf_size) \
return -1; \
buf[size] = (char)c; \
} \
size++; \
}
#define CHRS(c,n) { \
if (buf) { \
if (size + (n) > buf_size) \
return -1; \
memset (buf + size, c, n); \
} \
size += n; \
}
#define STR(s,n) { \
if (buf) { \
if (size + (n) > buf_size) \
return -1; \
memcpy (buf + size, s, n); \
} \
size += n; \
}
/*
· Arguments are delimited by white space, which is either a space or a tab.
· A string surrounded by double quotation marks is interpreted as a
single argument, regardless of white space contained within. A quoted
string can be embedded in an argument. Note that the caret (^) is not
recognized as an escape character or delimiter.
· A double quotation mark preceded by a backslash, \", is interpreted as
a literal double quotation mark (").
· Backslashes are interpreted literally, unless they immediately precede
a double quotation mark.
· If an even number of backslashes is followed by a double quotation
mark, then one backslash (\) is placed in the argv array for every pair
of backslashes (\\), and the double quotation mark (") is interpreted as
a string delimiter.
· If an odd number of backslashes is followed by a double quotation
mark, then one backslash (\) is placed in the argv array for every pair
of backslashes (\\) and the double quotation mark is interpreted as an
escape sequence by the remaining backslash, causing a literal double
quotation mark (") to be placed in argv.
*/
static size_t
decode_args (
char *buf,
size_t buf_size,
char *CommandLine,
char **argv,
int *argc) {
int bs;
int copy;
char *p;
int quote;
size_t size = 0;
*argc = 1;
p = CommandLine;
if (argv) *argv++ = buf;
if (*p++ == '\"'){
while (*p && *p != '\"') {
CHR(*p);
p++;
}
if (*p == '\"') p++;
}
else{
CHR(p[-1]);
while (*p && *p != ' ' && *p != '\t'){
CHR(*p);
p++;
}
}
CHR('\0');
quote = FALSE;
for(;;) {
if (*p) while (*p == ' ' || *p == '\t') p++;
if (!*p) break;
if (argv) *argv++ = &buf[size];
++*argc;
for (;;) {
copy = TRUE;
bs = 0;
while (*p == '\\') {
p++; bs++;
}
if (*p == '\"') {
if (!(bs % 2)) {
if (quote) {
if (p[1] == '\"') p++;
else copy = FALSE;
}
else copy = FALSE;
quote = !quote;
}
bs >>= bs;
}
CHRS('\\', bs);
if (!*p || (!quote && (*p == ' ' || *p == '\t'))) break;
if (copy) CHR(*p);
p++;
}
CHR('\0');
}
if (argv) *argv++ = NULL;
return size;
}
static size_t
encode_args (
char *buf,
size_t buf_size,
char **argv,
int argc,
const char *prog_name) {
size_t size = 0;
const char *src, *p, *base;
int quote, bs, shell = 0;
/* assume MS or cyg runtime */
base = basename(prog_name);
if (!strncasecmp(base, "cmd", 3) && (base[3] == '.' || base[3] == '\0'))
shell = 1;
else /* .com extension is required */
if (!strcasecmp (base, "command.com"))
shell = 2;
src = *argv++;
if (argc) {
STR (src, strlen (src));
src = *argv++;
}
for (;argc > 1;argc--) {
CHR (' ');
quote = FALSE;
if (!*src) quote = TRUE;
if (!quote)
for (p = src;*p;p++)
if (shell < 2)
if (*p == ' ' || *p == '\t' || *p == '&' || (*p == '"' && shell == 1)) {
quote = TRUE;
break;
}
if (quote) CHR ('"');
bs = 0;
while (*src) {
if (*src == '"' && !shell) {
CHRS ('\\', bs + 1);
bs = 0;
}
else
if (*src == '\\' && !shell)
bs++;
else
bs = 0;
CHR (*src);
src++;
}
if (quote) {
CHRS ('\\', bs);
bs = 0;
CHR ('"');
}
src = *argv++;
}
CHR ('\0');
return size;
}
#undef CHR
#undef CHRS
#undef STR
void
get_args(){
/* Most of this would be in mainCRTStartup normally */
char fname[MAX_PATH], *buf, **argv, *CommandLine = GetCommandLine();
int buf_size, argc;
if (!*CommandLine){
GetModuleFileName(NULL, fname, MAX_PATH);
CommandLine = fname;
}
printf("%s\n", CommandLine);
if ((buf_size = decode_args(NULL, 0, CommandLine, (char **)NULL, &argc)) < 0) abort();
if (!(buf = (char *)argv = (char **)alloca(((argc + 1) * sizeof(char *)) + buf_size))) abort();
buf += ((argc + 1) * sizeof(char *));
if ((buf_size = decode_args(buf, buf_size, CommandLine, argv, &argc)) < 0) abort();
while (*argv) printf("%s ", *argv++);
printf("\n");
/* main(argc, argv, __environ) */
exit(0);
}
HANDLE
exec_it(char **argv, char *fname){
STARTUPINFO si;
PROCESS_INFORMATION pi;
size_t buf_size;
char *p, *path_exec;
void *buf;
int WinErr;
char out_path[1024] = "PATH=";
int argc = strlen((char *)argv);
buf_size = encode_args (NULL, 0, argv, argc, fname);
if ((buf_size < 0)||(buf_size > 1024 * 32)){
errno = E2BIG;
return (HANDLE)-1;
}
buf = alloca (buf_size);
if (buf == NULL) {
errno = ENOMEM;
return (HANDLE)-1;
}
buf_size = encode_args (buf, buf_size, argv, argc, fname);
if ((buf_size < 0)||(buf_size > 1024 * 32)){
errno = E2BIG;
return (HANDLE)-1;
}
/* path must be all '\\' */
if ((p = path_exec = strdup((const char *)getenv("PATH")))){
while (*p) if (*p++ == '/') p[-1] = '\\';
putenv(strcat(out_path, path_exec));
free(path_exec);
}
if (fname == (p = basename(fname))) {
/* force .exe && search if needed */
if (!strncasecmp(fname, argv[0], strlen(fname)))
fname = NULL;
}
else {
p = fname;
while (*p) if (*p++ == '/') p[-1] = '\\';
}
/* console only */
memset(&si, 0, sizeof (STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = (HANDLE)_get_osfhandle(0);
si.hStdOutput = (HANDLE)_get_osfhandle(1);
si.hStdError = (HANDLE)_get_osfhandle(2);
_flushall();
if (!CreateProcess(fname, buf, NULL, NULL, TRUE, GetPriorityClass ((HANDLE)-1), NULL, NULL, &si, &pi)){
if (((WinErr = GetLastError()) > 187) && (WinErr < 203))
errno = ENOEXEC;
else{ /* ? */
errno = GetLastError();
perror("in CreateP");
}
}
else {
CloseHandle(pi.hThread);
return pi.hProcess;
}
return (HANDLE)-1;
}
int
main(int argc, char **argv){
HANDLE waitfor;
char *command_args[] = {"command.com", "/c", "echo \"this\""};
char *cmd_args[] = {"cmd", "/c", "echo \"this\""};
char *cmd2_args[] = {"cmd", "/c", "echo.&&echo."};
/* non cygwin */
char *sh_args[] = {"sh", "-c", "echo \\\\\\\"this\\\\\\\""};
char *sh1_args[] = {"\"sh\"", "-c", "echo \\\\\\\"this\\\\\\\""};
/* cygwin */
char *bash_args[] = {"bash", "-c", "echo \\\\\\\"this\\\\\\\""};
if (argc == 1) {
waitfor = exec_it(command_args, "CreateP.exe");
WaitForSingleObject(waitfor, 0x5000);
waitfor = exec_it(command_args, "command.com");
WaitForSingleObject(waitfor, 0x5000);
exec_it(cmd_args, "CreateP.exe");
WaitForSingleObject(waitfor, 0x5000);
exec_it(cmd_args, "cmd");
WaitForSingleObject(waitfor, 0x5000);
exec_it(cmd2_args, "CreateP.exe");
WaitForSingleObject(waitfor, 0x5000);
exec_it(cmd2_args, "cmd");
WaitForSingleObject(waitfor, 0x5000);
/* cygwin */
exec_it(bash_args, "CreateP.exe");
WaitForSingleObject(waitfor, 0x5000);
exec_it(bash_args, "d:\\bin\\bash.exe");
WaitForSingleObject(waitfor, 0x5000);
/* non cygwin */
exec_it(sh_args, "CreateP.exe");
WaitForSingleObject(waitfor, 0x5000);
exec_it(sh_args, "d:\\bin\\sh.exe");
WaitForSingleObject(waitfor, 0x5000);
exec_it(sh1_args, "CreateP.exe");
WaitForSingleObject(waitfor, 0x5000);
exec_it(sh1_args, "d:\\bin\\sh.exe");
WaitForSingleObject(waitfor, 0x5000);
}
else{
get_args();
}
return 0;
}
__________________________________________
NetZero - Defenders of the Free World
Get your FREE Internet Access and Email at
http://www.netzero.net/download/index.html
--
Want to unsubscribe from this list?
Send a message to cygwin-unsubscribe@sourceware.cygnus.com
next reply other threads:[~1999-12-12 12:33 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
1999-12-12 12:33 John R Hanson [this message]
1999-12-12 13:38 ` Chris Faylor
1999-12-12 14:04 ` John R Hanson
1999-12-12 17:06 ` Chris Faylor
1999-12-31 13:28 ` Chris Faylor
1999-12-31 13:28 ` John R Hanson
1999-12-31 13:28 ` Chris Faylor
1999-12-31 13:28 ` John R Hanson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3853f8e4.51785625@smtp.netzero.net \
--to=jrson@netzero.net \
--cc=cgf@cygnus.com \
--cc=cygwin@sourceware.cygnus.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).