View | Details | Raw Unified | Return to bug 57501
Collapse All | Expand All

(-)src/apache-2/mod_rivet.c (-32 / +129 lines)
Lines 101-106 Link Here
101
101
102
mod_rivet_globals* rivet_module_globals = NULL;
102
mod_rivet_globals* rivet_module_globals = NULL;
103
103
104
/* -- Rivet_PrintErrorMessage
105
 *
106
 * Utility function to print the error message stored in errorInfo
107
 * with a custom header. This procedure is called to print standard
108
 * errors when one of Tcl scripts fails
109
 * 
110
 * Arguments:
111
 *
112
 *   - Tcl_Interp* interp: the Tcl interpreter that was running the script
113
 *                         (and therefore the built-in variable errorInfo
114
 *                          keeps the message)
115
 *   - const char* error: Custom error header
116
 */
117
118
static void 
119
Rivet_PrintErrorMessage (Tcl_Interp* interp,const char* error_header)
120
{
121
    Tcl_Obj* errormsg  = Tcl_NewObj();
122
123
    Tcl_IncrRefCount(errormsg);
124
    Tcl_AppendStringsToObj(errormsg,"puts \"",error_header,"<br />\"\n",NULL);
125
    Tcl_AppendStringsToObj(errormsg,"puts \"<pre>$errorInfo</pre>\"\n",NULL);
126
    Tcl_EvalObjEx(interp,errormsg,0);
127
    Tcl_DecrRefCount(errormsg);
128
}
129
104
/*
130
/*
105
 * -- Rivet_chdir_file (const char* filename)
131
 * -- Rivet_chdir_file (const char* filename)
106
 * 
132
 * 
Lines 299-304 Link Here
299
    }
325
    }
300
}
326
}
301
327
328
/* -- Rivet_ExecuteErrorHandler
329
 *
330
 * Invoking either the default error handler or the ErrorScript.
331
 * In case the error handler fails a standard error message is printed
332
 * (you're better off if you make your error handlers fail save)
333
 *
334
 * Arguments:
335
 *
336
 *  - Tcl_Interp* interp: the Tcl interpreter
337
 *  - Tcl_Obj*    tcl_script_obj: the script that failed (to retrieve error
338
 *                info from it
339
 *  - request_rec* req: current request obj pointer
340
 * 
341
 * Returned value:
342
 *
343
 *  - A Tcl status
344
 */
345
346
static int 
347
Rivet_ExecuteErrorHandler (Tcl_Interp* interp,Tcl_Obj* tcl_script_obj, request_rec* req)
348
{
349
    int                     result;
350
    rivet_server_conf*      conf = Rivet_GetConf(req);
351
    Tcl_Obj*                errscript;
352
353
    /* We extract information from the errorOutbuf variable. Notice that tcl_script_obj
354
     * can either be the request processing script or conf->rivet_abort_script
355
     */
356
357
    Tcl_SetVar( interp, "errorOutbuf",Tcl_GetStringFromObj( tcl_script_obj, NULL ),TCL_GLOBAL_ONLY );
358
359
    /* If we don't have an error script, use the default error handler. */
360
    if (conf->rivet_error_script) {
361
        errscript = conf->rivet_error_script;
362
    } else {
363
        errscript = conf->rivet_default_error_script;
364
    }
365
366
    Tcl_IncrRefCount(errscript);
367
    result = Tcl_EvalObjEx(interp, errscript, 0);
368
    if (result == TCL_ERROR) {
369
        Rivet_PrintErrorMessage(interp,"<b>Rivet ErrorScript failed</b>");
370
    }
371
372
    /* This shouldn't make the default_error_script go away,
373
     * because it gets a Tcl_IncrRefCount when it is created.
374
     */
375
    Tcl_DecrRefCount(errscript);
376
377
    return result;
378
}
379
380
302
/* -- Rivet_ExecuteAndCheck
381
/* -- Rivet_ExecuteAndCheck
303
 * 
382
 * 
304
 * Tcl script execution central procedure. The script stored
383
 * Tcl script execution central procedure. The script stored
Lines 316-322 Link Here
316
 *
395
 *
317
 *   Returned value:
396
 *   Returned value:
318
 *
397
 *
319
 *      - invariably TCL_OK
398
 *      - One of the Tcl defined returned value of Tcl_EvelObjExe (TCL_OK, 
399
 *        TCL_ERROR, TCL_BREAK etc.)
320
 *
400
 *
321
 *   Side effects:
401
 *   Side effects:
322
 *
402
 *
Lines 330-336 Link Here
330
{
410
{
331
    int                     result;
411
    int                     result;
332
    rivet_server_conf*      conf = Rivet_GetConf(req);
412
    rivet_server_conf*      conf = Rivet_GetConf(req);
333
    rivet_interp_globals*   globals = Tcl_GetAssocData(interp, "rivet", NULL);
413
    rivet_interp_globals*   globals = Tcl_GetAssocData( conf->server_interp, "rivet", NULL );
334
414
335
    Tcl_Preserve (interp);
415
    Tcl_Preserve (interp);
336
    result = Tcl_EvalObjEx(interp, tcl_script_obj, 0);
416
    result = Tcl_EvalObjEx(interp, tcl_script_obj, 0);
Lines 337-343 Link Here
337
417
338
    if (result == TCL_ERROR) {
418
    if (result == TCL_ERROR) {
339
419
340
        Tcl_Obj*    errscript;
341
        Tcl_Obj*    errorCodeListObj;
420
        Tcl_Obj*    errorCodeListObj;
342
        Tcl_Obj*    errorCodeElementObj;
421
        Tcl_Obj*    errorCodeElementObj;
343
        char*       errorCodeSubString;
422
        char*       errorCodeSubString;
Lines 376-414 Link Here
376
            {
455
            {
377
                if (conf->rivet_abort_script) 
456
                if (conf->rivet_abort_script) 
378
                {
457
                {
458
459
                    /* Ideally an AbortScript should be fail safe, but in case
460
                     * it fails we give a chance to the subsequent ErrorScript
461
                     * to catch this error.
462
                     */
