Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 29893
Collapse All | Expand All

(-)httpd-2.0/modules/generators/mod_cgi.c (-160 / +319 lines)
Lines 32-39 Link Here
32
#include "apr_optional.h"
32
#include "apr_optional.h"
33
#include "apr_buckets.h"
33
#include "apr_buckets.h"
34
#include "apr_lib.h"
34
#include "apr_lib.h"
35
#include "apr_poll.h"
35
36
36
#define APR_WANT_STRFUNC
37
#define APR_WANT_STRFUNC
38
#define APR_WANT_MEMFUNC
37
#include "apr_want.h"
39
#include "apr_want.h"
38
40
39
#define CORE_PRIVATE
41
#define CORE_PRIVATE
Lines 191-203 Link Here
191
193
192
/* Soak up stderr from a script and redirect it to the error log. 
194
/* Soak up stderr from a script and redirect it to the error log. 
193
 */
195
 */
194
static void log_script_err(request_rec *r, apr_file_t *script_err)
196
static apr_status_t log_script_err(request_rec *r, apr_file_t *script_err)
195
{
197
{
196
    char argsbuffer[HUGE_STRING_LEN];
198
    char argsbuffer[HUGE_STRING_LEN];
197
    char *newline;
199
    char *newline;
200
    apr_status_t rv;
198
201
199
    while (apr_file_gets(argsbuffer, HUGE_STRING_LEN,
202
    while ((rv = apr_file_gets(argsbuffer, HUGE_STRING_LEN,
200
                         script_err) == APR_SUCCESS) {
203
                               script_err)) == APR_SUCCESS) {
201
        newline = strchr(argsbuffer, '\n');
204
        newline = strchr(argsbuffer, '\n');
202
        if (newline) {
205
        if (newline) {
203
            *newline = '\0';
206
            *newline = '\0';
Lines 205-210 Link Here
205
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 
208
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 
206
                      "%s", argsbuffer);            
209
                      "%s", argsbuffer);            
207
    }
210
    }
211
212
    return rv;
208
}
213
}
209
214
210
static int log_script(request_rec *r, cgi_server_conf * conf, int ret,
215
static int log_script(request_rec *r, cgi_server_conf * conf, int ret,
Lines 270-276 Link Here
270
        apr_file_printf(f, "%s\n", sbuf);
275
        apr_file_printf(f, "%s\n", sbuf);
271
276
272
    first = 1;
277
    first = 1;
273
    APR_BRIGADE_FOREACH(e, bb) {
278
    for (e = APR_BRIGADE_FIRST(bb);
279
         e != APR_BRIGADE_SENTINEL(bb);
280
         e = APR_BUCKET_NEXT(e))
281
    {
274
        if (APR_BUCKET_IS_EOS(e)) {
282
        if (APR_BUCKET_IS_EOS(e)) {
275
            break;
283
            break;
276
        }
284
        }
Lines 431-444 Link Here
431
    }
439
    }
432
    else {
440
    else {
433
        procnew = apr_pcalloc(p, sizeof(*procnew));
441
        procnew = apr_pcalloc(p, sizeof(*procnew));
434
        if (e_info->prog_type == RUN_AS_SSI) {
435
            SPLIT_AND_PASS_PRETAG_BUCKETS(*(e_info->bb), e_info->ctx,
436
                                          e_info->next, rc);
437
            if (rc != APR_SUCCESS) {
438
                return rc;
439
            }
440
        }
441
442
        rc = ap_os_create_privileged_process(r, procnew, command, argv, env,
442
        rc = ap_os_create_privileged_process(r, procnew, command, argv, env,
443
                                             procattr, p);
443
                                             procattr, p);
444
    
444
    
Lines 446-452 Link Here
446
            /* Bad things happened. Everyone should have cleaned up. */
446
            /* Bad things happened. Everyone should have cleaned up. */
447
            ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, rc, r,
447
            ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, rc, r,
448
                          "couldn't create child process: %d: %s", rc,
448
                          "couldn't create child process: %d: %s", rc,
449
                          apr_filename_of_pathname(r->filename));
449
                          apr_filepath_name_get(r->filename));
450
        }
450
        }
451
        else {
451
        else {
452
            apr_pool_note_subprocess(p, procnew, APR_KILL_AFTER_TIMEOUT);
452
            apr_pool_note_subprocess(p, procnew, APR_KILL_AFTER_TIMEOUT);
Lines 528-534 Link Here
528
    const char *buf;
528
    const char *buf;
529
    apr_size_t len;
529
    apr_size_t len;
530
    apr_status_t rv;
530
    apr_status_t rv;
531
    APR_BRIGADE_FOREACH(e, bb) {
531
532
    for (e = APR_BRIGADE_FIRST(bb);
533
         e != APR_BRIGADE_SENTINEL(bb);
534
         e = APR_BUCKET_NEXT(e))
535
    {
532
        if (APR_BUCKET_IS_EOS(e)) {
536
        if (APR_BUCKET_IS_EOS(e)) {
533
            break;
537
            break;
534
        }
538
        }
Lines 539-544 Link Here
539
    }
543
    }
540
}
544
}
541
545
546
#if APR_FILES_AS_SOCKETS
547
548
/* A CGI bucket type is needed to catch any output to stderr from the
549
 * script; see PR 22030. */
550
static const apr_bucket_type_t bucket_type_cgi;
551
552
struct cgi_bucket_data {
553
    apr_pollset_t *pollset;
554
    request_rec *r;
555
};
556
557
/* Create a CGI bucket using pipes from script stdout 'out'
558
 * and stderr 'err', for request 'r'. */
559
static apr_bucket *cgi_bucket_create(request_rec *r,
560
                                     apr_file_t *out, apr_file_t *err,
561
                                     apr_bucket_alloc_t *list)
562
{
563
    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
564
    apr_status_t rv;
565
    apr_pollfd_t fd;
566
    struct cgi_bucket_data *data = apr_palloc(r->pool, sizeof *data);
567
    
568
    APR_BUCKET_INIT(b);
569
    b->free = apr_bucket_free;
570
    b->list = list;
571
    b->type = &bucket_type_cgi;
572
    b->length = (apr_size_t)(-1);
573
    b->start = -1;
574
575
    /* Create the pollset */
576
    rv = apr_pollset_create(&data->pollset, 2, r->pool, 0);
577
    AP_DEBUG_ASSERT(rv == APR_SUCCESS);
578
579
    fd.desc_type = APR_POLL_FILE;
580
    fd.reqevents = APR_POLLIN;
581
    fd.p = r->pool;
582
    fd.desc.f = out; /* script's stdout */
583
    fd.client_data = (void *)1;
584
    rv = apr_pollset_add(data->pollset, &fd);
585
    AP_DEBUG_ASSERT(rv == APR_SUCCESS);
586
    
587
    fd.desc.f = err; /* script's stderr */
588
    fd.client_data = (void *)2;
589
    rv = apr_pollset_add(data->pollset, &fd);
590
    AP_DEBUG_ASSERT(rv == APR_SUCCESS);
591
    
592
    data->r = r;
593
    b->data = data;
594
    return b;
595
}
596
597
/* Create a duplicate CGI bucket using given bucket data */
598
static apr_bucket *cgi_bucket_dup(struct cgi_bucket_data *data,
599
                                  apr_bucket_alloc_t *list)
600
{
601
    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
602
    APR_BUCKET_INIT(b);
603
    b->free = apr_bucket_free;
604
    b->list = list;
605
    b->type = &bucket_type_cgi;
606
    b->length = (apr_size_t)(-1);
607
    b->start = -1;
608
    b->data = data;
609
    return b;
610
}
611
612
/* Handle stdout from CGI child.  Duplicate of logic from the _read
613
 * method of the real APR pipe bucket implementation. */
614
static apr_status_t cgi_read_stdout(apr_bucket *a, apr_file_t *out,
615
                                    const char **str, apr_size_t *len)
