Commit 0eb0f451 authored by Rob Swindell's avatar Rob Swindell 💬
Browse files

Implement svdm.ini file support to store settings and modem NVRAM

e.g. AT&W writes the current settings to the [modem] section.
parent ce285b1f
Pipeline #3034 failed with stage
in 9 minutes and 47 seconds
...@@ -29,9 +29,11 @@ ...@@ -29,9 +29,11 @@
#include <process.h> #include <process.h>
#include "genwrap.h" #include "genwrap.h"
#include "dirwrap.h"
#include "gen_defs.h" #include "gen_defs.h"
#include "sockwrap.h" #include "sockwrap.h"
#include "telnet.h" #include "telnet.h"
#include "ini_file.h"
#define TITLE "Synchronet Virtual DOS Modem for Windows" #define TITLE "Synchronet Virtual DOS Modem for Windows"
#define VERSION "0.0" #define VERSION "0.0"
...@@ -43,11 +45,14 @@ HANDLE hungup_event = INVALID_HANDLE_VALUE; // e.g. ATH0 ...@@ -43,11 +45,14 @@ HANDLE hungup_event = INVALID_HANDLE_VALUE; // e.g. ATH0
HANDLE carrier_event = INVALID_HANDLE_VALUE; HANDLE carrier_event = INVALID_HANDLE_VALUE;
HANDLE rdslot = INVALID_HANDLE_VALUE; HANDLE rdslot = INVALID_HANDLE_VALUE;
HANDLE wrslot = INVALID_HANDLE_VALUE; HANDLE wrslot = INVALID_HANDLE_VALUE;
str_list_t ini;
char ini_fname[MAX_PATH + 1];
union xp_sockaddr listening_interface; union xp_sockaddr listening_interface;
enum { enum {
RAW RAW
,TELNET ,TELNET
} mode; } mode;
char* modeNames[] = {"raw", "telnet", NULL};
struct { struct {
uint8_t local_option[0x100]; uint8_t local_option[0x100];
uint8_t remote_option[0x100]; uint8_t remote_option[0x100];
...@@ -65,12 +70,14 @@ struct { ...@@ -65,12 +70,14 @@ struct {
bool debug; bool debug;
bool terminate_on_disconnect; bool terminate_on_disconnect;
ulong data_rate; ulong data_rate;
bool server_echo;
enum { enum {
ADDRESS_FAMILY_UNSPEC ADDRESS_FAMILY_UNSPEC
,ADDRESS_FAMILY_INET ,ADDRESS_FAMILY_INET
,ADDRESS_FAMILY_INET6 ,ADDRESS_FAMILY_INET6
} address_family; } address_family;
} cfg; } cfg;
char* addrFamilyNames[] = {"unspec", "ipv4", "ipv6", NULL};
static void dprintf(const char *fmt, ...) static void dprintf(const char *fmt, ...)
{ {
...@@ -93,6 +100,7 @@ void usage(void) ...@@ -93,6 +100,7 @@ void usage(void)
const char* supported_cmds = "ADEHIMOQSVXZ&"; const char* supported_cmds = "ADEHIMOQSVXZ&";
const char* string_cmds = "D"; const char* string_cmds = "D";
#define MAX_SAVES 20
struct modem { struct modem {
enum { enum {
INIT INIT
...@@ -103,6 +111,8 @@ struct modem { ...@@ -103,6 +111,8 @@ struct modem {
char lf; char lf;
char bs; char bs;
char esc; char esc;
char save[MAX_SAVES][INI_MAX_VALUE_LEN];
char last[INI_MAX_VALUE_LEN];
bool echo_off; bool echo_off;
bool numeric_mode; bool numeric_mode;
bool offhook; bool offhook;
...@@ -125,18 +135,6 @@ void newcmd(struct modem* modem) ...@@ -125,18 +135,6 @@ void newcmd(struct modem* modem)
modem->buflen = 0; modem->buflen = 0;
} }
void init(struct modem* modem)
{
memset(modem, 0, sizeof(*modem));
modem->cr = '\r';
modem->lf = '\n';
modem->bs = '\b';
modem->esc = '+';
modem->ext_results = 4;
modem->dial_wait = 60;
modem->guard_time = 50;
}
ulong guard_time(struct modem* modem) ulong guard_time(struct modem* modem)
{ {
return modem->guard_time * 20; return modem->guard_time * 20;
...@@ -251,6 +249,58 @@ bool kbhit() ...@@ -251,6 +249,58 @@ bool kbhit()
return waiting != 0; return waiting != 0;
} }
void init(struct modem* modem)
{
const char* section = "modem";
memset(modem, 0, sizeof(*modem));
modem->auto_answer = iniGetBool(ini, section, "auto_answer", FALSE);
modem->echo_off = !iniGetBool(ini, section, "echo", TRUE);
modem->quiet = iniGetBool(ini, section, "quiet", FALSE);
modem->numeric_mode = iniGetBool(ini, section, "numeric", FALSE);
modem->cr = (char)iniGetInteger(ini, section, "cr", '\r');
modem->lf = (char)iniGetInteger(ini, section, "lf", '\n');
modem->bs = (char)iniGetInteger(ini, section, "bs", '\b');
modem->esc = (char)iniGetInteger(ini, section, "esc", '+');
modem->ext_results = iniGetInteger(ini, section, "ext_results", 4);
modem->dial_wait = iniGetInteger(ini, section, "dial_wait", 60);
modem->guard_time = iniGetInteger(ini, section, "guard_time", 50);
}
bool write_cfg(struct modem* modem)
{
dprintf(__FUNCTION__);
const char* section = "modem";
iniSetBool(&ini, section, "auto_answer", modem->auto_answer, /* style: */NULL);
bool result = false;
FILE* fp = iniOpenFile(ini_fname, /* create: */TRUE);
if(fp != NULL) {
if(iniWriteFile(fp, ini)) {
dprintf("Wrote config to: %s", ini_fname);
result = true;
}
iniCloseFile(fp);
}
return result;
}
bool write_save(struct modem* modem, ulong savnum)
{
char key[128];
str_list_t ini;
if(savnum >= MAX_SAVES)
return false;
SAFEPRINTF(key, "save%lu", savnum);
FILE* fp = iniOpenFile(ini_fname, /* create: */TRUE);
if(fp == NULL)
return false;
ini = iniReadFile(fp);
iniSetString(&ini, "modem", key, modem->save[savnum], /* style: */NULL);
bool result = iniWriteFile(fp, ini);
iniCloseFile(fp);
return result;
}
const char* protocol(enum mode mode) const char* protocol(enum mode mode)
{ {
switch(mode) { switch(mode) {
...@@ -431,16 +481,22 @@ char* dial(struct modem* modem, const char* number) ...@@ -431,16 +481,22 @@ char* dial(struct modem* modem, const char* number)
{ {
struct addrinfo hints; struct addrinfo hints;
struct addrinfo *res=NULL; struct addrinfo *res=NULL;
static char last[256];
char host[128]; char host[128];
char portnum[16]; char portnum[16];
uint16_t port = cfg.port; uint16_t port = cfg.port;
dprintf("dial(%s)", number); dprintf("dial(%s)", number);
if(stricmp(number, "L") == 0) if(stricmp(number, "L") == 0)
number = last; number = modem->last;
else else {
SAFECOPY(last, number); if(toupper(*number) == 'S' && IS_DIGIT(number[1])) {
char* p;
ulong val = strtoul(number+1, &p, 10);
if(val < MAX_SAVES && *p == '\0')
number = modem->save[val];
}
SAFECOPY(modem->last, number);
}
if(strncmp(number, "raw:", 4) == 0) { if(strncmp(number, "raw:", 4) == 0) {
mode = RAW; mode = RAW;
number += 4; number += 4;
...@@ -570,8 +626,10 @@ char* answer(struct modem* modem) ...@@ -570,8 +626,10 @@ char* answer(struct modem* modem)
if(mode == TELNET) { if(mode == TELNET) {
ZERO_VAR(telnet); ZERO_VAR(telnet);
/* Disable Telnet Terminal Echo */ if(cfg.server_echo) {
request_telnet_opt(TELNET_WILL,TELNET_ECHO); /* Disable Telnet Terminal Echo */
request_telnet_opt(TELNET_WILL,TELNET_ECHO);
}
/* Will suppress Go Ahead */ /* Will suppress Go Ahead */
request_telnet_opt(TELNET_WILL,TELNET_SUP_GA); request_telnet_opt(TELNET_WILL,TELNET_SUP_GA);
} }
...@@ -590,9 +648,31 @@ char* atmodem_exec(struct modem* modem) ...@@ -590,9 +648,31 @@ char* atmodem_exec(struct modem* modem)
return error(modem); return error(modem);
if(strchr(string_cmds, ch) == NULL) { if(strchr(string_cmds, ch) == NULL) {
if(ch == '&') { if(ch == '&') {
p++; ch = toupper(*p);
ch = toupper(*p); // unused ulong val = strtoul(p + 1, &p, 10); // unused
ulong val = strtoul(p, &p, 10); // unused switch(ch) {
case 'W':
resp = write_cfg(modem) ? ok(modem) : error(modem);
break;
case 'Z':
if(val >= MAX_SAVES)
return error(modem);
if(*p == '=') {
p++;
if(strcmp(p, "L") == 0)
p = modem->last;
SAFECOPY(modem->save[val], p);
return write_save(modem, val) ? ok(modem) : error(modem);
}
if(*p == '?' || strcmp(p, "L?") == 0) {
if(strcmp(p, "L?") == 0)
p = modem->last;
else
p = modem->save[val];
sprintf(respbuf, "%c%s%c%c%s", modem->lf, p, modem->cr, modem->lf, ok(modem));
return respbuf;
}
}
continue; continue;
} }
// Numeric argument commands // Numeric argument commands
...@@ -636,8 +716,10 @@ char* atmodem_exec(struct modem* modem) ...@@ -636,8 +716,10 @@ char* atmodem_exec(struct modem* modem)
dprintf("S%lu = %lu", sreg, val); dprintf("S%lu = %lu", sreg, val);
switch(sreg) { switch(sreg) {
case 0: case 0:
if(val && listening_sock == INVALID_SOCKET) if(val && listening_sock == INVALID_SOCKET) {
dprintf("Can't enable auto-answer when not in listening mode");
return error(modem); return error(modem);
}
modem->auto_answer = val; modem->auto_answer = val;
break; break;
case 1: case 1:
...@@ -707,8 +789,10 @@ char* atmodem_exec(struct modem* modem) ...@@ -707,8 +789,10 @@ char* atmodem_exec(struct modem* modem)
} else { // string argument commands } else { // string argument commands
switch(ch) { switch(ch) {
case 'D': case 'D':
if(sock != INVALID_SOCKET) if(sock != INVALID_SOCKET) {
dprintf("Can't dial: Already connected");
return error(modem); return error(modem);
}
if(*p == 'T' /* tone */|| *p == 'P' /* pulse */) if(*p == 'T' /* tone */|| *p == 'P' /* pulse */)
p++; p++;
return dial(modem, p); return dial(modem, p);
...@@ -837,7 +921,31 @@ int main(int argc, char** argv) ...@@ -837,7 +921,31 @@ int main(int argc, char** argv)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// Default configuration values
cfg.server_echo = TRUE;
cfg.port = IPPORT_TELNET; cfg.port = IPPORT_TELNET;
cfg.address_family = ADDRESS_FAMILY_INET;
ini = strListInit();
SAFECOPY(ini_fname, argv[0]);
char* ext = getfext(ini_fname);
if(ext != NULL)
*ext = 0;
SAFECAT(ini_fname, ".ini");
fprintf(stderr, "ini_fname = '%s'\n", ini_fname);
FILE* fp = iniOpenFile(ini_fname, /* create: */false);
if(fp != NULL) {
ini = iniReadFile(fp);
iniCloseFile(fp);
mode = iniGetEnum(ini, ROOT_SECTION, "mode", modeNames, mode);
cfg.port = iniGetShortInt(ini, ROOT_SECTION, "port", cfg.port);
cfg.node_num = iniGetInteger(ini, ROOT_SECTION, "node", cfg.node_num);
cfg.listen = iniGetBool(ini, ROOT_SECTION, "listen", cfg.listen);
cfg.debug = iniGetBool(ini, ROOT_SECTION, "debug", cfg.debug);
cfg.server_echo = iniGetBool(ini, ROOT_SECTION, "server_echo", cfg.server_echo);
cfg.data_rate = iniGetLongInt(ini, ROOT_SECTION, "rate", cfg.data_rate);
cfg.address_family = iniGetEnum(ini, ROOT_SECTION, "address_family", addrFamilyNames, cfg.address_family);
}
for(; argn < argc; argn++) { for(; argn < argc; argn++) {
char* arg = argv[argn]; char* arg = argv[argn];
...@@ -931,7 +1039,7 @@ int main(int argc, char** argv) ...@@ -931,7 +1039,7 @@ int main(int argc, char** argv)
} }
const char* dropfile = "dosxtrn.env"; const char* dropfile = "dosxtrn.env";
FILE* fp = fopen(dropfile, "w"); fp = fopen(dropfile, "w");
if(fp == NULL) { if(fp == NULL) {
perror(dropfile); perror(dropfile);
return EXIT_FAILURE; return EXIT_FAILURE;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment