xref: /aosp_15_r20/external/libwebsockets/lib/roles/cgi/cgi-server.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker  * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker  * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker  *
13*1c60b9acSAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker  *
16*1c60b9acSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker  * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker  */
24*1c60b9acSAndroid Build Coastguard Worker 
25*1c60b9acSAndroid Build Coastguard Worker #if !defined(_GNU_SOURCE)
26*1c60b9acSAndroid Build Coastguard Worker #define _GNU_SOURCE
27*1c60b9acSAndroid Build Coastguard Worker #endif
28*1c60b9acSAndroid Build Coastguard Worker 
29*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
30*1c60b9acSAndroid Build Coastguard Worker 
31*1c60b9acSAndroid Build Coastguard Worker #if defined(WIN32) || defined(_WIN32)
32*1c60b9acSAndroid Build Coastguard Worker #else
33*1c60b9acSAndroid Build Coastguard Worker #include <sys/wait.h>
34*1c60b9acSAndroid Build Coastguard Worker #endif
35*1c60b9acSAndroid Build Coastguard Worker 
36*1c60b9acSAndroid Build Coastguard Worker static const char *hex = "0123456789ABCDEF";
37*1c60b9acSAndroid Build Coastguard Worker 
38*1c60b9acSAndroid Build Coastguard Worker void
39*1c60b9acSAndroid Build Coastguard Worker lws_cgi_sul_cb(lws_sorted_usec_list_t *sul);
40*1c60b9acSAndroid Build Coastguard Worker 
41*1c60b9acSAndroid Build Coastguard Worker static int
urlencode(const char * in,int inlen,char * out,int outlen)42*1c60b9acSAndroid Build Coastguard Worker urlencode(const char *in, int inlen, char *out, int outlen)
43*1c60b9acSAndroid Build Coastguard Worker {
44*1c60b9acSAndroid Build Coastguard Worker 	char *start = out, *end = out + outlen;
45*1c60b9acSAndroid Build Coastguard Worker 
46*1c60b9acSAndroid Build Coastguard Worker 	while (inlen-- && out < end - 4) {
47*1c60b9acSAndroid Build Coastguard Worker 		if ((*in >= 'A' && *in <= 'Z') ||
48*1c60b9acSAndroid Build Coastguard Worker 		    (*in >= 'a' && *in <= 'z') ||
49*1c60b9acSAndroid Build Coastguard Worker 		    (*in >= '0' && *in <= '9') ||
50*1c60b9acSAndroid Build Coastguard Worker 		    *in == '-' ||
51*1c60b9acSAndroid Build Coastguard Worker 		    *in == '_' ||
52*1c60b9acSAndroid Build Coastguard Worker 		    *in == '.' ||
53*1c60b9acSAndroid Build Coastguard Worker 		    *in == '~') {
54*1c60b9acSAndroid Build Coastguard Worker 			*out++ = *in++;
55*1c60b9acSAndroid Build Coastguard Worker 			continue;
56*1c60b9acSAndroid Build Coastguard Worker 		}
57*1c60b9acSAndroid Build Coastguard Worker 		if (*in == ' ') {
58*1c60b9acSAndroid Build Coastguard Worker 			*out++ = '+';
59*1c60b9acSAndroid Build Coastguard Worker 			in++;
60*1c60b9acSAndroid Build Coastguard Worker 			continue;
61*1c60b9acSAndroid Build Coastguard Worker 		}
62*1c60b9acSAndroid Build Coastguard Worker 		*out++ = '%';
63*1c60b9acSAndroid Build Coastguard Worker 		*out++ = hex[(*in) >> 4];
64*1c60b9acSAndroid Build Coastguard Worker 		*out++ = hex[(*in++) & 15];
65*1c60b9acSAndroid Build Coastguard Worker 	}
66*1c60b9acSAndroid Build Coastguard Worker 	*out = '\0';
67*1c60b9acSAndroid Build Coastguard Worker 
68*1c60b9acSAndroid Build Coastguard Worker 	if (out >= end - 4)
69*1c60b9acSAndroid Build Coastguard Worker 		return -1;
70*1c60b9acSAndroid Build Coastguard Worker 
71*1c60b9acSAndroid Build Coastguard Worker 	return lws_ptr_diff(out, start);
72*1c60b9acSAndroid Build Coastguard Worker }
73*1c60b9acSAndroid Build Coastguard Worker 
74*1c60b9acSAndroid Build Coastguard Worker static void
lws_cgi_grace(lws_sorted_usec_list_t * sul)75*1c60b9acSAndroid Build Coastguard Worker lws_cgi_grace(lws_sorted_usec_list_t *sul)
76*1c60b9acSAndroid Build Coastguard Worker {
77*1c60b9acSAndroid Build Coastguard Worker 	struct lws_cgi *cgi = lws_container_of(sul, struct lws_cgi, sul_grace);
78*1c60b9acSAndroid Build Coastguard Worker 
79*1c60b9acSAndroid Build Coastguard Worker 	/* act on the reap cb from earlier */
80*1c60b9acSAndroid Build Coastguard Worker 
81*1c60b9acSAndroid Build Coastguard Worker 	if (!cgi->wsi->http.cgi->post_in_expected)
82*1c60b9acSAndroid Build Coastguard Worker 		cgi->wsi->http.cgi->cgi_transaction_over = 1;
83*1c60b9acSAndroid Build Coastguard Worker 
84*1c60b9acSAndroid Build Coastguard Worker 	lws_callback_on_writable(cgi->wsi);
85*1c60b9acSAndroid Build Coastguard Worker }
86*1c60b9acSAndroid Build Coastguard Worker 
87*1c60b9acSAndroid Build Coastguard Worker 
88*1c60b9acSAndroid Build Coastguard Worker static void
lws_cgi_reap_cb(void * opaque,lws_usec_t * accounting,siginfo_t * si,int we_killed_him)89*1c60b9acSAndroid Build Coastguard Worker lws_cgi_reap_cb(void *opaque, lws_usec_t *accounting, siginfo_t *si,
90*1c60b9acSAndroid Build Coastguard Worker 		 int we_killed_him)
91*1c60b9acSAndroid Build Coastguard Worker {
92*1c60b9acSAndroid Build Coastguard Worker 	struct lws *wsi = (struct lws *)opaque;
93*1c60b9acSAndroid Build Coastguard Worker 
94*1c60b9acSAndroid Build Coastguard Worker 	/*
95*1c60b9acSAndroid Build Coastguard Worker 	 * The cgi has come to an end, by itself or with a signal...
96*1c60b9acSAndroid Build Coastguard Worker 	 */
97*1c60b9acSAndroid Build Coastguard Worker 
98*1c60b9acSAndroid Build Coastguard Worker 	lwsl_wsi_info(wsi, "post_in_expected %d",
99*1c60b9acSAndroid Build Coastguard Worker 			   (int)wsi->http.cgi->post_in_expected);
100*1c60b9acSAndroid Build Coastguard Worker 
101*1c60b9acSAndroid Build Coastguard Worker 	/*
102*1c60b9acSAndroid Build Coastguard Worker 	 * Grace period to handle the incoming stdout
103*1c60b9acSAndroid Build Coastguard Worker 	 */
104*1c60b9acSAndroid Build Coastguard Worker 
105*1c60b9acSAndroid Build Coastguard Worker 	lws_sul_schedule(wsi->a.context, wsi->tsi, &wsi->http.cgi->sul_grace,
106*1c60b9acSAndroid Build Coastguard Worker 			 lws_cgi_grace, 1 * LWS_US_PER_SEC);
107*1c60b9acSAndroid Build Coastguard Worker }
108*1c60b9acSAndroid Build Coastguard Worker 
109*1c60b9acSAndroid Build Coastguard Worker int
lws_cgi(struct lws * wsi,const char * const * exec_array,int script_uri_path_len,int timeout_secs,const struct lws_protocol_vhost_options * mp_cgienv)110*1c60b9acSAndroid Build Coastguard Worker lws_cgi(struct lws *wsi, const char * const *exec_array,
111*1c60b9acSAndroid Build Coastguard Worker 	int script_uri_path_len, int timeout_secs,
112*1c60b9acSAndroid Build Coastguard Worker 	const struct lws_protocol_vhost_options *mp_cgienv)
113*1c60b9acSAndroid Build Coastguard Worker {
114*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
115*1c60b9acSAndroid Build Coastguard Worker 	struct lws_spawn_piped_info info;
116*1c60b9acSAndroid Build Coastguard Worker 	char *env_array[30], cgi_path[500], e[1024], *p = e,
117*1c60b9acSAndroid Build Coastguard Worker 	     *end = p + sizeof(e) - 1, tok[256], *t, *sum, *sumend;
118*1c60b9acSAndroid Build Coastguard Worker 	struct lws_cgi *cgi;
119*1c60b9acSAndroid Build Coastguard Worker 	int n, m = 0, i, uritok = -1, c;
120*1c60b9acSAndroid Build Coastguard Worker 
121*1c60b9acSAndroid Build Coastguard Worker 	/*
122*1c60b9acSAndroid Build Coastguard Worker 	 * give the cgi stream wsi a cgi struct
123*1c60b9acSAndroid Build Coastguard Worker 	 */
124*1c60b9acSAndroid Build Coastguard Worker 
125*1c60b9acSAndroid Build Coastguard Worker 	wsi->http.cgi = lws_zalloc(sizeof(*wsi->http.cgi), "new cgi");
126*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->http.cgi) {
127*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_err(wsi, "OOM");
128*1c60b9acSAndroid Build Coastguard Worker 		return -1;
129*1c60b9acSAndroid Build Coastguard Worker 	}
130*1c60b9acSAndroid Build Coastguard Worker 
131*1c60b9acSAndroid Build Coastguard Worker 	wsi->http.cgi->response_code = HTTP_STATUS_OK;
132*1c60b9acSAndroid Build Coastguard Worker 
133*1c60b9acSAndroid Build Coastguard Worker 	cgi = wsi->http.cgi;
134*1c60b9acSAndroid Build Coastguard Worker 	cgi->wsi = wsi; /* set cgi's owning wsi */
135*1c60b9acSAndroid Build Coastguard Worker 	sum = cgi->summary;
136*1c60b9acSAndroid Build Coastguard Worker 	sumend = sum + strlen(cgi->summary) - 1;
137*1c60b9acSAndroid Build Coastguard Worker 
138*1c60b9acSAndroid Build Coastguard Worker 	if (timeout_secs)
139*1c60b9acSAndroid Build Coastguard Worker 		lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, timeout_secs);
140*1c60b9acSAndroid Build Coastguard Worker 
141*1c60b9acSAndroid Build Coastguard Worker 	/* the cgi stdout is always sending us http1.x header data first */
142*1c60b9acSAndroid Build Coastguard Worker 	wsi->hdr_state = LCHS_HEADER;
143*1c60b9acSAndroid Build Coastguard Worker 
144*1c60b9acSAndroid Build Coastguard Worker 	/* add us to the pt list of active cgis */
145*1c60b9acSAndroid Build Coastguard Worker 	lwsl_wsi_debug(wsi, "adding cgi %p to list", wsi->http.cgi);
146*1c60b9acSAndroid Build Coastguard Worker 	cgi->cgi_list = pt->http.cgi_list;
147*1c60b9acSAndroid Build Coastguard Worker 	pt->http.cgi_list = cgi;
148*1c60b9acSAndroid Build Coastguard Worker 
149*1c60b9acSAndroid Build Coastguard Worker 	/* if it's not already running, start the cleanup timer */
150*1c60b9acSAndroid Build Coastguard Worker 	if (!pt->sul_cgi.list.owner)
151*1c60b9acSAndroid Build Coastguard Worker 		lws_sul_schedule(pt->context, (int)(pt - pt->context->pt), &pt->sul_cgi,
152*1c60b9acSAndroid Build Coastguard Worker 				 lws_cgi_sul_cb, 3 * LWS_US_PER_SEC);
153*1c60b9acSAndroid Build Coastguard Worker 
154*1c60b9acSAndroid Build Coastguard Worker 	sum += lws_snprintf(sum, lws_ptr_diff_size_t(sumend, sum), "%s ", exec_array[0]);
155*1c60b9acSAndroid Build Coastguard Worker 
156*1c60b9acSAndroid Build Coastguard Worker 	if (0) {
157*1c60b9acSAndroid Build Coastguard Worker 		char *pct = lws_hdr_simple_ptr(wsi,
158*1c60b9acSAndroid Build Coastguard Worker 				WSI_TOKEN_HTTP_CONTENT_ENCODING);
159*1c60b9acSAndroid Build Coastguard Worker 
160*1c60b9acSAndroid Build Coastguard Worker 		if (pct && !strcmp(pct, "gzip"))
161*1c60b9acSAndroid Build Coastguard Worker 			wsi->http.cgi->gzip_inflate = 1;
162*1c60b9acSAndroid Build Coastguard Worker 	}
163*1c60b9acSAndroid Build Coastguard Worker 
164*1c60b9acSAndroid Build Coastguard Worker 	/* prepare his CGI env */
165*1c60b9acSAndroid Build Coastguard Worker 
166*1c60b9acSAndroid Build Coastguard Worker 	n = 0;
167*1c60b9acSAndroid Build Coastguard Worker 
168*1c60b9acSAndroid Build Coastguard Worker 	if (lws_is_ssl(wsi)) {
169*1c60b9acSAndroid Build Coastguard Worker 		env_array[n++] = p;
170*1c60b9acSAndroid Build Coastguard Worker 		p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "HTTPS=ON");
171*1c60b9acSAndroid Build Coastguard Worker 		p++;
172*1c60b9acSAndroid Build Coastguard Worker 	}
173*1c60b9acSAndroid Build Coastguard Worker 
174*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->http.ah) {
175*1c60b9acSAndroid Build Coastguard Worker 		static const unsigned char meths[] = {
176*1c60b9acSAndroid Build Coastguard Worker 			WSI_TOKEN_GET_URI,
177*1c60b9acSAndroid Build Coastguard Worker 			WSI_TOKEN_POST_URI,
178*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS)
179*1c60b9acSAndroid Build Coastguard Worker 			WSI_TOKEN_OPTIONS_URI,
180*1c60b9acSAndroid Build Coastguard Worker 			WSI_TOKEN_PUT_URI,
181*1c60b9acSAndroid Build Coastguard Worker 			WSI_TOKEN_PATCH_URI,
182*1c60b9acSAndroid Build Coastguard Worker 			WSI_TOKEN_DELETE_URI,
183*1c60b9acSAndroid Build Coastguard Worker #endif
184*1c60b9acSAndroid Build Coastguard Worker 			WSI_TOKEN_CONNECT,
185*1c60b9acSAndroid Build Coastguard Worker 			WSI_TOKEN_HEAD_URI,
186*1c60b9acSAndroid Build Coastguard Worker 		#ifdef LWS_WITH_HTTP2
187*1c60b9acSAndroid Build Coastguard Worker 			WSI_TOKEN_HTTP_COLON_PATH,
188*1c60b9acSAndroid Build Coastguard Worker 		#endif
189*1c60b9acSAndroid Build Coastguard Worker 		};
190*1c60b9acSAndroid Build Coastguard Worker 		static const char * const meth_names[] = {
191*1c60b9acSAndroid Build Coastguard Worker 			"GET", "POST",
192*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS)
193*1c60b9acSAndroid Build Coastguard Worker 			"OPTIONS", "PUT", "PATCH", "DELETE",
194*1c60b9acSAndroid Build Coastguard Worker #endif
195*1c60b9acSAndroid Build Coastguard Worker 			"CONNECT", "HEAD", ":path"
196*1c60b9acSAndroid Build Coastguard Worker 		};
197*1c60b9acSAndroid Build Coastguard Worker 
198*1c60b9acSAndroid Build Coastguard Worker 		if (script_uri_path_len >= 0)
199*1c60b9acSAndroid Build Coastguard Worker 			for (m = 0; m < (int)LWS_ARRAY_SIZE(meths); m++)
200*1c60b9acSAndroid Build Coastguard Worker 				if (lws_hdr_total_length(wsi, meths[m]) >=
201*1c60b9acSAndroid Build Coastguard Worker 						script_uri_path_len) {
202*1c60b9acSAndroid Build Coastguard Worker 					uritok = meths[m];
203*1c60b9acSAndroid Build Coastguard Worker 					break;
204*1c60b9acSAndroid Build Coastguard Worker 				}
205*1c60b9acSAndroid Build Coastguard Worker 
206*1c60b9acSAndroid Build Coastguard Worker 		if (script_uri_path_len < 0 && uritok < 0)
207*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
208*1c60b9acSAndroid Build Coastguard Worker //		if (script_uri_path_len < 0)
209*1c60b9acSAndroid Build Coastguard Worker //			uritok = 0;
210*1c60b9acSAndroid Build Coastguard Worker 
211*1c60b9acSAndroid Build Coastguard Worker 		if (m >= 0) {
212*1c60b9acSAndroid Build Coastguard Worker 			env_array[n++] = p;
213*1c60b9acSAndroid Build Coastguard Worker 			if (m < (int)LWS_ARRAY_SIZE(meths) - 1) {
214*1c60b9acSAndroid Build Coastguard Worker 				p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
215*1c60b9acSAndroid Build Coastguard Worker 						  "REQUEST_METHOD=%s",
216*1c60b9acSAndroid Build Coastguard Worker 						  meth_names[m]);
217*1c60b9acSAndroid Build Coastguard Worker 				sum += lws_snprintf(sum, lws_ptr_diff_size_t(sumend, sum), "%s ",
218*1c60b9acSAndroid Build Coastguard Worker 						    meth_names[m]);
219*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_H2)
220*1c60b9acSAndroid Build Coastguard Worker 			} else {
221*1c60b9acSAndroid Build Coastguard Worker 				p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
222*1c60b9acSAndroid Build Coastguard Worker 						  "REQUEST_METHOD=%s",
223*1c60b9acSAndroid Build Coastguard Worker 			  lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD));
224*1c60b9acSAndroid Build Coastguard Worker 				sum += lws_snprintf(sum, lws_ptr_diff_size_t(sumend, sum), "%s ",
225*1c60b9acSAndroid Build Coastguard Worker 					lws_hdr_simple_ptr(wsi,
226*1c60b9acSAndroid Build Coastguard Worker 						  WSI_TOKEN_HTTP_COLON_METHOD));
227*1c60b9acSAndroid Build Coastguard Worker #endif
228*1c60b9acSAndroid Build Coastguard Worker 			}
229*1c60b9acSAndroid Build Coastguard Worker 			p++;
230*1c60b9acSAndroid Build Coastguard Worker 		}
231*1c60b9acSAndroid Build Coastguard Worker 
232*1c60b9acSAndroid Build Coastguard Worker 		if (uritok >= 0)
233*1c60b9acSAndroid Build Coastguard Worker 			sum += lws_snprintf(sum, lws_ptr_diff_size_t(sumend, sum), "%s ",
234*1c60b9acSAndroid Build Coastguard Worker 					    lws_hdr_simple_ptr(wsi, (enum lws_token_indexes)uritok));
235*1c60b9acSAndroid Build Coastguard Worker 
236*1c60b9acSAndroid Build Coastguard Worker 		env_array[n++] = p;
237*1c60b9acSAndroid Build Coastguard Worker 		p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "QUERY_STRING=");
238*1c60b9acSAndroid Build Coastguard Worker 		/* dump the individual URI Arg parameters */
239*1c60b9acSAndroid Build Coastguard Worker 		m = 0;
240*1c60b9acSAndroid Build Coastguard Worker 		while (script_uri_path_len >= 0) {
241*1c60b9acSAndroid Build Coastguard Worker 			i = lws_hdr_copy_fragment(wsi, tok, sizeof(tok),
242*1c60b9acSAndroid Build Coastguard Worker 					     WSI_TOKEN_HTTP_URI_ARGS, m);
243*1c60b9acSAndroid Build Coastguard Worker 			if (i < 0)
244*1c60b9acSAndroid Build Coastguard Worker 				break;
245*1c60b9acSAndroid Build Coastguard Worker 			t = tok;
246*1c60b9acSAndroid Build Coastguard Worker 			while (*t && *t != '=' && p < end - 4)
247*1c60b9acSAndroid Build Coastguard Worker 				*p++ = *t++;
248*1c60b9acSAndroid Build Coastguard Worker 			if (*t == '=')
249*1c60b9acSAndroid Build Coastguard Worker 				*p++ = *t++;
250*1c60b9acSAndroid Build Coastguard Worker 			i = urlencode(t, i - lws_ptr_diff(t, tok), p, lws_ptr_diff(end, p));
251*1c60b9acSAndroid Build Coastguard Worker 			if (i > 0) {
252*1c60b9acSAndroid Build Coastguard Worker 				p += i;
253*1c60b9acSAndroid Build Coastguard Worker 				*p++ = '&';
254*1c60b9acSAndroid Build Coastguard Worker 			}
255*1c60b9acSAndroid Build Coastguard Worker 			m++;
256*1c60b9acSAndroid Build Coastguard Worker 		}
257*1c60b9acSAndroid Build Coastguard Worker 		if (m)
258*1c60b9acSAndroid Build Coastguard Worker 			p--;
259*1c60b9acSAndroid Build Coastguard Worker 		*p++ = '\0';
260*1c60b9acSAndroid Build Coastguard Worker 
261*1c60b9acSAndroid Build Coastguard Worker 		if (uritok >= 0) {
262*1c60b9acSAndroid Build Coastguard Worker 			strcpy(cgi_path, "REQUEST_URI=");
263*1c60b9acSAndroid Build Coastguard Worker 			c = lws_hdr_copy(wsi, cgi_path + 12,
264*1c60b9acSAndroid Build Coastguard Worker 					 sizeof(cgi_path) - 12, (enum lws_token_indexes)uritok);
265*1c60b9acSAndroid Build Coastguard Worker 			if (c < 0)
266*1c60b9acSAndroid Build Coastguard Worker 				goto bail;
267*1c60b9acSAndroid Build Coastguard Worker 
268*1c60b9acSAndroid Build Coastguard Worker 			cgi_path[sizeof(cgi_path) - 1] = '\0';
269*1c60b9acSAndroid Build Coastguard Worker 			env_array[n++] = cgi_path;
270*1c60b9acSAndroid Build Coastguard Worker 		}
271*1c60b9acSAndroid Build Coastguard Worker 
272*1c60b9acSAndroid Build Coastguard Worker 		sum += lws_snprintf(sum, lws_ptr_diff_size_t(sumend, sum), "%s", env_array[n - 1]);
273*1c60b9acSAndroid Build Coastguard Worker 
274*1c60b9acSAndroid Build Coastguard Worker 		if (script_uri_path_len >= 0) {
275*1c60b9acSAndroid Build Coastguard Worker 			env_array[n++] = p;
276*1c60b9acSAndroid Build Coastguard Worker 			p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "PATH_INFO=%s",
277*1c60b9acSAndroid Build Coastguard Worker 				      cgi_path + 12 + script_uri_path_len);
278*1c60b9acSAndroid Build Coastguard Worker 			p++;
279*1c60b9acSAndroid Build Coastguard Worker 		}
280*1c60b9acSAndroid Build Coastguard Worker 	}
281*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS)
282*1c60b9acSAndroid Build Coastguard Worker 	if (script_uri_path_len >= 0 &&
283*1c60b9acSAndroid Build Coastguard Worker 	    lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_REFERER)) {
284*1c60b9acSAndroid Build Coastguard Worker 		env_array[n++] = p;
285*1c60b9acSAndroid Build Coastguard Worker 		p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "HTTP_REFERER=%s",
286*1c60b9acSAndroid Build Coastguard Worker 			      lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_REFERER));
287*1c60b9acSAndroid Build Coastguard Worker 		p++;
288*1c60b9acSAndroid Build Coastguard Worker 	}
289*1c60b9acSAndroid Build Coastguard Worker #endif
290*1c60b9acSAndroid Build Coastguard Worker 	if (script_uri_path_len >= 0 &&
291*1c60b9acSAndroid Build Coastguard Worker 	    lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) {
292*1c60b9acSAndroid Build Coastguard Worker 		env_array[n++] = p;
293*1c60b9acSAndroid Build Coastguard Worker 		p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "HTTP_HOST=%s",
294*1c60b9acSAndroid Build Coastguard Worker 			      lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST));
295*1c60b9acSAndroid Build Coastguard Worker 		p++;
296*1c60b9acSAndroid Build Coastguard Worker 	}
297*1c60b9acSAndroid Build Coastguard Worker 	if (script_uri_path_len >= 0 &&
298*1c60b9acSAndroid Build Coastguard Worker 	    lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE)) {
299*1c60b9acSAndroid Build Coastguard Worker 		env_array[n++] = p;
300*1c60b9acSAndroid Build Coastguard Worker 		p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "HTTP_COOKIE=");
301*1c60b9acSAndroid Build Coastguard Worker 		m = lws_hdr_copy(wsi, p, lws_ptr_diff(end, p), WSI_TOKEN_HTTP_COOKIE);
302*1c60b9acSAndroid Build Coastguard Worker 		if (m > 0)
303*1c60b9acSAndroid Build Coastguard Worker 			p += lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE);
304*1c60b9acSAndroid Build Coastguard Worker 		*p++ = '\0';
305*1c60b9acSAndroid Build Coastguard Worker 	}
306*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS)
307*1c60b9acSAndroid Build Coastguard Worker 	if (script_uri_path_len >= 0 &&
308*1c60b9acSAndroid Build Coastguard Worker 	    lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_USER_AGENT)) {
309*1c60b9acSAndroid Build Coastguard Worker 		env_array[n++] = p;
310*1c60b9acSAndroid Build Coastguard Worker 		p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "HTTP_USER_AGENT=%s",
311*1c60b9acSAndroid Build Coastguard Worker 			    lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_USER_AGENT));
312*1c60b9acSAndroid Build Coastguard Worker 		p++;
313*1c60b9acSAndroid Build Coastguard Worker 	}
314*1c60b9acSAndroid Build Coastguard Worker #endif
315*1c60b9acSAndroid Build Coastguard Worker 	if (script_uri_path_len >= 0 &&
316*1c60b9acSAndroid Build Coastguard Worker 	    lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_ENCODING)) {
317*1c60b9acSAndroid Build Coastguard Worker 		env_array[n++] = p;
318*1c60b9acSAndroid Build Coastguard Worker 		p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "HTTP_CONTENT_ENCODING=%s",
319*1c60b9acSAndroid Build Coastguard Worker 		      lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_ENCODING));
320*1c60b9acSAndroid Build Coastguard Worker 		p++;
321*1c60b9acSAndroid Build Coastguard Worker 	}
322*1c60b9acSAndroid Build Coastguard Worker 	if (script_uri_path_len >= 0 &&
323*1c60b9acSAndroid Build Coastguard Worker 	    lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_ACCEPT)) {
324*1c60b9acSAndroid Build Coastguard Worker 		env_array[n++] = p;
325*1c60b9acSAndroid Build Coastguard Worker 		p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "HTTP_ACCEPT=%s",
326*1c60b9acSAndroid Build Coastguard Worker 			      lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_ACCEPT));
327*1c60b9acSAndroid Build Coastguard Worker 		p++;
328*1c60b9acSAndroid Build Coastguard Worker 	}
329*1c60b9acSAndroid Build Coastguard Worker 	if (script_uri_path_len >= 0 &&
330*1c60b9acSAndroid Build Coastguard Worker 	    lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_ACCEPT_ENCODING)) {
331*1c60b9acSAndroid Build Coastguard Worker 		env_array[n++] = p;
332*1c60b9acSAndroid Build Coastguard Worker 		p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "HTTP_ACCEPT_ENCODING=%s",
333*1c60b9acSAndroid Build Coastguard Worker 		      lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_ACCEPT_ENCODING));
334*1c60b9acSAndroid Build Coastguard Worker 		p++;
335*1c60b9acSAndroid Build Coastguard Worker 	}
336*1c60b9acSAndroid Build Coastguard Worker 	if (script_uri_path_len >= 0 &&
337*1c60b9acSAndroid Build Coastguard Worker 	    uritok == WSI_TOKEN_POST_URI) {
338*1c60b9acSAndroid Build Coastguard Worker 		if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) {
339*1c60b9acSAndroid Build Coastguard Worker 			env_array[n++] = p;
340*1c60b9acSAndroid Build Coastguard Worker 			p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "CONTENT_TYPE=%s",
341*1c60b9acSAndroid Build Coastguard Worker 			  lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE));
342*1c60b9acSAndroid Build Coastguard Worker 			p++;
343*1c60b9acSAndroid Build Coastguard Worker 		}
344*1c60b9acSAndroid Build Coastguard Worker 		if (!wsi->http.cgi->gzip_inflate &&
345*1c60b9acSAndroid Build Coastguard Worker 		    lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
346*1c60b9acSAndroid Build Coastguard Worker 			env_array[n++] = p;
347*1c60b9acSAndroid Build Coastguard Worker 			p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "CONTENT_LENGTH=%s",
348*1c60b9acSAndroid Build Coastguard Worker 					  lws_hdr_simple_ptr(wsi,
349*1c60b9acSAndroid Build Coastguard Worker 					  WSI_TOKEN_HTTP_CONTENT_LENGTH));
350*1c60b9acSAndroid Build Coastguard Worker 			p++;
351*1c60b9acSAndroid Build Coastguard Worker 		}
352*1c60b9acSAndroid Build Coastguard Worker 
353*1c60b9acSAndroid Build Coastguard Worker 		if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH))
354*1c60b9acSAndroid Build Coastguard Worker 			wsi->http.cgi->post_in_expected = (lws_filepos_t)
355*1c60b9acSAndroid Build Coastguard Worker 				atoll(lws_hdr_simple_ptr(wsi,
356*1c60b9acSAndroid Build Coastguard Worker 						WSI_TOKEN_HTTP_CONTENT_LENGTH));
357*1c60b9acSAndroid Build Coastguard Worker 	}
358*1c60b9acSAndroid Build Coastguard Worker 
359*1c60b9acSAndroid Build Coastguard Worker 
360*1c60b9acSAndroid Build Coastguard Worker 	env_array[n++] = p;
361*1c60b9acSAndroid Build Coastguard Worker 	p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "PATH=/bin:/usr/bin:/usr/local/bin:/var/www/cgi-bin");
362*1c60b9acSAndroid Build Coastguard Worker 	p++;
363*1c60b9acSAndroid Build Coastguard Worker 
364*1c60b9acSAndroid Build Coastguard Worker 	env_array[n++] = p;
365*1c60b9acSAndroid Build Coastguard Worker 	p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "SCRIPT_PATH=%s", exec_array[0]);
366*1c60b9acSAndroid Build Coastguard Worker 	p++;
367*1c60b9acSAndroid Build Coastguard Worker 
368*1c60b9acSAndroid Build Coastguard Worker 	while (mp_cgienv) {
369*1c60b9acSAndroid Build Coastguard Worker 		env_array[n++] = p;
370*1c60b9acSAndroid Build Coastguard Worker 		p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "%s=%s", mp_cgienv->name,
371*1c60b9acSAndroid Build Coastguard Worker 			      mp_cgienv->value);
372*1c60b9acSAndroid Build Coastguard Worker 		if (!strcmp(mp_cgienv->name, "GIT_PROJECT_ROOT")) {
373*1c60b9acSAndroid Build Coastguard Worker 			wsi->http.cgi->implied_chunked = 1;
374*1c60b9acSAndroid Build Coastguard Worker 			wsi->http.cgi->explicitly_chunked = 1;
375*1c60b9acSAndroid Build Coastguard Worker 		}
376*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("   Applying mount-specific cgi env '%s'\n",
377*1c60b9acSAndroid Build Coastguard Worker 			   env_array[n - 1]);
378*1c60b9acSAndroid Build Coastguard Worker 		p++;
379*1c60b9acSAndroid Build Coastguard Worker 		mp_cgienv = mp_cgienv->next;
380*1c60b9acSAndroid Build Coastguard Worker 	}
381*1c60b9acSAndroid Build Coastguard Worker 
382*1c60b9acSAndroid Build Coastguard Worker 	env_array[n++] = p;
383*1c60b9acSAndroid Build Coastguard Worker 	p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "SERVER_SOFTWARE=lws");
384*1c60b9acSAndroid Build Coastguard Worker 	p++;
385*1c60b9acSAndroid Build Coastguard Worker 
386*1c60b9acSAndroid Build Coastguard Worker 	env_array[n] = NULL;
387*1c60b9acSAndroid Build Coastguard Worker 
388*1c60b9acSAndroid Build Coastguard Worker #if 0
389*1c60b9acSAndroid Build Coastguard Worker 	for (m = 0; m < n; m++)
390*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("    %s\n", env_array[m]);
391*1c60b9acSAndroid Build Coastguard Worker #endif
392*1c60b9acSAndroid Build Coastguard Worker 
393*1c60b9acSAndroid Build Coastguard Worker 	memset(&info, 0, sizeof(info));
394*1c60b9acSAndroid Build Coastguard Worker 	info.env_array = (const char **)env_array;
395*1c60b9acSAndroid Build Coastguard Worker 	info.exec_array = exec_array;
396*1c60b9acSAndroid Build Coastguard Worker 	info.max_log_lines = 20000;
397*1c60b9acSAndroid Build Coastguard Worker 	info.opt_parent = wsi;
398*1c60b9acSAndroid Build Coastguard Worker 	info.timeout_us = 5 * 60 * LWS_US_PER_SEC;
399*1c60b9acSAndroid Build Coastguard Worker 	info.tsi = wsi->tsi;
400*1c60b9acSAndroid Build Coastguard Worker 	info.vh = wsi->a.vhost;
401*1c60b9acSAndroid Build Coastguard Worker 	info.ops = &role_ops_cgi;
402*1c60b9acSAndroid Build Coastguard Worker 	info.plsp = &wsi->http.cgi->lsp;
403*1c60b9acSAndroid Build Coastguard Worker 	info.opaque = wsi;
404*1c60b9acSAndroid Build Coastguard Worker 	info.reap_cb = lws_cgi_reap_cb;
405*1c60b9acSAndroid Build Coastguard Worker 
406*1c60b9acSAndroid Build Coastguard Worker 	/*
407*1c60b9acSAndroid Build Coastguard Worker 	 * Actually having made the env, as a cgi we don't need the ah
408*1c60b9acSAndroid Build Coastguard Worker 	 * any more
409*1c60b9acSAndroid Build Coastguard Worker 	 */
410*1c60b9acSAndroid Build Coastguard Worker 	if (script_uri_path_len >= 0) {
411*1c60b9acSAndroid Build Coastguard Worker 		lws_header_table_detach(wsi, 0);
412*1c60b9acSAndroid Build Coastguard Worker 		info.disable_ctrlc = 1;
413*1c60b9acSAndroid Build Coastguard Worker 	}
414*1c60b9acSAndroid Build Coastguard Worker 
415*1c60b9acSAndroid Build Coastguard Worker 	wsi->http.cgi->lsp = lws_spawn_piped(&info);
416*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->http.cgi->lsp) {
417*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: spawn failed\n", __func__);
418*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
419*1c60b9acSAndroid Build Coastguard Worker 	}
420*1c60b9acSAndroid Build Coastguard Worker 
421*1c60b9acSAndroid Build Coastguard Worker 	/* we are the parent process */
422*1c60b9acSAndroid Build Coastguard Worker 
423*1c60b9acSAndroid Build Coastguard Worker 	wsi->a.context->count_cgi_spawned++;
424*1c60b9acSAndroid Build Coastguard Worker 
425*1c60b9acSAndroid Build Coastguard Worker 	/* inform cgi owner of the child PID */
426*1c60b9acSAndroid Build Coastguard Worker 	n = user_callback_handle_rxflow(wsi->a.protocol->callback, wsi,
427*1c60b9acSAndroid Build Coastguard Worker 				    LWS_CALLBACK_CGI_PROCESS_ATTACH,
428*1c60b9acSAndroid Build Coastguard Worker 				    wsi->user_space, NULL, (unsigned int)cgi->lsp->child_pid);
429*1c60b9acSAndroid Build Coastguard Worker 	(void)n;
430*1c60b9acSAndroid Build Coastguard Worker 
431*1c60b9acSAndroid Build Coastguard Worker 	return 0;
432*1c60b9acSAndroid Build Coastguard Worker 
433*1c60b9acSAndroid Build Coastguard Worker bail:
434*1c60b9acSAndroid Build Coastguard Worker 	lws_sul_cancel(&wsi->http.cgi->sul_grace);
435*1c60b9acSAndroid Build Coastguard Worker 	lws_free_set_NULL(wsi->http.cgi);
436*1c60b9acSAndroid Build Coastguard Worker 
437*1c60b9acSAndroid Build Coastguard Worker 	lwsl_err("%s: failed\n", __func__);
438*1c60b9acSAndroid Build Coastguard Worker 
439*1c60b9acSAndroid Build Coastguard Worker 	return -1;
440*1c60b9acSAndroid Build Coastguard Worker }
441*1c60b9acSAndroid Build Coastguard Worker 
442*1c60b9acSAndroid Build Coastguard Worker /* we have to parse out these headers in the CGI output */
443*1c60b9acSAndroid Build Coastguard Worker 
444*1c60b9acSAndroid Build Coastguard Worker static const char * const significant_hdr[SIGNIFICANT_HDR_COUNT] = {
445*1c60b9acSAndroid Build Coastguard Worker 	"content-length: ",
446*1c60b9acSAndroid Build Coastguard Worker 	"location: ",
447*1c60b9acSAndroid Build Coastguard Worker 	"status: ",
448*1c60b9acSAndroid Build Coastguard Worker 	"transfer-encoding: chunked",
449*1c60b9acSAndroid Build Coastguard Worker 	"content-encoding: gzip",
450*1c60b9acSAndroid Build Coastguard Worker };
451*1c60b9acSAndroid Build Coastguard Worker 
452*1c60b9acSAndroid Build Coastguard Worker enum header_recode {
453*1c60b9acSAndroid Build Coastguard Worker 	HR_NAME,
454*1c60b9acSAndroid Build Coastguard Worker 	HR_WHITESPACE,
455*1c60b9acSAndroid Build Coastguard Worker 	HR_ARG,
456*1c60b9acSAndroid Build Coastguard Worker 	HR_CRLF,
457*1c60b9acSAndroid Build Coastguard Worker };
458*1c60b9acSAndroid Build Coastguard Worker 
459*1c60b9acSAndroid Build Coastguard Worker int
lws_cgi_write_split_stdout_headers(struct lws * wsi)460*1c60b9acSAndroid Build Coastguard Worker lws_cgi_write_split_stdout_headers(struct lws *wsi)
461*1c60b9acSAndroid Build Coastguard Worker {
462*1c60b9acSAndroid Build Coastguard Worker 	int n, m, cmd;
463*1c60b9acSAndroid Build Coastguard Worker 	unsigned char buf[LWS_PRE + 4096], *start = &buf[LWS_PRE], *p = start,
464*1c60b9acSAndroid Build Coastguard Worker 			*end = &buf[sizeof(buf) - 1 - LWS_PRE], *name,
465*1c60b9acSAndroid Build Coastguard Worker 			*value = NULL;
466*1c60b9acSAndroid Build Coastguard Worker 	char c, hrs;
467*1c60b9acSAndroid Build Coastguard Worker 
468*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->http.cgi)
469*1c60b9acSAndroid Build Coastguard Worker 		return -1;
470*1c60b9acSAndroid Build Coastguard Worker 
471*1c60b9acSAndroid Build Coastguard Worker 	while (wsi->hdr_state != LHCS_PAYLOAD) {
472*1c60b9acSAndroid Build Coastguard Worker 		/*
473*1c60b9acSAndroid Build Coastguard Worker 		 * We have to separate header / finalize and payload chunks,
474*1c60b9acSAndroid Build Coastguard Worker 		 * since they need to be handled separately
475*1c60b9acSAndroid Build Coastguard Worker 		 */
476*1c60b9acSAndroid Build Coastguard Worker 		switch (wsi->hdr_state) {
477*1c60b9acSAndroid Build Coastguard Worker 		case LHCS_RESPONSE:
478*1c60b9acSAndroid Build Coastguard Worker 			lwsl_wsi_debug(wsi, "LHCS_RESPONSE: iss response %d",
479*1c60b9acSAndroid Build Coastguard Worker 					    wsi->http.cgi->response_code);
480*1c60b9acSAndroid Build Coastguard Worker 			if (lws_add_http_header_status(wsi,
481*1c60b9acSAndroid Build Coastguard Worker 						   (unsigned int)wsi->http.cgi->response_code,
482*1c60b9acSAndroid Build Coastguard Worker 						       &p, end))
483*1c60b9acSAndroid Build Coastguard Worker 				return 1;
484*1c60b9acSAndroid Build Coastguard Worker 			if (!wsi->http.cgi->explicitly_chunked &&
485*1c60b9acSAndroid Build Coastguard Worker 			    !wsi->http.cgi->content_length &&
486*1c60b9acSAndroid Build Coastguard Worker 				lws_add_http_header_by_token(wsi,
487*1c60b9acSAndroid Build Coastguard Worker 					WSI_TOKEN_HTTP_TRANSFER_ENCODING,
488*1c60b9acSAndroid Build Coastguard Worker 					(unsigned char *)"chunked", 7, &p, end))
489*1c60b9acSAndroid Build Coastguard Worker 				return 1;
490*1c60b9acSAndroid Build Coastguard Worker 			if (!(wsi->mux_substream))
491*1c60b9acSAndroid Build Coastguard Worker 				if (lws_add_http_header_by_token(wsi,
492*1c60b9acSAndroid Build Coastguard Worker 						WSI_TOKEN_CONNECTION,
493*1c60b9acSAndroid Build Coastguard Worker 						(unsigned char *)"close", 5,
494*1c60b9acSAndroid Build Coastguard Worker 						&p, end))
495*1c60b9acSAndroid Build Coastguard Worker 					return 1;
496*1c60b9acSAndroid Build Coastguard Worker 			n = lws_write(wsi, start, lws_ptr_diff_size_t(p, start),
497*1c60b9acSAndroid Build Coastguard Worker 				      LWS_WRITE_HTTP_HEADERS | LWS_WRITE_NO_FIN);
498*1c60b9acSAndroid Build Coastguard Worker 
499*1c60b9acSAndroid Build Coastguard Worker 			/*
500*1c60b9acSAndroid Build Coastguard Worker 			 * so we have a bunch of http/1 style ascii headers
501*1c60b9acSAndroid Build Coastguard Worker 			 * starting from wsi->http.cgi->headers_buf through
502*1c60b9acSAndroid Build Coastguard Worker 			 * wsi->http.cgi->headers_pos.  These are OK for http/1
503*1c60b9acSAndroid Build Coastguard Worker 			 * connections, but they're no good for http/2 conns.
504*1c60b9acSAndroid Build Coastguard Worker 			 *
505*1c60b9acSAndroid Build Coastguard Worker 			 * Let's redo them at headers_pos forward using the
506*1c60b9acSAndroid Build Coastguard Worker 			 * correct coding for http/1 or http/2
507*1c60b9acSAndroid Build Coastguard Worker 			 */
508*1c60b9acSAndroid Build Coastguard Worker 			if (!wsi->mux_substream)
509*1c60b9acSAndroid Build Coastguard Worker 				goto post_hpack_recode;
510*1c60b9acSAndroid Build Coastguard Worker 
511*1c60b9acSAndroid Build Coastguard Worker 			p = wsi->http.cgi->headers_start;
512*1c60b9acSAndroid Build Coastguard Worker 			wsi->http.cgi->headers_start =
513*1c60b9acSAndroid Build Coastguard Worker 					wsi->http.cgi->headers_pos;
514*1c60b9acSAndroid Build Coastguard Worker 			wsi->http.cgi->headers_dumped =
515*1c60b9acSAndroid Build Coastguard Worker 					wsi->http.cgi->headers_start;
516*1c60b9acSAndroid Build Coastguard Worker 			hrs = HR_NAME;
517*1c60b9acSAndroid Build Coastguard Worker 			name = buf;
518*1c60b9acSAndroid Build Coastguard Worker 
519*1c60b9acSAndroid Build Coastguard Worker 			while (p < wsi->http.cgi->headers_start) {
520*1c60b9acSAndroid Build Coastguard Worker 				switch (hrs) {
521*1c60b9acSAndroid Build Coastguard Worker 				case HR_NAME:
522*1c60b9acSAndroid Build Coastguard Worker 					/*
523*1c60b9acSAndroid Build Coastguard Worker 					 * in http/2 upper-case header names
524*1c60b9acSAndroid Build Coastguard Worker 					 * are illegal.  So convert to lower-
525*1c60b9acSAndroid Build Coastguard Worker 					 * case.
526*1c60b9acSAndroid Build Coastguard Worker 					 */
527*1c60b9acSAndroid Build Coastguard Worker 					if (name - buf > 64)
528*1c60b9acSAndroid Build Coastguard Worker 						return -1;
529*1c60b9acSAndroid Build Coastguard Worker 					if (*p != ':') {
530*1c60b9acSAndroid Build Coastguard Worker 						if (*p >= 'A' && *p <= 'Z')
531*1c60b9acSAndroid Build Coastguard Worker 							*name++ = (unsigned char)((*p++) +
532*1c60b9acSAndroid Build Coastguard Worker 								  ('a' - 'A'));
533*1c60b9acSAndroid Build Coastguard Worker 						else
534*1c60b9acSAndroid Build Coastguard Worker 							*name++ = *p++;
535*1c60b9acSAndroid Build Coastguard Worker 					} else {
536*1c60b9acSAndroid Build Coastguard Worker 						p++;
537*1c60b9acSAndroid Build Coastguard Worker 						*name++ = '\0';
538*1c60b9acSAndroid Build Coastguard Worker 						value = name;
539*1c60b9acSAndroid Build Coastguard Worker 						hrs = HR_WHITESPACE;
540*1c60b9acSAndroid Build Coastguard Worker 					}
541*1c60b9acSAndroid Build Coastguard Worker 					break;
542*1c60b9acSAndroid Build Coastguard Worker 				case HR_WHITESPACE:
543*1c60b9acSAndroid Build Coastguard Worker 					if (*p == ' ') {
544*1c60b9acSAndroid Build Coastguard Worker 						p++;
545*1c60b9acSAndroid Build Coastguard Worker 						break;
546*1c60b9acSAndroid Build Coastguard Worker 					}
547*1c60b9acSAndroid Build Coastguard Worker 					hrs = HR_ARG;
548*1c60b9acSAndroid Build Coastguard Worker 					/* fallthru */
549*1c60b9acSAndroid Build Coastguard Worker 				case HR_ARG:
550*1c60b9acSAndroid Build Coastguard Worker 					if (name > end - 64)
551*1c60b9acSAndroid Build Coastguard Worker 						return -1;
552*1c60b9acSAndroid Build Coastguard Worker 
553*1c60b9acSAndroid Build Coastguard Worker 					if (*p != '\x0a' && *p != '\x0d') {
554*1c60b9acSAndroid Build Coastguard Worker 						*name++ = *p++;
555*1c60b9acSAndroid Build Coastguard Worker 						break;
556*1c60b9acSAndroid Build Coastguard Worker 					}
557*1c60b9acSAndroid Build Coastguard Worker 					hrs = HR_CRLF;
558*1c60b9acSAndroid Build Coastguard Worker 					/* fallthru */
559*1c60b9acSAndroid Build Coastguard Worker 				case HR_CRLF:
560*1c60b9acSAndroid Build Coastguard Worker 					if ((*p != '\x0a' && *p != '\x0d') ||
561*1c60b9acSAndroid Build Coastguard Worker 					    p + 1 == wsi->http.cgi->headers_start) {
562*1c60b9acSAndroid Build Coastguard Worker 						*name = '\0';
563*1c60b9acSAndroid Build Coastguard Worker 						if ((strcmp((const char *)buf,
564*1c60b9acSAndroid Build Coastguard Worker 							    "transfer-encoding")
565*1c60b9acSAndroid Build Coastguard Worker 						)) {
566*1c60b9acSAndroid Build Coastguard Worker 							lwsl_debug("+ %s: %s\n",
567*1c60b9acSAndroid Build Coastguard Worker 								   buf, value);
568*1c60b9acSAndroid Build Coastguard Worker 							if (
569*1c60b9acSAndroid Build Coastguard Worker 					lws_add_http_header_by_name(wsi, buf,
570*1c60b9acSAndroid Build Coastguard Worker 					(unsigned char *)value, lws_ptr_diff(name, value),
571*1c60b9acSAndroid Build Coastguard Worker 					(unsigned char **)&wsi->http.cgi->headers_pos,
572*1c60b9acSAndroid Build Coastguard Worker 					(unsigned char *)wsi->http.cgi->headers_end))
573*1c60b9acSAndroid Build Coastguard Worker 								return 1;
574*1c60b9acSAndroid Build Coastguard Worker 							hrs = HR_NAME;
575*1c60b9acSAndroid Build Coastguard Worker 							name = buf;
576*1c60b9acSAndroid Build Coastguard Worker 							break;
577*1c60b9acSAndroid Build Coastguard Worker 						}
578*1c60b9acSAndroid Build Coastguard Worker 					}
579*1c60b9acSAndroid Build Coastguard Worker 					p++;
580*1c60b9acSAndroid Build Coastguard Worker 					break;
581*1c60b9acSAndroid Build Coastguard Worker 				}
582*1c60b9acSAndroid Build Coastguard Worker 			}
583*1c60b9acSAndroid Build Coastguard Worker post_hpack_recode:
584*1c60b9acSAndroid Build Coastguard Worker 			/* finalize cached headers before dumping them */
585*1c60b9acSAndroid Build Coastguard Worker 			if (lws_finalize_http_header(wsi,
586*1c60b9acSAndroid Build Coastguard Worker 			      (unsigned char **)&wsi->http.cgi->headers_pos,
587*1c60b9acSAndroid Build Coastguard Worker 			      (unsigned char *)wsi->http.cgi->headers_end)) {
588*1c60b9acSAndroid Build Coastguard Worker 
589*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("finalize failed\n");
590*1c60b9acSAndroid Build Coastguard Worker 				return -1;
591*1c60b9acSAndroid Build Coastguard Worker 			}
592*1c60b9acSAndroid Build Coastguard Worker 
593*1c60b9acSAndroid Build Coastguard Worker 			wsi->hdr_state = LHCS_DUMP_HEADERS;
594*1c60b9acSAndroid Build Coastguard Worker 			wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI_HEADERS;
595*1c60b9acSAndroid Build Coastguard Worker 			lws_callback_on_writable(wsi);
596*1c60b9acSAndroid Build Coastguard Worker 			/* back to the loop for writeability again */
597*1c60b9acSAndroid Build Coastguard Worker 			return 0;
598*1c60b9acSAndroid Build Coastguard Worker 
599*1c60b9acSAndroid Build Coastguard Worker 		case LHCS_DUMP_HEADERS:
600*1c60b9acSAndroid Build Coastguard Worker 
601*1c60b9acSAndroid Build Coastguard Worker 			n = (int)(wsi->http.cgi->headers_pos -
602*1c60b9acSAndroid Build Coastguard Worker 			    wsi->http.cgi->headers_dumped);
603*1c60b9acSAndroid Build Coastguard Worker 			if (n > 512)
604*1c60b9acSAndroid Build Coastguard Worker 				n = 512;
605*1c60b9acSAndroid Build Coastguard Worker 
606*1c60b9acSAndroid Build Coastguard Worker 			lwsl_wsi_debug(wsi, "LHCS_DUMP_HEADERS: %d", n);
607*1c60b9acSAndroid Build Coastguard Worker 
608*1c60b9acSAndroid Build Coastguard Worker 			cmd = LWS_WRITE_HTTP_HEADERS_CONTINUATION;
609*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->http.cgi->headers_dumped + n !=
610*1c60b9acSAndroid Build Coastguard Worker 						wsi->http.cgi->headers_pos) {
611*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("adding no fin flag\n");
612*1c60b9acSAndroid Build Coastguard Worker 				cmd |= LWS_WRITE_NO_FIN;
613*1c60b9acSAndroid Build Coastguard Worker 			}
614*1c60b9acSAndroid Build Coastguard Worker 
615*1c60b9acSAndroid Build Coastguard Worker 			m = lws_write(wsi,
616*1c60b9acSAndroid Build Coastguard Worker 				 (unsigned char *)wsi->http.cgi->headers_dumped,
617*1c60b9acSAndroid Build Coastguard Worker 				      (unsigned int)n, (enum lws_write_protocol)cmd);
618*1c60b9acSAndroid Build Coastguard Worker 			if (m < 0) {
619*1c60b9acSAndroid Build Coastguard Worker 				lwsl_wsi_debug(wsi, "write says %d", m);
620*1c60b9acSAndroid Build Coastguard Worker 				return -1;
621*1c60b9acSAndroid Build Coastguard Worker 			}
622*1c60b9acSAndroid Build Coastguard Worker 			wsi->http.cgi->headers_dumped += n;
623*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->http.cgi->headers_dumped ==
624*1c60b9acSAndroid Build Coastguard Worker 			    wsi->http.cgi->headers_pos) {
625*1c60b9acSAndroid Build Coastguard Worker 				wsi->hdr_state = LHCS_PAYLOAD;
626*1c60b9acSAndroid Build Coastguard Worker 				lws_free_set_NULL(wsi->http.cgi->headers_buf);
627*1c60b9acSAndroid Build Coastguard Worker 				lwsl_wsi_debug(wsi, "freed cgi headers");
628*1c60b9acSAndroid Build Coastguard Worker 
629*1c60b9acSAndroid Build Coastguard Worker 				if (wsi->http.cgi->post_in_expected) {
630*1c60b9acSAndroid Build Coastguard Worker 					lwsl_wsi_info(wsi, "post data still "
631*1c60b9acSAndroid Build Coastguard Worker 							   "expected, asking "
632*1c60b9acSAndroid Build Coastguard Worker 							   "for writeable");
633*1c60b9acSAndroid Build Coastguard Worker 					lws_callback_on_writable(wsi);
634*1c60b9acSAndroid Build Coastguard Worker 				}
635*1c60b9acSAndroid Build Coastguard Worker 
636*1c60b9acSAndroid Build Coastguard Worker 			} else {
637*1c60b9acSAndroid Build Coastguard Worker 				wsi->reason_bf |=
638*1c60b9acSAndroid Build Coastguard Worker 					LWS_CB_REASON_AUX_BF__CGI_HEADERS;
639*1c60b9acSAndroid Build Coastguard Worker 				lws_callback_on_writable(wsi);
640*1c60b9acSAndroid Build Coastguard Worker 			}
641*1c60b9acSAndroid Build Coastguard Worker 
642*1c60b9acSAndroid Build Coastguard Worker 			/*
643*1c60b9acSAndroid Build Coastguard Worker 			 * writeability becomes uncertain now we wrote
644*1c60b9acSAndroid Build Coastguard Worker 			 * something, we must return to the event loop
645*1c60b9acSAndroid Build Coastguard Worker 			 */
646*1c60b9acSAndroid Build Coastguard Worker 			return 0;
647*1c60b9acSAndroid Build Coastguard Worker 		}
648*1c60b9acSAndroid Build Coastguard Worker 
649*1c60b9acSAndroid Build Coastguard Worker 		if (!wsi->http.cgi->headers_buf) {
650*1c60b9acSAndroid Build Coastguard Worker 			/* if we don't already have a headers buf, cook one */
651*1c60b9acSAndroid Build Coastguard Worker 			n = 2048;
652*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->mux_substream)
653*1c60b9acSAndroid Build Coastguard Worker 				n = 4096;
654*1c60b9acSAndroid Build Coastguard Worker 			wsi->http.cgi->headers_buf = lws_malloc((unsigned int)n + LWS_PRE,
655*1c60b9acSAndroid Build Coastguard Worker 							   "cgi hdr buf");
656*1c60b9acSAndroid Build Coastguard Worker 			if (!wsi->http.cgi->headers_buf) {
657*1c60b9acSAndroid Build Coastguard Worker 				lwsl_wsi_err(wsi, "OOM");
658*1c60b9acSAndroid Build Coastguard Worker 				return -1;
659*1c60b9acSAndroid Build Coastguard Worker 			}
660*1c60b9acSAndroid Build Coastguard Worker 
661*1c60b9acSAndroid Build Coastguard Worker 			lwsl_wsi_debug(wsi, "allocated cgi hdrs");
662*1c60b9acSAndroid Build Coastguard Worker 			wsi->http.cgi->headers_start =
663*1c60b9acSAndroid Build Coastguard Worker 					wsi->http.cgi->headers_buf + LWS_PRE;
664*1c60b9acSAndroid Build Coastguard Worker 			wsi->http.cgi->headers_pos = wsi->http.cgi->headers_start;
665*1c60b9acSAndroid Build Coastguard Worker 			wsi->http.cgi->headers_dumped = wsi->http.cgi->headers_pos;
666*1c60b9acSAndroid Build Coastguard Worker 			wsi->http.cgi->headers_end =
667*1c60b9acSAndroid Build Coastguard Worker 					wsi->http.cgi->headers_buf + n - 1;
668*1c60b9acSAndroid Build Coastguard Worker 
669*1c60b9acSAndroid Build Coastguard Worker 			for (n = 0; n < SIGNIFICANT_HDR_COUNT; n++) {
670*1c60b9acSAndroid Build Coastguard Worker 				wsi->http.cgi->match[n] = 0;
671*1c60b9acSAndroid Build Coastguard Worker 				wsi->http.cgi->lp = 0;
672*1c60b9acSAndroid Build Coastguard Worker 			}
673*1c60b9acSAndroid Build Coastguard Worker 		}
674*1c60b9acSAndroid Build Coastguard Worker 
675*1c60b9acSAndroid Build Coastguard Worker 		n = lws_get_socket_fd(wsi->http.cgi->lsp->stdwsi[LWS_STDOUT]);
676*1c60b9acSAndroid Build Coastguard Worker 		if (n < 0)
677*1c60b9acSAndroid Build Coastguard Worker 			return -1;
678*1c60b9acSAndroid Build Coastguard Worker 		n = (int)read(n, &c, 1);
679*1c60b9acSAndroid Build Coastguard Worker 		if (n < 0) {
680*1c60b9acSAndroid Build Coastguard Worker 			if (errno != EAGAIN) {
681*1c60b9acSAndroid Build Coastguard Worker 				lwsl_wsi_debug(wsi, "read says %d", n);
682*1c60b9acSAndroid Build Coastguard Worker 				return -1;
683*1c60b9acSAndroid Build Coastguard Worker 			}
684*1c60b9acSAndroid Build Coastguard Worker 			else
685*1c60b9acSAndroid Build Coastguard Worker 				n = 0;
686*1c60b9acSAndroid Build Coastguard Worker 
687*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->http.cgi->headers_pos >=
688*1c60b9acSAndroid Build Coastguard Worker 					wsi->http.cgi->headers_end - 4) {
689*1c60b9acSAndroid Build Coastguard Worker 				lwsl_wsi_notice(wsi, "CGI hdrs > buf size");
690*1c60b9acSAndroid Build Coastguard Worker 
691*1c60b9acSAndroid Build Coastguard Worker 				return -1;
692*1c60b9acSAndroid Build Coastguard Worker 			}
693*1c60b9acSAndroid Build Coastguard Worker 		}
694*1c60b9acSAndroid Build Coastguard Worker 		if (!n)
695*1c60b9acSAndroid Build Coastguard Worker 			goto agin;
696*1c60b9acSAndroid Build Coastguard Worker 
697*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_debug(wsi, "-- 0x%02X %c %d %d", (unsigned char)c, c,
698*1c60b9acSAndroid Build Coastguard Worker 				    wsi->http.cgi->match[1], wsi->hdr_state);
699*1c60b9acSAndroid Build Coastguard Worker 		if (!c)
700*1c60b9acSAndroid Build Coastguard Worker 			return -1;
701*1c60b9acSAndroid Build Coastguard Worker 		switch (wsi->hdr_state) {
702*1c60b9acSAndroid Build Coastguard Worker 		case LCHS_HEADER:
703*1c60b9acSAndroid Build Coastguard Worker 			hdr:
704*1c60b9acSAndroid Build Coastguard Worker 			for (n = 0; n < SIGNIFICANT_HDR_COUNT; n++) {
705*1c60b9acSAndroid Build Coastguard Worker 				/*
706*1c60b9acSAndroid Build Coastguard Worker 				 * significant headers with
707*1c60b9acSAndroid Build Coastguard Worker 				 * numeric decimal payloads
708*1c60b9acSAndroid Build Coastguard Worker 				 */
709*1c60b9acSAndroid Build Coastguard Worker 				if (!significant_hdr[n][wsi->http.cgi->match[n]] &&
710*1c60b9acSAndroid Build Coastguard Worker 				    (c >= '0' && c <= '9') &&
711*1c60b9acSAndroid Build Coastguard Worker 				    wsi->http.cgi->lp < (int)sizeof(wsi->http.cgi->l) - 1) {
712*1c60b9acSAndroid Build Coastguard Worker 					wsi->http.cgi->l[wsi->http.cgi->lp++] = c;
713*1c60b9acSAndroid Build Coastguard Worker 					wsi->http.cgi->l[wsi->http.cgi->lp] = '\0';
714*1c60b9acSAndroid Build Coastguard Worker 					switch (n) {
715*1c60b9acSAndroid Build Coastguard Worker 					case SIGNIFICANT_HDR_CONTENT_LENGTH:
716*1c60b9acSAndroid Build Coastguard Worker 						wsi->http.cgi->content_length =
717*1c60b9acSAndroid Build Coastguard Worker 							(lws_filepos_t)atoll(wsi->http.cgi->l);
718*1c60b9acSAndroid Build Coastguard Worker 						break;
719*1c60b9acSAndroid Build Coastguard Worker 					case SIGNIFICANT_HDR_STATUS:
720*1c60b9acSAndroid Build Coastguard Worker 						wsi->http.cgi->response_code =
721*1c60b9acSAndroid Build Coastguard Worker 							atoi(wsi->http.cgi->l);
722*1c60b9acSAndroid Build Coastguard Worker 						lwsl_wsi_debug(wsi, "Status set to %d",
723*1c60b9acSAndroid Build Coastguard Worker 								wsi->http.cgi->response_code);
724*1c60b9acSAndroid Build Coastguard Worker 						break;
725*1c60b9acSAndroid Build Coastguard Worker 					default:
726*1c60b9acSAndroid Build Coastguard Worker 						break;
727*1c60b9acSAndroid Build Coastguard Worker 					}
728*1c60b9acSAndroid Build Coastguard Worker 				}
729*1c60b9acSAndroid Build Coastguard Worker 				/* hits up to the NUL are sticky until next hdr */
730*1c60b9acSAndroid Build Coastguard Worker 				if (significant_hdr[n][wsi->http.cgi->match[n]]) {
731*1c60b9acSAndroid Build Coastguard Worker 					if (tolower(c) ==
732*1c60b9acSAndroid Build Coastguard Worker 					    significant_hdr[n][wsi->http.cgi->match[n]])
733*1c60b9acSAndroid Build Coastguard Worker 						wsi->http.cgi->match[n]++;
734*1c60b9acSAndroid Build Coastguard Worker 					else
735*1c60b9acSAndroid Build Coastguard Worker 						wsi->http.cgi->match[n] = 0;
736*1c60b9acSAndroid Build Coastguard Worker 				}
737*1c60b9acSAndroid Build Coastguard Worker 			}
738*1c60b9acSAndroid Build Coastguard Worker 
739*1c60b9acSAndroid Build Coastguard Worker 			/* some cgi only send us \x0a for EOL */
740*1c60b9acSAndroid Build Coastguard Worker 			if (c == '\x0a') {
741*1c60b9acSAndroid Build Coastguard Worker 				wsi->hdr_state = LCHS_SINGLE_0A;
742*1c60b9acSAndroid Build Coastguard Worker 				*wsi->http.cgi->headers_pos++ = '\x0d';
743*1c60b9acSAndroid Build Coastguard Worker 			}
744*1c60b9acSAndroid Build Coastguard Worker 			*wsi->http.cgi->headers_pos++ = (unsigned char)c;
745*1c60b9acSAndroid Build Coastguard Worker 			if (c == '\x0d')
746*1c60b9acSAndroid Build Coastguard Worker 				wsi->hdr_state = LCHS_LF1;
747*1c60b9acSAndroid Build Coastguard Worker 
748*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->hdr_state != LCHS_HEADER &&
749*1c60b9acSAndroid Build Coastguard Worker 			    !significant_hdr[SIGNIFICANT_HDR_TRANSFER_ENCODING]
750*1c60b9acSAndroid Build Coastguard Worker 				    [wsi->http.cgi->match[
751*1c60b9acSAndroid Build Coastguard Worker 					 SIGNIFICANT_HDR_TRANSFER_ENCODING]]) {
752*1c60b9acSAndroid Build Coastguard Worker 				lwsl_wsi_info(wsi, "cgi produced chunked");
753*1c60b9acSAndroid Build Coastguard Worker 				wsi->http.cgi->explicitly_chunked = 1;
754*1c60b9acSAndroid Build Coastguard Worker 			}
755*1c60b9acSAndroid Build Coastguard Worker 
756*1c60b9acSAndroid Build Coastguard Worker 			/* presence of Location: mandates 302 retcode */
757*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->hdr_state != LCHS_HEADER &&
758*1c60b9acSAndroid Build Coastguard Worker 			    !significant_hdr[SIGNIFICANT_HDR_LOCATION][
759*1c60b9acSAndroid Build Coastguard Worker 			      wsi->http.cgi->match[SIGNIFICANT_HDR_LOCATION]]) {
760*1c60b9acSAndroid Build Coastguard Worker 				lwsl_wsi_debug(wsi, "CGI: Location hdr seen");
761*1c60b9acSAndroid Build Coastguard Worker 				wsi->http.cgi->response_code = 302;
762*1c60b9acSAndroid Build Coastguard Worker 			}
763*1c60b9acSAndroid Build Coastguard Worker 			break;
764*1c60b9acSAndroid Build Coastguard Worker 		case LCHS_LF1:
765*1c60b9acSAndroid Build Coastguard Worker 			*wsi->http.cgi->headers_pos++ = (unsigned char)c;
766*1c60b9acSAndroid Build Coastguard Worker 			if (c == '\x0a') {
767*1c60b9acSAndroid Build Coastguard Worker 				wsi->hdr_state = LCHS_CR2;
768*1c60b9acSAndroid Build Coastguard Worker 				break;
769*1c60b9acSAndroid Build Coastguard Worker 			}
770*1c60b9acSAndroid Build Coastguard Worker 			/* we got \r[^\n]... it's unreasonable */
771*1c60b9acSAndroid Build Coastguard Worker 			lwsl_wsi_debug(wsi, "funny CRLF 0x%02X",
772*1c60b9acSAndroid Build Coastguard Worker 					    (unsigned char)c);
773*1c60b9acSAndroid Build Coastguard Worker 			return -1;
774*1c60b9acSAndroid Build Coastguard Worker 
775*1c60b9acSAndroid Build Coastguard Worker 		case LCHS_CR2:
776*1c60b9acSAndroid Build Coastguard Worker 			if (c == '\x0d') {
777*1c60b9acSAndroid Build Coastguard Worker 				/* drop the \x0d */
778*1c60b9acSAndroid Build Coastguard Worker 				wsi->hdr_state = LCHS_LF2;
779*1c60b9acSAndroid Build Coastguard Worker 				break;
780*1c60b9acSAndroid Build Coastguard Worker 			}
781*1c60b9acSAndroid Build Coastguard Worker 			wsi->hdr_state = LCHS_HEADER;
782*1c60b9acSAndroid Build Coastguard Worker 			for (n = 0; n < SIGNIFICANT_HDR_COUNT; n++)
783*1c60b9acSAndroid Build Coastguard Worker 				wsi->http.cgi->match[n] = 0;
784*1c60b9acSAndroid Build Coastguard Worker 			wsi->http.cgi->lp = 0;
785*1c60b9acSAndroid Build Coastguard Worker 			goto hdr;
786*1c60b9acSAndroid Build Coastguard Worker 
787*1c60b9acSAndroid Build Coastguard Worker 		case LCHS_LF2:
788*1c60b9acSAndroid Build Coastguard Worker 		case LCHS_SINGLE_0A:
789*1c60b9acSAndroid Build Coastguard Worker 			m = wsi->hdr_state;
790*1c60b9acSAndroid Build Coastguard Worker 			if (c == '\x0a') {
791*1c60b9acSAndroid Build Coastguard Worker 				lwsl_wsi_debug(wsi, "Content-Length: %lld",
792*1c60b9acSAndroid Build Coastguard Worker 					(unsigned long long)
793*1c60b9acSAndroid Build Coastguard Worker 					wsi->http.cgi->content_length);
794*1c60b9acSAndroid Build Coastguard Worker 				wsi->hdr_state = LHCS_RESPONSE;
795*1c60b9acSAndroid Build Coastguard Worker 				/*
796*1c60b9acSAndroid Build Coastguard Worker 				 * drop the \0xa ... finalize
797*1c60b9acSAndroid Build Coastguard Worker 				 * will add it if needed (HTTP/1)
798*1c60b9acSAndroid Build Coastguard Worker 				 */
799*1c60b9acSAndroid Build Coastguard Worker 				break;
800*1c60b9acSAndroid Build Coastguard Worker 			}
801*1c60b9acSAndroid Build Coastguard Worker 			if (m == LCHS_LF2)
802*1c60b9acSAndroid Build Coastguard Worker 				/* we got \r\n\r[^\n]... unreasonable */
803*1c60b9acSAndroid Build Coastguard Worker 				return -1;
804*1c60b9acSAndroid Build Coastguard Worker 			/* we got \x0anext header, it's reasonable */
805*1c60b9acSAndroid Build Coastguard Worker 			*wsi->http.cgi->headers_pos++ = (unsigned char)c;
806*1c60b9acSAndroid Build Coastguard Worker 			wsi->hdr_state = LCHS_HEADER;
807*1c60b9acSAndroid Build Coastguard Worker 			for (n = 0; n < SIGNIFICANT_HDR_COUNT; n++)
808*1c60b9acSAndroid Build Coastguard Worker 				wsi->http.cgi->match[n] = 0;
809*1c60b9acSAndroid Build Coastguard Worker 			wsi->http.cgi->lp = 0;
810*1c60b9acSAndroid Build Coastguard Worker 			break;
811*1c60b9acSAndroid Build Coastguard Worker 		case LHCS_PAYLOAD:
812*1c60b9acSAndroid Build Coastguard Worker 			break;
813*1c60b9acSAndroid Build Coastguard Worker 		}
814*1c60b9acSAndroid Build Coastguard Worker 
815*1c60b9acSAndroid Build Coastguard Worker agin:
816*1c60b9acSAndroid Build Coastguard Worker 		/* ran out of input, ended the hdrs, or filled up the hdrs buf */
817*1c60b9acSAndroid Build Coastguard Worker 		if (!n || wsi->hdr_state == LHCS_PAYLOAD)
818*1c60b9acSAndroid Build Coastguard Worker 			return 0;
819*1c60b9acSAndroid Build Coastguard Worker 	}
820*1c60b9acSAndroid Build Coastguard Worker 
821*1c60b9acSAndroid Build Coastguard Worker 	/* payload processing */
822*1c60b9acSAndroid Build Coastguard Worker 
823*1c60b9acSAndroid Build Coastguard Worker 	m = !wsi->http.cgi->implied_chunked && !wsi->mux_substream &&
824*1c60b9acSAndroid Build Coastguard Worker 	//    !wsi->http.cgi->explicitly_chunked &&
825*1c60b9acSAndroid Build Coastguard Worker 	    !wsi->http.cgi->content_length;
826*1c60b9acSAndroid Build Coastguard Worker 	n = lws_get_socket_fd(wsi->http.cgi->lsp->stdwsi[LWS_STDOUT]);
827*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0)
828*1c60b9acSAndroid Build Coastguard Worker 		return -1;
829*1c60b9acSAndroid Build Coastguard Worker 	n = (int)read(n, start, sizeof(buf) - LWS_PRE);
830*1c60b9acSAndroid Build Coastguard Worker 
831*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0 && errno != EAGAIN) {
832*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_debug(wsi, "stdout read says %d", n);
833*1c60b9acSAndroid Build Coastguard Worker 		return -1;
834*1c60b9acSAndroid Build Coastguard Worker 	}
835*1c60b9acSAndroid Build Coastguard Worker 	if (n > 0) {
836*1c60b9acSAndroid Build Coastguard Worker 		// lwsl_hexdump_notice(buf, n);
837*1c60b9acSAndroid Build Coastguard Worker 
838*1c60b9acSAndroid Build Coastguard Worker 		if (!wsi->mux_substream && m) {
839*1c60b9acSAndroid Build Coastguard Worker 			char chdr[LWS_HTTP_CHUNK_HDR_SIZE];
840*1c60b9acSAndroid Build Coastguard Worker 			m = lws_snprintf(chdr, LWS_HTTP_CHUNK_HDR_SIZE - 3,
841*1c60b9acSAndroid Build Coastguard Worker 					 "%X\x0d\x0a", n);
842*1c60b9acSAndroid Build Coastguard Worker 			memmove(start + m, start, (unsigned int)n);
843*1c60b9acSAndroid Build Coastguard Worker 			memcpy(start, chdr, (unsigned int)m);
844*1c60b9acSAndroid Build Coastguard Worker 			memcpy(start + m + n, "\x0d\x0a", 2);
845*1c60b9acSAndroid Build Coastguard Worker 			n += m + 2;
846*1c60b9acSAndroid Build Coastguard Worker 		}
847*1c60b9acSAndroid Build Coastguard Worker 
848*1c60b9acSAndroid Build Coastguard Worker 
849*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP2)
850*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->mux_substream) {
851*1c60b9acSAndroid Build Coastguard Worker 			struct lws *nwsi = lws_get_network_wsi(wsi);
852*1c60b9acSAndroid Build Coastguard Worker 
853*1c60b9acSAndroid Build Coastguard Worker 			__lws_set_timeout(wsi,
854*1c60b9acSAndroid Build Coastguard Worker 				PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE, 31);
855*1c60b9acSAndroid Build Coastguard Worker 
856*1c60b9acSAndroid Build Coastguard Worker 			if (!nwsi->immortal_substream_count)
857*1c60b9acSAndroid Build Coastguard Worker 				__lws_set_timeout(nwsi,
858*1c60b9acSAndroid Build Coastguard Worker 					PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE, 31);
859*1c60b9acSAndroid Build Coastguard Worker 		}
860*1c60b9acSAndroid Build Coastguard Worker #endif
861*1c60b9acSAndroid Build Coastguard Worker 
862*1c60b9acSAndroid Build Coastguard Worker 		cmd = LWS_WRITE_HTTP;
863*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->http.cgi->content_length_seen + (unsigned int)n ==
864*1c60b9acSAndroid Build Coastguard Worker 						wsi->http.cgi->content_length)
865*1c60b9acSAndroid Build Coastguard Worker 			cmd = LWS_WRITE_HTTP_FINAL;
866*1c60b9acSAndroid Build Coastguard Worker 
867*1c60b9acSAndroid Build Coastguard Worker 		m = lws_write(wsi, (unsigned char *)start, (unsigned int)n, (enum lws_write_protocol)cmd);
868*1c60b9acSAndroid Build Coastguard Worker 		//lwsl_notice("write %d\n", m);
869*1c60b9acSAndroid Build Coastguard Worker 		if (m < 0) {
870*1c60b9acSAndroid Build Coastguard Worker 			lwsl_wsi_debug(wsi, "stdout write says %d\n", m);
871*1c60b9acSAndroid Build Coastguard Worker 			return -1;
872*1c60b9acSAndroid Build Coastguard Worker 		}
873*1c60b9acSAndroid Build Coastguard Worker 		wsi->http.cgi->content_length_seen += (unsigned int)n;
874*1c60b9acSAndroid Build Coastguard Worker 	} else {
875*1c60b9acSAndroid Build Coastguard Worker 
876*1c60b9acSAndroid Build Coastguard Worker 		if (!wsi->mux_substream && m) {
877*1c60b9acSAndroid Build Coastguard Worker 			uint8_t term[LWS_PRE + 6];
878*1c60b9acSAndroid Build Coastguard Worker 
879*1c60b9acSAndroid Build Coastguard Worker 			lwsl_wsi_info(wsi, "sent trailer");
880*1c60b9acSAndroid Build Coastguard Worker 			memcpy(term + LWS_PRE, (uint8_t *)"0\x0d\x0a\x0d\x0a", 5);
881*1c60b9acSAndroid Build Coastguard Worker 
882*1c60b9acSAndroid Build Coastguard Worker 			if (lws_write(wsi, term + LWS_PRE, 5,
883*1c60b9acSAndroid Build Coastguard Worker 				      LWS_WRITE_HTTP_FINAL) != 5)
884*1c60b9acSAndroid Build Coastguard Worker 				return -1;
885*1c60b9acSAndroid Build Coastguard Worker 
886*1c60b9acSAndroid Build Coastguard Worker 			wsi->http.cgi->cgi_transaction_over = 1;
887*1c60b9acSAndroid Build Coastguard Worker 
888*1c60b9acSAndroid Build Coastguard Worker 			return 0;
889*1c60b9acSAndroid Build Coastguard Worker 		}
890*1c60b9acSAndroid Build Coastguard Worker 
891*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->cgi_stdout_zero_length) {
892*1c60b9acSAndroid Build Coastguard Worker 			lwsl_wsi_debug(wsi, "stdout is POLLHUP'd");
893*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->mux_substream)
894*1c60b9acSAndroid Build Coastguard Worker 				m = lws_write(wsi, (unsigned char *)start, 0,
895*1c60b9acSAndroid Build Coastguard Worker 					      LWS_WRITE_HTTP_FINAL);
896*1c60b9acSAndroid Build Coastguard Worker 			else
897*1c60b9acSAndroid Build Coastguard Worker 				return -1;
898*1c60b9acSAndroid Build Coastguard Worker 			return 1;
899*1c60b9acSAndroid Build Coastguard Worker 		}
900*1c60b9acSAndroid Build Coastguard Worker 		wsi->cgi_stdout_zero_length = 1;
901*1c60b9acSAndroid Build Coastguard Worker 	}
902*1c60b9acSAndroid Build Coastguard Worker 	return 0;
903*1c60b9acSAndroid Build Coastguard Worker }
904*1c60b9acSAndroid Build Coastguard Worker 
905*1c60b9acSAndroid Build Coastguard Worker int
lws_cgi_kill(struct lws * wsi)906*1c60b9acSAndroid Build Coastguard Worker lws_cgi_kill(struct lws *wsi)
907*1c60b9acSAndroid Build Coastguard Worker {
908*1c60b9acSAndroid Build Coastguard Worker 	struct lws_cgi_args args;
909*1c60b9acSAndroid Build Coastguard Worker 	pid_t pid;
910*1c60b9acSAndroid Build Coastguard Worker 	int n, m;
911*1c60b9acSAndroid Build Coastguard Worker 
912*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->http.cgi || !wsi->http.cgi->lsp)
913*1c60b9acSAndroid Build Coastguard Worker 		return 0;
914*1c60b9acSAndroid Build Coastguard Worker 
915*1c60b9acSAndroid Build Coastguard Worker 	pid = wsi->http.cgi->lsp->child_pid;
916*1c60b9acSAndroid Build Coastguard Worker 
917*1c60b9acSAndroid Build Coastguard Worker 	args.stdwsi = &wsi->http.cgi->lsp->stdwsi[0];
918*1c60b9acSAndroid Build Coastguard Worker 	lws_spawn_piped_kill_child_process(wsi->http.cgi->lsp);
919*1c60b9acSAndroid Build Coastguard Worker 	/* that has invalidated and NULL'd wsi->http.cgi->lsp */
920*1c60b9acSAndroid Build Coastguard Worker 
921*1c60b9acSAndroid Build Coastguard Worker 	if (pid != -1) {
922*1c60b9acSAndroid Build Coastguard Worker 		m = wsi->http.cgi->being_closed;
923*1c60b9acSAndroid Build Coastguard Worker 		n = user_callback_handle_rxflow(wsi->a.protocol->callback, wsi,
924*1c60b9acSAndroid Build Coastguard Worker 						LWS_CALLBACK_CGI_TERMINATED,
925*1c60b9acSAndroid Build Coastguard Worker 						wsi->user_space, (void *)&args,
926*1c60b9acSAndroid Build Coastguard Worker 						(unsigned int)pid);
927*1c60b9acSAndroid Build Coastguard Worker 		if (n && !m)
928*1c60b9acSAndroid Build Coastguard Worker 			lws_close_free_wsi(wsi, 0, "lws_cgi_kill");
929*1c60b9acSAndroid Build Coastguard Worker 	}
930*1c60b9acSAndroid Build Coastguard Worker 
931*1c60b9acSAndroid Build Coastguard Worker 	return 0;
932*1c60b9acSAndroid Build Coastguard Worker }
933*1c60b9acSAndroid Build Coastguard Worker 
934*1c60b9acSAndroid Build Coastguard Worker int
lws_cgi_kill_terminated(struct lws_context_per_thread * pt)935*1c60b9acSAndroid Build Coastguard Worker lws_cgi_kill_terminated(struct lws_context_per_thread *pt)
936*1c60b9acSAndroid Build Coastguard Worker {
937*1c60b9acSAndroid Build Coastguard Worker 	struct lws_cgi **pcgi, *cgi = NULL;
938*1c60b9acSAndroid Build Coastguard Worker 	int status, n = 1;
939*1c60b9acSAndroid Build Coastguard Worker 
940*1c60b9acSAndroid Build Coastguard Worker 	while (n > 0) {
941*1c60b9acSAndroid Build Coastguard Worker 		/* find finished guys but don't reap yet */
942*1c60b9acSAndroid Build Coastguard Worker 		n = waitpid(-1, &status, WNOHANG);
943*1c60b9acSAndroid Build Coastguard Worker 		if (n <= 0)
944*1c60b9acSAndroid Build Coastguard Worker 			continue;
945*1c60b9acSAndroid Build Coastguard Worker 		lwsl_cx_debug(pt->context, "observed PID %d terminated", n);
946*1c60b9acSAndroid Build Coastguard Worker 
947*1c60b9acSAndroid Build Coastguard Worker 		pcgi = &pt->http.cgi_list;
948*1c60b9acSAndroid Build Coastguard Worker 
949*1c60b9acSAndroid Build Coastguard Worker 		/* check all the subprocesses on the cgi list */
950*1c60b9acSAndroid Build Coastguard Worker 		while (*pcgi) {
951*1c60b9acSAndroid Build Coastguard Worker 			/* get the next one first as list may change */
952*1c60b9acSAndroid Build Coastguard Worker 			cgi = *pcgi;
953*1c60b9acSAndroid Build Coastguard Worker 			pcgi = &(*pcgi)->cgi_list;
954*1c60b9acSAndroid Build Coastguard Worker 
955*1c60b9acSAndroid Build Coastguard Worker 			if (cgi->lsp->child_pid <= 0)
956*1c60b9acSAndroid Build Coastguard Worker 				continue;
957*1c60b9acSAndroid Build Coastguard Worker 
958*1c60b9acSAndroid Build Coastguard Worker 			/* finish sending cached headers */
959*1c60b9acSAndroid Build Coastguard Worker 			if (cgi->headers_buf)
960*1c60b9acSAndroid Build Coastguard Worker 				continue;
961*1c60b9acSAndroid Build Coastguard Worker 
962*1c60b9acSAndroid Build Coastguard Worker 			/* wait for stdout to be drained */
963*1c60b9acSAndroid Build Coastguard Worker 			if (cgi->content_length > cgi->content_length_seen)
964*1c60b9acSAndroid Build Coastguard Worker 				continue;
965*1c60b9acSAndroid Build Coastguard Worker 
966*1c60b9acSAndroid Build Coastguard Worker 			if (cgi->content_length) {
967*1c60b9acSAndroid Build Coastguard Worker 				lwsl_cx_debug(pt->context, "expected content "
968*1c60b9acSAndroid Build Coastguard Worker 							   "length seen: %lld",
969*1c60b9acSAndroid Build Coastguard Worker 				(unsigned long long)cgi->content_length_seen);
970*1c60b9acSAndroid Build Coastguard Worker 			}
971*1c60b9acSAndroid Build Coastguard Worker 
972*1c60b9acSAndroid Build Coastguard Worker 			/* reap it */
973*1c60b9acSAndroid Build Coastguard Worker 			waitpid(n, &status, WNOHANG);
974*1c60b9acSAndroid Build Coastguard Worker 			/*
975*1c60b9acSAndroid Build Coastguard Worker 			 * he's already terminated so no need for kill()
976*1c60b9acSAndroid Build Coastguard Worker 			 * but we should do the terminated cgi callback
977*1c60b9acSAndroid Build Coastguard Worker 			 * and close him if he's not already closing
978*1c60b9acSAndroid Build Coastguard Worker 			 */
979*1c60b9acSAndroid Build Coastguard Worker 			if (n == cgi->lsp->child_pid) {
980*1c60b9acSAndroid Build Coastguard Worker 
981*1c60b9acSAndroid Build Coastguard Worker 				if (!cgi->content_length) {
982*1c60b9acSAndroid Build Coastguard Worker 					/*
983*1c60b9acSAndroid Build Coastguard Worker 					 * well, if he sends chunked...
984*1c60b9acSAndroid Build Coastguard Worker 					 * give him 2s after the
985*1c60b9acSAndroid Build Coastguard Worker 					 * cgi terminated to send buffered
986*1c60b9acSAndroid Build Coastguard Worker 					 */
987*1c60b9acSAndroid Build Coastguard Worker 					cgi->chunked_grace++;
988*1c60b9acSAndroid Build Coastguard Worker 					continue;
989*1c60b9acSAndroid Build Coastguard Worker 				}
990*1c60b9acSAndroid Build Coastguard Worker 
991*1c60b9acSAndroid Build Coastguard Worker 				/* defeat kill() */
992*1c60b9acSAndroid Build Coastguard Worker 				cgi->lsp->child_pid = 0;
993*1c60b9acSAndroid Build Coastguard Worker 				lws_cgi_kill(cgi->wsi);
994*1c60b9acSAndroid Build Coastguard Worker 
995*1c60b9acSAndroid Build Coastguard Worker 				break;
996*1c60b9acSAndroid Build Coastguard Worker 			}
997*1c60b9acSAndroid Build Coastguard Worker 			cgi = NULL;
998*1c60b9acSAndroid Build Coastguard Worker 		}
999*1c60b9acSAndroid Build Coastguard Worker 		/* if not found on the cgi list, as he's one of ours, reap */
1000*1c60b9acSAndroid Build Coastguard Worker 		if (!cgi)
1001*1c60b9acSAndroid Build Coastguard Worker 			waitpid(n, &status, WNOHANG);
1002*1c60b9acSAndroid Build Coastguard Worker 
1003*1c60b9acSAndroid Build Coastguard Worker 	}
1004*1c60b9acSAndroid Build Coastguard Worker 
1005*1c60b9acSAndroid Build Coastguard Worker 	pcgi = &pt->http.cgi_list;
1006*1c60b9acSAndroid Build Coastguard Worker 
1007*1c60b9acSAndroid Build Coastguard Worker 	/* check all the subprocesses on the cgi list */
1008*1c60b9acSAndroid Build Coastguard Worker 	while (*pcgi) {
1009*1c60b9acSAndroid Build Coastguard Worker 		/* get the next one first as list may change */
1010*1c60b9acSAndroid Build Coastguard Worker 		cgi = *pcgi;
1011*1c60b9acSAndroid Build Coastguard Worker 		pcgi = &(*pcgi)->cgi_list;
1012*1c60b9acSAndroid Build Coastguard Worker 
1013*1c60b9acSAndroid Build Coastguard Worker 		if (!cgi || !cgi->lsp || cgi->lsp->child_pid <= 0)
1014*1c60b9acSAndroid Build Coastguard Worker 			continue;
1015*1c60b9acSAndroid Build Coastguard Worker 
1016*1c60b9acSAndroid Build Coastguard Worker 		/* we deferred killing him after reaping his PID */
1017*1c60b9acSAndroid Build Coastguard Worker 		if (cgi->chunked_grace) {
1018*1c60b9acSAndroid Build Coastguard Worker 			cgi->chunked_grace++;
1019*1c60b9acSAndroid Build Coastguard Worker 			if (cgi->chunked_grace < 2)
1020*1c60b9acSAndroid Build Coastguard Worker 				continue;
1021*1c60b9acSAndroid Build Coastguard Worker 			goto finish_him;
1022*1c60b9acSAndroid Build Coastguard Worker 		}
1023*1c60b9acSAndroid Build Coastguard Worker 
1024*1c60b9acSAndroid Build Coastguard Worker 		/* finish sending cached headers */
1025*1c60b9acSAndroid Build Coastguard Worker 		if (cgi->headers_buf)
1026*1c60b9acSAndroid Build Coastguard Worker 			continue;
1027*1c60b9acSAndroid Build Coastguard Worker 
1028*1c60b9acSAndroid Build Coastguard Worker 		/* wait for stdout to be drained */
1029*1c60b9acSAndroid Build Coastguard Worker 		if (cgi->content_length > cgi->content_length_seen)
1030*1c60b9acSAndroid Build Coastguard Worker 			continue;
1031*1c60b9acSAndroid Build Coastguard Worker 
1032*1c60b9acSAndroid Build Coastguard Worker 		if (cgi->content_length)
1033*1c60b9acSAndroid Build Coastguard Worker 			lwsl_wsi_debug(cgi->wsi, "expected cont len seen: %lld",
1034*1c60b9acSAndroid Build Coastguard Worker 				  (unsigned long long)cgi->content_length_seen);
1035*1c60b9acSAndroid Build Coastguard Worker 
1036*1c60b9acSAndroid Build Coastguard Worker 		/* reap it */
1037*1c60b9acSAndroid Build Coastguard Worker 		if (waitpid(cgi->lsp->child_pid, &status, WNOHANG) > 0) {
1038*1c60b9acSAndroid Build Coastguard Worker 
1039*1c60b9acSAndroid Build Coastguard Worker 			if (!cgi->content_length) {
1040*1c60b9acSAndroid Build Coastguard Worker 				/*
1041*1c60b9acSAndroid Build Coastguard Worker 				 * well, if he sends chunked...
1042*1c60b9acSAndroid Build Coastguard Worker 				 * give him 2s after the
1043*1c60b9acSAndroid Build Coastguard Worker 				 * cgi terminated to send buffered
1044*1c60b9acSAndroid Build Coastguard Worker 				 */
1045*1c60b9acSAndroid Build Coastguard Worker 				cgi->chunked_grace++;
1046*1c60b9acSAndroid Build Coastguard Worker 				continue;
1047*1c60b9acSAndroid Build Coastguard Worker 			}
1048*1c60b9acSAndroid Build Coastguard Worker finish_him:
1049*1c60b9acSAndroid Build Coastguard Worker 			lwsl_cx_debug(pt->context, "found PID %d on cgi list",
1050*1c60b9acSAndroid Build Coastguard Worker 						   cgi->lsp->child_pid);
1051*1c60b9acSAndroid Build Coastguard Worker 
1052*1c60b9acSAndroid Build Coastguard Worker 			/* defeat kill() */
1053*1c60b9acSAndroid Build Coastguard Worker 			cgi->lsp->child_pid = 0;
1054*1c60b9acSAndroid Build Coastguard Worker 			lws_cgi_kill(cgi->wsi);
1055*1c60b9acSAndroid Build Coastguard Worker 
1056*1c60b9acSAndroid Build Coastguard Worker 			break;
1057*1c60b9acSAndroid Build Coastguard Worker 		}
1058*1c60b9acSAndroid Build Coastguard Worker 	}
1059*1c60b9acSAndroid Build Coastguard Worker 
1060*1c60b9acSAndroid Build Coastguard Worker 	return 0;
1061*1c60b9acSAndroid Build Coastguard Worker }
1062*1c60b9acSAndroid Build Coastguard Worker 
1063*1c60b9acSAndroid Build Coastguard Worker struct lws *
lws_cgi_get_stdwsi(struct lws * wsi,enum lws_enum_stdinouterr ch)1064*1c60b9acSAndroid Build Coastguard Worker lws_cgi_get_stdwsi(struct lws *wsi, enum lws_enum_stdinouterr ch)
1065*1c60b9acSAndroid Build Coastguard Worker {
1066*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->http.cgi)
1067*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
1068*1c60b9acSAndroid Build Coastguard Worker 
1069*1c60b9acSAndroid Build Coastguard Worker 	return wsi->http.cgi->lsp->stdwsi[ch];
1070*1c60b9acSAndroid Build Coastguard Worker }
1071*1c60b9acSAndroid Build Coastguard Worker 
1072*1c60b9acSAndroid Build Coastguard Worker void
lws_cgi_remove_and_kill(struct lws * wsi)1073*1c60b9acSAndroid Build Coastguard Worker lws_cgi_remove_and_kill(struct lws *wsi)
1074*1c60b9acSAndroid Build Coastguard Worker {
1075*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
1076*1c60b9acSAndroid Build Coastguard Worker 	struct lws_cgi **pcgi = &pt->http.cgi_list;
1077*1c60b9acSAndroid Build Coastguard Worker 
1078*1c60b9acSAndroid Build Coastguard Worker 	/* remove us from the cgi list */
1079*1c60b9acSAndroid Build Coastguard Worker 
1080*1c60b9acSAndroid Build Coastguard Worker 	while (*pcgi) {
1081*1c60b9acSAndroid Build Coastguard Worker 		if (*pcgi == wsi->http.cgi) {
1082*1c60b9acSAndroid Build Coastguard Worker 			/* drop us from the pt cgi list */
1083*1c60b9acSAndroid Build Coastguard Worker 			*pcgi = (*pcgi)->cgi_list;
1084*1c60b9acSAndroid Build Coastguard Worker 			break;
1085*1c60b9acSAndroid Build Coastguard Worker 		}
1086*1c60b9acSAndroid Build Coastguard Worker 		pcgi = &(*pcgi)->cgi_list;
1087*1c60b9acSAndroid Build Coastguard Worker 	}
1088*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->http.cgi->headers_buf)
1089*1c60b9acSAndroid Build Coastguard Worker 		lws_free_set_NULL(wsi->http.cgi->headers_buf);
1090*1c60b9acSAndroid Build Coastguard Worker 
1091*1c60b9acSAndroid Build Coastguard Worker 	/* we have a cgi going, we must kill it */
1092*1c60b9acSAndroid Build Coastguard Worker 	wsi->http.cgi->being_closed = 1;
1093*1c60b9acSAndroid Build Coastguard Worker 	lws_cgi_kill(wsi);
1094*1c60b9acSAndroid Build Coastguard Worker 
1095*1c60b9acSAndroid Build Coastguard Worker 	if (!pt->http.cgi_list)
1096*1c60b9acSAndroid Build Coastguard Worker 		lws_sul_cancel(&pt->sul_cgi);
1097*1c60b9acSAndroid Build Coastguard Worker }
1098