31 #include <stdio.h> |
31 #include <stdio.h> |
32 #include <stdlib.h> |
32 #include <stdlib.h> |
33 #include <unistd.h> |
33 #include <unistd.h> |
34 |
34 |
35 #include "../util/util.h" |
35 #include "../util/util.h" |
|
36 #include "../util/pblock.h" |
36 #include "../../ucx/string.h" |
37 #include "../../ucx/string.h" |
37 |
38 |
38 #include "cgiutils.h" |
39 #include "cgiutils.h" |
39 |
40 |
40 #define CGI_VARS 32 |
41 #define CGI_VARS 32 |
41 |
42 |
42 #define CGI_RESPONSE_PARSER_BUFLEN 2048 |
43 #define CGI_RESPONSE_PARSER_BUFLEN 2048 |
43 #define CGI_RESPONSE_MAX_LINE_LENGTH 512 |
44 #define CGI_RESPONSE_MAX_LINE_LENGTH 512 |
44 |
45 |
45 int send_cgi(pblock *pb, Session *sn, Request *rq) { |
46 int send_cgi(pblock *pb, Session *sn, Request *rq) { |
46 char *path = pblock_findval("path", rq->vars); |
47 char *path = pblock_findkeyval(pb_key_path, rq->vars); |
|
48 char *ctlen = pblock_findkeyval(pb_key_content_length, rq->headers); |
|
49 int64_t content_length = 0; |
|
50 |
|
51 if(ctlen) { |
|
52 if(!util_strtoint(ctlen, &content_length)) { |
|
53 log_ereport( |
|
54 LOG_FAILURE, |
|
55 "send-cgi: content-length header is not an integer"); |
|
56 protocol_status(sn, rq, 400, NULL); |
|
57 return REQ_ABORTED; |
|
58 } |
|
59 } |
47 |
60 |
48 struct stat s; |
61 struct stat s; |
49 if(stat(path, &s)) { |
62 if(stat(path, &s)) { |
50 int statuscode = util_errno2status(errno); |
63 int statuscode = util_errno2status(errno); |
51 protocol_status(sn, rq, statuscode, NULL); |
64 protocol_status(sn, rq, statuscode, NULL); |
69 int ret = cgi_start(&cgip, path, argv, env); |
82 int ret = cgi_start(&cgip, path, argv, env); |
70 if(ret != REQ_PROCEED) { |
83 if(ret != REQ_PROCEED) { |
71 return ret; |
84 return ret; |
72 } |
85 } |
73 |
86 |
74 // TODO: send http body |
87 char buf[4096]; // I/O buffer |
|
88 ssize_t r; |
|
89 |
|
90 if(content_length > 0) { |
|
91 ssize_t n = 0; |
|
92 while(n < content_length) { |
|
93 r = netbuf_getbytes(sn->inbuf, buf, 4096); |
|
94 if(r <= 0) { |
|
95 // TODO: handleerror |
|
96 return REQ_ABORTED; |
|
97 } |
|
98 write(cgip.in[1], buf, r); |
|
99 n += r; |
|
100 } |
|
101 } |
75 close(cgip.in[1]); |
102 close(cgip.in[1]); |
76 |
103 |
77 // read from child |
104 // read from child |
78 CGIResponseParser *parser = cgi_parser_new(sn, rq); |
105 CGIResponseParser *parser = cgi_parser_new(sn, rq); |
79 WSBool cgiheader = TRUE; |
106 WSBool cgiheader = TRUE; |
80 |
107 |
81 char buf[4096]; |
|
82 ssize_t r; |
|
83 while((r = read(cgip.out[0], buf, 4096)) > 0) { |
108 while((r = read(cgip.out[0], buf, 4096)) > 0) { |
84 if(cgiheader) { |
109 if(cgiheader) { |
85 size_t pos; |
110 size_t pos; |
86 int ret = cgi_parse_response(parser, buf, r, &pos); |
111 int ret = cgi_parse_response(parser, buf, r, &pos); |
87 if(ret == -1) { |
112 if(ret == -1) { |