616
{
617
    char *buf;
618
    apr_status_t rv;
619
620
    *str = NULL;
621
    *len = APR_BUCKET_BUFF_SIZE;
622
    buf = apr_bucket_alloc(*len, a->list); /* XXX: check for failure? */
623
624
    rv = apr_file_read(out, buf, len);
625
626
    if (rv != APR_SUCCESS && rv != APR_EOF) {
627
        apr_bucket_free(buf);
628
        return rv;
629
    }
630
631
    if (*len > 0) {
632
        struct cgi_bucket_data *data = a->data;
633
        apr_bucket_heap *h;
634
635
        /* Change the current bucket to refer to what we read */
636
        a = apr_bucket_heap_make(a, buf, *len, apr_bucket_free);
637
        h = a->data;
638
        h->alloc_len = APR_BUCKET_BUFF_SIZE; /* note the real buffer size */
639
        *str = buf;
640
        APR_BUCKET_INSERT_AFTER(a, cgi_bucket_dup(data, a->list));
641
    }
642
    else {
643
        apr_bucket_free(buf);
644
        a = apr_bucket_immortal_make(a, "", 0);
645
        *str = a->data;
646
    }
647
    return rv;
648
}
649
650
/* Read method of CGI bucket: polls on stderr and stdout of the child,
651
 * sending any stderr output immediately away to the error log. */
652
static apr_status_t cgi_bucket_read(apr_bucket *b, const char **str,
653
                                    apr_size_t *len, apr_read_type_e block)
654
{
655
    struct cgi_bucket_data *data = b->data;
656
    apr_interval_time_t timeout;
657
    apr_status_t rv;
658
    int gotdata = 0;
659
660
    timeout = block == APR_NONBLOCK_READ ? 0 : data->r->server->timeout;
661
662
    do {
663
        const apr_pollfd_t *results;
664
        apr_int32_t num;
665
666
        rv = apr_pollset_poll(data->pollset, timeout, &num, &results);
667
        if (APR_STATUS_IS_TIMEUP(rv)) {
668
            return timeout == 0 ? APR_EAGAIN : rv;
669
        }
670
        else if (APR_STATUS_IS_EINTR(rv)) {
671
            continue;
672
        }
673
        else if (rv != APR_SUCCESS) {
674
            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, data->r,
675
                          "poll failed waiting for CGI child");
676
            return rv;
677
        }
678
        
679
        for (; num; num--, results++) {
680
            if (results[0].client_data == (void *)1) {
681
                /* stdout */
682
                rv = cgi_read_stdout(b, results[0].desc.f, str, len);
683
                if (APR_STATUS_IS_EOF(rv)) {
684
                    rv = APR_SUCCESS;
685
                }
686
                gotdata = 1;
687
            } else {
688
                /* stderr */
689
                apr_status_t rv2 = log_script_err(data->r, results[0].desc.f);
690
                if (APR_STATUS_IS_EOF(rv2)) {
691
                    apr_pollset_remove(data->pollset, &results[0]);
692
                }
693
            }
694
        }
695
696
    } while (!gotdata);
697
698
    return rv;
699
}
700
701
static const apr_bucket_type_t bucket_type_cgi = {
702
    "CGI", 5, APR_BUCKET_DATA,
703
    apr_bucket_destroy_noop,
704
    cgi_bucket_read,
705
    apr_bucket_setaside_notimpl,
706
    apr_bucket_split_notimpl,
707
    apr_bucket_copy_notimpl
708
};
709
710
#endif
711
542
static int cgi_handler(request_rec *r)
712
static int cgi_handler(request_rec *r)
543
{
713
{
544
    int nph;
714
    int nph;
Lines 556-561 Link Here
556
    cgi_server_conf *conf;
726
    cgi_server_conf *conf;
557
    apr_status_t rv;
727
    apr_status_t rv;
558
    cgi_exec_info_t e_info;
728
    cgi_exec_info_t e_info;
729
    conn_rec *c = r->connection;
559
730
560
    if(strcmp(r->handler, CGI_MAGIC_TYPE) && strcmp(r->handler, "cgi-script"))
731
    if(strcmp(r->handler, CGI_MAGIC_TYPE) && strcmp(r->handler, "cgi-script"))
561
        return DECLINED;
732
        return DECLINED;
Lines 571-577 Link Here
571
        return DECLINED;
742
        return DECLINED;
572
    }
743
    }
573
744
574
    argv0 = apr_filename_of_pathname(r->filename);
745
    argv0 = apr_filepath_name_get(r->filename);
575
    nph = !(strncmp(argv0, "nph-", 4));
746
    nph = !(strncmp(argv0, "nph-", 4));
576
    conf = ap_get_module_config(r->server->module_config, &cgi_module);
747
    conf = ap_get_module_config(r->server->module_config, &cgi_module);
577
748
Lines 637-643 Link Here
637
    /* Transfer any put/post args, CERN style...
808
    /* Transfer any put/post args, CERN style...
638
     * Note that we already ignore SIGPIPE in the core server.
809
     * Note that we already ignore SIGPIPE in the core server.
639
     */
810
     */
640
    bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
811
    bb = apr_brigade_create(r->pool, c->bucket_alloc);
641
    seen_eos = 0;
812
    seen_eos = 0;
642
    child_stopped_reading = 0;
813
    child_stopped_reading = 0;
643
    if (conf->logname) {
814
    if (conf->logname) {
Lines 654-660 Link Here
654
            return rv;
825
            return rv;
655
        }
826
        }
656
827
657
        APR_BRIGADE_FOREACH(bucket, bb) {
828
        for (bucket = APR_BRIGADE_FIRST(bb);
829
             bucket != APR_BRIGADE_SENTINEL(bb);
830
             bucket = APR_BUCKET_NEXT(bucket))
831
        {
658
            const char *data;
832
            const char *data;
659
            apr_size_t len;
833
            apr_size_t len;
660
834
Lines 710-727 Link Here
710
    apr_file_flush(script_out);
884
    apr_file_flush(script_out);
711
    apr_file_close(script_out);
885
    apr_file_close(script_out);
712
886
887
    AP_DEBUG_ASSERT(script_in != NULL);
888
889
    apr_brigade_cleanup(bb);
890
891
#if APR_FILES_AS_SOCKETS
892
    apr_file_pipe_timeout_set(script_in, 0);
893
    apr_file_pipe_timeout_set(script_err, 0);
894
    
895
    b = cgi_bucket_create(r, script_in, script_err, c->bucket_alloc);
896
#else
897
    b = apr_bucket_pipe_create(script_in, c->bucket_alloc);
898
#endif
899
    APR_BRIGADE_INSERT_TAIL(bb, b);
900
    b = apr_bucket_eos_create(c->bucket_alloc);
901
    APR_BRIGADE_INSERT_TAIL(bb, b);
902
713
    /* Handle script return... */
903
    /* Handle script return... */
714
    if (script_in && !nph) {
904
    if (!nph) {
715
        conn_rec *c = r->connection;
716
        const char *location;
905
        const char *location;
717
        char sbuf[MAX_STRING_LEN];
906
        char sbuf[MAX_STRING_LEN];
718
        int ret;
907
        int ret;
719
908
720
        b = apr_bucket_pipe_create(script_in, c->bucket_alloc);
721
        APR_BRIGADE_INSERT_TAIL(bb, b);
722
        b = apr_bucket_eos_create(c->bucket_alloc);
723
        APR_BRIGADE_INSERT_TAIL(bb, b);
724
725
        if ((ret = ap_scan_script_header_err_brigade(r, bb, sbuf))) {
909
        if ((ret = ap_scan_script_header_err_brigade(r, bb, sbuf))) {
726
            return log_script(r, conf, ret, dbuf, sbuf, bb, script_err);
910
            return log_script(r, conf, ret, dbuf, sbuf, bb, script_err);
727
        }
911
        }
Lines 731-736 Link Here
731
        if (location && location[0] == '/' && r->status == 200) {
915
        if (location && location[0] == '/' && r->status == 200) {
732
            discard_script_output(bb);
916
            discard_script_output(bb);
733
            apr_brigade_destroy(bb);
917
            apr_brigade_destroy(bb);
918
            apr_file_pipe_timeout_set(script_err, r->server->timeout);
734
            log_script_err(r, script_err);
919
            log_script_err(r, script_err);
735
            /* This redirect needs to be a GET no matter what the original
920
            /* This redirect needs to be a GET no matter what the original
736
             * method was.
921
             * method was.
Lines 757-778 Link Here
757
        }
942
        }
758
943
759
        rv = ap_pass_brigade(r->output_filters, bb);
944
        rv = ap_pass_brigade(r->output_filters, bb);
760
761
        /* don't soak up script output if errors occurred
762
         * writing it out...  otherwise, we prolong the
763
         * life of the script when the connection drops
764
         * or we stopped sending output for some other
765
         * reason
766
         */
767
        if (rv == APR_SUCCESS && !r->connection->aborted) {
768
            log_script_err(r, script_err);
769
        }
770
771
        apr_file_close(script_err);
772
    }
945
    }
773
946
    else /* nph */ {
774
    if (script_in && nph) {
775
        conn_rec *c = r->connection;
776
        struct ap_filter_t *cur;
947
        struct ap_filter_t *cur;
777
        
948
        
778
        /* get rid of all filters up through protocol...  since we
949
        /* get rid of all filters up through protocol...  since we
Lines 786-799 Link Here
786
        }
957
        }
787
        r->output_filters = r->proto_output_filters = cur;
958
        r->output_filters = r->proto_output_filters = cur;
788
959
789
        bb = apr_brigade_create(r->pool, c->bucket_alloc);
960
        rv = ap_pass_brigade(r->output_filters, bb);
790
        b = apr_bucket_pipe_create(script_in, c->bucket_alloc);
791
        APR_BRIGADE_INSERT_TAIL(bb, b);
792
        b = apr_bucket_eos_create(c->bucket_alloc);
793
        APR_BRIGADE_INSERT_TAIL(bb, b);
794
        ap_pass_brigade(r->output_filters, bb);
795
    }
961
    }
796
962
963
    /* don't soak up script output if errors occurred writing it
964
     * out...  otherwise, we prolong the life of the script when the
965
     * connection drops or we stopped sending output for some other
966
     * reason */
967
    if (rv == APR_SUCCESS && !r->connection->aborted) {
968
        apr_file_pipe_timeout_set(script_err, r->server->timeout);
969
        log_script_err(r, script_err);
970
    }
971
    
972
    apr_file_close(script_err);
973
797
    return OK;                      /* NOT r->status, even if it has changed. */
974
    return OK;                      /* NOT r->status, even if it has changed. */
798
}
975
}
799
976
Lines 803-894 Link Here
803
 *   is the code required to handle the "exec" SSI directive.
980
 *   is the code required to handle the "exec" SSI directive.
804
 *============================================================================
981
 *============================================================================
805
 *============================================================================*/
982
 *============================================================================*/
806
static int include_cgi(char *s, request_rec *r, ap_filter_t *next,
983
static apr_status_t include_cgi(include_ctx_t *ctx, ap_filter_t *f,
807
                       apr_bucket *head_ptr, apr_bucket **inserted_head)
984
                                apr_bucket_brigade *bb, char *s)
808
{
985
{
809
    request_rec *rr = ap_sub_req_lookup_uri(s, r, next);
986
    request_rec *r = f->r;
987
    request_rec *rr = ap_sub_req_lookup_uri(s, r, f->next);
810
    int rr_status;
988
    int rr_status;
811
    apr_bucket  *tmp_buck, *tmp2_buck;
812
989
813
    if (rr->status != HTTP_OK) {
990
    if (rr->status != HTTP_OK) {
814
        ap_destroy_sub_req(rr);
991
        ap_destroy_sub_req(rr);
815
        return -1;
992
        return APR_EGENERAL;
816
    }
993
    }
817
994
818
    /* No hardwired path info or query allowed */
995
    /* No hardwired path info or query allowed */
819
820
    if ((rr->path_info && rr->path_info[0]) || rr->args) {
996
    if ((rr->path_info && rr->path_info[0]) || rr->args) {
821
        ap_destroy_sub_req(rr);
997
        ap_destroy_sub_req(rr);
822
        return -1;
998
        return APR_EGENERAL;
823
    }
999
    }
824
    if (rr->finfo.filetype != APR_REG) {
1000
    if (rr->finfo.filetype != APR_REG) {
825
        ap_destroy_sub_req(rr);
1001
        ap_destroy_sub_req(rr);
826
        return -1;
1002
        return APR_EGENERAL;
827
    }
1003
    }
828
1004
829
    /* Script gets parameters of the *document*, for back compatibility */
1005
    /* Script gets parameters of the *document*, for back compatibility */
830
831
    rr->path_info = r->path_info;       /* hard to get right; see mod_cgi.c */
1006
    rr->path_info = r->path_info;       /* hard to get right; see mod_cgi.c */
832
    rr->args = r->args;
1007
    rr->args = r->args;
833
1008
834
    /* Force sub_req to be treated as a CGI request, even if ordinary
1009
    /* Force sub_req to be treated as a CGI request, even if ordinary
835
     * typing rules would have called it something else.
1010
     * typing rules would have called it something else.
836
     */
1011
     */
837
838
    ap_set_content_type(rr, CGI_MAGIC_TYPE);
1012
    ap_set_content_type(rr, CGI_MAGIC_TYPE);
839
1013
840
    /* Run it. */
1014
    /* Run it. */
841
842
    rr_status = ap_run_sub_req(rr);
1015
    rr_status = ap_run_sub_req(rr);
843
    if (ap_is_HTTP_REDIRECT(rr_status)) {
1016
    if (ap_is_HTTP_REDIRECT(rr_status)) {
844
        apr_size_t len_loc;
845
        const char *location = apr_table_get(rr->headers_out, "Location");
1017
        const char *location = apr_table_get(rr->headers_out, "Location");
846
        conn_rec *c = r->connection;
847
1018
848
        location = ap_escape_html(rr->pool, location);
1019
        if (location) {
849
        len_loc = strlen(location);
1020
            char *buffer;
850
1021
851
        /* XXX: if most of this stuff is going to get copied anyway,
1022
            location = ap_escape_html(rr->pool, location);
852
         * it'd be more efficient to pstrcat it into a single pool buffer
1023
            buffer = apr_pstrcat(ctx->pool, "<a href=\"", location, "\">",
853
         * and a single pool bucket */
1024
                                 location, "</a>", NULL);
854
1025
855
        tmp_buck = apr_bucket_immortal_create("<A HREF=\"",
1026
            APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pool_create(buffer,
856
                                              sizeof("<A HREF=\"") - 1,
1027
                                    strlen(buffer), ctx->pool,
857
                                              c->bucket_alloc);
1028
                                    f->c->bucket_alloc));
858
        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
859
        tmp2_buck = apr_bucket_heap_create(location, len_loc, NULL,
860
                                           c->bucket_alloc);
861
        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
862
        tmp2_buck = apr_bucket_immortal_create("\">", sizeof("\">") - 1,
863
                                               c->bucket_alloc);
864
        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
865
        tmp2_buck = apr_bucket_heap_create(location, len_loc, NULL,
866
                                           c->bucket_alloc);
867
        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
868
        tmp2_buck = apr_bucket_immortal_create("</A>", sizeof("</A>") - 1,
869
                                               c->bucket_alloc);
870
        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
871
872
        if (*inserted_head == NULL) {
873
            *inserted_head = tmp_buck;
874
        }
1029
        }
875
    }
1030
    }
876
1031
877
    ap_destroy_sub_req(rr);
1032
    ap_destroy_sub_req(rr);
878
1033
879
    return 0;
1034
    return APR_SUCCESS;
880
}
1035
}
881
1036
882
1037
static apr_status_t include_cmd(include_ctx_t *ctx, ap_filter_t *f,
883
static int include_cmd(include_ctx_t *ctx, apr_bucket_brigade **bb,
1038
                                apr_bucket_brigade *bb, const char *command)
884
                       const char *command, request_rec *r, ap_filter_t *f)
885
{
1039
{
886
    cgi_exec_info_t  e_info;
1040
    cgi_exec_info_t  e_info;
887
    const char   **argv;
1041
    const char **argv;
888
    apr_file_t    *script_out = NULL, *script_in = NULL, *script_err = NULL;
1042
    apr_file_t *script_out = NULL, *script_in = NULL, *script_err = NULL;
889
    apr_bucket_brigade *bcgi;
890
    apr_bucket *b;
891
    apr_status_t rv;
1043
    apr_status_t rv;
1044
    request_rec *r = f->r;
892
1045
893
    add_ssi_vars(r);
1046
    add_ssi_vars(r);
894
1047
Lines 899-913 Link Here
899
    e_info.out_pipe    = APR_FULL_BLOCK;
1052
    e_info.out_pipe    = APR_FULL_BLOCK;
900
    e_info.err_pipe    = APR_NO_PIPE;
1053
    e_info.err_pipe    = APR_NO_PIPE;
901
    e_info.prog_type   = RUN_AS_SSI;
1054
    e_info.prog_type   = RUN_AS_SSI;
902
    e_info.bb          = bb;
1055
    e_info.bb          = &bb;
903
    e_info.ctx         = ctx;
1056
    e_info.ctx         = ctx;
904
    e_info.next        = f->next;
1057
    e_info.next        = f->next;
905
1058
906
    if ((rv = cgi_build_command(&command, &argv, r, r->pool, &e_info)) != APR_SUCCESS) {
1059
    if ((rv = cgi_build_command(&command, &argv, r, r->pool,
1060
                                &e_info)) != APR_SUCCESS) {
907
        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
1061
        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
908
                      "don't know how to spawn cmd child process: %s", 
1062
                      "don't know how to spawn cmd child process: %s", 
909
                      r->filename);
1063
                      r->filename);
910
        return HTTP_INTERNAL_SERVER_ERROR;
1064
        return rv;
911
    }
1065
    }
912
1066
913
    /* run the script in its own process */
1067
    /* run the script in its own process */
Lines 916-1007 Link Here
916
                            &e_info)) != APR_SUCCESS) {
1070
                            &e_info)) != APR_SUCCESS) {
917
        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
1071
        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
918
                      "couldn't spawn child process: %s", r->filename);