463
379
                    if (Tcl_EvalObjEx(interp,conf->rivet_abort_script,0) == TCL_ERROR)
464
                    if (Tcl_EvalObjEx(interp,conf->rivet_abort_script,0) == TCL_ERROR)
380
                    {
465
                    {
381
                        CONST84 char *errorinfo = Tcl_GetVar( interp, "errorInfo", 0 );
466
382
                        TclWeb_PrintError("<b>Rivet AbortScript failed!</b>",1,globals->req);
467
                        /* This is not elegant, but we want to avoid to print
383
                        TclWeb_PrintError(errorinfo,0,globals->req);
468
                         * the default AbortScript error message if a custom ErrorScript 
469
                         * will handle this error and in case print its own error message.
470
                         */
471
472
                        if (conf->rivet_error_script == NULL) 
473
                        {
474
                            Rivet_PrintErrorMessage(interp,"<b>Rivet AbortScript failed</b>");
475
                        }
476
                        Rivet_ExecuteErrorHandler(interp,conf->rivet_abort_script,req);
384
                    }
477
                    }
385
                }
478
                }
386
                goto good;
387
            }
479
            }
388
        }
480
        }
481
        else if (!globals->page_aborting)
482
        {
483
            /* Invoke Rivet error handler */
389
484
390
        Tcl_SetVar( interp, "errorOutbuf",Tcl_GetStringFromObj( tcl_script_obj, NULL ),TCL_GLOBAL_ONLY );
485
            Rivet_ExecuteErrorHandler(interp,tcl_script_obj,req);
391
486
392
        /* If we don't have an error script, use the default error handler. */
393
        if (conf->rivet_error_script) {
394
            errscript = conf->rivet_error_script;
395
        } else {
396
            errscript = conf->rivet_default_error_script;
397
        }
487
        }
398
399
        Tcl_IncrRefCount(errscript);
400
        if (Tcl_EvalObjEx(interp, errscript, 0) == TCL_ERROR) {
401
            CONST84 char *errorinfo = Tcl_GetVar( interp, "errorInfo", 0 );
402
            TclWeb_PrintError("<b>Rivet ErrorScript failed!</b>",1,globals->req);
403
            TclWeb_PrintError( errorinfo, 0, globals->req );
404
        }
405
406
        /* This shouldn't make the default_error_script go away,
407
         * because it gets a Tcl_IncrRefCount when it is created. */
408
        Tcl_DecrRefCount(errscript);
409
    }
488
    }
410
411
good:
412
    
489
    
413
    /* Tcl_Flush moved to the end of Rivet_SendContent */
