bjh 99/07/19 02:48:28
Modified: src/include httpd.h src/main util.c util_script.c Log: OS/2: Fix spawning of CGI scripts to use appropriate type of command line escapes for OS/2's cmd.exe. Revision Changes Path 1.285 +1 -0 apache-1.3/src/include/httpd.h Index: httpd.h =================================================================== RCS file: /home/cvs/apache-1.3/src/include/httpd.h,v retrieving revision 1.284 retrieving revision 1.285 diff -u -r1.284 -r1.285 --- httpd.h 1999/06/30 08:12:48 1.284 +++ httpd.h 1999/07/19 09:48:24 1.285 @@ -992,6 +992,7 @@ API_EXPORT(char *) ap_uuencode(pool *p, char *string); #ifdef OS2 void os2pathname(char *path); +char *ap_double_quotes(pool *p, char *str); #endif API_EXPORT(int) ap_regexec(const regex_t *preg, const char *string, 1.166 +26 -0 apache-1.3/src/main/util.c Index: util.c =================================================================== RCS file: /home/cvs/apache-1.3/src/main/util.c,v retrieving revision 1.165 retrieving revision 1.166 diff -u -r1.165 -r1.166 --- util.c 1999/06/17 22:58:16 1.165 +++ util.c 1999/07/19 09:48:26 1.166 @@ -2140,6 +2140,32 @@ strcpy(path, newpath); }; + +/* quotes in the string are doubled up. + * Used to escape quotes in args passed to OS/2's cmd.exe + */ +char *ap_double_quotes(pool *p, char *str) +{ + int num_quotes = 0; + int len = 0; + char *quote_doubled_str, *dest; + + while (str[len]) { + num_quotes += str[len++] == '\"'; + } + + quote_doubled_str = ap_palloc(p, len + num_quotes + 1); + dest = quote_doubled_str; + + while (*str) { + if (*str == '\"') + *(dest++) = '\"'; + *(dest++) = *(str++); + } + + *dest = 0; + return quote_doubled_str; +} #endif 1.143 +112 -35 apache-1.3/src/main/util_script.c Index: util_script.c =================================================================== RCS file: /home/cvs/apache-1.3/src/main/util_script.c,v retrieving revision 1.142 retrieving revision 1.143 diff -u -r1.142 -r1.143 --- util_script.c 1999/06/28 22:38:26 1.142 +++ util_script.c 1999/07/19 09:48:27 1.143 @@ -67,6 +67,11 @@ #include "util_script.h" #include "util_date.h" /* For parseHTTPdate() */ +#ifdef OS2 +#define INCL_DOS +#include <os2.h> +#endif + /* * Various utility functions which are common to a whole lot of * script-type extensions mechanisms, and might as well be gathered @@ -750,54 +755,126 @@ #ifdef OS2 { /* Additions by Alec Kloss, to allow exec'ing of scripts under OS/2 */ - int is_script; + int is_script = 0; char interpreter[2048]; /* hope it's enough for the interpreter path */ + char error_object[260]; FILE *program; - + char *cmdline = r->filename, *cmdline_pos; + int cmdlen; + char *args = "", *args_end; + ULONG rc; + RESULTCODES rescodes; + int env_len, e; + char *env_block, *env_block_pos; + + if (r->args && r->args[0] && !strchr(r->args, '=')) + args = r->args; + program = fopen(r->filename, "rt"); + if (!program) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "fopen(%s) failed", r->filename); return (pid); } + fgets(interpreter, sizeof(interpreter), program); fclose(program); + if (!strncmp(interpreter, "#!", 2)) { is_script = 1; - interpreter[strlen(interpreter) - 1] = '\0'; - } - else { - is_script = 0; - } - - if ((!r->args) || (!r->args[0]) || strchr(r->args, '=')) { - /* More additions by Alec Kloss for OS/2 */ - if (is_script) { - /* here's the stuff to run the interpreter */ - pid = spawnle(P_NOWAIT, interpreter + 2, interpreter + 2, r->filename, NULL, env); - } - else if (strstr(strupr(r->filename), ".CMD") > 0) { - /* Special case to allow use of REXX commands as scripts. */ - os2pathname(r->filename); - pid = spawnle(P_NOWAIT, SHELL_PATH, SHELL_PATH, "/C", r->filename, NULL, env); - } - else { - pid = spawnle(P_NOWAIT, r->filename, argv0, NULL, env); - } - } - else { - if (strstr(strupr(r->filename), ".CMD") > 0) { - /* Special case to allow use of REXX commands as scripts. */ - os2pathname(r->filename); - pid = spawnve(P_NOWAIT, SHELL_PATH, create_argv_cmd(r->pool, argv0, r->args, - r->filename), env); - } - else { - pid = spawnve(P_NOWAIT, r->filename, - create_argv(r->pool, NULL, NULL, NULL, argv0, r->args), env); - } + interpreter[strlen(interpreter) - 1] = '\0'; + if (interpreter[2] != '/' && interpreter[2] != '\\' && interpreter[3] != ':') { + char buffer[300]; + if (DosSearchPath(SEARCH_ENVIRONMENT, "PATH", interpreter+2, buffer, sizeof(buffer)) == 0) { + strcpy(interpreter+2, buffer); + } else { + strcat(interpreter, ".exe"); + if (DosSearchPath(SEARCH_ENVIRONMENT, "PATH", interpreter+2, buffer, sizeof(buffer)) == 0) { + strcpy(interpreter+2, buffer); + } + } + } + } + + if (is_script) { + cmdline = ap_pstrcat(r->pool, interpreter+2, " ", r->filename, NULL); + } + else if (strstr(strupr(r->filename), ".CMD") > 0) { + /* Special case to allow use of REXX commands as scripts. */ + os2pathname(r->filename); + cmdline = ap_pstrcat(r->pool, SHELL_PATH, " /C ", r->filename, NULL); + } + else { + cmdline = r->filename; + } + + args = ap_pstrdup(r->pool, args); + ap_unescape_url(args); + args = ap_double_quotes(r->pool, args); + args_end = args + strlen(args); + + if (args_end - args > 4000) { /* cmd.exe won't handle lines longer than 4k */ + args_end = args + 4000; + *args_end = 0; + } + + /* +4 = 1 space between progname and args, 2 for double null at end, 2 for possible quote on first arg */ + cmdlen = strlen(cmdline) + strlen(args) + 4; + cmdline_pos = cmdline; + + while (*cmdline_pos) { + cmdlen += 2 * (*cmdline_pos == '+'); /* Allow space for each arg to be quoted */ + cmdline_pos++; + } + + cmdline = ap_pstrndup(r->pool, cmdline, cmdlen); + cmdline_pos = cmdline + strlen(cmdline); + + while (args < args_end) { + char *arg; + + arg = ap_getword_nc(r->pool, &args, '+'); + + if (strpbrk(arg, "&|<> ")) + arg = ap_pstrcat(r->pool, "\"", arg, "\"", NULL); + + *(cmdline_pos++) = ' '; + strcpy(cmdline_pos, arg); + cmdline_pos += strlen(cmdline_pos); + } + + *(++cmdline_pos) = 0; /* Add required second terminator */ + args = strchr(cmdline, ' '); + + if (args) { + *args = 0; + args++; + } + + /* Create environment block from list of envariables */ + for (env_len=1, e=0; env[e]; e++) + env_len += strlen(env[e]) + 1; + + env_block = ap_palloc(r->pool, env_len); + env_block_pos = env_block; + + for (e=0; env[e]; e++) { + strcpy(env_block_pos, env[e]); + env_block_pos += strlen(env_block_pos) + 1; + } + + *env_block_pos = 0; /* environment block is terminated by a double null */ + + rc = DosExecPgm(error_object, sizeof(error_object), EXEC_ASYNC, cmdline, env_block, &rescodes, cmdline); + + if (rc) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "DosExecPgm(%s %s) failed, %s - %s", + cmdline, args ? args : "", ap_os_error_message(rc), error_object ); + return -1; } - return (pid); + + return rescodes.codeTerminate; } #elif defined(WIN32) {