|
|
1.1 root 1: /* dosxtrn.c */
2:
3: /* Synchronet External DOS Program Launcher (16-bit MSVC 1.52c project) */
4:
1.1.1.2 ! root 5: /* $Id: dosxtrn.c,v 1.6 2001/09/16 21:31:07 rswindell Exp $ */
1.1 root 6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #include <stdio.h>
39: #include <stdlib.h>
40: #include <string.h>
41: #include <process.h>
42: #include <dos.h> /* _dos_set/getvect() */
43: #include <windows.h> /* BOOL, etc. */
44: #include "vdd_func.h"
45: #include "execvxd.h"
46: #include "isvbop.h" /* ddk\inc */
47:
48: /****************************************************************************/
49: /* Truncates white-space chars off end of 'str' and terminates at first tab */
50: /****************************************************************************/
51: static void truncsp(char *str)
52: {
53: size_t c;
54:
55: str[strcspn(str,"\t")]=0;
56: c=strlen(str);
57: while(c && (unsigned char)str[c-1]<=' ') c--;
58: str[c]=0;
59: }
60:
61: short vdd=0;
62: BYTE node_num=0;
63: int mode=0;
1.1.1.2 ! root 64: DWORD nodata=0;
! 65: DWORD polls_before_yield=10;
1.1 root 66:
67: void (interrupt *oldint14)();
68: void (interrupt *oldint16)();
69: void (interrupt *oldint29)();
70:
71: static int vdd_buf(BYTE op, int count, WORD buf_seg, WORD buf_off)
72: {
73: int retval;
74:
75: _asm {
76: push bx
77: push cx
78: push es
79: push di
80: mov ax, vdd
81: mov bh, node_num
82: mov bl, op
83: mov cx, count
84: mov es, buf_seg
85: mov di, buf_off
86: }
87: DispatchCall();
88: _asm {
89: mov retval, ax
90: pop di
91: pop es
92: pop cx
93: pop bx
94: }
95: return(retval);
96: }
97:
98: static int vdd_op(BYTE op)
99: {
100: int retval;
101:
1.1.1.2 ! root 102: #if FALSE /* disable yield? */
! 103: if(op==VDD_YIELD)
! 104: return(0);
! 105: #endif
1.1 root 106: _asm {
107: push bx
108: mov ax, vdd
109: mov bh, node_num
110: mov bl, op
111: }
112: DispatchCall();
113: _asm {
114: mov retval, ax
115: pop bx
116: }
117: return(retval);
118: }
119:
1.1.1.2 ! root 120: #if 0
! 121:
1.1 root 122: char win95int14[]={
123: 0xCF // IRET
124: ,0x90 // NOP
125: ,0x90
126: ,0x90
127: ,0x90
128: ,0x90
129: ,0x54 // FOSSIL sig
130: ,0x19 // FOSSIL sig
131: ,0x1B // FOSSIL highest func supported
132: };
133:
1.1.1.2 ! root 134: #else
! 135:
! 136: union REGS inregs;
! 137: struct SREGS sregs;
! 138: BOOL inside_int14=FALSE;
! 139:
! 140: /* This function is only necessary for naughty programs that call the vector
! 141: directly instead of issuing an interrupt
! 142: */
! 143: void interrupt win95int14(
! 144: unsigned _es, unsigned _ds,
! 145: unsigned _di, unsigned _si,
! 146: unsigned _bp, unsigned _sp,
! 147: unsigned _bx, unsigned _dx,
! 148: unsigned _cx, unsigned _ax,
! 149: unsigned flags )
! 150: {
! 151: union REGS outregs;
! 152:
! 153: /* prevent recursion, just incase the VXD isn't handling int14h */
! 154: if(inside_int14)
! 155: return;
! 156:
! 157: inside_int14=TRUE;
! 158:
! 159: inregs.x.ax=_ax;
! 160: inregs.x.bx=_bx;
! 161: inregs.x.cx=_cx;
! 162: inregs.x.dx=_dx;
! 163: inregs.x.si=_si;
! 164: inregs.x.di=_di;
! 165: inregs.x.cflag=flags;
! 166:
! 167: sregs.es=_es;
! 168: sregs.ds=_ds;
! 169:
! 170: int86x(0x14,&inregs,&outregs,&sregs);
! 171:
! 172: /* FOSSIL driver only touches these AX and BX */
! 173: _ax= outregs.x.ax;
! 174: _bx= outregs.x.bx;
! 175:
! 176: inside_int14=FALSE;
! 177: }
! 178:
! 179: #endif
! 180:
1.1 root 181: void vdd_getstatus(vdd_status_t* status)
182: {
183: WORD buf_seg;
184:
185: _asm mov buf_seg, ss;
186: if(vdd_buf(VDD_STATUS, sizeof(vdd_status_t), buf_seg, (WORD)status)!=0)
187: memset(status,0,sizeof(vdd_status_t));
188: }
189:
190: WORD PortStatus()
191: {
192: WORD status=0x0008; // AL bit 3 (change in DCD) always set
193: vdd_status_t vdd_status;
194:
195: vdd_getstatus(&vdd_status);
196:
197: if(vdd_status.online) // carrier detect
198: status|=0x0080; // DCD
199:
200: if(vdd_status.inbuf_full) // receive data ready
201: status|=0x0100; // RDA
202:
203: // if(vm->overrun) // overrun error detected
204: // status|=0x0200; // OVRN
205:
206: if(vdd_status.outbuf_full
207: <vdd_status.outbuf_size/2) // room available in output buffer
208: status|=0x2000; // THRE
209:
210: if(!vdd_status.outbuf_full) // output buffer is empty
211: status|=0x4000; // TSRE
212:
213: return(status);
214: }
215:
216: void interrupt winNTint14(
217: unsigned _es, unsigned _ds,
218: unsigned _di, unsigned _si,
219: unsigned _bp, unsigned _sp,
220: unsigned _bx, unsigned _dx,
221: unsigned _cx, unsigned _ax,
222: )
223: {
224: BYTE ch;
225: BYTE far* p;
226: WORD buf_seg;
227: int wr;
228: vdd_status_t vdd_status;
229: struct {
230: WORD info_size;
231: BYTE curr_fossil;
232: BYTE curr_rev;
233: DWORD id_string;
234: WORD inbuf_size;
235: WORD inbuf_free;
236: WORD outbuf_size;
237: WORD outbuf_free;
238: BYTE screen_width;
239: BYTE screen_height;
240: BYTE baud_rate;
241: } info= { sizeof(info), 5, 1, 0
242: ,0,0
243: ,0,0
244: ,80,25
245: ,1 // 38400
246: };
247:
248: switch(_ax>>8) {
249: case 0x00: /* Initialize/Set baud rate */
250: _ax = PortStatus();
251: break;
252: case 0x01: /* write char to com port */
253: ch=_ax&0xff;
254: _asm mov buf_seg, ss;
255: vdd_buf(VDD_WRITE, 1, buf_seg, (WORD)&ch);
256: _ax = PortStatus();
1.1.1.2 ! root 257: nodata=0;
1.1 root 258: break;
259: case 0x02: /* read char from com port */
260: _asm mov buf_seg, ss;
261: _ax = vdd_buf(VDD_READ, 1, buf_seg, (WORD)&ch);
1.1.1.2 ! root 262: if(!_ax) {
1.1 root 263: _ax = 0x8000; /* timed-out */
1.1.1.2 ! root 264: vdd_op(VDD_YIELD);
! 265: } else {
1.1 root 266: _ax = ch;
1.1.1.2 ! root 267: nodata=0;
! 268: }
1.1 root 269: break;
270: case 0x03: /* request status */
271: _ax=PortStatus();
1.1.1.2 ! root 272: if(_ax==0x6088 && ++nodata>=polls_before_yield)
! 273: vdd_op(VDD_YIELD);
1.1 root 274: break;
275: case 0x04: /* initialize */
276: _ax=0x1954; /* magic number = success */
277: _bx=0x051B; /* FOSSIL rev/maximum FOSSIL func supported */
278: break;
279: case 0x08: /* flush output buffer */
280: break;
281: case 0x09: /* purge output buffer */
282: vdd_op(VDD_OUTBUF_PURGE);
283: break;
284: case 0x0A: /* purge input buffer */
285: vdd_op(VDD_INBUF_PURGE);
286: break;
287: case 0x0B: /* write char to com port, no wait */
288: if(0 /*RingBufFree(&vm->out)<2 */) {
289: _ax=0; // char was not accepted
290: break;
291: }
292: ch=_ax&0xff;
293: _asm mov buf_seg, ss;
294: _ax = vdd_buf(VDD_WRITE, 1, buf_seg, (WORD)&ch);
1.1.1.2 ! root 295: nodata=0;
1.1 root 296: break;
297: case 0x0C: // non-destructive read-ahead
298: vdd_getstatus(&vdd_status);
299: if(!vdd_status.inbuf_full) {
300: _ax=0xffff; // no char available
1.1.1.2 ! root 301: vdd_op(VDD_YIELD);
1.1 root 302: break;
303: }
304: _asm mov buf_seg, ss;
305: _ax = vdd_buf(VDD_PEEK, 1, buf_seg, (WORD)&ch);
1.1.1.2 ! root 306: if(_ax == 0)
! 307: vdd_op(VDD_YIELD);
! 308: else
! 309: nodata=0;
1.1 root 310: break;
311: case 0x18: /* read bock */
312: _ax = vdd_buf(VDD_READ, _cx, _es, _di);
1.1.1.2 ! root 313: if(_ax == 0)
! 314: vdd_op(VDD_YIELD);
! 315: else
! 316: nodata=0;
1.1 root 317: break;
318: case 0x19: /* write block */
319: _ax = vdd_buf(VDD_WRITE, _cx, _es, _di);
1.1.1.2 ! root 320: nodata=0;
1.1 root 321: break;
322: case 0x1B: /* driver info */
323: vdd_getstatus(&vdd_status);
324: info.inbuf_size=vdd_status.inbuf_size;
325: info.inbuf_free=info.inbuf_size-vdd_status.inbuf_full;
326: info.outbuf_size=vdd_status.outbuf_size;
327: info.outbuf_free=info.outbuf_size-vdd_status.outbuf_full;
328:
1.1.1.2 ! root 329: if(vdd_status.inbuf_full==vdd_status.outbuf_full==0
! 330: && ++nodata>=polls_before_yield)
! 331: vdd_op(VDD_YIELD);
! 332:
1.1 root 333: p = _MK_FP(_es,_di);
334: wr=sizeof(info);
335: if(wr>_cx)
336: wr=_cx;
337: _fmemcpy(p, &info, wr);
338: _ax=wr;
339: break;
340: }
341: }
342:
343: void interrupt winNTint16(
344: unsigned _es, unsigned _ds,
345: unsigned _di, unsigned _si,
346: unsigned _bp, unsigned _sp,
347: unsigned _bx, unsigned _dx,
348: unsigned _cx, unsigned _ax,
349: unsigned _ip, unsigned _cs,
350: unsigned flags )
351: {
352: BYTE ch;
353: WORD buf_seg;
354: vdd_status_t status;
355:
356: vdd_getstatus(&status);
357: switch(_ax>>8) {
358: case 0x00: // Read char from keyboard
359: case 0x10: // Read char from enhanced keyboard
360: if(status.inbuf_full) {
361: _asm mov buf_seg, ss;
362: vdd_buf(VDD_READ, 1, buf_seg, (WORD)&ch);
363: _ax=ch;
1.1.1.2 ! root 364: nodata=0;
1.1 root 365: return;
1.1.1.2 ! root 366: }
! 367: if(++nodata>=polls_before_yield)
! 368: vdd_op(VDD_YIELD);
1.1 root 369: break;
370: case 0x01: // Get keyboard status
371: case 0x11: // Get enhanced keyboard status
372: if(status.inbuf_full) {
373: _asm mov buf_seg, ss;
374: vdd_buf(VDD_PEEK, 1, buf_seg, (WORD)&ch);
375: flags&=~(1<<6); // clear zero flag
376: _ax=ch;
1.1.1.2 ! root 377: nodata=0;
1.1 root 378: return;
1.1.1.2 ! root 379: }
! 380: if(++nodata>=polls_before_yield)
! 381: vdd_op(VDD_YIELD);
1.1 root 382: break;
383: }
384:
385: _chain_intr(oldint16);
386: }
387:
388: void interrupt winNTint29(
389: unsigned _es, unsigned _ds,
390: unsigned _di, unsigned _si,
391: unsigned _bp, unsigned _sp,
392: unsigned _bx, unsigned _dx,
393: unsigned _cx, unsigned _ax,
394: )
395: {
396: char ch;
397: WORD buf_seg;
398:
399: ch=_ax&0xff;
400: _asm mov buf_seg, ss
401: vdd_buf(VDD_WRITE, 1, buf_seg, (WORD)&ch);
1.1.1.2 ! root 402: nodata=0;
1.1 root 403:
404: _chain_intr(oldint29);
405: }
406:
407: char * DllName ="SBBSEXEC.DLL";
408: char * InitFunc ="VDDInitialize";
409: char * DispFunc ="VDDDispatch";
410:
411: int main(int argc, char **argv)
412: {
413: char str[128];
414: char cmdline[128],*p;
415: char dll[512];
416: char* envvar[10];
417: char* arg[16];
418: int i,c,d,envnum=0;
419: FILE* fp;
420: BOOL NT=FALSE;
421: BOOL success=FALSE;
422: WORD seg;
423:
424: if(argc<2) {
425: fprintf(stderr
426: ,"This program is for the internal use of Synchronet BBS only\n");
427: return(1);
428: }
1.1.1.2 ! root 429:
1.1 root 430: strcpy(dll,argv[0]);
431: p=strrchr(dll,'\\');
432: if(p!=NULL) *(p+1)=0;
433: strcat(dll,"SBBSEXEC.DLL");
434: DllName=dll;
435:
1.1.1.2 ! root 436: if(argc>2 && !strcmp(argv[2],"NT"))
1.1 root 437: NT=TRUE;
1.1.1.2 ! root 438: if(argc>3)
! 439: node_num=atoi(argv[3]);
! 440: if(argc>4)
! 441: mode=atoi(argv[4]);
! 442: if(argc>5)
! 443: polls_before_yield=atol(argv[5]);
1.1 root 444:
445: if((fp=fopen(argv[1],"r"))==NULL) {
446: fprintf(stderr,"!Error opening %s\n",argv[1]);
447: return(2);
448: }
449:
450: fgets(cmdline, sizeof(cmdline), fp);
451: truncsp(cmdline);
452:
453: arg[0]=cmdline; /* point to the beginning of the string */
454: for(c=0,d=1;cmdline[c];c++) /* Break up command line */
455: if(cmdline[c]==' ') {
456: cmdline[c]=0; /* insert nulls */
457: arg[d++]=cmdline+c+1; } /* point to the beginning of the next arg */
458: arg[d]=0;
459:
460: while(!feof(fp)) {
461: if(!fgets(str, sizeof(str), fp))
462: break;
463: truncsp(str);
464: envvar[envnum]=malloc(strlen(str)+1);
465: if(envvar[envnum]==NULL) {
466: fprintf(stderr,"!MALLOC ERROR\n");
467: return(4);
468: }
469: strcpy(envvar[envnum],str);
470: _putenv(envvar[envnum++]);
471: }
472: fclose(fp);
473:
474: /* Save int14 handler */
475: oldint14=_dos_getvect(0x14);
476:
477: if(NT) { /* Windows NT/2000 */
478:
479: /* Register VDD */
480: _asm {
481: push es
482: push ds
483: pop es
484: mov si, DllName ; ds:si = dll name
485: mov di, InitFunc ; es:di = init routine
486: mov bx, DispFunc ; ds:bx = dispatch routine
487: };
488: RegisterModule();
489: _asm {
490: mov vdd, ax
491: jc err
492: mov success, TRUE
493: err:
494: pop es
495: }
496: if(!success) {
497: fprintf(stderr,"Error %d loading %s\n",vdd,DllName);
498: return(-1);
499: }
500: #if 0
501: fprintf(stderr,"vdd handle=%d\n",vdd);
502: fprintf(stderr,"mode=%d\n",mode);
503: #endif
504:
505: i=vdd_op(VDD_OPEN);
506: if(i) {
507: fprintf(stderr,"!VDD_OPEN ERROR: %d\n",i);
508: UnRegisterModule();
509: return(-1);
510: }
511:
512: oldint16=_dos_getvect(0x16);
513: oldint29=_dos_getvect(0x29);
514: if(mode==SBBSEXEC_MODE_FOSSIL)
515: _dos_setvect(0x14,(void(interrupt *)())winNTint14);
516: if(mode&SBBSEXEC_MODE_DOS_IN)
517: _dos_setvect(0x16,winNTint16);
518: if(mode&SBBSEXEC_MODE_DOS_OUT)
519: _dos_setvect(0x29,winNTint29);
520: }
1.1.1.2 ! root 521: else if(mode==SBBSEXEC_MODE_FOSSIL) /* Windows 95/98/Millennium */
1.1 root 522: _dos_setvect(0x14,(void(interrupt *)())win95int14);
523:
524: _heapmin();
525: i=_spawnvp(_P_WAIT, arg[0], arg);
526:
527: p=argv[1]+(strlen(argv[1])-3);
528: strcpy(p,"RET");
529: if((fp=fopen(argv[1],"w+"))==NULL) {
530: fprintf(stderr,"!Error opening %s\n",argv[1]);
531: return(3);
532: }
533: fprintf(fp,"%d",i);
534:
535: /* Restore original ISRs */
536: _dos_setvect(0x14,oldint14);
537:
538: if(NT) {
539: vdd_op(VDD_CLOSE);
540:
541: _dos_setvect(0x16,oldint16);
542: _dos_setvect(0x29,oldint29);
543:
544: /* Unregister VDD */
545: _asm mov ax, vdd;
546: UnRegisterModule();
547: }
548: return(i);
549: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.