diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 69339d54..b3de0567 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -768,6 +768,9 @@ void DOSBOX_Init(void) { Pstring = Pmulti_remain->GetSection()->Add_string("parameters",Property::Changeable::WhenIdle,""); Pmulti_remain->Set_help("see serial1"); + Pstring = secprop->Add_path("phonebookfile", Property::Changeable::OnlyAtStart, "phonebook-" VERSION ".txt"); + Pstring->Set_help("File used to map fake phone numbers to addresses."); + /* All the DOS Related stuff, which will eventually start up in the shell */ secprop=control->AddSection_prop("dos",&DOS_Init,false);//done diff --git a/src/hardware/serialport/serialport.cpp b/src/hardware/serialport/serialport.cpp index 977f8704..5d7df467 100644 --- a/src/hardware/serialport/serialport.cpp +++ b/src/hardware/serialport/serialport.cpp @@ -1214,8 +1214,7 @@ bool CSerial::Putchar(Bit8u data, bool wait_dsr, bool wait_cts, Bitu timeout) { #if SERIAL_DEBUG log_ser(dbg_aux,"Putchar 0x%x",data); -#endif - +#endif return true; } @@ -1225,6 +1224,11 @@ public: Bit16u biosParameter[4] = { 0, 0, 0, 0 }; Section_prop *section = static_cast (configuration); +#if C_MODEM + const Prop_path *pbFilename = section->Get_path("phonebookfile"); + MODEM_ReadPhonebook(pbFilename->realpath); +#endif + char s_property[] = "serialx"; for(Bitu i = 0; i < 4; i++) { // get the configuration property diff --git a/src/hardware/serialport/softmodem.cpp b/src/hardware/serialport/softmodem.cpp index 665c99bf..8ed4262e 100644 --- a/src/hardware/serialport/softmodem.cpp +++ b/src/hardware/serialport/softmodem.cpp @@ -23,12 +23,85 @@ #include #include #include +#include +#include #include "support.h" #include "serialport.h" #include "softmodem.h" #include "misc_util.h" +class PhonebookEntry { +public: + PhonebookEntry(const std::string &_phone, const std::string &_address) : + phone(_phone), + address(_address) { + } + + bool IsMatchingPhone(const std::string &input) const { + return (input == phone); + } + + const std::string &GetAddress() const { + return address; + } + +private: + std::string phone; + std::string address; +}; + +static std::vector phones; +static const char phoneValidChars[] = "01234567890*=,;#+>"; + +static bool MODEM_IsPhoneValid(const std::string &input) { + size_t found = input.find_first_not_of(phoneValidChars); + if (found != std::string::npos) { + LOG_MSG("SERIAL: Phone %s contains invalid character %c", input.c_str(), input[found]); + return false; + } + + return true; +} + +bool MODEM_ReadPhonebook(const std::string &filename) { + std::ifstream loadfile(filename); + if (!loadfile) + return false; + + LOG_MSG("SERIAL: Loading phonebook from %s", filename.c_str()); + + std::string linein; + while (std::getline(loadfile, linein)) { + std::istringstream iss(linein); + std::string phone, address; + + if (!(iss >> phone >> address)) { + LOG_MSG("SERIAL: Skipped a bad line in %s", filename.c_str()); + continue; + } + + // Check phone number for characters ignored by Hayes modems. + if (!MODEM_IsPhoneValid(phone)) + continue; + + LOG_MSG("SERIAL: Mapped phone %s to address %s", phone.c_str(), address.c_str()); + PhonebookEntry *pbEntry = new PhonebookEntry(phone, address); + phones.push_back(pbEntry); + } + + return true; +} + +static const char *MODEM_GetAddressFromPhone(const char *input) { + for (const auto entry : phones) { + if (entry->IsMatchingPhone(input)) + return entry->GetAddress().c_str(); + } + + return nullptr; +} + CSerialModem::CSerialModem(Bitu id, CommandLine* cmd) : CSerial(id, cmd), rqueue(new CFifo(MODEM_BUFFER_QUEUE_SIZE)), @@ -187,21 +260,26 @@ void CSerialModem::SendRes(const ResTypes response) { } } -bool CSerialModem::Dial(char * host) { +bool CSerialModem::Dial(const char * host) { + char buf[128] = ""; + safe_strcpy(buf, host); + + const char *destination = buf; // Scan host for port Bit16u port; - char * hasport = strrchr(host,':'); + char * hasport = strrchr(buf,':'); if (hasport) { *hasport++ = 0; port = (Bit16u)atoi(hasport); } - else + else { port = MODEM_DEFAULT_PORT; + } // Resolve host we're gonna dial - LOG_MSG("Connecting to host %s port %u", host, port); - clientsocket.reset(new TCPClientSocket(host, port)); + LOG_MSG("Connecting to host %s port %u", destination, port); + clientsocket.reset(new TCPClientSocket(destination, port)); if (!clientsocket->isopen) { clientsocket.reset(nullptr); LOG_MSG("Failed to connect."); @@ -381,6 +459,12 @@ void CSerialModem::DoCommand() { helper--; } + const char *mappedaddr = MODEM_GetAddressFromPhone(foundstr); + if (mappedaddr) { + Dial(mappedaddr); + return; + } + //Large enough scope, so the buffers are still valid when reaching Dail. char buffer[128]; char obuffer[128]; diff --git a/src/hardware/serialport/softmodem.h b/src/hardware/serialport/softmodem.h index 8741b05f..6a73cf77 100644 --- a/src/hardware/serialport/softmodem.h +++ b/src/hardware/serialport/softmodem.h @@ -57,6 +57,8 @@ enum ResTypes { #define TEL_CLIENT 0 #define TEL_SERVER 1 +bool MODEM_ReadPhonebook(const std::string &filename); + class CFifo { public: CFifo(Bitu _size) @@ -181,9 +183,7 @@ public: void EnterIdleState(); void EnterConnectedState(); - - void openConnection(void); - bool Dial(char * host); + bool Dial(const char *host); void AcceptIncomingCall(void); Bitu ScanNumber(char * & scan) const; char GetChar(char * & scan) const;