490
    /* Tcl_Flush moved to the end of Rivet_SendContent */
414
491
Lines 425-431 Link Here
425
 * if a Tcl script.
502
 * if a Tcl script.
426
 *
503
 *
427
 * This is a separate function so that it may be called from command 'parse'
504
 * This is a separate function so that it may be called from command 'parse'
505
 * 
506
 * Returned value:
428
 *
507
 *
508
 *   - One of the Tcl defined values returned by Rivet_ExecuteAndCheck (TCL_OK, 
509
 *     TCL_ERROR, TCL_BREAK etc.)
510
 *
429
 * Arguments:
511
 * Arguments:
430
 *
512
 *
431
 *   - TclWebRequest: pointer to the structure collecting Tcl and Apache data
513
 *   - TclWebRequest: pointer to the structure collecting Tcl and Apache data
Lines 434-439 Link Here
434
 *   - toplevel:      integer to be interpreted as a boolean meaning the
516
 *   - toplevel:      integer to be interpreted as a boolean meaning the
435
 *                    file is pointed by the request. When 0 that's a subtemplate
517
 *                    file is pointed by the request. When 0 that's a subtemplate
436
 *                    to be parsed and executed from another template
518
 *                    to be parsed and executed from another template
519
 *
437
 */
520
 */
438
521
439
int
522
int
Lines 443-449 Link Here
443
    int isNew = 0;
526
    int isNew = 0;
444
    int result = 0;
527
    int result = 0;
445
528
446
    Tcl_Obj *outbuf = NULL;
529
    Tcl_Obj *outbuf      = NULL;
447
    Tcl_HashEntry *entry = NULL;
530
    Tcl_HashEntry *entry = NULL;
448
531
449
    time_t ctime;
532
    time_t ctime;
Lines 596-601 Link Here
596
679
597
    rsc->user_scripts_updated = 0;
680
    rsc->user_scripts_updated = 0;
598
    result = Rivet_ExecuteAndCheck(interp, outbuf, req->req);
681
    result = Rivet_ExecuteAndCheck(interp, outbuf, req->req);
682
683
    if (result == TCL_ERROR)
684
    {
685
        rivet_interp_globals* globals = Tcl_GetAssocData( rsc->server_interp, "rivet", NULL );
686
687
        /* If this is a toplevel script */
688
689
        if (toplevel && globals->page_aborting) 
690
        {
691
            result = TCL_OK;
692
        }
693
    } 
694
599
    Tcl_DecrRefCount(outbuf);
695
    Tcl_DecrRefCount(outbuf);
600
696
601
    return result;
697
    return result;
Lines 1477-1483 Link Here
1477
    if (Rivet_ParseExecFile(globals->req, r->filename, 1) != TCL_OK)
1573
    if (Rivet_ParseExecFile(globals->req, r->filename, 1) != TCL_OK)
1478
    {
1574
    {
1479
        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r->server, 
1575
        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r->server, 
1480
                     MODNAME ": Error parsing exec file '%s': %s",
1576
                     MODNAME ": Error in Rivet_ParseExecFile exec file '%s': %s",
1481
                     r->filename,
1577
                     r->filename,
1482
                     Tcl_GetVar(interp, "errorInfo", 0));
1578
                     Tcl_GetVar(interp, "errorInfo", 0));
1483
    }
1579
    }
Lines 1486-1496 Link Here
1486
1582
1487
    if (rsc->after_every_script)
1583
    if (rsc->after_every_script)
1488
    {
1584
    {
1489
        if (Rivet_ExecuteAndCheck(interp, rsc->after_every_script,r) == TCL_ERROR)
1585
        int tcl_status;
1586
1587
        tcl_status = Rivet_ExecuteAndCheck(interp, rsc->after_every_script,r);
1588
        if ((tcl_status == TCL_ERROR) && !globals->page_aborting)
1490
        {
1589
        {
1491
            CONST84 char *errorinfo = Tcl_GetVar( interp, "errorInfo", 0 );
1590
            Rivet_PrintErrorMessage(interp,"<b>Rivet AfterEveryScript failed</b>");
1492
            TclWeb_PrintError("<b>Rivet AfterEveryScript failed!</b>",1,globals->req);
1493
            TclWeb_PrintError( errorinfo, 0, globals->req );
1494
        }
1591
        }
1495
    }
1592
    }
1496
1593

Return to bug 57501