src/server/safs/cgi.c

Fri, 31 Oct 2025 21:15:19 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Fri, 31 Oct 2025 21:15:19 +0100
changeset 618
e42a8de6d66f
parent 617
01228719b3ce
child 621
956c03c25edd
permissions
-rw-r--r--

use vfs_stat instead of stat in send_cgi

118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
1 /*
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
3 *
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
4 * Copyright 2016 Olaf Wintermann. All rights reserved.
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
5 *
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
6 * Redistribution and use in source and binary forms, with or without
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
7 * modification, are permitted provided that the following conditions are met:
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
8 *
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
9 * 1. Redistributions of source code must retain the above copyright
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
10 * notice, this list of conditions and the following disclaimer.
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
11 *
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
12 * 2. Redistributions in binary form must reproduce the above copyright
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
13 * notice, this list of conditions and the following disclaimer in the
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
14 * documentation and/or other materials provided with the distribution.
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
15 *
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
26 * POSSIBILITY OF SUCH DAMAGE.
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
27 */
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
28
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
29 #include "cgi.h"
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
30
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
31 #include <stdio.h>
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
32 #include <stdlib.h>
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
33 #include <unistd.h>
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
34
162
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
35 #include <sys/types.h>
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
36 #include <signal.h>
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
37 #include <sys/wait.h>
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
38
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
39 #include <cx/string.h>
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 171
diff changeset
40
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
41 #include "../util/util.h"
119
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
42 #include "../util/pblock.h"
171
af7e2d80dee6 adds wrapper for close syscall with error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 164
diff changeset
43 #include "../daemon/netsite.h"
450
d7b276de183b fix cgi pipes not closed in some error case + minor improvements
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 433
diff changeset
44 #include "../daemon/vfs.h"
125
c913d515be1e adds more error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 124
diff changeset
45 #include "../util/io.h"
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
46 #include "../daemon/event.h"
125
c913d515be1e adds more error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 124
diff changeset
47
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
48 #include "cgiutils.h"
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
49
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
50 #define CGI_VARS 32
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
51
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
52 #define CGI_RESPONSE_PARSER_BUFLEN 2048
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
53 #define CGI_RESPONSE_MAX_LINE_LENGTH 512
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
54
567
fed45fc71e7c check and close pipes if cgi_start fails
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 566
diff changeset
55 static void close_std_pipes(int fds[static 6]) {
fed45fc71e7c check and close pipes if cgi_start fails
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 566
diff changeset
56 for(int i=0;i<6;i++) {
fed45fc71e7c check and close pipes if cgi_start fails
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 566
diff changeset
57 if(fds[i] >= 0) {
fed45fc71e7c check and close pipes if cgi_start fails
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 566
diff changeset
58 close(fds[i]);
fed45fc71e7c check and close pipes if cgi_start fails
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 566
diff changeset
59 }
fed45fc71e7c check and close pipes if cgi_start fails
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 566
diff changeset
60 }
fed45fc71e7c check and close pipes if cgi_start fails
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 566
diff changeset
61 }
fed45fc71e7c check and close pipes if cgi_start fails
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 566
diff changeset
62
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
63 int send_cgi(pblock *pb, Session *sn, Request *rq) {
119
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
64 char *path = pblock_findkeyval(pb_key_path, rq->vars);
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
65 char *ctlen = pblock_findkeyval(pb_key_content_length, rq->headers);
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
66 int64_t content_length = 0;
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
67
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
68 log_ereport(LOG_DEBUG, "cgi-send: path: %s req: %p content-length: %s", path, rq, ctlen);
503
aeaf7db26fac fix webdav mkcol error status codes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 502
diff changeset
69
119
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
70 if(ctlen) {
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
71 if(!util_strtoint(ctlen, &content_length)) {
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
72 log_ereport(
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
73 LOG_FAILURE,
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
74 "send-cgi: content-length header is not an integer");
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
75 protocol_status(sn, rq, 400, NULL);
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
76 return REQ_ABORTED;
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
77 }
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
78 }
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
79
618
e42a8de6d66f use vfs_stat instead of stat in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 617
diff changeset
80 // running scripts/executables only works with the sys fs
e42a8de6d66f use vfs_stat instead of stat in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 617
diff changeset
81 // however we still use vfs_stat to run ACL checks
450
d7b276de183b fix cgi pipes not closed in some error case + minor improvements
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 433
diff changeset
82 if(!vfs_is_sys(rq->vfs)) {
d7b276de183b fix cgi pipes not closed in some error case + minor improvements
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 433
diff changeset
83 log_ereport(LOG_WARN, "send-cgi: VFS setting ignored");
d7b276de183b fix cgi pipes not closed in some error case + minor improvements
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 433
diff changeset
84 }
d7b276de183b fix cgi pipes not closed in some error case + minor improvements
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 433
diff changeset
85
618
e42a8de6d66f use vfs_stat instead of stat in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 617
diff changeset
86 VFSContext *vfs = vfs_request_context(sn, rq);
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
87 struct stat s;
618
e42a8de6d66f use vfs_stat instead of stat in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 617
diff changeset
88 if(vfs_stat(vfs, path, &s)) {
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
89 int statuscode = util_errno2status(errno);
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
90 protocol_status(sn, rq, statuscode, NULL);
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
91 return REQ_ABORTED;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
92 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
93 if(S_ISDIR(s.st_mode)) {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
94 protocol_status(sn, rq, 403, NULL);
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
95 return REQ_ABORTED;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
96 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
97
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
98 param_free(pblock_remove("content-type", rq->srvhdrs));
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
99
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
100 const char *args = pblock_findval("query", rq->reqpb);
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
101 char **argv = cgi_create_argv(path, NULL, args);
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
102 if(!argv) {
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
103 return REQ_ABORTED;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
104 }
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
105
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
106 char **env = http_hdrs2env(rq->headers);
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
107 env = cgi_common_vars(sn, rq, env);
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
108 env = cgi_specific_vars(sn, rq, args, env, 1);
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
109
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
110 // event handler object for non-blocking io event handler
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
111 CGIHandler *handler = pool_malloc(sn->pool, sizeof(CGIHandler));
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
112 if(!handler) {
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
113 return REQ_ABORTED;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
114 }
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
115 ZERO(handler, sizeof(CGIHandler));
567
fed45fc71e7c check and close pipes if cgi_start fails
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 566
diff changeset
116 handler->process.out[0] = -1;
fed45fc71e7c check and close pipes if cgi_start fails
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 566
diff changeset
117 handler->process.out[1] = -1;
fed45fc71e7c check and close pipes if cgi_start fails
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 566
diff changeset
118 handler->process.err[0] = -1;
617
01228719b3ce fix cgi pipe fd initialization
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 585
diff changeset
119 handler->process.err[1] = -1;
567
fed45fc71e7c check and close pipes if cgi_start fails
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 566
diff changeset
120 handler->process.in[0] = -1;
617
01228719b3ce fix cgi pipe fd initialization
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 585
diff changeset
121 handler->process.in[1] = -1;
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
122 handler->path = path;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
123
566
963edce64e6e log all cgi pipe fds
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 565
diff changeset
124 int ret = cgi_start(rq, &handler->process, path, argv, env);
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
125 if(ret != REQ_PROCEED) {
567
fed45fc71e7c check and close pipes if cgi_start fails
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 566
diff changeset
126 close_std_pipes((int[6]){
fed45fc71e7c check and close pipes if cgi_start fails
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 566
diff changeset
127 handler->process.out[0], handler->process.out[1],
fed45fc71e7c check and close pipes if cgi_start fails
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 566
diff changeset
128 handler->process.err[0], handler->process.err[1],
fed45fc71e7c check and close pipes if cgi_start fails
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 566
diff changeset
129 handler->process.in[0], handler->process.in[1]});
145
1c93281ca4bf fixes memory leaks in request_stat_path and send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 144
diff changeset
130 util_env_free(env);
1c93281ca4bf fixes memory leaks in request_stat_path and send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 144
diff changeset
131 cgi_free_argv(argv);
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
132 return ret;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
133 }
566
963edce64e6e log all cgi pipe fds
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 565
diff changeset
134 log_ereport(LOG_DEBUG, "send-cgi: req: %p pid: %d", rq, (int)handler->process.pid);
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
135
124
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
136 util_env_free(env);
145
1c93281ca4bf fixes memory leaks in request_stat_path and send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 144
diff changeset
137 cgi_free_argv(argv);
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
138
119
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
139 char buf[4096]; // I/O buffer
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
140 ssize_t r;
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
141
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
142 if(content_length > 0) {
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
143 ssize_t n = 0;
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
144 while(n < content_length) {
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
145 r = netbuf_getbytes(sn->inbuf, buf, 4096);
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
146 if(r <= 0) {
162
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
147 log_ereport(
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
148 LOG_FAILURE,
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
149 "send-cgi: script: %s: cannot read request body",
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
150 path);
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
151 kill(handler->process.pid, SIGTERM);
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
152 cgi_close(&handler->process);
162
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
153 return REQ_ABORTED;
119
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
154 }
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
155 ssize_t w = write(handler->process.in[1], buf, r);
162
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
156 if(w <= 0) {
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
157 log_ereport(
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
158 LOG_FAILURE,
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
159 "send-cgi: script: %s: cannot send request body to cgi process",
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
160 path);
528
8206bfafb7a6 use sigterm to kill cgi scripts
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 527
diff changeset
161 kill(handler->process.pid, SIGTERM);
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
162 cgi_close(&handler->process);
162
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
163 return REQ_ABORTED;
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
164 }
119
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
165 n += r;
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
166 }
155cbab9eefd adds support for CGI with request bodies
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 118
diff changeset
167 }
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
168 system_close(handler->process.in[1]);
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
169 handler->process.in[1] = -1;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
170
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
171 handler->parser = cgi_parser_new(sn, rq);
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
172
431
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
173 // set pipes non-blocking
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
174 int flags;
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
175 if ((flags = fcntl(handler->process.err[0], F_GETFL, 0)) == -1) {
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
176 flags = 0;
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
177 }
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
178 if (fcntl(handler->process.err[0], F_SETFL, flags | O_NONBLOCK) != 0) {
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
179 log_ereport(LOG_FAILURE, "cgi-bin: fcntl err[0] failed: %s", strerror(errno));
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
180 }
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
181 if ((flags = fcntl(handler->process.out[0], F_GETFL, 0)) == -1) {
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
182 flags = 0;
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
183 }
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
184 if (fcntl(handler->process.out[0], F_SETFL, flags | O_NONBLOCK) != 0) {
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
185 log_ereport(LOG_FAILURE, "cgi-bin: fcntl out[0] failed: %s", strerror(errno));
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
186 }
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
187
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
188 // create events for reading cgi's stdout/stderr
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
189 Event *readev = pool_malloc(sn->pool, sizeof(Event));
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
190 ZERO(readev, sizeof(Event));
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
191 readev->cookie = handler;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
192 readev->fn = cgi_stdout_readevent;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
193 readev->finish = cgi_event_finish;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
194
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
195 Event *stderr_readev = pool_malloc(sn->pool, sizeof(Event));
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
196 ZERO(stderr_readev, sizeof(Event));
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
197 stderr_readev->cookie = handler;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
198 stderr_readev->fn = cgi_stderr_readevent;
499
ef77854a91f3 fix cgi event handling, pipes were not always closed
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 498
diff changeset
199 stderr_readev->finish = cgi_event_finish;
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
200
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
201 Event *writeev = pool_malloc(sn->pool, sizeof(Event));
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
202 ZERO(writeev, sizeof(Event));
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
203 writeev->cookie = handler;
499
ef77854a91f3 fix cgi event handling, pipes were not always closed
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 498
diff changeset
204 writeev->fn = cgi_writeevent;
ef77854a91f3 fix cgi event handling, pipes were not always closed
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 498
diff changeset
205 writeev->finish = cgi_event_finish;
498
0d80f8a2b29f fix net_http_write when used with chunked transfer encoding and non-blocking IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 497
diff changeset
206
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
207 handler->readev = readev;
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
208 handler->writeev = writeev;
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
209
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
210 net_setnonblock(sn->csd, 1);
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
211
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
212 // add poll events for cgi stdout/stderr and netout
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
213 int error = 0;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
214 if(ev_pollin(sn->ev, handler->process.err[0], stderr_readev)) {
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
215 log_ereport(LOG_FAILURE, "send-cgi: stderr ev_pollin failed");
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
216 error = 1;
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
217 } else {
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
218 handler->wait_read = TRUE;
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
219 handler->events++;
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
220 }
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
221 if(!error && ev_pollin(sn->ev, handler->process.out[0], readev)) {
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
222 log_ereport(LOG_FAILURE, "send-cgi: stdout ev_pollin failed");
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
223 error = 1;
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
224 } else {
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
225 handler->events++;
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
226 }
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
227
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
228 // don't poll sn->csd yet, we wait until the first net_write fails
499
ef77854a91f3 fix cgi event handling, pipes were not always closed
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 498
diff changeset
229
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
230 if(error) {
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
231 log_ereport(LOG_FAILURE, "cgi-send: initialization error: kill script: %s", path);
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
232 kill(handler->process.pid, SIGKILL);
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
233 cgi_parser_free(handler->parser);
450
d7b276de183b fix cgi pipes not closed in some error case + minor improvements
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 433
diff changeset
234 cgi_close(&handler->process);
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
235 return REQ_ABORTED;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
236 }
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
237
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
238 return REQ_PROCESSING;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
239 }
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
240
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
241 /*
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
242 * Try to flush the CGIHandler write buffer
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
243 *
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
244 * When successful, cgi_try_write_flush() returns 0. If an error occurs,
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
245 * 1 is returned.
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
246 *
538
f9a7b5c76208 replace EWOULDBLOCK with EAGAIN
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 536
diff changeset
247 * If the error is not EAGAIN, handler->result is set to REQ_ABORTED.
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
248 */
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
249 static int cgi_try_write_flush(CGIHandler *handler, Session *sn) {
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
250 ssize_t wr = 0;
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
251 while(
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
252 handler->writebuf_size - handler->writebuf_pos > 0 &&
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
253 (wr = net_write(
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
254 sn->csd,
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
255 handler->writebuf + handler->writebuf_pos,
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
256 handler->writebuf_size - handler->writebuf_pos))
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
257 > 0)
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
258 {
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
259 handler->writebuf_pos += wr;
502
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
260 handler->count_write += wr;
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
261 }
502
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
262 if(handler->writebuf_size - handler->writebuf_pos > 0) {
538
f9a7b5c76208 replace EWOULDBLOCK with EAGAIN
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 536
diff changeset
263 if(net_errno(sn->csd) != EAGAIN) {
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
264 handler->result = REQ_ABORTED;
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
265 log_ereport(
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
266 LOG_FAILURE,
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
267 "cgi pid %d %s: network error: %s",
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
268 (int)handler->process.pid,
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
269 handler->path,
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
270 strerror(net_errno(sn->csd)));
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
271 }
502
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
272
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
273 return 1;
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
274 }
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
275 return 0;
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
276 }
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
277
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
278 /*
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
279 * Try to write the buffer to sn->csd
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
280 * In case the socket is non-blocking and not all bytes could be written,
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
281 * the remaining bytes are copied to the CGIHandler write buffer.
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
282 *
538
f9a7b5c76208 replace EWOULDBLOCK with EAGAIN
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 536
diff changeset
283 * If an error occurs that is not EAGAIN, handler->result is set to
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
284 * REQ_ABORTED.
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
285 *
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
286 * Returns 0 if all bytes are successfully written, otherwise 1
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
287 */
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
288 static int cgi_try_write(CGIHandler *handler, EventHandler *ev, Session *sn, char *buf, size_t size) {
502
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
289
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
290 size_t pos = 0;
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
291 ssize_t wr = 0;
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
292 while(size - pos > 0 && (wr = net_write(sn->csd, buf + pos, size - pos)) > 0) {
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
293 pos += wr;
502
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
294 handler->count_write += wr;
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
295 }
502
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
296
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
297 if(pos < size) {
538
f9a7b5c76208 replace EWOULDBLOCK with EAGAIN
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 536
diff changeset
298 if(net_errno(sn->csd) == EAGAIN) {
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
299 // copy remaining bytes to the write buffer
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
300 // we assume there are no remaining bytes in writebuf
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
301 size_t remaining = size-pos;
497
8827517054ec fix cgi response could send an uninitialized buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 451
diff changeset
302 if(remaining > handler->writebuf_alloc) {
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
303 handler->writebuf_alloc = size > 4096 ? size : 4096;
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
304 handler->writebuf = pool_realloc(sn->pool, handler->writebuf, handler->writebuf_alloc);
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
305 if(!handler->writebuf) {
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
306 handler->result = REQ_ABORTED;
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
307 return 1;
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
308 }
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
309 }
497
8827517054ec fix cgi response could send an uninitialized buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 451
diff changeset
310 memcpy(handler->writebuf, buf+pos, remaining);
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
311 handler->writebuf_size = remaining;
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
312 handler->writebuf_pos = 0;
497
8827517054ec fix cgi response could send an uninitialized buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 451
diff changeset
313 } else {
8827517054ec fix cgi response could send an uninitialized buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 451
diff changeset
314 handler->result = REQ_ABORTED;
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
315 log_ereport(
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
316 LOG_FAILURE,
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
317 "cgi pid %d %s: network error: %s",
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
318 (int)handler->process.pid,
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
319 handler->path,
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
320 strerror(net_errno(sn->csd)));
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
321 }
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
322 return 1;
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
323 }
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
324
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
325 return 0;
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
326 }
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
327
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
328 int cgi_stdout_readevent(EventHandler *ev, Event *event) {
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
329 CGIHandler *handler = event->cookie;
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
330
521
536a2305f3fa add more cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 520
diff changeset
331 if(handler->debug_finished) {
522
317cd83fa3df fix build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 521
diff changeset
332 log_ereport(LOG_DEBUG, "cgi-send: req: %p debug_finished: 1 cgi_stdout_readevent events: %d", handler->parser->rq, handler->events);
521
536a2305f3fa add more cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 520
diff changeset
333 }
536a2305f3fa add more cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 520
diff changeset
334
532
d8212d4f24f2 stop cgi read-event processing if an error occured
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 530
diff changeset
335 if(handler->cgi_eof || handler->result == REQ_ABORTED) {
530
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
336 // cgi_eof will be set to true by cgi_read_output
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
337 // if it is true here, the cgi handling was finished by cgi_writeevent
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
338 // in that case, cgi_writeevent will finish the request processing
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
339 // and nothing needs to be done here
535
bf07abfe7f0a add more debug logging to cgi_stdout_readevent
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 534
diff changeset
340 log_ereport(LOG_DEBUG, "cgi-send: req: %p readevent cgi_eof = TRUE result: %d", handler->parser->rq, handler->result);
530
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
341 handler->wait_read = FALSE;
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
342 event->finish = NULL;
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
343 return 0;
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
344 }
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
345
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
346 event->finish = cgi_event_finish;
536
e95fa761db0c fix cgi_writeevent not returning immediately when cgi IO is already done
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 535
diff changeset
347 handler->writeev->finish = NULL; // TODO: maybe this can be removed
534
bf62eddbdb9b add more cgi logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 532
diff changeset
348 CgiIOResult ret = cgi_read_output(handler, ev, "readevent");
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
349 switch(ret) {
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
350 case CGI_IO_COMPLETE: {
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
351 break;
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
352 }
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
353 case CGI_IO_NEED_READ: {
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
354 return 1;
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
355 }
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
356 case CGI_IO_NEED_WRITE: {
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
357 // writeev is only enabled, if needed
518
538a8a22f622 fix don't try to enable pollout if it is already active (cgi)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 517
diff changeset
358 if(handler->poll_out) {
538a8a22f622 fix don't try to enable pollout if it is already active (cgi)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 517
diff changeset
359 return 1;
538a8a22f622 fix don't try to enable pollout if it is already active (cgi)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 517
diff changeset
360 }
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
361 if(event_pollout(ev, handler->parser->sn->csd, handler->writeev)) {
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
362 handler->result = REQ_ABORTED;
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
363 } else {
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
364 handler->poll_out = TRUE;
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
365 log_ereport(LOG_DEBUG, "cgi-send: req: %p enable poll out", handler->parser->rq);
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
366 return 1; // keep readevent active
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
367 }
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
368 }
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
369 case CGI_IO_ERROR: {
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
370 break;
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
371 }
502
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
372 }
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
373
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
374 handler->wait_read = FALSE;
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
375 return 0;
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
376 }
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
377
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
378 int cgi_writeevent(EventHandler *ev, Event *event) {
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
379 CGIHandler *handler = event->cookie;
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
380
532
d8212d4f24f2 stop cgi read-event processing if an error occured
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 530
diff changeset
381 if(handler->cgi_eof || handler->result == REQ_ABORTED) {
536
e95fa761db0c fix cgi_writeevent not returning immediately when cgi IO is already done
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 535
diff changeset
382 // same as in cgi_stdout_readevent
e95fa761db0c fix cgi_writeevent not returning immediately when cgi IO is already done
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 535
diff changeset
383 // request processing will be finished by the read event
532
d8212d4f24f2 stop cgi read-event processing if an error occured
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 530
diff changeset
384 log_ereport(LOG_DEBUG, "cgi-send: req: %p writeevent cgi_eof = TRUE result: %d", handler->parser->rq, handler->result);
536
e95fa761db0c fix cgi_writeevent not returning immediately when cgi IO is already done
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 535
diff changeset
385 handler->poll_out = FALSE;
e95fa761db0c fix cgi_writeevent not returning immediately when cgi IO is already done
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 535
diff changeset
386 event->finish = NULL;
e95fa761db0c fix cgi_writeevent not returning immediately when cgi IO is already done
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 535
diff changeset
387 return 0;
530
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
388 }
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
389
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
390 event->finish = cgi_event_finish;
536
e95fa761db0c fix cgi_writeevent not returning immediately when cgi IO is already done
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 535
diff changeset
391 handler->readev->finish = NULL; // TODO: maybe this can be removed
534
bf62eddbdb9b add more cgi logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 532
diff changeset
392 CgiIOResult ret = cgi_read_output(handler, ev, "writeevent");
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
393 switch(ret) {
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
394 case CGI_IO_COMPLETE: {
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
395 break;
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
396 }
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
397 case CGI_IO_NEED_READ: {
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
398 return 1;
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
399 }
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
400 case CGI_IO_NEED_WRITE: {
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
401 return 1;
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
402 }
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
403 case CGI_IO_ERROR: {
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
404 break;
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
405 }
502
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
406 }
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
407
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
408 handler->poll_out = FALSE;
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
409 return 0;
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
410 }
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
411
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
412
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
413
534
bf62eddbdb9b add more cgi logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 532
diff changeset
414 CgiIOResult cgi_read_output(CGIHandler *handler, EventHandler *ev, const char *debug_log) {
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
415 CGIResponseParser *parser = handler->parser;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
416 Session *sn = parser->sn;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
417 Request *rq = parser->rq;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
418
517
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
419 if(handler->result == REQ_ABORTED) {
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
420 return CGI_IO_ERROR;
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
421 }
be62c9604377 improve cgi io event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 516
diff changeset
422
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
423 // try to flush handler->writebuf
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
424 // if writebuf is empty, this does nothing and returns 0
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
425 if(cgi_try_write_flush(handler, sn)) {
498
0d80f8a2b29f fix net_http_write when used with chunked transfer encoding and non-blocking IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 497
diff changeset
426 if(handler->result == REQ_ABORTED) {
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
427 return CGI_IO_ERROR;
498
0d80f8a2b29f fix net_http_write when used with chunked transfer encoding and non-blocking IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 497
diff changeset
428 } else {
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
429 return CGI_IO_NEED_WRITE;
498
0d80f8a2b29f fix net_http_write when used with chunked transfer encoding and non-blocking IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 497
diff changeset
430 }
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
431 }
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
432
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
433 char buf[4096]; // I/O buffer
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
434 ssize_t r;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
435
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
436 int ret = CGI_IO_COMPLETE;
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
437 handler->result = REQ_PROCEED;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
438 while((r = read(handler->process.out[0], buf, 4096)) > 0) {
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
439 if(parser->cgiheader) {
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
440 size_t pos;
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
441 int ret = cgi_parse_response(parser, buf, r, &pos);
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
442 if(ret == -1) {
162
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
443 log_ereport(
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
444 LOG_FAILURE,
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
445 "broken cgi script response: path: %s", handler->path);
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
446 protocol_status(sn, rq, 500, NULL);
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
447 handler->result = REQ_ABORTED;
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
448 return CGI_IO_ERROR;
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
449 } else if(ret == 1) {
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
450 WS_ASSERT(pos <= r);
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
451
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
452 parser->response_length += r-pos;
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
453
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
454 parser->cgiheader = FALSE;
124
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
455 if(parser->status > 0) {
585
bae488d2b3c2 make cgi response status header check case insensitive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 579
diff changeset
456 log_ereport(LOG_DEBUG, "cgi-send: req: %p pid: %d response status code: %d", rq, handler->process.pid, parser->status);
124
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
457 protocol_status(sn, rq, parser->status, parser->msg);
585
bae488d2b3c2 make cgi response status header check case insensitive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 579
diff changeset
458 } else {
bae488d2b3c2 make cgi response status header check case insensitive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 579
diff changeset
459 log_ereport(LOG_DEBUG, "cgi-send: req: %p pid: %d no status code", rq, handler->process.pid);
bae488d2b3c2 make cgi response status header check case insensitive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 579
diff changeset
460 protocol_status(sn, rq, 200, NULL); // default 200 ok
124
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
461 }
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
462
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
463 handler->response = http_create_response(sn, rq);
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
464 if(!handler->response) {
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
465 handler->result = REQ_ABORTED;
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
466 return CGI_IO_ERROR;
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
467 }
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
468
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
469 int send_response = http_send_response(handler->response);
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
470 if(send_response < 0) {
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
471 handler->result = REQ_ABORTED;
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
472 ret = CGI_IO_ERROR;
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
473 break;
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
474 } else if(send_response == 1) {
538
f9a7b5c76208 replace EWOULDBLOCK with EAGAIN
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 536
diff changeset
475 // EAGAIN
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
476 if(!handler->poll_out) {
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
477 if(event_pollout(ev, sn->csd, handler->writeev)) {
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
478 handler->result = REQ_ABORTED;
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
479 return CGI_IO_ERROR;
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
480 }
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
481 handler->poll_out = TRUE;
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
482 return CGI_IO_NEED_WRITE;
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
483 }
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
484 } else {
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
485 handler->response = NULL;
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
486 }
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
487
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
488 if(pos < r) {
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
489 if(cgi_try_write(handler, ev, sn, &buf[pos], r-pos)) {
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
490 return handler->result == REQ_ABORTED ? CGI_IO_ERROR : CGI_IO_NEED_WRITE;
125
c913d515be1e adds more error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 124
diff changeset
491 }
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
492 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
493 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
494 } else {
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
495 parser->response_length += r;
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
496 if(cgi_try_write(handler, ev, sn, buf, r)) {
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
497 return handler->result == REQ_ABORTED ? CGI_IO_ERROR : CGI_IO_NEED_WRITE;
125
c913d515be1e adds more error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 124
diff changeset
498 }
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
499 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
500 }
538
f9a7b5c76208 replace EWOULDBLOCK with EAGAIN
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 536
diff changeset
501 if(r < 0 && errno == EAGAIN) {
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
502 return CGI_IO_NEED_READ;
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
503 }
502
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
504 handler->cgi_eof = TRUE;
536
e95fa761db0c fix cgi_writeevent not returning immediately when cgi IO is already done
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 535
diff changeset
505 log_ereport(LOG_DEBUG, "cgi-send: req: %p pid: %d set cgi_eof : %s", rq, handler->process.pid, debug_log);
516
ec22d4ccd081 fix cgi poll event handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 503
diff changeset
506 return ret;
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
507 }
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
508
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
509 int cgi_stderr_readevent(EventHandler *ev, Event *event) {
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
510 CGIHandler *handler = event->cookie;
431
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
511 pool_handle_t *pool = handler->parser->sn->pool;
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
512
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
513 char buf[4096];
431
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
514 char *line = buf;
451
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
515 int line_start;
431
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
516 ssize_t r;
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
517 while((r = read(handler->process.err[0], buf, 4096)) > 0) {
451
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
518 line_start = 0;
431
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
519 int pos = 0;
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
520 // log stderr output lines
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
521 for(int i=0;i<r;i++) {
451
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
522 if(buf[i] == '\n') {
431
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
523 log_ereport(
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
524 LOG_INFORM,
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
525 "cgi pid %d %s stderr: %.*s%.*s",
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
526 (int)handler->process.pid,
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
527 handler->path,
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
528 (int)handler->stderr_tmplen,
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
529 handler->stderr_tmp,
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
530 i - line_start,
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
531 line + line_start);
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
532 line_start = i+1;
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
533 pos = i+1;
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
534
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
535 if(handler->stderr_tmp) {
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
536 handler->stderr_tmplen = 0;
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
537 }
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
538 }
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
539 }
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
540
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
541 // check for incomplete line
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
542 if(pos < r) {
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
543 int tmplen = r-pos;
451
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
544 if(handler->stderr_tmplen > 0) {
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
545 // append new text to the temp buffer
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
546 if(handler->stderr_tmplen + tmplen > handler->stderr_tmpalloc) {
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
547 handler->stderr_tmpalloc = handler->stderr_tmplen + tmplen;
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
548 handler->stderr_tmp = pool_realloc(pool, handler->stderr_tmp, handler->stderr_tmpalloc);
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
549 if(!handler->stderr_tmp) {
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
550 log_ereport(LOG_FAILURE, "send-cgi: cannot create tmp buffer for parsing stderr");
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
551 handler->stderr_tmpalloc = 0;
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
552 handler->stderr_tmplen = 0;
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
553 continue;
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
554 }
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
555 }
431
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
556 memcpy(handler->stderr_tmp + handler->stderr_tmplen, line + line_start, tmplen);
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
557 handler->stderr_tmplen += tmplen;
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
558 } else {
451
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
559 if(handler->stderr_tmpalloc < tmplen) {
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
560 // tmp buffer too small or not allocated
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
561 handler->stderr_tmpalloc = tmplen < 256 ? 256 : tmplen;
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
562 if(handler->stderr_tmp) {
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
563 // free old tmp buf
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
564 // pool_realloc doesn't make sense here, because it
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
565 // is just free+malloc+memcpy and we don't need the
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
566 // memcpy part, because we are just reusing the buffer
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
567 // and the previous content doesn't matter
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
568 pool_free(pool, handler->stderr_tmp);
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
569 }
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
570 handler->stderr_tmp = pool_malloc(pool, handler->stderr_tmpalloc);
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
571 if(!handler->stderr_tmp) {
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
572 log_ereport(LOG_FAILURE, "send-cgi: cannot create tmp buffer for parsing stderr");
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
573 handler->stderr_tmpalloc = 0;
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
574 handler->stderr_tmplen = 0;
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
575 continue;
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
576 }
edbbb3000494 fix cgi stderr logger + reuse stderr tmp buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 450
diff changeset
577 }
431
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
578 memcpy(handler->stderr_tmp, line + line_start, tmplen);
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
579 handler->stderr_tmplen = tmplen;
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
580 }
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
581 } else {
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
582 handler->stderr_tmplen = 0;
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
583 }
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
584 }
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
585
431
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
586
538
f9a7b5c76208 replace EWOULDBLOCK with EAGAIN
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 536
diff changeset
587 if(r < 0 && errno == EAGAIN) {
431
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
588 return 1;
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
589 }
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
590
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
591 if(handler->stderr_tmp) {
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
592 pool_free(handler->parser->sn->pool, handler->stderr_tmp);
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
593 }
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
594 return 0;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
595 }
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
596
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
597 int cgi_event_finish(EventHandler *ev, Event *event) {
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
598 CGIHandler *handler = event->cookie;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
599 CGIResponseParser *parser = handler->parser;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
600 Session *sn = parser->sn;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
601 Request *rq = parser->rq;
501
2aa6bd9f166f fix cgi-send inactive write event blocking request termination
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 499
diff changeset
602
502
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
603 char *event_fn = "";
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
604 if(event->fn == cgi_stdout_readevent) {
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
605 event_fn = "stdout";
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
606 } else if(event->fn == cgi_stderr_readevent) {
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
607 event_fn = "stderr";
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
608 } else if(event->fn == cgi_writeevent) {
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
609 event_fn = "httpout";
521
536a2305f3fa add more cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 520
diff changeset
610 log_ereport(LOG_DEBUG, "cgi-send: req: %p finish: pid: %d", rq, handler->process.pid);
502
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
611 }
520
0b09f0cb6098 add wait_read to cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 519
diff changeset
612 log_ereport(LOG_DEBUG, "cgi-send: req: %p finish: event: %d pollout: %d wait_read: %d cgi_eof: %d fn: %s", rq, handler->events, handler->poll_out, handler->wait_read, handler->cgi_eof, event_fn);
0b09f0cb6098 add wait_read to cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 519
diff changeset
613
521
536a2305f3fa add more cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 520
diff changeset
614 handler->debug_finished = TRUE;
532
d8212d4f24f2 stop cgi read-event processing if an error occured
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 530
diff changeset
615 if(event->fn != cgi_stderr_readevent) {
534
bf62eddbdb9b add more cgi logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 532
diff changeset
616 log_ereport(LOG_DEBUG, "cgi-send: req: %p finish set cgi_eof: %s", rq, event_fn);
532
d8212d4f24f2 stop cgi read-event processing if an error occured
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 530
diff changeset
617 handler->cgi_eof = TRUE;
d8212d4f24f2 stop cgi read-event processing if an error occured
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 530
diff changeset
618 }
521
536a2305f3fa add more cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 520
diff changeset
619
530
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
620 if(handler->result == REQ_ABORTED && handler->process.pid != 0 && handler->cgi_kill == 0) {
525
072d7794bcca use SIGKILL instead of SIGTERM to cgi scripts in case of errors
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 524
diff changeset
621 log_ereport(LOG_FAILURE, "cgi-send: kill script: %s pid: %d", handler->path, (int)handler->process.pid);
528
8206bfafb7a6 use sigterm to kill cgi scripts
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 527
diff changeset
622 if(kill(handler->process.pid, SIGTERM)) {
526
6c06b845701a handle killpg error
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 525
diff changeset
623 log_ereport(LOG_FAILURE, "cgi-send: pid: %d kill failed: %s", (int)handler->process.pid, strerror(errno));
528
8206bfafb7a6 use sigterm to kill cgi scripts
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 527
diff changeset
624 } else {
8206bfafb7a6 use sigterm to kill cgi scripts
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 527
diff changeset
625 log_ereport(LOG_DEBUG, "cgi-send: finish: req: %p kill %d successful", rq, (int)handler->process.pid);
530
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
626 handler->cgi_kill = SIGTERM;
526
6c06b845701a handle killpg error
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 525
diff changeset
627 }
524
9f1d30988231 kill broken cgi processes as soon as possible
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 523
diff changeset
628 }
9f1d30988231 kill broken cgi processes as soon as possible
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 523
diff changeset
629
521
536a2305f3fa add more cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 520
diff changeset
630 if(--handler->events > 0) {
536a2305f3fa add more cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 520
diff changeset
631 return 0;
536a2305f3fa add more cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 520
diff changeset
632 }
536a2305f3fa add more cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 520
diff changeset
633
520
0b09f0cb6098 add wait_read to cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 519
diff changeset
634 if(handler->poll_out) {
0b09f0cb6098 add wait_read to cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 519
diff changeset
635 // write event registered, however it will not be activated anymore
0b09f0cb6098 add wait_read to cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 519
diff changeset
636 // we can safely remove the event
0b09f0cb6098 add wait_read to cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 519
diff changeset
637 log_ereport(LOG_DEBUG, "cgi-send: req: %p finish: remove-poll write", rq);
0b09f0cb6098 add wait_read to cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 519
diff changeset
638 if(event_removepoll(ev, sn->csd)) {
0b09f0cb6098 add wait_read to cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 519
diff changeset
639 log_ereport(LOG_FAILURE, "cgi_event_finish: event_removepoll: %s", strerror(errno));
0b09f0cb6098 add wait_read to cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 519
diff changeset
640 }
0b09f0cb6098 add wait_read to cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 519
diff changeset
641 handler->poll_out = FALSE;
0b09f0cb6098 add wait_read to cgi debug logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 519
diff changeset
642 }
502
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
643
530
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
644 if(handler->wait_read) {
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
645 // read event registered, however it will not be activated anymore
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
646 // (currently unsure if this can happen)
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
647 log_ereport(LOG_DEBUG, "cgi-send: req: %p finish: remove-poll read", rq);
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
648 if(ev_remove_poll(ev, handler->process.out[0])) {
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
649 log_ereport(LOG_FAILURE, "cgi_event_finish: req: %p ev_remove_poll: %s", rq, strerror(errno));
501
2aa6bd9f166f fix cgi-send inactive write event blocking request termination
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 499
diff changeset
650 }
530
1e117b5d6710 handle eof in cgi_stdout_readevent to fix potential double free in cgi_event_finish
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 528
diff changeset
651 handler->wait_read = FALSE;
162
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
652 }
359
79b28ae7bfbd check cgi exit code
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
653
502
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
654 log_ereport(LOG_DEBUG, "cgi-send: req: %p cgi_close", rq);
431
032b0ad35ee3 parse cgi stderr output for logging and use non-blocking pipes
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 430
diff changeset
655
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
656 int exit_code = cgi_close(&handler->process);
359
79b28ae7bfbd check cgi exit code
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
657 if(exit_code != 0) {
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
658 log_ereport(LOG_FAILURE, "send-cgi: script: %s exited with code %d", handler->path, exit_code);
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
659 handler->result = REQ_ABORTED;
359
79b28ae7bfbd check cgi exit code
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
660 }
126
631aaa01b2b5 fixes chunked transfer encoding
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 125
diff changeset
661
124
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
662 cgi_parser_free(parser);
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
663
502
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
664 WSBool response_length_error = FALSE;
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
665 // check if content-length set by the cgi script matches the number
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
666 // of writes, that were written to the stream
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
667 // this ensures, that broken cgi scripts don't break the connection
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
668 char *ctlen_header = pblock_findkeyval(pb_key_content_length, rq->srvhdrs);
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
669 if(ctlen_header) {
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
670 int64_t ctlenhdr;
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
671 if(util_strtoint(ctlen_header, &ctlenhdr)) {
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
672 if(ctlenhdr != parser->response_length) {
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
673 log_ereport(
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
674 LOG_FAILURE,
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
675 "cgi-send: script: %s: content length mismatch",
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
676 handler->path);
502
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
677 response_length_error = TRUE;
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
678 }
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
679 }
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
680 }
502
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
681 // make sure we haven't lost any bytes
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
682 // should not happen unless the non-blocking IO code is buggy
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
683 if(handler->result != REQ_ABORTED && handler->parser->response_length != handler->count_write) {
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
684 log_ereport(
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
685 LOG_FAILURE,
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
686 "cgi-send: script: %s: IO error: cgi response length != http response length",
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
687 handler->path);
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
688 response_length_error = TRUE;
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
689 }
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
690
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
691 // if the response length is broken, we must close the connection
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
692 if(response_length_error) {
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
693 rq->rq_attr.keep_alive = 0;
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
694 handler->result = REQ_ABORTED;
11ac3761c0e3 fix non-blocking CGI handler and non-blocking SSL-IO
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 501
diff changeset
695 }
433
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
696
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
697 net_setnonblock(sn->csd, 0);
39fe86ae4db0 use non-blocking IO for pipes and socket in send_cgi
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 431
diff changeset
698
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
699 // return to nsapi loop
497
8827517054ec fix cgi response could send an uninitialized buffer
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 451
diff changeset
700 log_ereport(LOG_DEBUG, "cgi-send: req: %p event-finish nsapi return", rq);
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
701 nsapi_function_return(sn, rq, handler->result);
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
702 return 0;
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
703 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
704
566
963edce64e6e log all cgi pipe fds
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 565
diff changeset
705 int cgi_start(Request *rq, CGIProcess *p, char *path, char *const argv[], char *const envp[]) {
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
706 if(pipe(p->in) || pipe(p->out) || pipe(p->err)) {
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
707 log_ereport(
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
708 LOG_FAILURE,
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
709 "send-cgi: cannot create pipe: %s",
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
710 strerror(errno));
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
711 return REQ_ABORTED;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
712 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
713
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
714 p->pid = fork();
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
715 if(p->pid == 0) {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
716 // child
120
d2eb5fd97df0 adds chdir before cgi execution
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 119
diff changeset
717
d2eb5fd97df0 adds chdir before cgi execution
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 119
diff changeset
718 // get script directory and script name
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
719 cxstring script = cx_str(path);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
720 cxmutstr parent;
120
d2eb5fd97df0 adds chdir before cgi execution
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 119
diff changeset
721 int len = strlen(path);
d2eb5fd97df0 adds chdir before cgi execution
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 119
diff changeset
722 for(int i=len-1;i>=0;i--) {
d2eb5fd97df0 adds chdir before cgi execution
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 119
diff changeset
723 if(path[i] == '/') {
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
724 script = cx_strn(path + i + 1, len - i);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
725 parent = cx_strdup(cx_strn(path, i));
120
d2eb5fd97df0 adds chdir before cgi execution
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 119
diff changeset
726 if(chdir(parent.ptr)) {
d2eb5fd97df0 adds chdir before cgi execution
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 119
diff changeset
727 perror("cgi_start: chdir");
d2eb5fd97df0 adds chdir before cgi execution
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 119
diff changeset
728 free(parent.ptr);
d2eb5fd97df0 adds chdir before cgi execution
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 119
diff changeset
729 exit(-1);
d2eb5fd97df0 adds chdir before cgi execution
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 119
diff changeset
730 }
d2eb5fd97df0 adds chdir before cgi execution
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 119
diff changeset
731 free(parent.ptr);
d2eb5fd97df0 adds chdir before cgi execution
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 119
diff changeset
732 break;
d2eb5fd97df0 adds chdir before cgi execution
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 119
diff changeset
733 }
d2eb5fd97df0 adds chdir before cgi execution
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 119
diff changeset
734 }
d2eb5fd97df0 adds chdir before cgi execution
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 119
diff changeset
735
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
736 if(dup2(p->in[0], STDIN_FILENO) == -1) {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
737 perror("cgi_start: dup2");
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
738 exit(EXIT_FAILURE);
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
739 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
740 if(dup2(p->out[1], STDOUT_FILENO) == -1) {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
741 perror("cgi_start: dup2");
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
742 exit(EXIT_FAILURE);
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
743 }
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
744 if(dup2(p->err[1], STDERR_FILENO) == -1) {
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
745 perror("cgi_start: dup2");
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
746 exit(EXIT_FAILURE);
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
747 }
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
748
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
749 // we need to close this unused pipe
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
750 // otherwise stdin cannot reach EOF
171
af7e2d80dee6 adds wrapper for close syscall with error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 164
diff changeset
751 system_close(p->in[1]);
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
752
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
753 // execute program
120
d2eb5fd97df0 adds chdir before cgi execution
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 119
diff changeset
754 exit(execve(script.ptr, argv, envp));
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
755 } else {
566
963edce64e6e log all cgi pipe fds
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 565
diff changeset
756 log_ereport(LOG_DEBUG, "send-cgi: start-cgi: req: %p pid: %d pipes: [%d, %d][%d, %d][%d, %d]", rq, (int)p->pid, p->out[0], p->out[1], p->err[0], p->err[1], p->in[0], p->in[1]);
963edce64e6e log all cgi pipe fds
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 565
diff changeset
757 // parent
171
af7e2d80dee6 adds wrapper for close syscall with error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 164
diff changeset
758 system_close(p->out[1]);
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
759 system_close(p->err[1]);
144
4b546c4f25ed fixes cgi fd leak
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 133
diff changeset
760 p->out[1] = -1;
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
761 p->err[1] = -1;
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
762 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
763
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
764 return REQ_PROCEED;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
765 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
766
519
857e5b92828b add workaround for blocking cgi waitpid
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 518
diff changeset
767 int cgi_close(CGIProcess *p) {
144
4b546c4f25ed fixes cgi fd leak
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 133
diff changeset
768 if(p->in[0] != -1) {
171
af7e2d80dee6 adds wrapper for close syscall with error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 164
diff changeset
769 system_close(p->in[0]);
144
4b546c4f25ed fixes cgi fd leak
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 133
diff changeset
770 }
4b546c4f25ed fixes cgi fd leak
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 133
diff changeset
771 if(p->in[1] != -1) {
171
af7e2d80dee6 adds wrapper for close syscall with error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 164
diff changeset
772 system_close(p->in[1]);
144
4b546c4f25ed fixes cgi fd leak
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 133
diff changeset
773 }
4b546c4f25ed fixes cgi fd leak
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 133
diff changeset
774 if(p->out[0] != -1) {
171
af7e2d80dee6 adds wrapper for close syscall with error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 164
diff changeset
775 system_close(p->out[0]);
144
4b546c4f25ed fixes cgi fd leak
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 133
diff changeset
776 }
4b546c4f25ed fixes cgi fd leak
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 133
diff changeset
777 if(p->out[1] != -1) {
171
af7e2d80dee6 adds wrapper for close syscall with error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 164
diff changeset
778 system_close(p->out[1]);
144
4b546c4f25ed fixes cgi fd leak
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 133
diff changeset
779 }
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
780 if(p->err[0] != -1) {
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
781 system_close(p->err[0]);
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
782 }
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
783 if(p->err[1] != -1) {
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
784 system_close(p->err[1]);
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
785 }
162
b169992137a8 improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 161
diff changeset
786
519
857e5b92828b add workaround for blocking cgi waitpid
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 518
diff changeset
787 // TODO: Because of WNOHANG, waitpid could fail and the process
857e5b92828b add workaround for blocking cgi waitpid
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 518
diff changeset
788 // is still running. In that case, another waitpid call should
857e5b92828b add workaround for blocking cgi waitpid
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 518
diff changeset
789 // be done later somewhere.
857e5b92828b add workaround for blocking cgi waitpid
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 518
diff changeset
790 int status = -1;
857e5b92828b add workaround for blocking cgi waitpid
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 518
diff changeset
791 if(waitpid(p->pid, &status, WNOHANG) == 0) {
857e5b92828b add workaround for blocking cgi waitpid
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 518
diff changeset
792 log_ereport(LOG_DEBUG, "cgi_close: waitpid returned 0: pid: %d", (int)p->pid);
857e5b92828b add workaround for blocking cgi waitpid
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 518
diff changeset
793 // cgi process still running
857e5b92828b add workaround for blocking cgi waitpid
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 518
diff changeset
794 // workaround: sleep 1 sec and try again, if that fails again
857e5b92828b add workaround for blocking cgi waitpid
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 518
diff changeset
795 sleep(1);
857e5b92828b add workaround for blocking cgi waitpid
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 518
diff changeset
796 if(waitpid(p->pid, &status, WNOHANG) == 0) {
857e5b92828b add workaround for blocking cgi waitpid
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 518
diff changeset
797 log_ereport(LOG_DEBUG, "cgi_close: waitpid returned 0 again: pid: %d", (int)p->pid);
857e5b92828b add workaround for blocking cgi waitpid
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 518
diff changeset
798 }
857e5b92828b add workaround for blocking cgi waitpid
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 518
diff changeset
799 }
857e5b92828b add workaround for blocking cgi waitpid
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 518
diff changeset
800
359
79b28ae7bfbd check cgi exit code
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
801 return status;
144
4b546c4f25ed fixes cgi fd leak
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 133
diff changeset
802 }
4b546c4f25ed fixes cgi fd leak
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 133
diff changeset
803
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
804 CGIResponseParser* cgi_parser_new(Session *sn, Request *rq) {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
805 CGIResponseParser* parser = pool_malloc(sn->pool, sizeof(CGIResponseParser));
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
806 parser->sn = sn;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
807 parser->rq = rq;
124
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
808 parser->status = 0;
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
809 parser->msg = NULL;
430
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
810 parser->response_length = 0;
83560f32e7d5 refactor send_cgi into non-blocking SAF (wip)
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
811 parser->cgiheader = TRUE;
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
812 cxBufferInit(&parser->tmp, NULL, 64, pool_allocator(sn->pool), CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
813 return parser;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
814 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
815
124
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
816 void cgi_parser_free(CGIResponseParser *parser) {
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
817 if(parser->tmp.space) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
818 cxBufferDestroy(&parser->tmp);
124
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
819 }
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
820 pool_free(parser->sn->pool, parser);
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
821 }
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
822
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
823 /*
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
824 * parses a cgi response line and adds the response header to rq->srvhdrs
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
825 * returns 0: incomplete line
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
826 * 1: successfully parsed lines
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
827 * 2: cgi response header complete (empty line)
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
828 * -1: error
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
829 */
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
830 static int parse_lines(CGIResponseParser *parser, char *buf, size_t len, int *pos) {
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
831 CxAllocator *a = pool_allocator(parser->sn->pool);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
832 cxmutstr name;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
833 cxmutstr value;
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
834 WSBool space = TRUE;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
835 int i;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
836
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
837 int line_begin = 0;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
838 int value_begin = 0;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
839 for(i=0;i<len;i++) {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
840 char c = buf[i];
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
841 if(value_begin == line_begin && c == ':') {
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
842 name = cx_mutstrn(buf + line_begin, i - line_begin);
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
843 value_begin = i + 1;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
844 } else if(c == '\n') {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
845 if(value_begin == line_begin) {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
846 if(space) {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
847 *pos = i + 1;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
848 return 2;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
849 } else {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
850 // line ends with content but without ':' -> error
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
851 return -1;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
852 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
853 }
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
854 value = cx_mutstrn(buf + value_begin, i - value_begin);
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
855
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 567
diff changeset
856 for(int l=0;i<name.length;l++) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 567
diff changeset
857 name.ptr[l] = tolower(name.ptr[l]);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 567
diff changeset
858 }
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
859 name = cx_strdup_a(a, cx_strtrim((cxstring){name.ptr, name.length}));
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
860 value = cx_strtrim_m(value);
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
861
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
862 if(name.length == 0 || value.length == 0) {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
863 return -1;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
864 }
124
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
865
585
bae488d2b3c2 make cgi response status header check case insensitive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 579
diff changeset
866 if(!cx_strcasecmp((cxstring){name.ptr, name.length}, (cxstring)CX_STR("status"))) {
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
867 cxmutstr codestr = value;
133
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
868 int j;
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
869 for(j=0;j<codestr.length;j++) {
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
870 if(!isdigit(codestr.ptr[j])) {
124
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
871 break;
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
872 }
133
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
873 if(j > 2) {
124
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
874 break;
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
875 }
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
876 }
133
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
877 codestr.ptr[j] = '\0';
124
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
878
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
879 int64_t s = 0;
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
880 util_strtoint(codestr.ptr, &s);
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
881 parser->status = (int)s;
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
882
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
883 cxmutstr msg = cx_strtrim_m(cx_strsubs_m(value, j + 1));
124
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
884
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
885 if(msg.length > 0) {
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
886 parser->msg = cx_strdup_pool(parser->sn->pool, msg).ptr;
124
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
887 }
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
888 } else {
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
889 pblock_nvlinsert(
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
890 name.ptr,
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
891 name.length,
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
892 value.ptr,
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
893 value.length,
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
894 parser->rq->srvhdrs);
85985e88f63b using the status code from cgi output now
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 123
diff changeset
895 }
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
896
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
897 line_begin = i+1;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
898 value_begin = line_begin;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
899 space = TRUE;
121
a881dc866e23 adds more CGI stuff
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 120
diff changeset
900 } else if(!isspace(c)) {
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
901 space = FALSE;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
902 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
903 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
904
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
905 if(i < len) {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
906 *pos = i;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
907 return 0;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
908 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
909 return 1;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
910 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
911
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
912 /*
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
913 * returns -1: error
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
914 * 0: response header incomplete
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
915 * 1: complete
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
916 */
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
917 int cgi_parse_response(CGIResponseParser *parser, char *buf, size_t len, size_t *bpos) {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
918 *bpos = 0;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
919 int pos = 0;
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
920 if(parser->tmp.pos > 0) {
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
921 // the tmp buffer contains an unfinished line
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
922 // fill up the buffer until the line is complete
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
923 WSBool nb = FALSE;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
924 for(pos=0;pos<len;pos++) {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
925 if(buf[pos] == '\n') {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
926 nb = TRUE;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
927 break;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
928 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
929 }
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
930 cxBufferWrite(buf, 1, pos, &parser->tmp);
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
931
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
932 if(nb) {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
933 // line complete
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
934 int npos;
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
935 int r = parse_lines(parser, parser->tmp.space, parser->tmp.pos, &npos);
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
936 switch(r) {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
937 case -1: return -1;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
938 case 0: return -1;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
939 case 1: break;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
940 case 2: {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
941 *bpos = pos + 1;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
942 return 1;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
943 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
944 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
945 // reset tmp buffer
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
946 parser->tmp.pos = 0;
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
947 } else {
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
948 if(parser->tmp.pos > CGI_RESPONSE_MAX_LINE_LENGTH) {
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
949 return -1;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
950 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
951 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
952 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
953
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
954 int npos = 0;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
955 int r = parse_lines(parser, buf + pos, len - pos, &npos);
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
956 switch(r) {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
957 default: return -1;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
958 case 0:
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
959 case 1: {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
960 int newlen = len - npos;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
961 if(npos > 0) {
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 359
diff changeset
962 cxBufferWrite(buf + npos, 1, newlen, &parser->tmp);
118
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
963 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
964 return 0;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
965 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
966 case 2: {
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
967 *bpos = pos + npos;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
968 return 1;
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
969 }
38bf6dd8f4e7 adds minimal cgi implementation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
970 }
171
af7e2d80dee6 adds wrapper for close syscall with error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 164
diff changeset
971 }

mercurial