if (debug) log_d("read(%d [script], %p + %d, %d) = %d", p->pfd, p->pbuf, p->ipp, bytestoread, r);
static int pipe_run(struct pipe_params *p, struct connection *cn){	int done;	struct pollfd pollfds[2];	char c;	ssize_t r;	size_t room;	size_t bytestocopy;	int n;	int convert_result;	size_t bytestoread;	char chunkbuf[16];	size_t chunkheaderlen;	done = 1;	pollfds[0].fd = -1;	pollfds[1].fd = -1;	pollfds[0].events = 0;	pollfds[1].events = 0;	pollfds[0].revents = 0;	pollfds[1].revents = 0;	if (p->haslen && p->pmax == 0)		p->pstate = 2;	if (p->istate == 1 && p->ibp < p->isize && p->imax) {		done = 0;		pollfds[0].fd = p->cfd;		pollfds[0].events |= POLLIN;	}	if (p->otop > p->obp) {		done = 0;		pollfds[0].fd = p->cfd;		pollfds[0].events |= POLLOUT;	}	if (p->pstate == 1 && p->ipp < p->psize && (p->chunkit || p->haslen == 0 || p->pmax)) {		done = 0;		pollfds[1].fd = p->pfd;		pollfds[1].events |= POLLIN;	}	if (p->ibp > p->opp) {		done = 0;		pollfds[1].fd = p->pfd;		pollfds[1].events |= POLLOUT;	}	if (done)		return 1;	if (gotsigchld) {		gotsigchld = 0;		if (stub_reap() == -1)			return 1;	}	n = poll(pollfds, 2, p->timeout);	current_time = time(0);	if (gotsigchld) {		gotsigchld = 0;		if (stub_reap() == -1)			return 1;	}	if (n == -1) {		if (errno == EINTR)			return 0;		lerror("poll");		return 1;	}	if (n == 0) {		log_d("pipe_run: timeout");		return 1;	}	if (pollfds[0].revents & ~(POLLIN | POLLOUT)) {		log_d("pipe_run: pollfds[%d].revents=%d", 0, pollfds[0].revents);		return 1;	}	if (pollfds[1].revents & ~(POLLIN | POLLOUT)) {		log_d("pipe_run: pollfds[%d].revents=%d", 1, pollfds[1].revents);		return 1;	}	if (pollfds[0].revents & POLLIN) {		bytestoread = p->isize - p->ibp;		if (bytestoread > p->imax)			bytestoread = p->imax;		r = read(p->cfd, p->ibuf + p->ibp, bytestoread);		if (debug)			log_d("read(%d [client], %p + %d, %d) = %d", p->cfd, p->ibuf, p->ibp, bytestoread, r);		switch (r) {		case -1:			if (errno == EAGAIN)				break;			lerror("pipe_run: error reading from client");			return 1;		case 0:			log_d("pipe_run: client went away while posting data");			return 1;		default:			cn->nread += r;			p->ibp += r;			p->imax -= r;			break;		}	}	if (pollfds[0].revents & POLLOUT) {		r = write(p->cfd, p->obuf + p->obp, p->otop - p->obp);		if (debug)			log_d("write(%d [client], %p + %d, %d) = %d", p->cfd, p->obuf, p->obp, p->otop - p->obp, r);		switch (r) {		case -1:			if (errno == EAGAIN)				break;			lerror("pipe_run: error writing to client");			return 1;		default:			cn->nwritten += r;			p->obp += r;			break;		}	}	if (pollfds[1].revents & POLLIN) {		bytestoread = p->isize - p->ibp;		if (p->haslen && bytestoread > p->pmax)			bytestoread = p->pmax;		r = read(p->pfd, p->pbuf + p->ipp, bytestoread);		if (debug)			log_d("read(%d [script], %p + %d, %d) = %d", p->pfd, p->pbuf, p->ipp, bytestoread, r);		switch (r) {		case -1:			if (errno == EAGAIN)				break;			lerror("pipe_run: error reading from script");			p->pstate = 2;			break;		case 0:			if (p->state == 0) {				log_d("pipe_run: premature end of script headers");				return 1;			}			if (p->haslen) {				log_d("pipe_run: script went away");				return 1;			}			p->pstate = 2;			break;		default:			p->ipp += r;			if (p->haslen)				p->pmax -= r;			break;		}	}	if (pollfds[1].revents & POLLOUT) {		r = write(p->pfd, p->ibuf + p->opp, p->ibp - p->opp);		if (debug)			log_d("write(%d [script], %p + %d, %d) = %d", p->pfd, p->ibuf, p->opp, p->ibp - p->opp, r);		switch (r) {		case -1:			if (errno == EAGAIN)				break;			lerror("pipe_run: error writing to script");			return 1;		default:			p->opp += r;			break;		}	}	if (p->opp && p->opp == p->ibp)		p->opp = p->ibp = 0;	if (p->obp && p->obp == p->otop)		p->obp = p->otop = 0;	if (p->ipp && p->state != 2) {		while (p->pstart < p->ipp && p->state != 2) {			c = p->pbuf[p->pstart++];			switch (p->state) {			case 0:				if (c == '\n')					p->state = 1;				break;			case 1:				switch (c) {				case '\r':					break;				case '\n':					p->state = 2;					break;				default:					p->state = 0;					break;				}				break;			}		}		if (p->state == 2) {			convert_result = convert_cgi_headers(p, &cn->r->status);			if (convert_result == -1) {				log_d("pipe_run: problem in convert_cgi_headers");				return 1;			}			if (p->haslen && p->pstart < p->ipp) {				if (debug)					log_d("pipe_run: p->pstart = %d, p->ipp = %d, p->pmax = %d", p->pstart, p->ipp, p->pmax);				if (p->ipp > p->pstart + p->pmax) {					log_d("extra garbage from script ignored");					p->pmax = 0;				} else					p->pmax -= p->ipp - p->pstart;				if (debug)					log_d("pipe_run: p->pmax is now %d", p->pmax);			}		} else if (p->pstart == p->psize) {			log_d("pipe_run: too many headers");			return 1;		}	}	if (p->state == 2 && p->pstart < p->ipp) {		if (p->nocontent)			p->pstart = p->ipp = 0;		else {			room = p->osize - p->otop;			bytestocopy = p->ipp - p->pstart;			if (bytestocopy > room)				bytestocopy = room;			if (bytestocopy && p->chunkit) {				chunkheaderlen = sprintf(chunkbuf, "%lx\r\n", (unsigned long) bytestocopy);				if (chunkheaderlen + 2 >= room)					bytestocopy = 0;				else {					if (bytestocopy + chunkheaderlen + 2 > room) {						bytestocopy -= chunkheaderlen + 2;						chunkheaderlen = sprintf(chunkbuf, "%lx\r\n", (unsigned long) bytestocopy);					}					memcpy(p->obuf + p->otop, chunkbuf, chunkheaderlen);					p->otop += chunkheaderlen;				}			}			if (bytestocopy) {				memcpy(p->obuf + p->otop, p->pbuf + p->pstart, bytestocopy);				p->otop += bytestocopy;				p->pstart += bytestocopy;				if (p->pstart == p->ipp)					p->pstart = p->ipp = 0;				if (p->chunkit) {					memcpy(p->obuf + p->otop, "\r\n", 2);					p->otop += 2;				}			}		}	}	if (p->pstate == 2 && p->chunkit && p->nocontent == 0) {		if (p->osize - p->otop >= 5) {			memcpy(p->obuf + p->otop, "0\r\n\r\n", 5);			p->otop += 5;			p->pstate = 3;		}	}	return 0;}