Annotation of parser3/src/targets/cgi/parser3.C, revision 1.216.2.3
1.27 paf 1: /** @file
2: Parser: scripting and CGI main.
3:
1.216.2.1 paf 4: Copyright(c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)
1.154 paf 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.189 paf 6: */
1.27 paf 7:
1.216.2.3! paf 8: static const char* IDENT_PARSER3_C="$Date: 2003/01/31 16:05:59 $";
1.1 paf 9:
1.40 paf 10: #include "pa_config_includes.h"
1.3 paf 11:
1.139 paf 12: #if _MSC_VER
1.131 paf 13: # include <new.h>
1.148 paf 14: # include <crtdbg.h>
1.3 paf 15: #endif
1.27 paf 16:
1.37 paf 17: #include "pa_sapi.h"
1.76 paf 18: #include "classes.h"
1.24 paf 19: #include "pa_common.h"
1.2 paf 20: #include "pa_request.h"
1.57 paf 21: #include "pa_socks.h"
1.68 paf 22: #include "pa_version.h"
1.207 paf 23:
1.149 paf 24: #ifdef WIN32
25: # include <windows.h>
1.184 paf 26: # include "getopt.h"
27: #else
28: # include <getopt.h>
1.120 parser 29: #endif
30:
1.158 paf 31: //#define DEBUG_POOL_MALLOC
1.162 paf 32: //#define DEBUG_STRING_APPENDS_VS_EXPANDS
1.196 paf 33: //#define DEBUG_MAILRECEIVE "mailreceive.eml"
1.160 paf 34:
35: #ifdef DEBUG_STRING_APPENDS_VS_EXPANDS
36: extern ulong
37: string_piece_appends,
38: wcontext_result_size,
39: total_alloc_size,
40: string_string_shortcut_economy;
41: #endif
1.84 parser 42:
1.109 parser 43: // consts
1.84 parser 44:
1.175 paf 45: #define REDIRECT_PREFIX "REDIRECT_"
1.181 paf 46: #define PARSER_CONFIG_ENV_NAME "CGI_PARSER_CONFIG"
1.159 paf 47:
1.42 paf 48: /// IIS refuses to read bigger chunks
49: const size_t READ_POST_CHUNK_SIZE=0x400*0x400; // 1M
50:
1.216.2.1 paf 51: static const char* argv0;
52: static const char* config_filespec_cstr=0;
1.193 paf 53: static bool fail_on_config_read_problem=true;
1.192 paf 54:
1.184 paf 55: static bool cgi; ///< we were started as CGI?
56: static bool mail_received=false; ///< we were started with -m option? [asked to parse incoming message to $mail:received]
1.5 paf 57:
1.201 paf 58: // for signal handlers
59: Request *request=0;
60:
1.46 paf 61: // SAPI
1.86 parser 62:
1.216.2.3! paf 63: class SAPI_Info{} SAPI_info;
! 64:
1.216.2.1 paf 65: static void log(const char* fmt, va_list args) {
1.193 paf 66: bool opened=false;
1.61 paf 67: FILE *f=0;
68:
1.193 paf 69: if(config_filespec_cstr) {
70: char beside_config_path[MAX_STRING];
71: strncpy(beside_config_path, config_filespec_cstr, MAX_STRING-1); beside_config_path[MAX_STRING-1]=0;
72: if(!(
73: rsplit(beside_config_path, '/') ||
74: rsplit(beside_config_path, '\\'))) { // strip filename
75: // no path, just filename
76: beside_config_path[0]='.'; beside_config_path[1]=0;
77: }
78:
79: char file_spec[MAX_STRING];
80: snprintf(file_spec, MAX_STRING,
81: "%s/parser3.log", beside_config_path);
82: f=fopen(file_spec, "at");
83: opened=f!=0;
84: }
1.192 paf 85: // fallback to stderr
1.61 paf 86: if(!opened)
87: f=stderr;
1.208 paf 88:
89: // use no memory [so that we could log out-of-memory error]
90: setbuf(f, 0); // stderr stream is unbuffered by default, but still...
1.61 paf 91:
92: // prefix
93: time_t t=time(0);
1.216.2.1 paf 94: if(const char* stamp=ctime(&t)) { // never saw that
1.173 paf 95: if(size_t len=strlen(stamp)) // saw once stamp being =""
1.172 paf 96: fprintf(f, "[%.*s] ", len-1, stamp);
1.171 paf 97: }
1.61 paf 98: // message
1.117 parser 99:
100: char buf[MAX_STRING];
101: size_t size=vsnprintf(buf, MAX_STRING, fmt, args);
102: remove_crlf(buf, buf+size);
103:
104: fwrite(buf, size, 1, f);
1.61 paf 105: // newline
106: fprintf(f, "\n");
107:
108: if(opened)
109: fclose(f);
1.85 parser 110: else
111: fflush(f);
1.124 parser 112: }
113:
114: // appends to parser3.log located beside my binary if openable, to stderr otherwize
1.216.2.3! paf 115: void SAPI::log(SAPI_Info&, const char* fmt, ...) {
1.124 parser 116: va_list args;
117: va_start(args,fmt);
118: ::log(fmt, args);
119: va_end(args);
120: }
121:
1.216.2.1 paf 122: void SAPI::die(const char* fmt, ...) {
1.137 paf 123: #ifdef DEBUG_POOL_MALLOC
124: extern void log_pool_stats(Pool& pool);
1.216.2.3! paf 125: log_pool_stats(SAPI_info);
1.137 paf 126: #endif
127:
1.144 paf 128: va_list args;
129: va_start(args,fmt);
1.138 paf 130: // log
131:
132: // logging is more important than user
1.204 paf 133: // she can cancel download, we'd get SIGPIPE,
1.138 paf 134: // nothing would be logged then
1.124 parser 135: ::log(fmt, args);
136:
1.138 paf 137: // inform user
138:
1.134 paf 139: char body[MAX_STRING];
1.138 paf 140: int content_length=vsnprintf(body, MAX_STRING, fmt, args);
1.134 paf 141:
1.144 paf 142: va_end(args);
143:
1.134 paf 144: // prepare header
145: // let's be honest, that's bad we couldn't produce valid output
1.216.2.3! paf 146: SAPI::add_header_attribute(SAPI_info, "status", "500");
! 147: SAPI::add_header_attribute(SAPI_info, "content-type", "text/plain");
1.134 paf 148: char content_length_cstr[MAX_NUMBER];
1.168 paf 149: snprintf(content_length_cstr, sizeof(content_length_cstr), "%u", content_length);
1.216.2.3! paf 150: SAPI::add_header_attribute(SAPI_info, "content-length", content_length_cstr);
1.134 paf 151:
152: // send header
1.216.2.3! paf 153: SAPI::send_header(SAPI_info);
1.134 paf 154:
155: // body
1.216.2.3! paf 156: SAPI::send_body(SAPI_info, body, content_length);
1.134 paf 157:
1.214 paf 158: #ifdef WIN32
159: // IIS with abort failes to show STDOUT, it just barks "abnormal program termination"
160: exit(1);
161: #else
1.211 paf 162: // exit & try to produce core dump
163: abort();
1.214 paf 164: #endif
1.61 paf 165: }
166:
1.216.2.3! paf 167: CharPtr SAPI::get_env(SAPI_Info& , const char* name) {
! 168: if(char *local=getenv(name)) {
! 169: size_t size=strlen(local)+1;
! 170: char *heap=new char[size];
! 171: memcpy(heap, local, size);
! 172: return CharPtr(heap);
! 173: }
! 174: else
! 175: return CharPtr(0);
1.28 paf 176: }
177:
1.216.2.3! paf 178: const char* const *SAPI::environment(SAPI_Info&, Pool&) {
1.180 paf 179: #ifdef _MSC_VER
180: extern char **_environ;
181: return _environ;
182: #else
183: extern char **environ;
184: return environ;
185: #endif
186: }
187:
1.216.2.3! paf 188: size_t SAPI::read_post(SAPI_Info& , char *buf, size_t max_bytes) {
1.59 paf 189: size_t read_size=0;
1.12 paf 190: do {
1.200 paf 191: ssize_t chunk_size=read(fileno(stdin),
1.42 paf 192: buf+read_size, min(READ_POST_CHUNK_SIZE, max_bytes-read_size));
1.129 paf 193: if(chunk_size<=0)
1.12 paf 194: break;
195: read_size+=chunk_size;
196: } while(read_size<max_bytes);
197:
198: return read_size;
1.10 paf 199: }
200:
1.216.2.3! paf 201: void SAPI::add_header_attribute(SAPI_Info& , const char* dont_store_key, const char* dont_store_value) {
1.68 paf 202: if(cgi)
1.216.2.2 paf 203: printf("%s: %s\n", dont_store_key, dont_store_value);
1.19 paf 204: }
205:
1.56 paf 206: /// @todo intelligent cache-control
1.216.2.3! paf 207: void SAPI::send_header(SAPI_Info& ) {
1.33 paf 208: if(cgi) {
1.147 paf 209: // puts("expires: Fri, 23 Mar 2001 09:32:23 GMT");
1.33 paf 210:
211: // header | body delimiter
1.20 paf 212: puts("");
1.33 paf 213: }
1.30 paf 214: }
1.20 paf 215:
1.216.2.3! paf 216: void SAPI::send_body(SAPI_Info& , const void *buf, size_t size) {
1.19 paf 217: stdout_write(buf, size);
1.58 paf 218: }
219:
1.97 parser 220: //
221:
1.216.2.1 paf 222: static void full_file_spec(const char* file_name, char *buf, size_t buf_size) {
1.210 paf 223: if(file_name)
1.167 paf 224: if(file_name[0]=='/'
225: #ifdef WIN32
1.210 paf 226: || file_name[0] && file_name[1]==':'
1.167 paf 227: #endif
1.210 paf 228: )
1.167 paf 229: strncpy(buf, file_name, buf_size);
230: else {
231: char cwd[MAX_STRING]; getcwd(cwd, MAX_STRING);
232: snprintf(buf, buf_size, "%s/%s", cwd, file_name);
233: }
234: else
235: buf[0]=0;
1.166 paf 236: #ifdef WIN32
237: back_slashes_to_slashes(buf);
238: #endif
1.97 parser 239: }
240:
1.216.2.1 paf 241: static void log_signal(const char* signal_name) {
1.216.2.3! paf 242: SAPI::log(SAPI_info, request? "%s received. uri=%s, qs=%s"
1.205 paf 243: :"%s received. no request being processed",
244: signal_name,
1.216.2.3! paf 245: request && request->request_info.uri?request->request_info.uri:"-",
! 246: request && request->request_info.query_string?request->request_info.query_string:"-");
1.205 paf 247: }
248:
1.201 paf 249: #ifdef SIGUSR1
1.205 paf 250: static void SIGUSR1_handler(int /*sig*/){
251: log_signal("SIGUSR1");
1.201 paf 252: }
253: #endif
254:
255: #ifdef SIGPIPE
1.205 paf 256: static void SIGPIPE_handler(int /*sig*/){
257: log_signal("SIGPIPE");
1.201 paf 258: if(request)
259: request->interrupt();
260: }
261: #endif
262:
1.40 paf 263: /**
1.122 parser 264: main workhorse
1.19 paf 265:
1.122 parser 266: @todo
1.40 paf 267: IIS: remove trailing default-document[index.html] from $request.uri.
268: to do that we need to consult metabase,
269: wich is tested but seems slow.
1.144 paf 270: IIS5 todo find out proper 'illegal call' check
1.40 paf 271: */
1.184 paf 272: static void real_parser_handler(
1.216.2.1 paf 273: const char* filespec_to_process,
274: const char* request_method, bool header_only) {
1.122 parser 275: // init socks
1.216.2.3! paf 276: pa_init_socks();
1.122 parser 277:
278: // init global variables
1.216.2.3! paf 279: pa_globals_init();
1.122 parser 280:
1.198 paf 281: // request pool, must be different ptr from global [used in VStateless_class.add_method]
1.216.2.3! paf 282: Pool request_pool;
1.198 paf 283:
1.186 paf 284: if(!filespec_to_process || !*filespec_to_process)
1.144 paf 285: SAPI::die("Parser/%s", PARSER_VERSION);
1.122 parser 286:
287: // Request info
1.216.2.3! paf 288: Request_info request_info;
1.166 paf 289: char document_root_buf[MAX_STRING];
1.122 parser 290: if(cgi) {
1.216.2.3! paf 291: if(CharPtr env_document_root=SAPI::get_env(SAPI_info, "DOCUMENT_ROOT"))
1.122 parser 292: request_info.document_root=env_document_root;
1.216.2.3! paf 293: else if(const char* path_info=SAPI::get_env(SAPI_info, "PATH_INFO")) {
1.122 parser 294: // IIS
1.166 paf 295: size_t len=min(sizeof(document_root_buf)-1, strlen(filespec_to_process)-strlen(path_info));
296: memcpy(document_root_buf, filespec_to_process, len); document_root_buf[len]=0;
297: request_info.document_root=document_root_buf;
1.122 parser 298: } else
1.165 paf 299: throw Exception("parser.runtime",
1.216.2.3! paf 300: Exception::undefined_source,
1.165 paf 301: "CGI: no PATH_INFO defined(in reinventing DOCUMENT_ROOT)");
1.122 parser 302: } else {
1.166 paf 303: full_file_spec("", document_root_buf, sizeof(document_root_buf));
304: request_info.document_root=document_root_buf;
1.122 parser 305: }
306: request_info.path_translated=filespec_to_process;
307: request_info.method=request_method ? request_method : "GET";
1.216.2.3! paf 308: const char* query_string=SAPI::get_env(SAPI_info, "QUERY_STRING");
1.122 parser 309: request_info.query_string=query_string;
310: if(cgi) {
1.214 paf 311: // few absolute obligatory
1.216.2.3! paf 312: const char* path_info=SAPI::get_env(SAPI_info, "PATH_INFO");
1.214 paf 313: if(!path_info)
314: SAPI::die("CGI: illegal call (missing PATH_INFO)");
1.216.2.3! paf 315: const char* script_name=SAPI::get_env(SAPI_info, "SCRIPT_NAME");
1.214 paf 316: if(!script_name)
317: SAPI::die("CGI: illegal call (missing SCRIPT_NAME)");
318:
1.216.2.3! paf 319: const char* env_request_uri=SAPI::get_env(SAPI_info, "REQUEST_URI");
1.214 paf 320: if(env_request_uri)
1.122 parser 321: request_info.uri=env_request_uri;
1.214 paf 322: else
1.122 parser 323: if(query_string) {
1.198 paf 324: char *reconstructed_uri=(char *)request_pool.malloc(
1.122 parser 325: strlen(path_info)+1/*'?'*/+
326: strlen(query_string)+1/*0*/);
327: strcpy(reconstructed_uri, path_info);
328: strcat(reconstructed_uri, "?");
329: strcat(reconstructed_uri, query_string);
330: request_info.uri=reconstructed_uri;
331: } else
332: request_info.uri=path_info;
1.214 paf 333:
334: if(env_request_uri) { // apache & others stuck to standards
335: /*
336: http://parser3/env.html?123 =OK
337: $request:uri=/env.html?123
338: REQUEST_URI='/env.html?123'
339: SCRIPT_NAME='/cgi-bin/parser3'
340: PATH_INFO='/env.html'
341:
342: http://parser3/cgi-bin/parser3/env.html?123 =ERROR
343: $request:uri=/cgi-bin/parser3/env.html?123
344: REQUEST_URI='/cgi-bin/parser3/env.html?123'
345: SCRIPT_NAME='/cgi-bin/parser3'
346: PATH_INFO='/env.html'
347: */
348: size_t script_name_len=strlen(script_name);
349: size_t uri_len=strlen(env_request_uri);
350: if(strncmp(env_request_uri, script_name, script_name_len)==0 &&
351: script_name_len != uri_len) // under IIS they are the same
352: SAPI::die("CGI: illegal call (1)");
353: } else { // seen on IIS5
354: /*
355: http://nestle/env.html?123 =OK
356: $request:uri=/env.html?123
357: REQUEST_URI=''
358: SCRIPT_NAME='/env.html'
359: PATH_INFO='/env.html'
360:
361: http://nestle/cgi-bin/parser3.exe/env.html =ERROR
362: $request:uri=/env.html
363: REQUEST_URI=''
364: SCRIPT_NAME='/cgi-bin/parser3.exe'
365: PATH_INFO='/env.html'
366: */
367: if(strcmp(script_name, path_info)!=0)
368: SAPI::die("CGI: illegal call (2)");
369: }
1.122 parser 370: } else
1.177 paf 371: request_info.uri="";
1.122 parser 372:
1.216.2.3! paf 373: request_info.content_type=SAPI::get_env(SAPI_info, "CONTENT_TYPE");
! 374: const char* content_length=SAPI::get_env(SAPI_info, "CONTENT_LENGTH");
1.122 parser 375: request_info.content_length=(content_length?atoi(content_length):0);
1.216.2.3! paf 376: request_info.cookie=SAPI::get_env(SAPI_info, "HTTP_COOKIE");
1.184 paf 377: request_info.mail_received=mail_received;
378:
1.198 paf 379:
1.122 parser 380: // prepare to process request
1.216.2.3! paf 381: Request request(SAPI_info, request_pool,
1.122 parser 382: request_info,
1.184 paf 383: /*#ifdef _DEBUG
1.143 paf 384: String::UL_HTML|String::UL_OPTIMIZE_BIT
1.184 paf 385: #else*/
1.143 paf 386: cgi ? String::UL_HTML|String::UL_OPTIMIZE_BIT : String::UL_AS_IS
1.184 paf 387: /*#endif*/
1.143 paf 388: ,
1.130 paf 389: true /* status_allowed */);
1.201 paf 390:
391: // get request ptr for signal handlers
392: ::request=&request;
393:
1.181 paf 394: char config_filespec_buf[MAX_STRING];
1.193 paf 395: if(!config_filespec_cstr) {
1.216.2.1 paf 396: const char* config_by_env=getenv(PARSER_CONFIG_ENV_NAME);
1.193 paf 397: if(!config_by_env)
398: config_by_env=getenv(REDIRECT_PREFIX PARSER_CONFIG_ENV_NAME);
399: if(config_by_env)
400: config_filespec_cstr=config_by_env;
401: else {
402: // beside by binary
403: char beside_binary_path[MAX_STRING];
404: strncpy(beside_binary_path, argv0, MAX_STRING-1); beside_binary_path[MAX_STRING-1]=0; // filespec of my binary
405: if(!(
406: rsplit(beside_binary_path, '/') ||
407: rsplit(beside_binary_path, '\\'))) { // strip filename
408: // no path, just filename
409: // @todo full path, not ./!
410: beside_binary_path[0]='.'; beside_binary_path[1]=0;
411: }
412: snprintf(config_filespec_buf, MAX_STRING,
413: "%s/%s",
414: beside_binary_path, AUTO_FILE_NAME);
415: config_filespec_cstr=config_filespec_buf;
1.197 paf 416: fail_on_config_read_problem=entry_exists(config_filespec_cstr);
1.193 paf 417: }
1.122 parser 418: }
419:
420: // process the request
421: request.core(
1.193 paf 422: config_filespec_cstr, fail_on_config_read_problem,
1.122 parser 423: header_only);
1.201 paf 424:
425: // no request [prevent signal handlers from accessing invalid memory]
426: ::request=0;
1.122 parser 427:
428: //
1.216.2.3! paf 429: pa_done_socks();
1.122 parser 430:
431: #ifdef DEBUG_POOL_MALLOC
432: extern void log_pool_stats(Pool& pool);
1.198 paf 433: log_pool_stats(request_pool);
1.122 parser 434: #endif
1.160 paf 435:
436: #ifdef DEBUG_STRING_APPENDS_VS_EXPANDS
1.216.2.3! paf 437: SAPI::log(SAPI_info,
1.161 paf 438: "string piece appends=%lu, wcontext_result_size=%lu, string_string_shortcut_economy_closer=%lu, total_alloc_size=%lu",
1.160 paf 439: string_piece_appends,
440: wcontext_result_size,
441: string_string_shortcut_economy,
442: total_alloc_size);
443: #endif
444:
1.122 parser 445: }
446:
1.184 paf 447: static void call_real_parser_handler__do_SEH(
1.216.2.1 paf 448: const char* filespec_to_process,
449: const char* request_method, bool header_only) {
1.133 paf 450: #if _MSC_VER && !defined(_DEBUG)
1.122 parser 451: LPEXCEPTION_POINTERS system_exception=0;
452: __try {
453: #endif
454: real_parser_handler(
455: filespec_to_process,
456: request_method, header_only);
457:
1.133 paf 458: #if _MSC_VER && !defined(_DEBUG)
1.122 parser 459: } __except (
460: (system_exception=GetExceptionInformation()),
461: EXCEPTION_EXECUTE_HANDLER) {
462:
463: if(system_exception)
464: if(_EXCEPTION_RECORD *er=system_exception->ExceptionRecord)
1.165 paf 465: throw Exception(0,
466: 0,
467: "Exception 0x%08X at 0x%08X", er->ExceptionCode, er->ExceptionAddress);
1.122 parser 468: else
1.165 paf 469: throw Exception(0, 0, "Exception <no exception record>");
1.122 parser 470: else
1.165 paf 471: throw Exception(0, 0, "Exception <no exception information>");
1.122 parser 472: }
473: #endif
474: }
475:
1.139 paf 476: #if _MSC_VER
1.135 paf 477: int failed_new(size_t size) {
478: SAPI::die("out of memory in 'new', failed to allocated %u bytes", size);
479: return 0; // not reached
1.131 paf 480: }
1.135 paf 481: #endif
1.131 paf 482:
1.135 paf 483: #ifdef HAVE_SET_NEW_HANDLER
1.184 paf 484: static void failed_new() {
1.135 paf 485: SAPI::die("out of memory in 'new'");
1.131 paf 486: }
487: #endif
488:
1.216.2.1 paf 489: static void usage(const char* program) {
1.188 paf 490: printf(
1.216.2.1 paf 491: "Parser/%s Copyright(c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)\n"
1.184 paf 492: "Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)\n"
493: "\n"
494: "Usage: %s [options] file\n"
495: "Options are:\n"
1.185 paf 496: #ifdef WITH_MAILRECEIVE
1.193 paf 497: " -m Parse mail, put received letter to $mail:received\n"
1.184 paf 498: #endif
1.193 paf 499: " -f config_file Use this config file (/path/to/auto.p)\n"
500: " -h Display usage information (this message)\n"
1.184 paf 501: , PARSER_VERSION,
502: program);
503: exit(EINVAL);
504: }
505:
1.195 paf 506: int main(int argc, char *argv[]) {
1.203 paf 507: #ifdef SIGUSR1
1.205 paf 508: if(signal(SIGUSR1, SIGUSR1_handler)==SIG_ERR)
1.203 paf 509: SAPI::die("Can not set handler for SIGUSR1");
510: #endif
511: #ifdef SIGPIPE
1.205 paf 512: if(signal(SIGPIPE, SIGPIPE_handler)==SIG_ERR)
1.203 paf 513: SAPI::die("Can not set handler for SIGPIPE");
514: #endif
515:
516:
1.185 paf 517: #ifdef DEBUG_MAILRECEIVE
518: if(FILE *fake_in=fopen(DEBUG_MAILRECEIVE, "rt")) {
1.184 paf 519: dup2(fake_in->_file, 0/*STDIN_FILENO*/);
520: }
521: #endif
522:
1.178 paf 523: #ifdef _DEBUG
524: // _crtBreakAlloc=33112;
525: #endif
1.144 paf 526: // _asm int 3;
1.193 paf 527: argv0=argv[0];
1.45 paf 528:
1.32 paf 529: umask(2);
530:
1.3 paf 531: // were we started as CGI?
1.146 paf 532: cgi=
1.109 parser 533: getenv("SERVER_SOFTWARE") ||
534: getenv("SERVER_NAME") ||
535: getenv("GATEWAY_INTERFACE") ||
536: getenv("REQUEST_METHOD");
1.5 paf 537:
1.184 paf 538: char *raw_filespec_to_process;
1.210 paf 539: if(cgi) {
1.184 paf 540: raw_filespec_to_process=getenv("PATH_TRANSLATED");
1.210 paf 541: if(raw_filespec_to_process && !*raw_filespec_to_process)
542: raw_filespec_to_process=0;
543: } else {
1.184 paf 544: optind = 1;
545: opterr = 0;
546: int c;
1.193 paf 547: while((c = getopt(argc, argv, "hf:"
1.185 paf 548: #ifdef WITH_MAILRECEIVE
1.184 paf 549: "m"
550: #endif
551: )) > 0) {
552: switch (c) {
553: case 'h':
554: usage(argv[0]);
1.193 paf 555: break;
556: case 'f':
557: config_filespec_cstr=optarg;
1.184 paf 558: break;
1.185 paf 559: #ifdef WITH_MAILRECEIVE
1.184 paf 560: case 'm':
561: mail_received=true;
562: break;
563: #endif
564: default:
565: fprintf(stderr, "%s: invalid option '%c'\n", argv[0], optopt);
566: usage(argv[0]);
567: break;
568: }
569: }
570: if (optind != argc - 1) {
571: fprintf(stderr, "%s: file not specified\n", argv[0]);
572: usage(argv[0]);
1.10 paf 573: }
1.184 paf 574:
575: raw_filespec_to_process=argv[optind++];
1.10 paf 576: }
577:
1.100 parser 578: #ifdef WIN32
579: setmode(fileno(stdin), _O_BINARY);
580: setmode(fileno(stdout), _O_BINARY);
581: setmode(fileno(stderr), _O_BINARY);
582: #endif
583:
1.139 paf 584: #if _MSC_VER
1.138 paf 585: _set_new_handler(failed_new);
1.148 paf 586:
587: #ifdef _DEBUG
588: // Get current flag
589: int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
590:
591: // Turn on leak-checking bit
592: tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
593:
594: // Set flag to the new value
595: _CrtSetDbgFlag( tmpFlag );
596: // _CrtSetBreakAlloc(471);
597:
598: #endif
599:
1.138 paf 600: #endif
601:
602: #ifdef HAVE_SET_NEW_HANDLER
603: std::set_new_handler(failed_new);
604: #endif
605:
1.166 paf 606: char filespec_to_process[MAX_STRING];
607: full_file_spec(raw_filespec_to_process, filespec_to_process, sizeof(filespec_to_process));
1.10 paf 608:
1.216.2.1 paf 609: const char* request_method=getenv("REQUEST_METHOD");
1.35 paf 610: bool header_only=request_method && strcasecmp(request_method, "HEAD")==0;
1.131 paf 611:
1.122 parser 612: try { // global try
613: call_real_parser_handler__do_SEH(
614: filespec_to_process,
615: request_method, header_only);
616: } catch(const Exception& e) { // global problem
1.44 paf 617: // don't allocate anything on pool here:
618: // possible pool' exception not catch-ed now
619: // and there could be out-of-memory exception
1.43 paf 620:
1.144 paf 621: SAPI::die("exception in request exception handler: %s", e.comment());
1.134 paf 622: #ifndef _DEBUG
1.131 paf 623: } catch(...) {
1.134 paf 624: SAPI::die("<unknown exception>");
1.133 paf 625: #endif
1.16 paf 626: }
1.109 parser 627:
1.203 paf 628: //_asm int 3;
1.134 paf 629: return 0;
1.1 paf 630: }
E-mail: