|
|
3.12a Javascript
/* dosxtrn.c */
/* Synchronet External DOS Program Launcher (16-bit MSVC 1.52c project) */
/* $Id: dosxtrn.c,v 1.1.1.2 2018/04/24 16:41:15 root Exp $ */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* See the GNU General Public License for more details: gpl.txt or *
* http://www.fsf.org/copyleft/gpl.html *
* *
* Anonymous FTP access to the most recent released source is available at *
* ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
* *
* Anonymous CVS access to the development source and modification history *
* is available at cvs.synchro.net:/cvsroot/sbbs, example: *
* cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
* (just hit return, no password is necessary) *
* cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* You are encouraged to submit any modifications (preferably in Unix diff *
* format) via e-mail to [email protected] *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <process.h>
#include <dos.h> /* _dos_set/getvect() */
#include <windows.h> /* BOOL, etc. */
#include "vdd_func.h"
#include "execvxd.h"
#include "isvbop.h" /* ddk\inc */
/****************************************************************************/
/* Truncates white-space chars off end of 'str' and terminates at first tab */
/****************************************************************************/
static void truncsp(char *str)
{
size_t c;
str[strcspn(str,"\t")]=0;
c=strlen(str);
while(c && (unsigned char)str[c-1]<=' ') c--;
str[c]=0;
}
short vdd=0;
BYTE node_num=0;
int mode=0;
DWORD nodata=0;
DWORD polls_before_yield=10;
void (interrupt *oldint14)();
void (interrupt *oldint16)();
void (interrupt *oldint29)();
static int vdd_buf(BYTE op, int count, WORD buf_seg, WORD buf_off)
{
int retval;
_asm {
push bx
push cx
push es
push di
mov ax, vdd
mov bh, node_num
mov bl, op
mov cx, count
mov es, buf_seg
mov di, buf_off
}
DispatchCall();
_asm {
mov retval, ax
pop di
pop es
pop cx
pop bx
}
return(retval);
}
static int vdd_op(BYTE op)
{
int retval;
#if FALSE /* disable yield? */
if(op==VDD_YIELD)
return(0);
#endif
_asm {
push bx
mov ax, vdd
mov bh, node_num
mov bl, op
}
DispatchCall();
_asm {
mov retval, ax
pop bx
}
return(retval);
}
#if 0
char win95int14[]={
0xCF // IRET
,0x90 // NOP
,0x90
,0x90
,0x90
,0x90
,0x54 // FOSSIL sig
,0x19 // FOSSIL sig
,0x1B // FOSSIL highest func supported
};
#else
union REGS inregs;
struct SREGS sregs;
BOOL inside_int14=FALSE;
/* This function is only necessary for naughty programs that call the vector
directly instead of issuing an interrupt
*/
void interrupt win95int14(
unsigned _es, unsigned _ds,
unsigned _di, unsigned _si,
unsigned _bp, unsigned _sp,
unsigned _bx, unsigned _dx,
unsigned _cx, unsigned _ax,
unsigned flags )
{
union REGS outregs;
/* prevent recursion, just incase the VXD isn't handling int14h */
if(inside_int14)
return;
inside_int14=TRUE;
inregs.x.ax=_ax;
inregs.x.bx=_bx;
inregs.x.cx=_cx;
inregs.x.dx=_dx;
inregs.x.si=_si;
inregs.x.di=_di;
inregs.x.cflag=flags;
sregs.es=_es;
sregs.ds=_ds;
int86x(0x14,&inregs,&outregs,&sregs);
/* FOSSIL driver only touches these AX and BX */
_ax= outregs.x.ax;
_bx= outregs.x.bx;
inside_int14=FALSE;
}
#endif
void vdd_getstatus(vdd_status_t* status)
{
WORD buf_seg;
_asm mov buf_seg, ss;
if(vdd_buf(VDD_STATUS, sizeof(vdd_status_t), buf_seg, (WORD)status)!=0)
memset(status,0,sizeof(vdd_status_t));
}
WORD PortStatus()
{
WORD status=0x0008; // AL bit 3 (change in DCD) always set
vdd_status_t vdd_status;
vdd_getstatus(&vdd_status);
if(vdd_status.online) // carrier detect
status|=0x0080; // DCD
if(vdd_status.inbuf_full) // receive data ready
status|=0x0100; // RDA
// if(vm->overrun) // overrun error detected
// status|=0x0200; // OVRN
if(vdd_status.outbuf_full
<vdd_status.outbuf_size/2) // room available in output buffer
status|=0x2000; // THRE
if(!vdd_status.outbuf_full) // output buffer is empty
status|=0x4000; // TSRE
return(status);
}
void interrupt winNTint14(
unsigned _es, unsigned _ds,
unsigned _di, unsigned _si,
unsigned _bp, unsigned _sp,
unsigned _bx, unsigned _dx,
unsigned _cx, unsigned _ax,
)
{
BYTE ch;
BYTE far* p;
WORD buf_seg;
int wr;
vdd_status_t vdd_status;
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
,0,0
,0,0
,80,25
,1 // 38400
};
switch(_ax>>8) {
case 0x00: /* Initialize/Set baud rate */
_ax = PortStatus();
break;
case 0x01: /* write char to com port */
ch=_ax&0xff;
_asm mov buf_seg, ss;
vdd_buf(VDD_WRITE, 1, buf_seg, (WORD)&ch);
_ax = PortStatus();
nodata=0;
break;
case 0x02: /* read char from com port */
_asm mov buf_seg, ss;
_ax = vdd_buf(VDD_READ, 1, buf_seg, (WORD)&ch);
if(!_ax) {
_ax = 0x8000; /* timed-out */
vdd_op(VDD_YIELD);
} else {
_ax = ch;
nodata=0;
}
break;
case 0x03: /* request status */
_ax=PortStatus();
if(_ax==0x6088 && ++nodata>=polls_before_yield)
vdd_op(VDD_YIELD);
break;
case 0x04: /* initialize */
_ax=0x1954; /* magic number = success */
_bx=0x051B; /* FOSSIL rev/maximum FOSSIL func supported */
break;
case 0x08: /* flush output buffer */
break;
case 0x09: /* purge output buffer */
vdd_op(VDD_OUTBUF_PURGE);
break;
case 0x0A: /* purge input buffer */
vdd_op(VDD_INBUF_PURGE);
break;
case 0x0B: /* write char to com port, no wait */
if(0 /*RingBufFree(&vm->out)<2 */) {
_ax=0; // char was not accepted
break;
}
ch=_ax&0xff;
_asm mov buf_seg, ss;
_ax = vdd_buf(VDD_WRITE, 1, buf_seg, (WORD)&ch);
nodata=0;
break;
case 0x0C: // non-destructive read-ahead
vdd_getstatus(&vdd_status);
if(!vdd_status.inbuf_full) {
_ax=0xffff; // no char available
vdd_op(VDD_YIELD);
break;
}
_asm mov buf_seg, ss;
_ax = vdd_buf(VDD_PEEK, 1, buf_seg, (WORD)&ch);
if(_ax == 0)
vdd_op(VDD_YIELD);
else
nodata=0;
break;
case 0x18: /* read bock */
_ax = vdd_buf(VDD_READ, _cx, _es, _di);
if(_ax == 0)
vdd_op(VDD_YIELD);
else
nodata=0;
break;
case 0x19: /* write block */
_ax = vdd_buf(VDD_WRITE, _cx, _es, _di);
nodata=0;
break;
case 0x1B: /* driver info */
vdd_getstatus(&vdd_status);
info.inbuf_size=vdd_status.inbuf_size;
info.inbuf_free=info.inbuf_size-vdd_status.inbuf_full;
info.outbuf_size=vdd_status.outbuf_size;
info.outbuf_free=info.outbuf_size-vdd_status.outbuf_full;
if(vdd_status.inbuf_full==vdd_status.outbuf_full==0
&& ++nodata>=polls_before_yield)
vdd_op(VDD_YIELD);
p = _MK_FP(_es,_di);
wr=sizeof(info);
if(wr>_cx)
wr=_cx;
_fmemcpy(p, &info, wr);
_ax=wr;
break;
}
}
void interrupt winNTint16(
unsigned _es, unsigned _ds,
unsigned _di, unsigned _si,
unsigned _bp, unsigned _sp,
unsigned _bx, unsigned _dx,
unsigned _cx, unsigned _ax,
unsigned _ip, unsigned _cs,
unsigned flags )
{
BYTE ch;
WORD buf_seg;
vdd_status_t status;
vdd_getstatus(&status);
switch(_ax>>8) {
case 0x00: // Read char from keyboard
case 0x10: // Read char from enhanced keyboard
if(status.inbuf_full) {
_asm mov buf_seg, ss;
vdd_buf(VDD_READ, 1, buf_seg, (WORD)&ch);
_ax=ch;
nodata=0;
return;
}
if(++nodata>=polls_before_yield)
vdd_op(VDD_YIELD);
break;
case 0x01: // Get keyboard status
case 0x11: // Get enhanced keyboard status
if(status.inbuf_full) {
_asm mov buf_seg, ss;
vdd_buf(VDD_PEEK, 1, buf_seg, (WORD)&ch);
flags&=~(1<<6); // clear zero flag
_ax=ch;
nodata=0;
return;
}
if(++nodata>=polls_before_yield)
vdd_op(VDD_YIELD);
break;
}
_chain_intr(oldint16);
}
void interrupt winNTint29(
unsigned _es, unsigned _ds,
unsigned _di, unsigned _si,
unsigned _bp, unsigned _sp,
unsigned _bx, unsigned _dx,
unsigned _cx, unsigned _ax,
)
{
char ch;
WORD buf_seg;
ch=_ax&0xff;
_asm mov buf_seg, ss
vdd_buf(VDD_WRITE, 1, buf_seg, (WORD)&ch);
nodata=0;
_chain_intr(oldint29);
}
char * DllName ="SBBSEXEC.DLL";
char * InitFunc ="VDDInitialize";
char * DispFunc ="VDDDispatch";
int main(int argc, char **argv)
{
char str[128];
char cmdline[128],*p;
char dll[512];
char* envvar[10];
char* arg[16];
int i,c,d,envnum=0;
FILE* fp;
BOOL NT=FALSE;
BOOL success=FALSE;
WORD seg;
if(argc<2) {
fprintf(stderr
,"This program is for the internal use of Synchronet BBS only\n");
return(1);
}
strcpy(dll,argv[0]);
p=strrchr(dll,'\\');
if(p!=NULL) *(p+1)=0;
strcat(dll,"SBBSEXEC.DLL");
DllName=dll;
if(argc>2 && !strcmp(argv[2],"NT"))
NT=TRUE;
if(argc>3)
node_num=atoi(argv[3]);
if(argc>4)
mode=atoi(argv[4]);
if(argc>5)
polls_before_yield=atol(argv[5]);
if((fp=fopen(argv[1],"r"))==NULL) {
fprintf(stderr,"!Error opening %s\n",argv[1]);
return(2);
}
fgets(cmdline, sizeof(cmdline), fp);
truncsp(cmdline);
arg[0]=cmdline; /* point to the beginning of the string */
for(c=0,d=1;cmdline[c];c++) /* Break up command line */
if(cmdline[c]==' ') {
cmdline[c]=0; /* insert nulls */
arg[d++]=cmdline+c+1; } /* point to the beginning of the next arg */
arg[d]=0;
while(!feof(fp)) {
if(!fgets(str, sizeof(str), fp))
break;
truncsp(str);
envvar[envnum]=malloc(strlen(str)+1);
if(envvar[envnum]==NULL) {
fprintf(stderr,"!MALLOC ERROR\n");
return(4);
}
strcpy(envvar[envnum],str);
_putenv(envvar[envnum++]);
}
fclose(fp);
/* Save int14 handler */
oldint14=_dos_getvect(0x14);
if(NT) { /* Windows NT/2000 */
/* Register VDD */
_asm {
push es
push ds
pop es
mov si, DllName ; ds:si = dll name
mov di, InitFunc ; es:di = init routine
mov bx, DispFunc ; ds:bx = dispatch routine
};
RegisterModule();
_asm {
mov vdd, ax
jc err
mov success, TRUE
err:
pop es
}
if(!success) {
fprintf(stderr,"Error %d loading %s\n",vdd,DllName);
return(-1);
}
#if 0
fprintf(stderr,"vdd handle=%d\n",vdd);
fprintf(stderr,"mode=%d\n",mode);
#endif
i=vdd_op(VDD_OPEN);
if(i) {
fprintf(stderr,"!VDD_OPEN ERROR: %d\n",i);
UnRegisterModule();
return(-1);
}
oldint16=_dos_getvect(0x16);
oldint29=_dos_getvect(0x29);
if(mode==SBBSEXEC_MODE_FOSSIL)
_dos_setvect(0x14,(void(interrupt *)())winNTint14);
if(mode&SBBSEXEC_MODE_DOS_IN)
_dos_setvect(0x16,winNTint16);
if(mode&SBBSEXEC_MODE_DOS_OUT)
_dos_setvect(0x29,winNTint29);
}
else if(mode==SBBSEXEC_MODE_FOSSIL) /* Windows 95/98/Millennium */
_dos_setvect(0x14,(void(interrupt *)())win95int14);
_heapmin();
i=_spawnvp(_P_WAIT, arg[0], arg);
p=argv[1]+(strlen(argv[1])-3);
strcpy(p,"RET");
if((fp=fopen(argv[1],"w+"))==NULL) {
fprintf(stderr,"!Error opening %s\n",argv[1]);
return(3);
}
fprintf(fp,"%d",i);
/* Restore original ISRs */
_dos_setvect(0x14,oldint14);
if(NT) {
vdd_op(VDD_CLOSE);
_dos_setvect(0x16,oldint16);
_dos_setvect(0x29,oldint29);
/* Unregister VDD */
_asm mov ax, vdd;
UnRegisterModule();
}
return(i);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.