TEST_F(RingBuf, RingBufRW2_1) { RingBuf_t ringbuf; uint8_t wbuf[3]; uint8_t rbuf[3]; size_t sz; for (int i = 0; i < 3; i++) { RingBufAlloc(&ringbuf, 3); ringbuf.wpos = i; //ずらす ringbuf.rpos = (ringbuf.wpos + 1) % 3; memset(ringbuf.buf, 0xdd, 3); ringbuf.empty = false; //1回ずつ書いて、1回ずつ読む //書ける wbuf[0] = 0x12; sz = 1; RingBufWrite(&ringbuf, wbuf, &sz); ASSERT_EQ(1UL, sz); //書けない wbuf[0] = 0x78; sz = 1; RingBufWrite(&ringbuf, wbuf, &sz); ASSERT_EQ(0UL, sz); //読める sz = 1; RingBufRead(&ringbuf, rbuf, &sz); ASSERT_EQ(1UL, sz); ASSERT_EQ(0xdd, rbuf[0]); //読める sz = 1; RingBufRead(&ringbuf, rbuf, &sz); ASSERT_EQ(1UL, sz); ASSERT_EQ(0xdd, rbuf[0]); //読める sz = 1; RingBufRead(&ringbuf, rbuf, &sz); ASSERT_EQ(1UL, sz); ASSERT_EQ(0x12, rbuf[0]); //読めない sz = 1; RingBufRead(&ringbuf, rbuf, &sz); ASSERT_EQ(0UL, sz); RingBufFree(&ringbuf); } }
TEST_F(RingBuf, RingBufRW1_2) { RingBuf_t ringbuf; uint8_t wbuf[3]; uint8_t rbuf[5]; size_t sz; for (int i = 0; i < 3; i++) { RingBufAlloc(&ringbuf, 3); ringbuf.rpos = ringbuf.wpos = i; //ずらす //2回で書いて、1回で読む //書ける wbuf[0] = 0x12; wbuf[1] = 0x34; sz = 2; RingBufWrite(&ringbuf, wbuf, &sz); ASSERT_EQ(2UL, sz); //書ける wbuf[0] = 0x56; wbuf[1] = 0x78; sz = 2; RingBufWrite(&ringbuf, wbuf, &sz); ASSERT_EQ(1UL, sz); //書けない wbuf[0] = 0x78; sz = 1; RingBufWrite(&ringbuf, wbuf, &sz); ASSERT_EQ(0UL, sz); //読める sz = 5; RingBufRead(&ringbuf, rbuf, &sz); ASSERT_EQ(3UL, sz); ASSERT_EQ(0x12, rbuf[0]); ASSERT_EQ(0x34, rbuf[1]); ASSERT_EQ(0x56, rbuf[2]); //読めない sz = 1; RingBufRead(&ringbuf, rbuf, &sz); ASSERT_EQ(0UL, sz); RingBufFree(&ringbuf); } }
TEST_F(RingBuf2, RingBufWrite5) { //空きがない // +---+ // 2| | // RW1| | // 0| | // +---+ RingBuf2::mBuf.rpos = 1; RingBuf2::mBuf.wpos = 1; RingBuf2::mBuf.empty = false; const uint8_t DATA[] = { 6, 7 }; size_t sz = sizeof(DATA); RingBufWrite(&RingBuf2::mBuf, DATA, &sz); ASSERT_EQ(1, RingBuf2::mBuf.rpos); ASSERT_EQ(1, RingBuf2::mBuf.wpos); ASSERT_EQ(0xcc, RingBuf2::mBuf.buf[0]); ASSERT_EQ(0xcc, RingBuf2::mBuf.buf[1]); ASSERT_EQ(0xcc, RingBuf2::mBuf.buf[2]); ASSERT_FALSE(RingBuf2::mBuf.empty); ASSERT_EQ(0UL, sz); }
//***************************************************************************** // // The interrupt-context handler for touch screen events from the touch screen // driver. This function merely bundles up the event parameters and posts // them to a message queue. In the context of the main loop, they will be // read from the queue and handled using TSMainHandler(). // //***************************************************************************** int32_t TSHandler(uint32_t ui32Message, int32_t i32X, int32_t i32Y) { tScribbleMessage sMsg; // // Build the message that we will write to the queue. // sMsg.ui32Msg = ui32Message; sMsg.i32X = i32X; sMsg.i32Y = i32Y; // // Make sure the queue isn't full. If it is, we just ignore this message. // if(!RingBufFull(&g_sMsgQueue)) { RingBufWrite(&g_sMsgQueue, (uint8_t *)&sMsg, sizeof(tScribbleMessage)); } // // Tell the touch handler that everything is fine. // return(1); }
TEST_F(RingBuf2, RingBufWrite7) { //空き上がは1つで、下に1つ // +---+ // W2| | // R1| | // 0| | // +---+ RingBuf2::mBuf.rpos = 1; RingBuf2::mBuf.wpos = 2; RingBuf2::mBuf.empty = false; //下エリアの空きが足りない const uint8_t DATA[] = { 5, 6, 7 }; size_t sz = sizeof(DATA); RingBufWrite(&RingBuf2::mBuf, DATA, &sz); ASSERT_EQ(1, RingBuf2::mBuf.rpos); ASSERT_EQ(1, RingBuf2::mBuf.wpos); ASSERT_EQ(6, RingBuf2::mBuf.buf[0]); ASSERT_EQ(0xcc, RingBuf2::mBuf.buf[1]); ASSERT_EQ(5, RingBuf2::mBuf.buf[2]); ASSERT_FALSE(RingBuf2::mBuf.empty); ASSERT_EQ(2UL, sz); }
TEST_F(RingBuf2, RingBufWrite4) { //空き上がは2つで、下に空きがない // +---+ // 2| | // W1| | // R0| | // +---+ RingBuf2::mBuf.rpos = 0; RingBuf2::mBuf.wpos = 1; RingBuf2::mBuf.empty = false; const uint8_t DATA[] = { 4, 5 }; size_t sz = sizeof(DATA); RingBufWrite(&RingBuf2::mBuf, DATA, &sz); ASSERT_EQ(0, RingBuf2::mBuf.rpos); ASSERT_EQ(0, RingBuf2::mBuf.wpos); ASSERT_EQ(0xcc, RingBuf2::mBuf.buf[0]); ASSERT_EQ(4, RingBuf2::mBuf.buf[1]); ASSERT_EQ(5, RingBuf2::mBuf.buf[2]); ASSERT_FALSE(RingBuf2::mBuf.empty); ASSERT_EQ(2UL, sz); }
void sbbs_t::ungetkey(char ch) { #if 0 /* this way breaks ansi_getxy() */ RingBufWrite(&inbuf,(uchar*)&ch,sizeof(uchar)); #else keybuf[keybuftop++]=ch; if(keybuftop==KEY_BUFSIZE) keybuftop=0; #endif }
//***************************************************************************** // // Puts a UART message on the line to the RNP. // // \param pui8Msg pointer to the data that will be put on the bus. Must be // already formated with SOF, length and checksum by the caller. // // \param ui16Length the number of bytes that are to be put out the UART. // // This function copies the message to the ring buffer and then starts a // transmission process. Application must assure that transmitter is not busy. // //***************************************************************************** void RemoTIUARTPutMsg(uint8_t* pui8Msg, uint_fast16_t ui16Length) { bool bIntState; // // Capture the current state of the master interrupt enable. // bIntState = IntMasterDisable(); // // Store the message in the ringbuffer for transmission. // RingBufWrite(&g_rbRemoTITxRingBuf, pui8Msg, ui16Length); // // If the UART transmit is idle prime the transmitter with first byte and. // enable transmit interrupts. // if(!g_bTxBusy) { // // Enable the TX interrupts and start the transmission of the first // byte. // UARTIntEnable(g_ui32UARTBase, UART_INT_TX); UARTCharPutNonBlocking(g_ui32UARTBase, RingBufReadOne(&g_rbRemoTITxRingBuf)); // // Set the Transmit busy flag. // g_bTxBusy = true; } // // Restore the master interrupt enable to its previous state. // if(!bIntState) { IntMasterEnable(); } // // Finished. // }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - BOOL SBBSExecInt29::handler(VMHANDLE hVM, CLIENT_STRUCT* pRegs, DWORD intno) { vm_t* vm = find_vm(hVM); if(vm==NULL || !(vm->mode&SBBSEXEC_MODE_DOS_OUT)) { return(FALSE); // Tells VMM that interrupt was not handled } if(!RingBufFree(&vm->out)) { DBTRACEx(0,"!Int29 OUTPUT BUFFER OVERFLOW, hVM", hVM); vm->overrun=true; return(FALSE); } DBTRACEx(1,"Int29 OUTPUT", _clientAL); BYTE ch=_clientAL; RingBufWrite(&vm->out,&ch,1); vm->overrun=false; return(FALSE); }
TEST_F(RingBuf2, RingBufWrite1) { //最小 // +---+ // 2| | // 1| | // RW0| | // +---+ const uint8_t DATA[] = { 1, }; size_t sz = sizeof(DATA); RingBufWrite(&RingBuf2::mBuf, DATA, &sz); ASSERT_EQ(0, RingBuf2::mBuf.rpos); ASSERT_EQ(1, RingBuf2::mBuf.wpos); ASSERT_EQ(1, RingBuf2::mBuf.buf[0]); ASSERT_EQ(0xcc, RingBuf2::mBuf.buf[1]); ASSERT_EQ(0xcc, RingBuf2::mBuf.buf[2]); ASSERT_FALSE(RingBuf2::mBuf.empty); ASSERT_EQ(1UL, sz); }
TEST_F(RingBuf2, RingBufWrite0) { //最小-1 // +---+ // 2| | // 1| | // RW0| | // +---+ const uint8_t DATA[] = { 1, }; size_t sz = 0; RingBufWrite(&RingBuf2::mBuf, DATA, &sz); ASSERT_EQ(0, RingBuf2::mBuf.rpos); ASSERT_EQ(0, RingBuf2::mBuf.wpos); ASSERT_EQ(0xcc, RingBuf2::mBuf.buf[0]); ASSERT_EQ(0xcc, RingBuf2::mBuf.buf[1]); ASSERT_EQ(0xcc, RingBuf2::mBuf.buf[2]); ASSERT_TRUE(RingBuf2::mBuf.empty); ASSERT_EQ(0UL, sz); }
void _cdecl input_thread(void* arg) { char buf[LINEAR_RX_BUFLEN]; int count; lprintf(LOG_DEBUG,"input_thread: started"); while(1) { count=RingBufFree(&rdbuf); if(count<1) { lprintf(LOG_WARNING,"input_thread: input buffer full!"); YIELD(); continue; } if(count>sizeof(buf)) count=sizeof(buf); if(!ReadFile(rdslot,buf,count,&count,NULL)) { if(GetLastError()==ERROR_HANDLE_EOF) { /* closed by VDD_CLOSE */ lprintf(LOG_INFO,"input_thread: ReadFile returned EOF"); break; } lprintf(LOG_ERR,"!input_thread: ReadFile Error %d (size=%d)" ,GetLastError(),count); continue; } if(count==0) { lprintf(LOG_ERR,"!input_thread: ReadFile read 0"); continue; } RingBufWrite(&rdbuf,buf,count); if(virtualize_uart) { /* Set the "Data ready" bit in the LSR */ uart_lsr_reg |= UART_LSR_DATA_READY; assert_interrupt(UART_IER_RX_DATA); /* assert rx data interrupt */ } } lprintf(LOG_DEBUG,"input_thread: terminated"); }
int send_byte(void* unused, uchar ch, unsigned timeout) { uchar buf[2] = { TELNET_IAC, TELNET_IAC }; unsigned len=1; DWORD result; if(telnet && ch==TELNET_IAC) /* escape IAC char */ len=2; else buf[0]=ch; if(RingBufFree(&outbuf)<len) { fprintf(statfp,"FLOW"); flows++; result=WaitForEvent(outbuf_empty,timeout*1000); fprintf(statfp,"\b\b\b\b \b\b\b\b"); if(result!=WAIT_OBJECT_0) { fprintf(statfp ,"\n!TIMEOUT (%d) waiting for output buffer to flush (%u seconds, %u bytes)\n" ,result, timeout, RingBufFull(&outbuf)); newline=TRUE; if(RingBufFree(&outbuf)<len) return(-1); } } RingBufWrite(&outbuf,buf,len); #if !defined(RINGBUF_EVENT) ResetEvent(outbuf_empty); #endif #if 0 if(debug_tx) lprintf(LOG_DEBUG,"TX: %s",chr(ch)); #endif return(0); }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - BOOL SBBSExecInt10::handler(VMHANDLE hVM, CLIENT_STRUCT* pRegs, DWORD intno) { BYTE ch; DWORD avail; vm_t* vm = find_vm(hVM); if(vm==NULL || !(vm->mode&SBBSEXEC_MODE_DOS_OUT)) { return(FALSE); // Tells VMM that interrupt was not handled } avail=RingBufFree(&vm->out); switch(_clientAH) { case 0x02: // Set Cursor Position DBTRACE(1,"Int10 func 2 - Set cursor position"); break; case 0x09: // Write char and attr at cursor DBTRACE(1,"Int10 func 9 - Write char and attr at curosr"); case 0x10: // Write char at cursor #if 0 DBTRACE(1,"Int10 func 9 - Write char at curosr"); if(!avail) { DBTRACEx(0,"!OUTPUT BUFFER OVERFLOW, hVM", hVM); vm->overrun=true; break; } ch=_clientAL; RingBufWrite(&vm->out,&ch,1); vm->overrun=false; #endif break; } return(FALSE); }
void sbbs_t::telnet_gate(char* destaddr, ulong mode, char* client_user_name, char* server_user_name, char* term_type) { char* p; uchar buf[512]; int i; int rd; uint attempts; ulong l; bool gotline; ushort port; ulong ip_addr; ulong save_console; SOCKET remote_socket; SOCKADDR_IN addr; if(mode&TG_RLOGIN) port=513; else port=IPPORT_TELNET; p=strchr(destaddr,':'); if(p!=NULL) { *p=0; port=atoi(p+1); } ip_addr=resolve_ip(destaddr); if(ip_addr==INADDR_NONE) { lprintf(LOG_NOTICE,"!TELGATE Failed to resolve address: %s",destaddr); bprintf("!Failed to resolve address: %s\r\n",destaddr); return; } if((remote_socket = open_socket(SOCK_STREAM, client.protocol)) == INVALID_SOCKET) { errormsg(WHERE,ERR_OPEN,"socket",0); return; } memset(&addr,0,sizeof(addr)); addr.sin_addr.s_addr = htonl(startup->telnet_interface); addr.sin_family = AF_INET; if((i=bind(remote_socket, (struct sockaddr *) &addr, sizeof (addr)))!=0) { lprintf(LOG_NOTICE,"!TELGATE ERROR %d (%d) binding to socket %d",i, ERROR_VALUE, remote_socket); bprintf("!ERROR %d (%d) binding to socket\r\n",i, ERROR_VALUE); close_socket(remote_socket); return; } memset(&addr,0,sizeof(addr)); addr.sin_addr.s_addr = ip_addr; addr.sin_family = AF_INET; addr.sin_port = htons(port); if((i=connect(remote_socket, (struct sockaddr *)&addr, sizeof(addr)))!=0) { lprintf(LOG_NOTICE,"!TELGATE ERROR %d (%d) connecting to server: %s" ,i,ERROR_VALUE, destaddr); bprintf("!ERROR %d (%d) connecting to server: %s\r\n" ,i,ERROR_VALUE, destaddr); close_socket(remote_socket); return; } l=1; if((i = ioctlsocket(remote_socket, FIONBIO, &l))!=0) { lprintf(LOG_NOTICE,"!TELGATE ERROR %d (%d) disabling socket blocking" ,i, ERROR_VALUE); close_socket(remote_socket); return; } lprintf(LOG_INFO,"Node %d %s gate to %s port %u on socket %d" ,cfg.node_num ,mode&TG_RLOGIN ? "RLogin" : "Telnet" ,destaddr,port,remote_socket); if(!(mode&TG_CTRLKEYS)) console|=CON_RAW_IN; if(mode&TG_RLOGIN) { p=(char*)buf; *(p++)=0; p+=sprintf(p,"%s",client_user_name==NULL ? useron.alias : client_user_name); p++; // Add NULL p+=sprintf(p,"%s",server_user_name==NULL ? useron.name : server_user_name); p++; // Add NULL if(term_type!=NULL) p+=sprintf(p,"%s",term_type); else p+=sprintf(p,"%s/%u",terminal, cur_rate); p++; // Add NULL l=p-(char*)buf; sendsocket(remote_socket,(char*)buf,l); mode|=TG_NOLF; /* Send LF (to remote host) when Telnet client sends CRLF (when not in binary mode) */ } /* This is required for gating to Unix telnetd */ if(mode&TG_NOTERMTYPE) request_telnet_opt(TELNET_DONT,TELNET_TERM_TYPE, 3000); // Re-negotiation of terminal type /* Text/NVT mode by default */ request_telnet_opt(TELNET_DONT,TELNET_BINARY_TX, 3000); if(!(telnet_mode&TELNET_MODE_OFF) && (mode&TG_PASSTHRU)) telnet_mode|=TELNET_MODE_GATE; // Pass-through telnet commands while(online) { if(!(mode&TG_NOCHKTIME)) gettimeleft(); rd=RingBufRead(&inbuf,buf,sizeof(buf)); if(rd) { #if 0 if(memchr(buf,TELNET_IAC,rd)) { char dump[2048]; dump[0]; p=dump; for(int i=0;i<rd;i++) p+=sprintf(p,"%u ",buf[i]); lprintf(LOG_DEBUG,"Node %d Telnet cmd from client: %s", cfg.node_num, dump); } #endif if(telnet_remote_option[TELNET_BINARY_TX]!=TELNET_WILL) { if(*buf==0x1d) { // ^] save_console=console; console&=~CON_RAW_IN; // Allow Ctrl-U/Ctrl-P CRLF; while(online) { SYNC; mnemonics("\1n\r\n\1h\1bTelnet Gate: \1y~D\1wisconnect, " "\1y~E\1wcho toggle, \1y~L\1wist Users, \1y~P\1wrivate message, " "\1y~Q\1wuit: "); switch(getkeys("DELPQ",0)) { case 'D': closesocket(remote_socket); break; case 'E': mode^=TG_ECHO; bprintf(text[EchoIsNow] ,mode&TG_ECHO ? text[ON]:text[OFF]); continue; case 'L': whos_online(true); continue; case 'P': nodemsg(); continue; } break; } attr(LIGHTGRAY); console=save_console; } else if(*buf<' ' && (mode&TG_CTRLKEYS)) handle_ctrlkey(*buf, K_NONE); gotline=false; if((mode&TG_LINEMODE) && buf[0]!='\r') { ungetkey(buf[0]); l=K_CHAT; if(!(mode&TG_ECHO)) l|=K_NOECHO; rd=getstr((char*)buf,sizeof(buf)-1,l); if(!rd) continue; strcat((char*)buf,crlf); rd+=2; gotline=true; } if((mode&TG_CRLF) && buf[rd-1]=='\r') buf[rd++]='\n'; else if((mode&TG_NOLF) && buf[rd-1]=='\n') rd--; if(!gotline && (mode&TG_ECHO) && rd) { RingBufWrite(&outbuf,buf,rd); } } /* Not Telnet Binary mode */ if(rd > 0) { for(attempts=0;attempts<60 && online; attempts++) /* added retry loop here, Jan-20-2003 */ { if((i=sendsocket(remote_socket,(char*)buf,rd))>=0) break; if(ERROR_VALUE!=EWOULDBLOCK) break; mswait(500); } if(i<0) { lprintf(LOG_NOTICE,"!TELGATE ERROR %d sending on socket %d",ERROR_VALUE,remote_socket); break; } } } rd=recv(remote_socket,(char*)buf,sizeof(buf),0); if(rd<0) { if(ERROR_VALUE==EWOULDBLOCK) { if(mode&TG_NODESYNC) { SYNC; } else { // Check if the node has been interrupted getnodedat(cfg.node_num,&thisnode,0); if(thisnode.misc&NODE_INTR) break; } YIELD(); continue; } lprintf(LOG_NOTICE,"!TELGATE ERROR %d receiving on socket %d",ERROR_VALUE,remote_socket); break; } if(!rd) { lprintf(LOG_INFO,"Node %d Telnet gate disconnected",cfg.node_num); break; } #if 0 if(memchr(buf,TELNET_IAC,rd)) { char dump[2048]; dump[0]; p=dump; for(int i=0;i<rd;i++) p+=sprintf(p,"%u ",buf[i]); lprintf(LOG_DEBUG,"Node %d Telnet cmd from server: %s", cfg.node_num, dump); } #endif RingBufWrite(&outbuf,buf,rd); } console&=~CON_RAW_IN; telnet_mode&=~TELNET_MODE_GATE; /* Disable Telnet Terminal Echo */ request_telnet_opt(TELNET_WILL,TELNET_ECHO); close_socket(remote_socket); lprintf(LOG_INFO,"Node %d Telnet gate to %s finished",cfg.node_num,destaddr); }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - BOOL SBBSExecInt21::handler(VMHANDLE hVM, CLIENT_STRUCT* pRegs, DWORD intno) { BYTE ch; BYTE* buffer; WORD buflen; vm_t* vm = find_vm(hVM); if(vm==NULL || !(vm->mode&SBBSEXEC_MODE_DOS_OUT)) { #if 0 if(vm && !(vm->mode&SBBSEXEC_MODE_DOS_OUT)) { DBTRACEx(0,"Int21 on unsupported VM", hVM); } #endif return(FALSE); // Tells VMM that interrupt was not handled } DBTRACEx(1,"Int21 function", _clientAH); DWORD avail = RingBufFree(&vm->out); switch(_clientAH) { case 0x01: DBTRACE(0,"!Int21 Char input WITH echo"); break; case 0x06: // Direct console I/O DBTRACEx(0,"DOS DIRECT CONSOLE IO, DL", _clientDL); if(_clientDL==0xff) { avail=RingBufFull(&vm->in); if(avail) { DBTRACEd(0,"avail",avail); RingBufRead(&vm->in, &ch, 1); _clientFlags&=~(1<<6); // clear zero flag _clientAX=ch; return(TRUE); } break; } // fall-through case 0x02: // Character output DBTRACEx(1,"Int21 function", _clientAH); if(!avail) { DBTRACEx(0,"!OUTPUT BUFFER OVERFLOW, hVM", hVM); vm->overrun=true; break; } ch=_clientDL; RingBufWrite(&vm->out,&ch,1); vm->overrun=false; break; case 0x09: // Display string DBTRACE(0,"!Int21 func 09 - DISPLAY STRING"); break; case 0x0A: // Buffered keyboard input DBTRACE(0,"Int21 Func 0A - Buffered Keyboard Input"); /* Need to get a string from the user, echo, and copy to DS:DX */ /* byte 0 = max length, byte 1 = actual read (minus CR) */ break; case 0x40: // Write file or device if(_clientBX!=1 && _clientBX!=2) { // !stdout and !stderr DBTRACEd(1,"!Int21 write to unsupported device", _clientBX); break; } DBTRACEdd(1,"Int21 write file", _clientBX, _clientCX); buffer = (BYTE*)MAPFLAT(CRS.Client_DS, CWRS.Client_DX); buflen = _clientCX; if(avail<buflen) { DBTRACEd(0,"!OUTPUT BUFFER OVERFLOW, avail", avail); vm->overrun=true; if(!avail) break; buflen=avail; } RingBufWrite(&vm->out,buffer,buflen); vm->overrun=false; break; } return(FALSE); // Tells VMM that interrupt was not handled }
BOOL SBBSExecInt14::handler(VMHANDLE hVM, CLIENT_STRUCT* pRegs, DWORD intno) { BYTE* buffer; BYTE ch; WORD buflen; WORD rd,wr; WORD avail; vm_t* vm = find_vm(hVM); if(vm==NULL || vm->mode!=SBBSEXEC_MODE_FOSSIL) { return(FALSE); // Tells VMM that interrupt was not handled } DBTRACEx(4,"Int14 func",_clientAH); switch(_clientAH) { case 0x00: /* Initialize/Set baud rate */ DBTRACE(0,"Int14 init"); _clientAX=PortStatus(vm); break; case 0x01: /* write char to com port */ if(RingBufFree(&vm->out)<2) { DBTRACEx(1,"!OUTPUT BUFFER OVERFLOW, hVM", hVM); vm->output_sem=Create_Semaphore(0); Wait_Semaphore(vm->output_sem,BLOCK_THREAD_IDLE); Destroy_Semaphore(vm->output_sem); vm->output_sem=NULL; if(!vm->online) { DBTRACE(0,"!USER HUNG UP"); return(true); } } ch=_clientAL; RingBufWrite(&vm->out,&ch,1); #if 0 /* Now done in SBBS.DLL/XTRN.CPP */ if(ch==0xff) { /* escape TELNET IAC */ RingBufWrite(&vm->out,&ch,1); DBTRACE(1,"Escaped IAC in output stream"); } #endif vm->overrun=false; _clientAX=PortStatus(vm); break; case 0x02: /* read char from com port */ if(!RingBufFull(&vm->in)) { DBTRACEx(0,"Waiting on input semaphore, hVM", hVM); vm->input_sem=Create_Semaphore(0); Wait_Semaphore(vm->input_sem,BLOCK_THREAD_IDLE); Destroy_Semaphore(vm->input_sem); vm->input_sem=NULL; #if 0 _clientAH=0x80; /* timed-out */ return(TRUE); #endif } RingBufRead(&vm->in,&ch,1); _clientAH=0; _clientAL=ch; break; case 0x03: /* request status */ _clientAX=PortStatus(vm); break; case 0x04: /* initialize */ DBTRACE(0,"Int14 func 4 init"); _clientAX=0x1954; /* magic number = success */ _clientBH=5; /* FOSSIL rev */ _clientBL=0x1B; /* maximum FOSSIL func supported */ break; case 0x08: // flush output buffer DBTRACE(0,"Int14 FLUSH OUTPUT BUFFER"); vm->output_sem=Create_Semaphore(0); Wait_Semaphore(vm->output_sem,BLOCK_THREAD_IDLE); Destroy_Semaphore(vm->output_sem); vm->output_sem=NULL; break; case 0x09: // purge output buffer DBTRACE(0,"Int14 PURGE OUTPUT BUFFER"); RingBufReInit(&vm->out); break; case 0x0A: // purge input buffer DBTRACE(0,"Int14 PURGE INPUT BUFFER"); RingBufReInit(&vm->in); break; case 0x0B: /* write char to com port, no wait */ if(RingBufFree(&vm->out)<2) { _clientAX=0; // char was not accepted break; } ch=_clientAL; RingBufWrite(&vm->out,&ch,1); #if 0 /* Now done in SBBS.DLL/XTRN.CPP */ if(ch==0xff) { /* escape TELNET IAC */ RingBufWrite(&vm->out,&ch,1); DBTRACE(1,"Escaped IAC in output stream"); } #endif _clientAX=1; // char was accepted break; case 0x0C: // non-destructive read-ahead if(!RingBufFull(&vm->in)) { _clientAX=0xffff; // no char available break; } RingBufPeek(&vm->in,&ch,1); _clientAH=0; _clientAL=ch; break; case 0x13: /* write to display */ dprintf("%c",_clientAL); break; case 0x18: /* read bock */ rd=_clientCX; avail=RingBufFull(&vm->in); if(rd>avail) rd=avail; if(rd) { buffer = (BYTE*)MAPFLAT(CRS.Client_ES, CWRS.Client_DI); rd = RingBufRead(&vm->in, buffer, rd); } _clientAX = rd; break; case 0x19: /* write block */ wr=_clientCX; avail=RingBufFree(&vm->out); if(wr>avail) wr=avail; if(wr) { buffer = (BYTE*)MAPFLAT(CRS.Client_ES, CWRS.Client_DI); wr = RingBufWrite(&vm->out, buffer, wr); } _clientAX = wr; break; #if 1 case 0x1B: // driver info { DBTRACE(1,"Int14 driver info"); struct { WORD info_size; BYTE curr_fossil; BYTE curr_rev; DWORD id_string; WORD inbuf_size; WORD inbuf_free; WORD outbuf_size; WORD outbuf_free; BYTE screen_width; BYTE screen_height; BYTE baud_rate; } info={ sizeof(info), 5, 1, 0 ,RINGBUF_SIZE_IN-1, RingBufFree(&vm->in) ,RINGBUF_SIZE_OUT-1, RingBufFree(&vm->out) ,80,25 ,1 // 38400 }; // Map_Lin_To_VM_Addr buffer = (BYTE*)MAPFLAT(CRS.Client_ES, CWRS.Client_DI); wr=sizeof(info); if(wr>_clientCX) wr=_clientCX; memcpy(buffer, &info, wr); _clientAX=wr; break; } #endif default: DBTRACEx(0,"!UNHANDLED INTERRUPT 14h function",_clientAH); break; } return(TRUE); // Tells VMM that interrupt was handled }
bool sbbs_t::spy(uint i /* node_num */) { char ch; char ansi_seq[32]; int ansi_len; int in; if(!i || i>MAX_NODES) { bprintf("Invalid node number: %d\r\n",i); return(false); } if(i==cfg.node_num) { bprintf("Can't spy on yourself.\r\n"); return(false); } if(spy_socket[i-1]!=INVALID_SOCKET) { bprintf("Node %d already being spied (%lx)\r\n",i,spy_socket[i-1]); return(false); } bprintf("*** Synchronet Remote Spy on Node %d: Ctrl-C to Abort ***" "\r\n\r\n",i); spy_socket[i-1]=client_socket; ansi_len=0; while(online && client_socket!=INVALID_SOCKET && spy_socket[i-1]!=INVALID_SOCKET && !msgabort()) { in=incom(1000); if(in==NOINP) { gettimeleft(); continue; } ch=in; if(ch==ESC) { if(!ansi_len) { ansi_seq[ansi_len++]=ch; continue; } ansi_len=0; } if(ansi_len && ansi_len<(int)sizeof(ansi_seq)-2) { if(ansi_len==1) { if(ch=='[') { ansi_seq[ansi_len++]=ch; continue; } ansi_len=0; } if(ch=='R') { /* throw-away cursor position report */ ansi_len=0; continue; } ansi_seq[ansi_len++]=ch; if(isalpha(ch)) { RingBufWrite(node_inbuf[i-1],(uchar*)ansi_seq,ansi_len); ansi_len=0; } continue; } if(ch<' ') { lncntr=0; /* defeat pause */ spy_socket[i-1]=INVALID_SOCKET; /* disable spy output */ ch=handle_ctrlkey(ch,K_NONE); spy_socket[i-1]=client_socket; /* enable spy output */ if(ch==0) continue; } if(node_inbuf[i-1]!=NULL) RingBufWrite(node_inbuf[i-1],(uchar*)&ch,1); } spy_socket[i-1]=INVALID_SOCKET; return(true); }
DWORD SBBSExec::OnW32DeviceIoControl(PIOCTLPARAMS pIOCTL) { DWORD rd; DWORD wr; DWORD avail; vm_t* vm; // DBTRACEd(0,"SBBSEXEC ioctl" //,pIOCTL->dioc_IOCtlCode); switch(pIOCTL->dioc_IOCtlCode) { case DIOC_OPEN: DBTRACEd(0,"IOCTL: OPEN",Get_System_Time()); break; case DIOC_CLOSEHANDLE: DBTRACEd(0,"IOCTL: CLOSE",Get_System_Time()); break; case SBBSEXEC_IOCTL_START: DBTRACEd(0,"IOCTL: START",Get_System_Time()); DBTRACEx(0,"Current Thread Handle",Get_Cur_Thread_Handle()); if(start.event) { DBTRACE(0,"Exec already started!"); return(SBBSEXEC_ERROR_INUSE); } if (pIOCTL->dioc_InBuf==NULL || pIOCTL->dioc_cbInBuf!=sizeof(start)) { return(SBBSEXEC_ERROR_INBUF); } start=*(sbbsexec_start_t*)pIOCTL->dioc_InBuf; break; case SBBSEXEC_IOCTL_COMPLETE: DBTRACEd(0,"IOCTL: COMPLETE",Get_System_Time()); if(start.event || new_vm==NULL) { DBTRACE(0,"!VM never created"); start.event=0; return(SBBSEXEC_ERROR_INUSE); } if(pIOCTL->dioc_OutBuf==NULL || pIOCTL->dioc_cbOutBuf<sizeof(VMHANDLE)) { DBTRACE(0,"!Invalid OUTBUF"); return(SBBSEXEC_ERROR_OUTBUF); } *(VMHANDLE*)pIOCTL->dioc_OutBuf=new_vm->handle; DBTRACEx(0,"CREATED VM HANDLE", new_vm->handle); new_vm=NULL; if(pIOCTL->dioc_bytesret!=NULL) *pIOCTL->dioc_bytesret = sizeof(VMHANDLE); break; case SBBSEXEC_IOCTL_READ: if (pIOCTL->dioc_InBuf==NULL || pIOCTL->dioc_cbInBuf!=sizeof(VMHANDLE)) { DBTRACE(0,"!INVALID INBUF"); return(SBBSEXEC_ERROR_INBUF); } if (pIOCTL->dioc_OutBuf==NULL || pIOCTL->dioc_cbOutBuf==0) { DBTRACE(0,"!INVALID OUTBUF"); return(SBBSEXEC_ERROR_OUTBUF); } vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf); if(vm==NULL) { DBTRACE(0,"!NO VM LIST"); return(SBBSEXEC_ERROR_INDATA); } rd = RingBufFull(&vm->out); if(rd>pIOCTL->dioc_cbOutBuf) { DBTRACEdd(0,"Reducing read size" ,rd, pIOCTL->dioc_cbOutBuf); rd=pIOCTL->dioc_cbOutBuf; } RingBufRead(&vm->out, (BYTE*)pIOCTL->dioc_OutBuf, rd); if(pIOCTL->dioc_bytesret!=NULL) *pIOCTL->dioc_bytesret = rd; if(vm->output_sem!=NULL) // Wake up int14 handler Signal_Semaphore(vm->output_sem); if(rd>1) { DBTRACEd(1,"IOCTL_READ bytes", rd); } break; case SBBSEXEC_IOCTL_WRITE: if (pIOCTL->dioc_InBuf==NULL || pIOCTL->dioc_cbInBuf<sizeof(VMHANDLE)+1) { DBTRACE(0,"!INVALID INBUF"); return(SBBSEXEC_ERROR_INBUF); } if (pIOCTL->dioc_OutBuf==NULL || pIOCTL->dioc_cbOutBuf!=sizeof(DWORD)) { DBTRACE(0,"!INVALID OUTBUF"); return(SBBSEXEC_ERROR_OUTBUF); } vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf); if(vm==NULL) { DBTRACE(0,"!NO VM LIST"); return(SBBSEXEC_ERROR_INDATA); } wr = pIOCTL->dioc_cbInBuf-sizeof(VMHANDLE); avail = RingBufFree(&vm->in); if(wr>avail) { DBTRACEdd(0,"Reducing write size", wr, avail); wr=avail; } RingBufWrite(&vm->in, (BYTE*)pIOCTL->dioc_InBuf+sizeof(VMHANDLE), wr); *(DWORD *)pIOCTL->dioc_OutBuf = wr; if(pIOCTL->dioc_bytesret!=NULL) *pIOCTL->dioc_bytesret = sizeof(DWORD); if(vm->input_sem!=NULL) // Wake up int14 handler Signal_Semaphore(vm->input_sem); // Wake up the VDM (improves keyboard response - dramatically!) Wake_Up_VM(vm->handle); break; case SBBSEXEC_IOCTL_DISCONNECT: DBTRACEd(0,"IOCTL: DISCONNECT",Get_System_Time()); if (pIOCTL->dioc_InBuf==NULL || pIOCTL->dioc_cbInBuf!=sizeof(VMHANDLE)) { DBTRACE(0,"!INVALID INBUF"); return(SBBSEXEC_ERROR_INBUF); } vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf); if(vm==NULL) { DBTRACE(0,"!NO VM LIST"); return(SBBSEXEC_ERROR_INDATA); } vm->online=false; if(vm->input_sem!=NULL) // Wake up int14 handler Signal_Semaphore(vm->input_sem); if(vm->output_sem!=NULL) // Wake up int14 handler Signal_Semaphore(vm->output_sem); break; case SBBSEXEC_IOCTL_STOP: DBTRACEd(0,"IOCTL: STOP",Get_System_Time()); if (pIOCTL->dioc_InBuf==NULL || pIOCTL->dioc_cbInBuf!=sizeof(VMHANDLE)) { DBTRACE(0,"!INVALID INBUF"); return(SBBSEXEC_ERROR_INBUF); } vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf); if(vm==NULL) { DBTRACE(0,"!NO VM LIST"); return(SBBSEXEC_ERROR_INDATA); } DBTRACEx(0,"CLOSING VM HANDLE", vm->handle); vm->handle=NULL; // Mark as available RingBufDispose(&vm->in); RingBufDispose(&vm->out); if(vm->input_sem!=NULL) // Wake up int14 handler Signal_Semaphore(vm->input_sem); if(vm->output_sem!=NULL) // Wake up int14 handler Signal_Semaphore(vm->output_sem); vm->input_sem=NULL; vm->output_sem=NULL; break; default: DBTRACEdx(0,"!UNKNOWN IOCTL" ,pIOCTL->dioc_IOCtlCode,pIOCTL->dioc_IOCtlCode); return(SBBSEXEC_ERROR_IOCTL); } return (0); // DEVIOCTL_NOERROR); }
void __fastcall TSpyForm::FormKeyPress(TObject *Sender, char &Key) { if(KeyboardActive->Checked && inbuf!=NULL && *inbuf!=NULL) RingBufWrite(*inbuf,&Key,1); }