|
|
1.1 root 1: /* dosxtrn.c */
2:
3: /* Synchronet External DOS Program Launcher (16-bit MSVC 1.52c project) */
4:
5: /* $Id: dosxtrn.c,v 1.1.1.1 2000/10/10 11:27:07 rswindell Exp $ */
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;
64:
65: void (interrupt *oldint14)();
66: void (interrupt *oldint16)();
67: void (interrupt *oldint29)();
68:
69: static int vdd_buf(BYTE op, int count, WORD buf_seg, WORD buf_off)
70: {
71: int retval;
72:
73: _asm {
74: push bx
75: push cx
76: push es
77: push di
78: mov ax, vdd
79: mov bh, node_num
80: mov bl, op
81: mov cx, count
82: mov es, buf_seg
83: mov di, buf_off
84: }
85: DispatchCall();
86: _asm {
87: mov retval, ax
88: pop di
89: pop es
90: pop cx
91: pop bx
92: }
93: return(retval);
94: }
95:
96: static int vdd_op(BYTE op)
97: {
98: int retval;
99:
100: _asm {
101: push bx
102: mov ax, vdd
103: mov bh, node_num
104: mov bl, op
105: }
106: DispatchCall();
107: _asm {
108: mov retval, ax
109: pop bx
110: }
111: return(retval);
112: }
113:
114: char win95int14[]={
115: 0xCF // IRET
116: ,0x90 // NOP
117: ,0x90
118: ,0x90
119: ,0x90
120: ,0x90
121: ,0x54 // FOSSIL sig
122: ,0x19 // FOSSIL sig
123: ,0x1B // FOSSIL highest func supported
124: };
125:
126: void vdd_getstatus(vdd_status_t* status)
127: {
128: WORD buf_seg;
129:
130: _asm mov buf_seg, ss;
131: if(vdd_buf(VDD_STATUS, sizeof(vdd_status_t), buf_seg, (WORD)status)!=0)
132: memset(status,0,sizeof(vdd_status_t));
133: }
134:
135: #if 1
136:
137: WORD PortStatus()
138: {
139: WORD status=0x0008; // AL bit 3 (change in DCD) always set
140: vdd_status_t vdd_status;
141:
142: vdd_getstatus(&vdd_status);
143:
144: if(vdd_status.online) // carrier detect
145: status|=0x0080; // DCD
146:
147: if(vdd_status.inbuf_full) // receive data ready
148: status|=0x0100; // RDA
149:
150: // if(vm->overrun) // overrun error detected
151: // status|=0x0200; // OVRN
152:
153: if(vdd_status.outbuf_full
154: <vdd_status.outbuf_size/2) // room available in output buffer
155: status|=0x2000; // THRE
156:
157: if(!vdd_status.outbuf_full) // output buffer is empty
158: status|=0x4000; // TSRE
159:
160: return(status);
161: }
162:
163: #else
164:
165: WORD PortStatus()
166: {
167: WORD status=0x0008; // AL bit 3 (change in DCD) always set
168: static poll;
169: static online=1;
170: static outbuf_full;
171: static outbuf_size;
172:
173: if(!poll)
174: outbuf_size=vdd_op(VDD_OUTBUF_SIZE);
175:
176: if(!(poll%500)) {
177: online=vdd_op(VDD_ONLINE);
178: outbuf_full=vdd_op(VDD_OUTBUF_FULL);
179: }
180:
181: if(online) // carrier detect
182: status|=0x0080; // DCD
183:
184: if(vdd_op(VDD_INBUF_FULL)) // receive data ready
185: status|=0x0100; // RDA
186:
187: // if(vm->overrun) // overrun error detected
188: // status|=0x0200; // OVRN
189:
190: if(outbuf_full
191: <outbuf_size/2) // room available in output buffer
192: status|=0x2000; // THRE
193:
194: if(!outbuf_full) // output buffer is empty
195: status|=0x4000; // TSRE
196:
197: poll++;
198:
199: return(status);
200: }
201:
202: #endif
203:
204: void interrupt winNTint14(
205: unsigned _es, unsigned _ds,
206: unsigned _di, unsigned _si,
207: unsigned _bp, unsigned _sp,
208: unsigned _bx, unsigned _dx,
209: unsigned _cx, unsigned _ax,
210: )
211: {
212: BYTE ch;
213: BYTE far* p;
214: WORD buf_seg;
215: int wr;
216: vdd_status_t vdd_status;
217: struct {
218: WORD info_size;
219: BYTE curr_fossil;
220: BYTE curr_rev;
221: DWORD id_string;
222: WORD inbuf_size;
223: WORD inbuf_free;
224: WORD outbuf_size;
225: WORD outbuf_free;
226: BYTE screen_width;
227: BYTE screen_height;
228: BYTE baud_rate;
229: } info= { sizeof(info), 5, 1, 0
230: ,0,0
231: ,0,0
232: ,80,25
233: ,1 // 38400
234: };
235:
236: switch(_ax>>8) {
237: case 0x00: /* Initialize/Set baud rate */
238: _ax = PortStatus();
239: break;
240: case 0x01: /* write char to com port */
241: ch=_ax&0xff;
242: _asm mov buf_seg, ss;
243: vdd_buf(VDD_WRITE, 1, buf_seg, (WORD)&ch);
244: _ax = PortStatus();
245: break;
246: case 0x02: /* read char from com port */
247: _asm mov buf_seg, ss;
248: _ax = vdd_buf(VDD_READ, 1, buf_seg, (WORD)&ch);
249: if(!_ax)
250: _ax = 0x8000; /* timed-out */
251: else
252: _ax = ch;
253: break;
254: case 0x03: /* request status */
255: _ax=PortStatus();
256: break;
257: case 0x04: /* initialize */
258: _ax=0x1954; /* magic number = success */
259: _bx=0x051B; /* FOSSIL rev/maximum FOSSIL func supported */
260: break;
261: case 0x08: /* flush output buffer */
262: break;
263: case 0x09: /* purge output buffer */
264: vdd_op(VDD_OUTBUF_PURGE);
265: break;
266: case 0x0A: /* purge input buffer */
267: vdd_op(VDD_INBUF_PURGE);
268: break;
269: case 0x0B: /* write char to com port, no wait */
270: if(0 /*RingBufFree(&vm->out)<2 */) {
271: _ax=0; // char was not accepted
272: break;
273: }
274: ch=_ax&0xff;
275: _asm mov buf_seg, ss;
276: _ax = vdd_buf(VDD_WRITE, 1, buf_seg, (WORD)&ch);
277: break;
278: case 0x0C: // non-destructive read-ahead
279: vdd_getstatus(&vdd_status);
280: if(!vdd_status.inbuf_full) {
281: _ax=0xffff; // no char available
282: break;
283: }
284: _asm mov buf_seg, ss;
285: _ax = vdd_buf(VDD_PEEK, 1, buf_seg, (WORD)&ch);
286: break;
287: case 0x18: /* read bock */
288: _ax = vdd_buf(VDD_READ, _cx, _es, _di);
289: break;
290: case 0x19: /* write block */
291: _ax = vdd_buf(VDD_WRITE, _cx, _es, _di);
292: break;
293: case 0x1B: /* driver info */
294: vdd_getstatus(&vdd_status);
295: info.inbuf_size=vdd_status.inbuf_size;
296: info.inbuf_free=info.inbuf_size-vdd_status.inbuf_full;
297: info.outbuf_size=vdd_status.outbuf_size;
298: info.outbuf_free=info.outbuf_size-vdd_status.outbuf_full;
299:
300: p = _MK_FP(_es,_di);
301: wr=sizeof(info);
302: if(wr>_cx)
303: wr=_cx;
304: _fmemcpy(p, &info, wr);
305: _ax=wr;
306: break;
307: }
308: }
309:
310: void interrupt winNTint16(
311: unsigned _es, unsigned _ds,
312: unsigned _di, unsigned _si,
313: unsigned _bp, unsigned _sp,
314: unsigned _bx, unsigned _dx,
315: unsigned _cx, unsigned _ax,
316: unsigned _ip, unsigned _cs,
317: unsigned flags )
318: {
319: BYTE ch;
320: WORD buf_seg;
321: vdd_status_t status;
322:
323: vdd_getstatus(&status);
324: switch(_ax>>8) {
325: case 0x00: // Read char from keyboard
326: case 0x10: // Read char from enhanced keyboard
327: if(status.inbuf_full) {
328: _asm mov buf_seg, ss;
329: vdd_buf(VDD_READ, 1, buf_seg, (WORD)&ch);
330: _ax=ch;
331: return;
332: }
333: break;
334: case 0x01: // Get keyboard status
335: case 0x11: // Get enhanced keyboard status
336: if(status.inbuf_full) {
337: _asm mov buf_seg, ss;
338: vdd_buf(VDD_PEEK, 1, buf_seg, (WORD)&ch);
339: flags&=~(1<<6); // clear zero flag
340: _ax=ch;
341: return;
342: }
343: break;
344: }
345:
346: _chain_intr(oldint16);
347: }
348:
349: void interrupt winNTint29(
350: unsigned _es, unsigned _ds,
351: unsigned _di, unsigned _si,
352: unsigned _bp, unsigned _sp,
353: unsigned _bx, unsigned _dx,
354: unsigned _cx, unsigned _ax,
355: )
356: {
357: char ch;
358: WORD buf_seg;
359:
360: ch=_ax&0xff;
361: _asm mov buf_seg, ss
362: vdd_buf(VDD_WRITE, 1, buf_seg, (WORD)&ch);
363:
364: _chain_intr(oldint29);
365: }
366:
367: char * DllName ="SBBSEXEC.DLL";
368: char * InitFunc ="VDDInitialize";
369: char * DispFunc ="VDDDispatch";
370:
371: int main(int argc, char **argv)
372: {
373: char str[128];
374: char cmdline[128],*p;
375: char dll[512];
376: char* envvar[10];
377: char* arg[16];
378: int i,c,d,envnum=0;
379: FILE* fp;
380: BOOL NT=FALSE;
381: BOOL success=FALSE;
382: WORD seg;
383:
384: if(argc<2) {
385: fprintf(stderr
386: ,"This program is for the internal use of Synchronet BBS only\n");
387: return(1);
388: }
389: #if 1
390: strcpy(dll,argv[0]);
391: p=strrchr(dll,'\\');
392: if(p!=NULL) *(p+1)=0;
393: strcat(dll,"SBBSEXEC.DLL");
394: DllName=dll;
395: #endif
396:
397: if(argc>2 && !strcmp(argv[2],"NT")) {
398: NT=TRUE;
399: if(argc>3)
400: node_num=atoi(argv[3]);
401: if(argc>4)
402: mode=atoi(argv[4]);
403: }
404:
405: if((fp=fopen(argv[1],"r"))==NULL) {
406: fprintf(stderr,"!Error opening %s\n",argv[1]);
407: return(2);
408: }
409:
410: fgets(cmdline, sizeof(cmdline), fp);
411: truncsp(cmdline);
412:
413: arg[0]=cmdline; /* point to the beginning of the string */
414: for(c=0,d=1;cmdline[c];c++) /* Break up command line */
415: if(cmdline[c]==' ') {
416: cmdline[c]=0; /* insert nulls */
417: arg[d++]=cmdline+c+1; } /* point to the beginning of the next arg */
418: arg[d]=0;
419:
420: while(!feof(fp)) {
421: if(!fgets(str, sizeof(str), fp))
422: break;
423: truncsp(str);
424: envvar[envnum]=malloc(strlen(str)+1);
425: if(envvar[envnum]==NULL) {
426: fprintf(stderr,"!MALLOC ERROR\n");
427: return(4);
428: }
429: strcpy(envvar[envnum],str);
430: _putenv(envvar[envnum++]);
431: }
432: fclose(fp);
433:
434: /* Save int14 handler */
435: oldint14=_dos_getvect(0x14);
436:
437: if(NT) { /* Windows NT/2000 */
438:
439: /* Register VDD */
440: _asm {
441: push es
442: push ds
443: pop es
444: mov si, DllName ; ds:si = dll name
445: mov di, InitFunc ; es:di = init routine
446: mov bx, DispFunc ; ds:bx = dispatch routine
447: };
448: RegisterModule();
449: _asm {
450: mov vdd, ax
451: jc err
452: mov success, TRUE
453: err:
454: pop es
455: }
456: if(!success) {
457: fprintf(stderr,"Error %d loading %s\n",vdd,DllName);
458: return(-1);
459: }
460: #if 0
461: fprintf(stderr,"vdd handle=%d\n",vdd);
462: fprintf(stderr,"mode=%d\n",mode);
463: #endif
464:
465: i=vdd_op(VDD_OPEN);
466: if(i) {
467: fprintf(stderr,"!VDD_OPEN ERROR: %d\n",i);
468: UnRegisterModule();
469: return(-1);
470: }
471:
472: oldint16=_dos_getvect(0x16);
473: oldint29=_dos_getvect(0x29);
474: if(mode==SBBSEXEC_MODE_FOSSIL)
475: _dos_setvect(0x14,(void(interrupt *)())winNTint14);
476: if(mode&SBBSEXEC_MODE_DOS_IN)
477: _dos_setvect(0x16,winNTint16);
478: if(mode&SBBSEXEC_MODE_DOS_OUT)
479: _dos_setvect(0x29,winNTint29);
480: }
481: else /* Windows 95/98/Millennium */
482: _dos_setvect(0x14,(void(interrupt *)())win95int14);
483:
484: _heapmin();
485: i=_spawnvp(_P_WAIT, arg[0], arg);
486:
487: p=argv[1]+(strlen(argv[1])-3);
488: strcpy(p,"RET");
489: if((fp=fopen(argv[1],"w+"))==NULL) {
490: fprintf(stderr,"!Error opening %s\n",argv[1]);
491: return(3);
492: }
493: fprintf(fp,"%d",i);
494:
495: /* Restore original ISRs */
496: _dos_setvect(0x14,oldint14);
497:
498: if(NT) {
499: vdd_op(VDD_CLOSE);
500:
501: _dos_setvect(0x16,oldint16);
502: _dos_setvect(0x29,oldint29);
503:
504: /* Unregister VDD */
505: _asm mov ax, vdd;
506: UnRegisterModule();
507: }
508: return(i);
509: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.