int iswrite(const char UUFAR *data, unsigned int len) { unsigned int i; union REGS xmtregs; ShowModem(); /*--------------------------------------------------------------------*/ /* For an INT14 interface, just spit the data bytes out one */ /* at a time. */ /*--------------------------------------------------------------------*/ xmtregs.h.ah = FS_XMIT1; xmtregs.x.dx = portNum; /* Port number */ xmtregs.x.bx = 0; for (i = 0; i < len; i++) { union REGS outregs; xmtregs.h.al = (unsigned char) data[i]; int86(0x14, &xmtregs, &outregs); #if 1 /* Richard H. Gumpertz ([email protected]), 29 September 1993 */ if (((outregs.h.ah & 0x61) == 0x01) && (commBufferUsed < commBufferLength)) isread(NULL, commBufferLength, 0); /* do some read ahead */ #endif /* RHG */ } traceData( data, len, KWTrue ); /*--------------------------------------------------------------------*/ /* Return byte count transmitted to caller */ /*--------------------------------------------------------------------*/ return len; } /* iswrite */
int nswrite(const char UUFAR *input, unsigned int len) { char UUFAR *data = (char UUFAR *) input; #ifdef __OS2__ ULONG bytes; #else size_t bytes; #endif APIRET rc; hangupNeeded = KWTrue; /* Flag that the port is now dirty */ /*--------------------------------------------------------------------*/ /* Write the data out as the queue becomes available */ /*--------------------------------------------------------------------*/ rc = DosWrite( commHandle, data , len, &bytes); if (rc) { printOS2error( "DosWrite", rc ); return bytes; } /*if */ /*--------------------------------------------------------------------*/ /* Log the data written */ /*--------------------------------------------------------------------*/ traceData( data, len, KWTrue); /*--------------------------------------------------------------------*/ /* Return bytes written to the port to the caller */ /*--------------------------------------------------------------------*/ return len; } /* nswrite */
static void readFromCgi(Cgi *cgi, int channel) { HttpConn *conn; HttpPacket *packet; HttpTx *tx; HttpQueue *q, *writeq; MprCmd *cmd; ssize nbytes; int err; cmd = cgi->cmd; conn = cgi->conn; tx = conn->tx; q = cgi->readq; writeq = conn->writeq; assert(conn->sock); assert(conn->state > HTTP_STATE_BEGIN); if (tx->finalized) { mprCloseCmdFd(cmd, channel); } while (mprGetCmdFd(cmd, channel) >= 0 && !tx->finalized && writeq->count < writeq->max) { if ((packet = cgi->headers) != 0) { if (mprGetBufSpace(packet->content) < ME_MAX_BUFFER && mprGrowBuf(packet->content, ME_MAX_BUFFER) < 0) { break; } } else if ((packet = httpCreateDataPacket(ME_MAX_BUFFER)) == 0) { break; } nbytes = mprReadCmd(cmd, channel, mprGetBufEnd(packet->content), ME_MAX_BUFFER); if (nbytes < 0) { err = mprGetError(); if (err == EINTR) { continue; } else if (err == EAGAIN || err == EWOULDBLOCK) { break; } mprCloseCmdFd(cmd, channel); break; } else if (nbytes == 0) { mprCloseCmdFd(cmd, channel); break; } else { traceData(cmd, mprGetBufEnd(packet->content), nbytes); mprAdjustBufEnd(packet->content, nbytes); } if (channel == MPR_CMD_STDERR) { mprLog("error cgi", 0, "CGI failed uri=\"%s\", details: %s", conn->rx->uri, mprGetBufStart(packet->content)); httpSetStatus(conn, HTTP_CODE_SERVICE_UNAVAILABLE); cgi->seenHeader = 1; } if (!cgi->seenHeader) { if (!parseCgiHeaders(cgi, packet)) { cgi->headers = packet; return; } cgi->headers = 0; cgi->seenHeader = 1; } if (!tx->finalizedOutput && httpGetPacketLength(packet) > 0) { /* Put the data to the CGI readq, then cgiToBrowserService will take care of it */ httpPutPacket(q, packet); } } }
unsigned int nsread(char UUFAR *output, unsigned int wanted, unsigned int timeout) { APIRET rc; time_t stop_time ; time_t now ; USHORT com_error; KWBoolean firstPass = ( currentSpeed > 2400 ) && ( wanted == 1 ); /* Perform extended read only on high- speed modem links when looking for packet data */ #ifdef __OS2__ ULONG ParmLengthInOut; ULONG DataLengthInOut; #endif /*--------------------------------------------------------------------*/ /* Validate input */ /*--------------------------------------------------------------------*/ if ( wanted > commBufferLength ) { printmsg(0,"nsread: Overlength read, wanted %u bytes into %u buffer!", (unsigned int) wanted, (unsigned int) commBufferLength ); panic(); } /*--------------------------------------------------------------------*/ /* Determine if our internal buffer has the data */ /*--------------------------------------------------------------------*/ if (commBufferUsed >= wanted) { MEMCPY( output, commBuffer, wanted ); commBufferUsed -= wanted; if ( commBufferUsed ) /* Any data left over? */ MEMMOVE( commBuffer, commBuffer + wanted, commBufferUsed ); /* Yes --> Save it */ return wanted + commBufferUsed; } /* if */ /*--------------------------------------------------------------------*/ /* Reset any errors on the communications port */ /*--------------------------------------------------------------------*/ #ifdef __OS2__ ParmLengthInOut = 0; DataLengthInOut = sizeof(com_error); rc = DosDevIOCtl( commHandle, IOCTL_ASYNC, ASYNC_GETCOMMERROR, NULL, 0L, &ParmLengthInOut, (PVOID) &com_error, sizeof(com_error), &DataLengthInOut); #else rc = DosDevIOCtl( &com_error, FAR_NULL, ASYNC_GETCOMMERROR , IOCTL_ASYNC, commHandle); #endif if (rc ) { printOS2error( "ASYNC_GETCOMMERROR", rc ); } /*if */ else if ( com_error ) ShowError( com_error ); /*--------------------------------------------------------------------*/ /* Determine when to stop processing */ /*--------------------------------------------------------------------*/ if ( timeout == 0 ) { stop_time = 0; now = 1; /* Any number greater than stop time */ } else { time( & now ); stop_time = now + timeout; } /*--------------------------------------------------------------------*/ /* Try to read any needed data into the buffer */ /*--------------------------------------------------------------------*/ do { USHORT needed = (USHORT) wanted - commBufferUsed; USHORT portTimeout; #ifdef __OS2__ ULONG received = 0; #else USHORT received = 0; #endif /*--------------------------------------------------------------------*/ /* Handle an aborted program */ /*--------------------------------------------------------------------*/ if ( raised ) return 0; if ( terminate_processing ) { static KWBoolean recurse = KWFalse; if ( ! recurse ) { printmsg(2,"nsread: User aborted processing"); recurse = KWTrue; } return 0; } /*--------------------------------------------------------------------*/ /* Compute a new timeout for the read, if needed */ /*--------------------------------------------------------------------*/ if ((stop_time <= now ) || firstPass ) { portTimeout = 0; firstPass = KWFalse; } else { if ( ((stop_time - now) / needed) > (USHRT_MAX / 100 )) portTimeout = USHRT_MAX; else portTimeout = (USHORT) (stop_time - now) / needed * 100; if (portTimeout < 100) portTimeout = 100; } /* else */ if ( portTimeout != com_dcbinfo.usReadTimeout ) { com_dcbinfo.usReadTimeout = portTimeout; #ifdef __OS2__ ParmLengthInOut = sizeof(com_dcbinfo); DataLengthInOut = 0; rc = DosDevIOCtl( commHandle, IOCTL_ASYNC, ASYNC_SETDCBINFO, (PVOID) &com_dcbinfo, sizeof(com_dcbinfo), &ParmLengthInOut, NULL, 0L, &DataLengthInOut); #else rc = DosDevIOCtl(FAR_NULL, &com_dcbinfo, ASYNC_SETDCBINFO, IOCTL_ASYNC, commHandle); #endif if ( rc ) { printOS2error( "ASYNC_SETDCBINFO", rc ); panic(); } /* if */ } /* if */ #ifdef UDEBUG printmsg(15,"nsread: Port time out is %ud seconds/100", portTimeout); #endif /*--------------------------------------------------------------------*/ /* Read the data from the serial port */ /*--------------------------------------------------------------------*/ rc = DosRead( commHandle, commBuffer + commBufferUsed, portTimeout ? needed : commBufferLength - commBufferUsed, &received ); if ( rc == ERROR_INTERRUPT) { printmsg(2,"Read Interrupted"); return 0; } else if ( rc != 0 ) { printmsg(0,"nsread: Read from comm port for %d bytes failed.", needed); printOS2error( "DosRead", rc ); commBufferUsed = 0; return 0; } #ifdef UDEBUG printmsg(15,"nsread: Want %d characters, received %d, total %d in buffer", (int) wanted, (int) received, (int) commBufferUsed + received); #endif /*--------------------------------------------------------------------*/ /* Log the newly received data */ /*--------------------------------------------------------------------*/ traceData( commBuffer + commBufferUsed, (unsigned) received, KWFalse ); /*--------------------------------------------------------------------*/ /* If we got the data, return it to the caller */ /*--------------------------------------------------------------------*/ commBufferUsed += received; if ( commBufferUsed >= wanted ) { MEMCPY( output, commBuffer, wanted ); commBufferUsed -= wanted; if ( commBufferUsed ) /* Any data left over? */ MEMMOVE( commBuffer, commBuffer + wanted, commBufferUsed ); return wanted; } /* if */ /*--------------------------------------------------------------------*/ /* Update the clock for the next pass */ /*--------------------------------------------------------------------*/ if (stop_time > 0) time( &now ); } while (stop_time > now); /*--------------------------------------------------------------------*/ /* We don't have enough data; report what we do have */ /*--------------------------------------------------------------------*/ return commBufferUsed; } /*nsread*/
static void cgiEvent(MaQueue *q, MprCmd *cmd, int channel) { MaConn *conn; MaResponse *resp; MprBuf *buf; int space, nbytes, err; mprLog(cmd, 6, "CGI callback channel %d", channel); buf = 0; conn = q->conn; resp = conn->response; mprAssert(resp); cmd->lastActivity = mprGetTime(cmd); switch (channel) { case MPR_CMD_STDIN: writeToCGI(q->pair); return; case MPR_CMD_STDOUT: buf = cmd->stdoutBuf; break; case MPR_CMD_STDERR: buf = cmd->stderrBuf; break; } mprAssert(buf); mprResetBufIfEmpty(buf); /* Come here for CGI stdout, stderr events. ie. reading data from the CGI program. */ while (mprGetCmdFd(cmd, channel) >= 0) { /* Read as much data from the CGI as possible */ do { if ((space = mprGetBufSpace(buf)) == 0) { mprGrowBuf(buf, MA_BUFSIZE); if ((space = mprGetBufSpace(buf)) == 0) { break; } } nbytes = mprReadCmdPipe(cmd, channel, mprGetBufEnd(buf), space); mprLog(q, 5, "CGI: read from gateway %d on channel %d. errno %d", nbytes, channel, nbytes >= 0 ? 0 : mprGetOsError()); if (nbytes < 0) { err = mprGetError(); if (err == EINTR) { continue; } else if (err == EAGAIN || err == EWOULDBLOCK) { break; } mprLog(cmd, 5, "CGI read error %d for %", mprGetError(), (channel == MPR_CMD_STDOUT) ? "stdout" : "stderr"); mprCloseCmdFd(cmd, channel); } else if (nbytes == 0) { /* This may reap the terminated child and thus clear cmd->process if both stderr and stdout are closed. */ mprLog(cmd, 5, "CGI EOF for %s", (channel == MPR_CMD_STDOUT) ? "stdout" : "stderr"); mprCloseCmdFd(cmd, channel); break; } else { mprLog(cmd, 5, "CGI read %d bytes from %s", nbytes, (channel == MPR_CMD_STDOUT) ? "stdout" : "stderr"); mprAdjustBufEnd(buf, nbytes); traceData(cmd, mprGetBufStart(buf), nbytes); } } while ((space = mprGetBufSpace(buf)) > 0); if (mprGetBufLength(buf) == 0) { return; } if (channel == MPR_CMD_STDERR) { /* If we have an error message, send that to the client */ if (mprGetBufLength(buf) > 0) { mprAddNullToBuf(buf); mprLog(conn, 4, mprGetBufStart(buf)); if (writeToClient(q, cmd, buf, channel) < 0) { return; } maSetResponseCode(conn, MPR_HTTP_CODE_SERVICE_UNAVAILABLE); cmd->userFlags |= MA_CGI_SEEN_HEADER; cmd->status = 0; } } else { if (!(cmd->userFlags & MA_CGI_SEEN_HEADER) && !parseHeader(conn, cmd)) { return; } if (cmd->userFlags & MA_CGI_SEEN_HEADER) { if (writeToClient(q, cmd, buf, channel) < 0) { return; } } } } }
static void readFromCgi(Cgi *cgi, int channel) { HttpConn *conn; HttpPacket *packet; HttpTx *tx; HttpQueue *q, *writeq; MprCmd *cmd; ssize nbytes; int err; cmd = cgi->cmd; conn = cgi->conn; tx = conn->tx; q = cgi->readq; writeq = conn->writeq; assert(conn->sock); assert(conn->state > HTTP_STATE_BEGIN); if (tx->finalized) { mprCloseCmdFd(cmd, channel); } while (mprGetCmdFd(cmd, channel) >= 0 && !tx->finalized && writeq->count < writeq->max) { if ((packet = cgi->headers) != 0) { if (mprGetBufSpace(packet->content) < ME_MAX_BUFFER && mprGrowBuf(packet->content, ME_MAX_BUFFER) < 0) { break; } } else if ((packet = httpCreateDataPacket(ME_MAX_BUFFER)) == 0) { break; } nbytes = mprReadCmd(cmd, channel, mprGetBufEnd(packet->content), ME_MAX_BUFFER); if (nbytes < 0) { err = mprGetError(); if (err == EINTR) { continue; } else if (err == EAGAIN || err == EWOULDBLOCK) { break; } mprTrace(6, "CGI: Gateway read error %d for %s", err, (channel == MPR_CMD_STDOUT) ? "stdout" : "stderr"); mprCloseCmdFd(cmd, channel); break; } else if (nbytes == 0) { mprTrace(6, "CGI: Gateway EOF for %s, pid %d", (channel == MPR_CMD_STDOUT) ? "stdout" : "stderr", cmd->pid); mprCloseCmdFd(cmd, channel); break; } else { mprTrace(6, "CGI: Gateway read %d bytes from %s", nbytes, (channel == MPR_CMD_STDOUT) ? "stdout" : "stderr"); traceData(cmd, mprGetBufEnd(packet->content), nbytes); mprAdjustBufEnd(packet->content, nbytes); } if (channel == MPR_CMD_STDERR) { // FUTURE - should be an option to keep going despite stderr output mprError("CGI: Error for \"%s\"\n\n%s", conn->rx->uri, mprGetBufStart(packet->content)); httpSetStatus(conn, HTTP_CODE_SERVICE_UNAVAILABLE); cgi->seenHeader = 1; } if (!cgi->seenHeader) { if (!parseCgiHeaders(cgi, packet)) { cgi->headers = packet; return; } cgi->headers = 0; cgi->seenHeader = 1; } if (!tx->finalizedOutput && httpGetPacketLength(packet) > 0) { /* Put the data to the CGI readq, then cgiToBrowserService will take care of it */ httpPutPacket(q, packet); } } }
unsigned int isread(char UUFAR *buffer, unsigned int wanted, unsigned int timeout) { union REGS rcvregs, outregs; time_t quit = time( NULL ) + timeout; size_t commBufferCached = commBufferUsed; if ( wanted > commBufferLength ) { printmsg(0,"nsread: Overlength read, wanted %u bytes into %u buffer!", (unsigned int) wanted, (unsigned int) commBufferLength ); panic(); } #ifdef ARTICOMM_INT14 /* Richard H. Gumpertz ([email protected]), 28 Sep 1993 */ union REGS timregs; /* Scratch area for interrupt calls. */ timregs.x.ax = 0x8009; /* Set timeouts */ timregs.x.cx = timeout * 91 / 5; /* Receive timeout in ticks */ timregs.x.bx = 0x7FFF/*???*/; /* Send timeout in ticks */ timregs.x.dx = portNum; /* Port number */ int86(0x14, &timregs, &outregs); #endif /* ARTICOMM_INT14 */ rcvregs.h.ah = FS_RECV1; rcvregs.h.al = 0; rcvregs.x.dx = portNum; /* Port number */ rcvregs.x.bx = 0; while (commBufferUsed < wanted) { if ( terminate_processing ) { static KWBoolean recurse = KWFalse; if ( ! recurse ) { printmsg(2,"isread: User aborted processing"); recurse = KWTrue; } commBufferUsed = 0; return commBufferUsed; } int86(0x14, &rcvregs, &outregs); if (!(outregs.h.ah & 0x80)) commBuffer[commBufferUsed++] = (char) outregs.h.al; else { /* the read timed out */ if (timeout == 0) /* If not interested in waiting */ return commBufferUsed; /* then get out of here fast */ ShowModem(); /* Report modem status */ if ( time(NULL) >= quit ) { printmsg(20, "isread: Timeout (timeout=%u, want=%u, have=%u)", timeout, wanted, commBufferUsed); return commBufferUsed; } #ifdef ARTICOMM_INT14 /* Richard H. Gumpertz ([email protected]), 28 Sep 1993 */ timregs.x.cx = (unsigned short)(quit - now) * 91 / 5; /* Receive timeout in ticks */ int86(0x14, &timregs, &outregs); #endif /* ARTICOMM_INT14 */ } /* else */ } /* while (commBufferUsed < wanted) */ traceData( commBuffer + commBufferCached, commBufferUsed - commBufferCached, KWFalse ); if ( buffer != NULL ) { MEMCPY(buffer, commBuffer, wanted); commBufferUsed -= wanted; if (commBufferUsed) MEMMOVE(commBuffer, commBuffer + wanted, commBufferUsed); } return wanted + commBufferUsed; } /* isread */