|
|
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.