Mailing-List: contact cygwin-help AT sourceware DOT cygnus DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT sourceware DOT cygnus DOT com Delivered-To: mailing list cygwin AT sourceware DOT cygnus DOT com From: JRSON AT NetZero DOT Net (John R Hanson) To: cygwin AT sourceware DOT cygnus DOT com, cgf AT cygnus DOT com Subject: cygwin->msvcrt argv expansion algorithems Date: Sun, 12 Dec 1999 19:43:34 GMT Reply-To: JRSON AT NetZero DOT Net Message-ID: <3853f8e4.51785625@smtp.netzero.net> X-Mailer: Forte Agent 1.5/32.452 MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit 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 #include #include #include #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 AT sourceware DOT cygnus DOT com