static void browserToCgiService(HttpQueue *q) { HttpConn *conn; HttpPacket *packet; Cgi *cgi; MprCmd *cmd; MprBuf *buf; ssize rc, len; int err; if ((cgi = q->queueData) == 0) { return; } assert(q == cgi->writeq); cmd = cgi->cmd; assert(cmd); conn = cgi->conn; for (packet = httpGetPacket(q); packet; packet = httpGetPacket(q)) { if ((buf = packet->content) == 0) { /* End packet */ continue; } len = mprGetBufLength(buf); rc = mprWriteCmd(cmd, MPR_CMD_STDIN, mprGetBufStart(buf), len); if (rc < 0) { err = mprGetError(); if (err == EINTR) { continue; } else if (err == EAGAIN || err == EWOULDBLOCK) { httpPutBackPacket(q, packet); break; } mprLog(2, "CGI: write to gateway failed for %d bytes, rc %d, errno %d", len, rc, mprGetOsError()); mprCloseCmdFd(cmd, MPR_CMD_STDIN); httpDiscardQueueData(q, 1); httpError(conn, HTTP_CODE_BAD_GATEWAY, "Cannot write body data to CGI gateway"); break; } mprTrace(6, "CGI: browserToCgiService %d/%d, qmax %d", rc, len, q->max); mprAdjustBufStart(buf, rc); if (mprGetBufLength(buf) > 0) { httpPutBackPacket(q, packet); break; } } if (q->count > 0) { /* Wait for writable event so cgiCallback can recall this routine */ mprEnableCmdEvents(cmd, MPR_CMD_STDIN); } else if (conn->rx->eof) { mprCloseCmdFd(cmd, MPR_CMD_STDIN); } else { mprDisableCmdEvents(cmd, MPR_CMD_STDIN); } }
/* Default callback routine for the mprRunCmd routines. Uses may supply their own callback instead of this routine. The callback is run whenever there is I/O to read/write to the CGI gateway. */ static void defaultCmdCallback(MprCmd *cmd, int channel, void *data) { MprBuf *buf; ssize len, space; int errCode; /* Note: stdin, stdout and stderr are named from the client's perspective */ buf = 0; switch (channel) { case MPR_CMD_STDIN: return; case MPR_CMD_STDOUT: buf = cmd->stdoutBuf; break; case MPR_CMD_STDERR: buf = cmd->stderrBuf; break; default: /* Child death notification */ return; } /* Read and aggregate the result into a single string */ space = mprGetBufSpace(buf); if (space < (ME_BUFSIZE / 4)) { if (mprGrowBuf(buf, ME_BUFSIZE) < 0) { mprCloseCmdFd(cmd, channel); return; } space = mprGetBufSpace(buf); } len = mprReadCmd(cmd, channel, mprGetBufEnd(buf), space); errCode = mprGetError(); if (len <= 0) { if (len == 0 || (len < 0 && !(errCode == EAGAIN || errCode == EWOULDBLOCK))) { mprCloseCmdFd(cmd, channel); return; } } else { mprAdjustBufEnd(buf, len); } mprAddNullToBuf(buf); mprEnableCmdEvents(cmd, channel); }