Commits (1)
  • Rob Swindell's avatar
    Add "Disable Local Display" option for doors, parse DOSXTRN.ERR · dc0d401d
    Rob Swindell authored
    New option to disable local screen display for door programs: sets the 'Screen' value appropriately in door.sys or pcboard.sys drop files and on Windows, doesn't create a new console window.
    
    Also, now parsing the DOSXTRN.ERR file created by the latest/greatest dosxtrn.exe when failing to execute the child/DOS program and log the parsed error details (errno value and description), helpful in debugging the reason why a DOS program may not have been successfully executed by DOSXTRN.
    dc0d401d
......@@ -399,6 +399,7 @@ typedef enum { /* Values for xtrn_t.event */
#define XTRN_TEMP_DIR (1<<24) /* Place drop files in temp dir */
#define XTRN_UART (1<<25) /* Enable the virtual UART driver */
#define XTRN_FOSSIL (1<<26) /* Enable the int14h/FOSSIL driver */
#define XTRN_NODISPLAY (1<<27) /* Disable local screen/display */
#define XTRN_CONIO (1<<31) /* Intercept Windows Console I/O (Drwy) */
/* Bits in user.qwk */
......@@ -815,6 +816,7 @@ enum { /* readmail and delmailidx which types */
#define EX_STDIO (EX_STDIN|EX_STDOUT)
#define EX_UART XTRN_UART
#define EX_FOSSIL XTRN_FOSSIL
#define EX_NODISPLAY XTRN_NODISPLAY
#define EX_NOLOG (1<<30) /* Don't log intercepted stdio */
#define EX_CONIO (1<<31) /* Intercept Windows console I/O (doorway) */
#define EX_UNSPECIFIED -1
......
......@@ -1220,6 +1220,8 @@ void xtrn_cfg(uint section)
sprintf(opt[k++],"%-27.27s%s","Execute on Event",str);
sprintf(opt[k++],"%-27.27s%s","Pause After Execution"
,cfg.xtrn[i]->misc&XTRN_PAUSE ? "Yes" : "No");
sprintf(opt[k++],"%-27.27s%s","Disable Local Display"
,cfg.xtrn[i]->misc&XTRN_NODISPLAY ? "Yes" : "No");
sprintf(opt[k++],"%-23.23s%-4s%s","BBS Drop File Type"
,cfg.xtrn[i]->misc&REALNAME ? "(R)":nulstr
,dropfile(cfg.xtrn[i]->type,cfg.xtrn[i]->misc));
......@@ -1255,7 +1257,7 @@ void xtrn_cfg(uint section)
case -CIO_KEY_RIGHT-2:
i = next;
break;
case 0:
case __COUNTER__:
uifc.helpbuf=
"`Online Program Name:`\n"
"\n"
......@@ -1266,7 +1268,7 @@ void xtrn_cfg(uint section)
,cfg.xtrn[i]->name,sizeof(cfg.xtrn[i]->name)-1,K_EDIT))
SAFECOPY(cfg.xtrn[i]->name,str);
break;
case 1:
case __COUNTER__:
uifc.helpbuf=
"`Online Program Internal Code:`\n"
"\n"
......@@ -1285,7 +1287,7 @@ void xtrn_cfg(uint section)
uifc.helpbuf=0;
}
break;
case 2:
case __COUNTER__:
uifc.helpbuf=
"`Online Program Start-up Directory:`\n"
"\n"
......@@ -1298,7 +1300,7 @@ void xtrn_cfg(uint section)
uifc.input(WIN_MID|WIN_SAV,0,10,""
,cfg.xtrn[i]->path,sizeof(cfg.xtrn[i]->path)-1,K_EDIT);
break;
case 3:
case __COUNTER__:
uifc.helpbuf=
"`Online Program Command Line:`\n"
"\n"
......@@ -1309,7 +1311,7 @@ void xtrn_cfg(uint section)
uifc.input(WIN_MID|WIN_SAV,0,10,"Command"
,cfg.xtrn[i]->cmd,sizeof(cfg.xtrn[i]->cmd)-1,K_EDIT);
break;
case 4:
case __COUNTER__:
uifc.helpbuf=
"`Online Program Clean-up Command:`\n"
"\n"
......@@ -1321,7 +1323,7 @@ void xtrn_cfg(uint section)
uifc.input(WIN_MID|WIN_SAV,0,10,"Clean-up"
,cfg.xtrn[i]->clean,sizeof(cfg.xtrn[i]->clean)-1,K_EDIT);
break;
case 5:
case __COUNTER__:
ultoa(cfg.xtrn[i]->cost,str,10);
uifc.helpbuf=
"`Online Program Cost to Run:`\n"
......@@ -1334,15 +1336,15 @@ void xtrn_cfg(uint section)
,str,10,K_EDIT|K_NUMBER);
cfg.xtrn[i]->cost=atol(str);
break;
case 6:
case __COUNTER__:
sprintf(str,"%s Access",cfg.xtrn[i]->name);
getar(str,cfg.xtrn[i]->arstr);
break;
case 7:
case __COUNTER__:
sprintf(str,"%s Execution",cfg.xtrn[i]->name);
getar(str,cfg.xtrn[i]->run_arstr);
break;
case 8:
case __COUNTER__:
k=(cfg.xtrn[i]->misc&MULTIUSER) ? 0:1;
uifc.helpbuf=
"`Supports Multiple Users:`\n"
......@@ -1361,10 +1363,10 @@ void xtrn_cfg(uint section)
uifc.changes=TRUE;
}
break;
case 9:
case __COUNTER__:
choose_io_method(&cfg.xtrn[i]->misc);
break;
case 10:
case __COUNTER__:
k=(cfg.xtrn[i]->misc&XTRN_NATIVE) ? 0:1;
uifc.helpbuf=native_help;
k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
......@@ -1378,7 +1380,7 @@ void xtrn_cfg(uint section)
uifc.changes=TRUE;
}
break;
case 11:
case __COUNTER__:
k=(cfg.xtrn[i]->misc&XTRN_SH) ? 0:1;
uifc.helpbuf = use_shell_help;
k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
......@@ -1392,7 +1394,7 @@ void xtrn_cfg(uint section)
uifc.changes=TRUE;
}
break;
case 12:
case __COUNTER__:
k=(cfg.xtrn[i]->misc&MODUSERDAT) ? 0:1;
uifc.helpbuf=
"`Program Can Modify User Data:`\n"
......@@ -1412,7 +1414,7 @@ void xtrn_cfg(uint section)
uifc.changes=TRUE;
}
break;
case 13:
case __COUNTER__:
k=0;
strcpy(opt[k++],"No");
strcpy(opt[k++],"Logon");
......@@ -1466,7 +1468,7 @@ void xtrn_cfg(uint section)
uifc.changes=TRUE;
}
break;
case 14:
case __COUNTER__:
k=(cfg.xtrn[i]->misc&XTRN_PAUSE) ? 0:1;
uifc.helpbuf=
"`Pause Screen After Execution:`\n"
......@@ -1486,7 +1488,27 @@ void xtrn_cfg(uint section)
uifc.changes=TRUE;
}
break;
case 15:
case __COUNTER__:
k=(cfg.xtrn[i]->misc&XTRN_NODISPLAY) ? 0:1;
uifc.helpbuf=
"`Disable Local Screen Display:`\n"
"\n"
"Set this option to `Yes` if you wish to prevent this program from\n"
"displaying on the local screen.\n"
"\n"
"This will disable 'Screen' output in the `DOOR.SYS` and `PCBOARD.SYS` drop\n"
"files and on Windows, stop the creation a new console window when\n"
"executing this program."
;
k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
,"Disable Local Screen Display", uifcYesNoOpts);
if((!k && !(cfg.xtrn[i]->misc & XTRN_NODISPLAY))
|| (k && (cfg.xtrn[i]->misc & XTRN_NODISPLAY))) {
cfg.xtrn[i]->misc ^= XTRN_NODISPLAY;
uifc.changes=TRUE;
}
break;
case __COUNTER__:
k=0;
strcpy(opt[k++],"None");
sprintf(opt[k++],"%-15s %s","Synchronet","XTRN.DAT");
......@@ -1561,7 +1583,7 @@ void xtrn_cfg(uint section)
}
}
break;
case 16:
case __COUNTER__:
k = (cfg.xtrn[i]->misc & STARTUPDIR) ? 1 : (cfg.xtrn[i]->misc & XTRN_TEMP_DIR) ? 2 : 0;
strcpy(opt[0],"Node Directory");
strcpy(opt[1],"Start-up Directory");
......@@ -1600,7 +1622,7 @@ void xtrn_cfg(uint section)
uifc.changes=TRUE;
}
break;
case 17:
case __COUNTER__:
while(1) {
k=0;
if(cfg.xtrn[i]->textra)
......
......@@ -448,6 +448,8 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
SAFEPRINTF(path,"%sDOSXTRN.RET", cfg.node_dir);
(void)remove(path);
SAFEPRINTF(path,"%sDOSXTRN.ERR", cfg.node_dir);
(void)remove(path);
// Create temporary environment file
SAFEPRINTF(path,"%sDOSXTRN.ENV", node_dir);
......@@ -595,13 +597,14 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
pthread_mutex_lock(&input_thread_mutex);
}
DWORD creation_flags = (mode & EX_NODISPLAY) ? CREATE_NO_WINDOW : CREATE_NEW_CONSOLE;
success=CreateProcess(
NULL, // pointer to name of executable module
fullcmdline, // pointer to command line string
NULL, // process security attributes
NULL, // thread security attributes
native && !(mode&EX_OFFLINE), // handle inheritance flag
CREATE_NEW_CONSOLE/*|CREATE_SEPARATE_WOW_VDM*/, // creation flags
creation_flags, // creation flags
env_block, // pointer to new environment block
p_startup_dir, // pointer to current directory name
&startup_info, // pointer to STARTUPINFO
......@@ -791,8 +794,7 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
if(online && hangup_event!=NULL
&& WaitForSingleObject(hangup_event,0)==WAIT_OBJECT_0) {
lprintf(LOG_NOTICE,"Node %d External program requested hangup (dropped DTR)"
,cfg.node_num);
lputs(LOG_NOTICE, "External program requested hangup (dropped DTR)");
hangup();
}
......@@ -831,21 +833,40 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
errormsg(WHERE, ERR_CHK, "ExitCodeProcess",(DWORD)process_info.hProcess);
if(retval==STILL_ACTIVE) {
lprintf(LOG_INFO,"Node %d Terminating process from line %d",cfg.node_num,__LINE__);
lprintf(LOG_INFO,"Terminating process from line %d", __LINE__);
TerminateProcess(process_info.hProcess, GetLastError());
}
// Get return value
if(!native) {
sprintf(str,"%sDOSXTRN.RET", cfg.node_dir);
FILE* fp=fopen(str,"r");
if(fp!=NULL) {
SAFEPRINTF(path, "%sDOSXTRN.RET", cfg.node_dir);
FILE* fp=fopen(path,"r");
if(fp == NULL) {
lprintf(LOG_ERR, "Error %d opening %s", errno, path);
} else {
if(fscanf(fp,"%d",&retval) != 1) {
lprintf(LOG_ERR, "Node %d Error reading return value from %s", cfg.node_num, str);
retval = -1;
lprintf(LOG_ERR, "Error reading return value from %s", path);
retval = -2;
}
fclose(fp);
}
if(retval == -1) {
SAFEPRINTF(path, "%sDOSXTRN.ERR", cfg.node_dir);
fp = fopen(path, "r");
if(fp == NULL) {
lprintf(LOG_ERR, "Error %d opening %s after DOSXTRN.RET contained -1", errno, path);
} else {
char errstr[256] = "";
int errval = 0;
if(fscanf(fp, "%d\n", &errval) == 1) {
fgets(errstr, sizeof(errstr), fp);
truncsp(errstr);
lprintf(LOG_ERR, "DOSXTRN Error %d (%s) executing: %s", errval, errstr, cmdline);
} else
lprintf(LOG_ERR, "DOSXTRN.RET contained -1 and we failed to parse: %s", path);
fclose(fp);
}
}
}
}
......
......@@ -381,7 +381,7 @@ void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tl
,8 /* 03: Data bits */
,cfg.node_num /* 04: Node number */
,dte_rate /* 05: DTE rate */
,'Y' /* 06: Screen display */
,(misc & XTRN_NODISPLAY) ? 'N': 'Y' /* 06: Screen display */
,'Y' /* 07: Printer toggle */
,'Y' /* 08: Page bell */
,'Y'); /* 09: Caller alarm */
......@@ -712,7 +712,7 @@ void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tl
return;
}
PCBoard::sys sys{};
sys.Screen = true;
sys.Screen = !(misc & XTRN_NODISPLAY);
sys.PageBell = sys_status & SS_SYSPAGE;
sys.Alarm = startup->sound.answer[0] && !sound_muted(&cfg);
sys.ErrorCorrected = true;
......@@ -1393,7 +1393,7 @@ bool sbbs_t::exec_xtrn(uint xtrnnum)
mode|=EX_UART;
else if(cfg.xtrn[xtrnnum]->misc&XTRN_FOSSIL)
mode|=EX_FOSSIL;
mode|=(cfg.xtrn[xtrnnum]->misc&(XTRN_CHKTIME|XTRN_NATIVE|XTRN_NOECHO|WWIVCOLOR));
mode|=(cfg.xtrn[xtrnnum]->misc&(XTRN_CHKTIME|XTRN_NATIVE|XTRN_NOECHO|XTRN_NODISPLAY|WWIVCOLOR));
if(cfg.xtrn[xtrnnum]->misc&MODUSERDAT) { /* Delete MODUSER.DAT */
SAFEPRINTF(str,"%sMODUSER.DAT",dropdir); /* if for some weird */
(void)removecase(str); /* reason it's there */
......