1072
                      "couldn't spawn child process: %s", r->filename);
919
        return HTTP_INTERNAL_SERVER_ERROR;
1073
        return rv;
920
    }
1074
    }
921
1075
922
    bcgi = apr_brigade_create(r->pool, f->c->bucket_alloc);
1076
    APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pipe_create(script_in,
923
    b = apr_bucket_pipe_create(script_in, f->c->bucket_alloc);
1077
                            f->c->bucket_alloc));
924
    APR_BRIGADE_INSERT_TAIL(bcgi, b);
1078
    ctx->flush_now = 1;
925
    ap_pass_brigade(f->next, bcgi);
926
1079
927
    /* We can't close the pipe here, because we may return before the
1080
    /* We can't close the pipe here, because we may return before the
928
     * full CGI has been sent to the network.  That's okay though,
1081
     * full CGI has been sent to the network.  That's okay though,
929
     * because we can rely on the pool to close the pipe for us.
1082
     * because we can rely on the pool to close the pipe for us.
930
     */
1083
     */
931
1084
    return APR_SUCCESS;
932
    return 0;
933
}
1085
}
934
1086
935
static int handle_exec(include_ctx_t *ctx, apr_bucket_brigade **bb,
1087
static apr_status_t handle_exec(include_ctx_t *ctx, ap_filter_t *f,
936
                       request_rec *r, ap_filter_t *f, apr_bucket *head_ptr,
1088
                                apr_bucket_brigade *bb)
937
                       apr_bucket **inserted_head)
938
{
1089
{
939
    char *tag     = NULL;
1090
    char *tag = NULL;
940
    char *tag_val = NULL;
1091
    char *tag_val = NULL;
1092
    request_rec *r = f->r;
941
    char *file = r->filename;
1093
    char *file = r->filename;
942
    apr_bucket  *tmp_buck;
943
    char parsed_string[MAX_STRING_LEN];
1094
    char parsed_string[MAX_STRING_LEN];
944
1095
945
    *inserted_head = NULL;
1096
    if (!ctx->argc) {
946
    if (ctx->flags & FLAG_PRINTING) {
1097
        ap_log_rerror(APLOG_MARK,
947
        if (ctx->flags & FLAG_NO_EXEC) {
1098
                      (ctx->flags & SSI_FLAG_PRINTING)
948
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1099
                          ? APLOG_ERR : APLOG_WARNING,
949
                          "exec used but not allowed in %s", r->filename);
1100
                      0, r, "missing argument for exec element in %s",
950
            CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
1101
                      r->filename);
1102
    }
1103
1104
    if (!(ctx->flags & SSI_FLAG_PRINTING)) {
1105
        return APR_SUCCESS;
1106
    }
1107
1108
    if (!ctx->argc) {
1109
        SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
1110
        return APR_SUCCESS;
1111
    }
1112
1113
    if (ctx->flags & SSI_FLAG_NO_EXEC) {
1114
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "exec used but not allowed "
1115
                      "in %s", r->filename);
1116
        SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
1117
        return APR_SUCCESS;
1118
    }
1119
1120
    while (1) {
1121
        cgi_pfn_gtv(ctx, &tag, &tag_val, SSI_VALUE_DECODED);
1122
        if (!tag || !tag_val) {
1123
            break;
951
        }
1124
        }
952
        else {
953
            while (1) {
954
                cgi_pfn_gtv(ctx, &tag, &tag_val, 1);
955
                if (tag_val == NULL) {
956
                    if (tag == NULL) {
957
                        return 0;
958
                    }
959
                    else {
960
                        return 1;
961
                    }
962
                }
963
                if (!strcmp(tag, "cmd")) {
964
                    cgi_pfn_ps(r, ctx, tag_val, parsed_string,
965
                               sizeof(parsed_string), 1);
966
                    if (include_cmd(ctx, bb, parsed_string, r, f) == -1) {
967
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
968
                                    "execution failure for parameter \"%s\" "
969
                                    "to tag exec in file %s", tag, r->filename);
970
                        CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr,
971
                                            *inserted_head);
972
                    }
973
                }
974
                else if (!strcmp(tag, "cgi")) {
975
                    apr_status_t retval = APR_SUCCESS;
976
1125
977
                    cgi_pfn_ps(r, ctx, tag_val, parsed_string,
1126
        if (!strcmp(tag, "cmd")) {
978
                               sizeof(parsed_string), 0);
1127
            apr_status_t rv;
979
1128
980
                    SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next, retval);
1129
            cgi_pfn_ps(ctx, tag_val, parsed_string, sizeof(parsed_string),
981
                    if (retval != APR_SUCCESS) {
1130
                       SSI_EXPAND_LEAVE_NAME);
982
                        return retval;
1131
983
                    }
1132
            rv = include_cmd(ctx, f, bb, parsed_string);
984
1133
            if (!APR_STATUS_IS_SUCCESS(rv)) {
985
                    if (include_cgi(parsed_string, r, f->next, head_ptr,
1134
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "execution failure "
986
                                    inserted_head) == -1) {
1135
                              "for parameter \"%s\" to tag exec in file %s",
987
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1136
                              tag, r->filename);
988
                                      "invalid CGI ref \"%s\" in %s",
1137
                SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
989
                                      tag_val, file);
1138
                break;
990
                        CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr,
1139
            }
991
                                            *inserted_head);
1140
        }
992
                    }
1141
        else if (!strcmp(tag, "cgi")) {
993
                }
1142
            apr_status_t rv;
994
                else {
1143
995
                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1144
            cgi_pfn_ps(ctx, tag_val, parsed_string, sizeof(parsed_string),
996
                                  "unknown parameter \"%s\" to tag exec in %s",
1145
                       SSI_EXPAND_DROP_NAME);
997
                                  tag, file);
1146
998
                    CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr,
1147
            rv = include_cgi(ctx, f, bb, parsed_string);
999
                                        *inserted_head);
1148
            if (!APR_STATUS_IS_SUCCESS(rv)) {
1000
                }
1149
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "invalid CGI ref "
1150
                              "\"%s\" in %s", tag_val, file);
1151
                SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
1152
                break;
1001
            }
1153
            }
1002
        }
1154
        }
1155
        else {
1156
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "unknown parameter "
1157
                          "\"%s\" to tag exec in %s", tag, file);
1158
            SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
1159
            break;
1160
        }
1003
    }
1161
    }
1004
    return 0;
1162
1163
    return APR_SUCCESS;
1005
}
1164
}
1006
1165
1007
1166

Return to bug 29893