Annotation of sbbs/sbbs3/xtrn.cpp, revision 1.1

1.1     ! root        1: /* xtrn.cpp */
        !             2: 
        !             3: /* Synchronet external program support routines */
        !             4: 
        !             5: /* $Id: xtrn.cpp,v 1.27 2000/12/06 22:10:20 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 "sbbs.h"
        !            39: #include "cmdshell.h"
        !            40: #include "telnet.h"
        !            41: 
        !            42: #ifdef __unix__
        !            43:        #include <sys/wait.h>   // WEXITSTATUS
        !            44: #endif
        !            45: 
        !            46: /*****************************************************************************/
        !            47: /* Interrupt routine to expand WWIV Ctrl-C# codes into ANSI escape sequences */
        !            48: /*****************************************************************************/
        !            49: BYTE* wwiv_expand(BYTE* buf, ulong buflen, BYTE* outbuf, ulong& newlen
        !            50:        ,ulong user_misc, bool& ctrl_c)
        !            51: {
        !            52:     char       ansi_seq[32];
        !            53:        ulong   i,j,k;
        !            54: 
        !            55:     for(i=j=0;i<buflen;i++) {
        !            56:         if(buf[i]==3) {        /* ctrl-c, WWIV color escape char */
        !            57:             ctrl_c=true;
        !            58:             continue;
        !            59:         }
        !            60:         if(!ctrl_c) {
        !            61:             outbuf[j++]=buf[i];
        !            62:             continue;
        !            63:         }
        !            64:         ctrl_c=false;
        !            65:         if(user_misc&ANSI) {
        !            66:             switch(buf[i]) {
        !            67:                 default:
        !            68:                     strcpy(ansi_seq,"\x1b[0m");          /* low grey */
        !            69:                     break;
        !            70:                 case '1':
        !            71:                     strcpy(ansi_seq,"\x1b[0;1;36m");     /* high cyan */
        !            72:                     break;
        !            73:                 case '2':
        !            74:                     strcpy(ansi_seq,"\x1b[0;1;33m");     /* high yellow */
        !            75:                     break;
        !            76:                 case '3':
        !            77:                     strcpy(ansi_seq,"\x1b[0;35m");       /* low magenta */
        !            78:                     break;
        !            79:                 case '4':
        !            80:                     strcpy(ansi_seq,"\x1b[0;1;44m");     /* white on blue */
        !            81:                     break;
        !            82:                 case '5':
        !            83:                     strcpy(ansi_seq,"\x1b[0;32m");       /* low green */
        !            84:                     break;
        !            85:                 case '6':
        !            86:                     strcpy(ansi_seq,"\x1b[0;1;5;31m");   /* high blinking red */
        !            87:                     break;
        !            88:                 case '7':
        !            89:                     strcpy(ansi_seq,"\x1b[0;1;34m");     /* high blue */
        !            90:                     break;
        !            91:                 case '8':
        !            92:                     strcpy(ansi_seq,"\x1b[0;34m");       /* low blue */
        !            93:                     break;
        !            94:                 case '9':
        !            95:                     strcpy(ansi_seq,"\x1b[0;36m");       /* low cyan */
        !            96:                     break;
        !            97:             }
        !            98:             for(k=0;ansi_seq[k];k++)
        !            99:                 outbuf[j++]=ansi_seq[k];
        !           100:         }
        !           101:     }
        !           102:     newlen=j;
        !           103:     return(outbuf);
        !           104: }
        !           105: 
        !           106: /*****************************************************************************/
        !           107: // Escapes Telnet IAC (255) by doubling the IAC char
        !           108: /*****************************************************************************/
        !           109: BYTE* telnet_expand(BYTE* inbuf, ulong inlen, BYTE* outbuf, ulong& newlen, bool& iac)
        !           110: {
        !           111:        BYTE*   first_iac;
        !           112:        ulong   i,outlen;
        !           113: 
        !           114:     first_iac=(BYTE*)memchr(inbuf, TELNET_IAC, inlen);
        !           115: 
        !           116:        if(first_iac==NULL && !iac) {   /* Nothing to expand */
        !           117:                newlen=inlen;
        !           118:                return(inbuf);
        !           119:        }
        !           120: 
        !           121:        if(first_iac!=NULL) {
        !           122:                outlen=first_iac-inbuf;
        !           123:                memcpy(outbuf, inbuf, outlen);
        !           124:        } else
        !           125:                outlen=0;
        !           126: 
        !           127:     for(i=outlen;i<inlen;i++) {
        !           128:                if(iac==true) {
        !           129:                        outbuf[outlen++]=TELNET_IAC;
        !           130: //                     lprintf("Telnet IAC escaped");
        !           131:                }
        !           132:                if(inbuf[i]==TELNET_IAC)
        !           133:                        iac=true;
        !           134:                else
        !           135:                        iac=false;
        !           136:                outbuf[outlen++]=inbuf[i];
        !           137:        }
        !           138:     newlen=outlen;
        !           139:     return(outbuf);
        !           140: }
        !           141: 
        !           142: 
        !           143: #ifdef _WIN32
        !           144: 
        !           145: #include "execvxd.h"   /* Win9X FOSSIL VxD API */
        !           146: 
        !           147: #define XTRN_IO_BUF_LEN 5000
        !           148: 
        !           149: extern SOCKET node_socket[];
        !           150: 
        !           151: // -------------------------------------------------------------------------
        !           152: // GetAddressOfOpenVxDHandle
        !           153: //
        !           154: // This function returns the address of OpenVxDHandle. OpenVxDHandle is a 
        !           155: // KERNEL32 function that returns a ring 0 event handle that corresponds to a
        !           156: // given ring 3 event handle. The ring 0 handle can be used by VxDs to
        !           157: // synchronize with the Win32 app.
        !           158: //
        !           159: typedef HANDLE (WINAPI *OPENVXDHANDLE)(HANDLE);
        !           160: 
        !           161: OPENVXDHANDLE GetAddressOfOpenVxDHandle(void)
        !           162: {
        !           163:        HINSTANCE hK32;
        !           164: 
        !           165:        if ((hK32 = LoadLibrary("KERNEL32")) == NULL)
        !           166:                return NULL;
        !           167: 
        !           168:        return((OPENVXDHANDLE)GetProcAddress(hK32, "OpenVxDHandle"));
        !           169: }
        !           170: 
        !           171: /****************************************************************************/
        !           172: /* Runs an external program                                                                                            */
        !           173: /****************************************************************************/
        !           174: int sbbs_t::external(char* cmdline, long mode, char* startup_dir)
        !           175: {
        !           176:        char    str[256],*p,*p_startup_dir;
        !           177:        char    fname[128];
        !           178:     char       fullcmdline[256];
        !           179:        char    realcmdline[256];
        !           180:        char    comspec_str[128];
        !           181:        char    title[256];
        !           182:        BYTE    buf[XTRN_IO_BUF_LEN],*bp;
        !           183:     BYTE       telnet_buf[XTRN_IO_BUF_LEN*2];
        !           184:     BYTE       wwiv_buf[XTRN_IO_BUF_LEN*2];
        !           185:     bool       wwiv_flag=false;
        !           186:        bool    telnet_flag=false;
        !           187:     bool       native=false;                   // DOS program by default
        !           188:     bool       was_online=true;
        !           189:     uint       i;
        !           190:     time_t     hungup=0;
        !           191:        bool    nt=false;
        !           192:        HANDLE  vxd=INVALID_HANDLE_VALUE;
        !           193:        HANDLE  rdslot=INVALID_HANDLE_VALUE;
        !           194:        HANDLE  wrslot=INVALID_HANDLE_VALUE;
        !           195:        HANDLE  start_event;
        !           196:        HANDLE  hungup_event=NULL;
        !           197:     PROCESS_INFORMATION process_info;
        !           198:        DWORD   hVM;
        !           199:        DWORD   rd;
        !           200:     DWORD      wr;
        !           201:     DWORD      len;
        !           202:     DWORD      avail;
        !           203:        DWORD   dummy;  
        !           204:        DWORD   retval;
        !           205:        DWORD   last_error;
        !           206:        DWORD   loop_since_io=0;
        !           207:        struct  tm * tm_p;
        !           208:        sbbsexec_start_t start;
        !           209:        OPENVXDHANDLE OpenVxDHandle;
        !           210: 
        !           211:        if(cmdline[0]=='*') {   /* Baja module */
        !           212:                sprintf(str,"%.*s",sizeof(str)-1,cmdline+1);
        !           213:                p=strchr(str,SP);
        !           214:                if(p) {
        !           215:                        strcpy(main_csi.str,p+1);
        !           216:                        *p=0; }
        !           217:                return(exec_bin(str,&main_csi)); 
        !           218:        }
        !           219: 
        !           220:        attr(cfg.color[clr_external]);        /* setup default attributes */
        !           221: 
        !           222:     strcpy(str,cmdline);               /* Set str to program name only */
        !           223:     p=strchr(str,SP);
        !           224:     if(p) *p=0;
        !           225:     strcpy(fname,str);
        !           226: 
        !           227:     p=strrchr(fname,'/');
        !           228:     if(!p) p=strrchr(fname,'\\');
        !           229:     if(!p) p=strchr(fname,':');
        !           230:     if(!p) p=fname;
        !           231:     else   p++;
        !           232: 
        !           233:     for(i=0;i<cfg.total_natvpgms;i++)
        !           234:         if(!stricmp(p,cfg.natvpgm[i]->name))
        !           235:             break;
        !           236:     if(i<cfg.total_natvpgms || mode&EX_NATIVE)
        !           237:         native=true;
        !           238: 
        !           239:        if(strcspn(cmdline,"<>|")!=strlen(cmdline)) 
        !           240:                sprintf(comspec_str,"%s /C ", comspec);
        !           241:        else
        !           242:                comspec_str[0]=0;
        !           243: 
        !           244:     if(startup_dir && cmdline[1]!=':' && cmdline[0]!='/'
        !           245:        && cmdline[0]!='\\' && cmdline[0]!='.')
        !           246:                sprintf(fullcmdline, "%s%s%s", comspec_str, startup_dir, cmdline);
        !           247:     else
        !           248:        sprintf(fullcmdline, "%s%s", comspec_str, cmdline);
        !           249: 
        !           250:        strcpy(realcmdline, fullcmdline);       // for errormsg if failed to execute
        !           251: 
        !           252:        now=time(NULL);
        !           253:        tm_p=gmtime(&now);
        !           254: 
        !           255:        if(native) { // Native (32-bit) external
        !           256: 
        !           257:                // Current environment passed to child process
        !           258:                sprintf(dszlog,"DSZLOG=%sPROTOCOL.LOG",cfg.node_dir);
        !           259:                if(putenv(dszlog))              /* Makes the DSZ LOG active */
        !           260:                errormsg(WHERE,ERR_WRITE,"environment",0);
        !           261:                sprintf(sbbsnode,"SBBSNODE=%s",cfg.node_dir);
        !           262:                putenv(sbbsnode);               /* create environment var to contain node num */
        !           263:                sprintf(sbbsnnum,"SBBSNNUM=%d",cfg.node_num);
        !           264:                putenv(sbbsnnum);          /* create environment var to contain node num */
        !           265: 
        !           266:     } else { // DOS external
        !           267: 
        !           268:                sprintf(str,"%sDOSXTRN.RET", cfg.node_dir);
        !           269:                remove(str);
        !           270: 
        !           271:        // Create temporary environment file
        !           272:        sprintf(str,"%sDOSXTRN.ENV", cfg.node_dir);
        !           273:         FILE* fp=fopen(str,"w");
        !           274:         if(fp==NULL) {
        !           275:                errormsg(WHERE, ERR_CREATE, str, 0);
        !           276:             return(1);
        !           277:         }
        !           278:         fprintf(fp, "%s\n", fullcmdline);
        !           279:                fprintf(fp, "DSZLOG=%sPROTOCOL.LOG\n", cfg.node_dir);
        !           280:         fprintf(fp, "SBBSCTRL=%s\n", cfg.ctrl_dir);
        !           281:         fprintf(fp, "SBBSNODE=%s\n", cfg.node_dir);
        !           282:         fprintf(fp, "SBBSNNUM=%d\n", cfg.node_num);
        !           283:                if(tm_p!=NULL) {
        !           284:                        fprintf(fp, "DAY=%02u\n", tm_p->tm_mday);
        !           285:                        fprintf(fp, "WEEKDAY=%s\n",wday[tm_p->tm_wday]);
        !           286:                        fprintf(fp, "MONTHNAME=%s\n",mon[tm_p->tm_mon]);
        !           287:                        fprintf(fp, "MONTH=%02u\n",tm_p->tm_mon+1);
        !           288:                        fprintf(fp, "YEAR=%u\n",1900+tm_p->tm_year);
        !           289:                }
        !           290:         fclose(fp);
        !           291: 
        !           292:         sprintf(fullcmdline, "%sDOSXTRN.EXE %s", cfg.exec_dir, str);
        !           293: 
        !           294:                if((retval=WaitForSingleObject(exec_mutex,5000))!=WAIT_OBJECT_0) {
        !           295:                        errormsg(WHERE, ERR_TIMEOUT, "exec_mutex", retval);
        !           296:                        return(GetLastError());
        !           297:                }
        !           298: 
        !           299:                OpenVxDHandle=GetAddressOfOpenVxDHandle();
        !           300: 
        !           301:                if(!(mode&EX_OFFLINE) && OpenVxDHandle==NULL) { // Windows NT/2000
        !           302:                        nt=true;
        !           303:                        i=SBBSEXEC_MODE_FOSSIL;
        !           304:                        if(mode&EX_INR)
        !           305:                        i|=SBBSEXEC_MODE_DOS_IN;
        !           306:                        if(mode&EX_OUTR)
        !           307:                        i|=SBBSEXEC_MODE_DOS_OUT;
        !           308:                        sprintf(str," NT %d %d",cfg.node_num,i);
        !           309:                        strcat(fullcmdline,str);
        !           310: 
        !           311:                        sprintf(str,"sbbsexec_hungup%d",cfg.node_num);
        !           312:                        if((hungup_event=CreateEvent(
        !           313:                                 NULL   // pointer to security attributes
        !           314:                                ,TRUE   // flag for manual-reset event
        !           315:                                ,FALSE  // flag for initial state
        !           316:                                ,str    // pointer to event-object name
        !           317:                                ))==NULL) {
        !           318:                                last_error=GetLastError();
        !           319:                                ReleaseMutex(exec_mutex);
        !           320:                                SetLastError(last_error);
        !           321:                                errormsg(WHERE, ERR_CREATE, "exec start event", 0);
        !           322:                                return(GetLastError());
        !           323:                        }
        !           324: 
        !           325:                        sprintf(str,"\\\\.\\mailslot\\sbbsexec\\rd%d"
        !           326:                                ,cfg.node_num);
        !           327:                        rdslot=CreateMailslot(str
        !           328:                                ,sizeof(buf)                    // Maximum message size (0=unlimited)
        !           329:                                ,0                                              // Read time-out
        !           330:                                ,NULL);                 // Security
        !           331:                        if(rdslot==INVALID_HANDLE_VALUE) {
        !           332:                                last_error=GetLastError();
        !           333:                                ReleaseMutex(exec_mutex);
        !           334:                                CloseHandle(hungup_event);
        !           335:                                SetLastError(last_error);
        !           336:                                errormsg(WHERE, ERR_CREATE, str, 0);
        !           337:                                return(GetLastError());
        !           338:                        }
        !           339:                }
        !           340:                else if(!(mode&EX_OFFLINE)) {
        !           341: 
        !           342:                        // Load vxd to intercept interrupts
        !           343: 
        !           344:                        sprintf(str,"\\\\.\\%s%s",cfg.exec_dir, SBBSEXEC_VXD);
        !           345:                        if((vxd=CreateFile(str,0,0,0
        !           346:                                ,CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE,0))
        !           347:                                 ==INVALID_HANDLE_VALUE) {
        !           348:                                last_error=GetLastError();
        !           349:                                ReleaseMutex(exec_mutex);
        !           350:                                SetLastError(last_error);
        !           351:                                errormsg(WHERE, ERR_OPEN, str, 0);
        !           352:                                return(GetLastError());
        !           353:                        }
        !           354: 
        !           355:                        if((start_event=CreateEvent(
        !           356:                                 NULL   // pointer to security attributes
        !           357:                                ,TRUE   // flag for manual-reset event
        !           358:                                ,FALSE  // flag for initial state
        !           359:                                ,NULL   // pointer to event-object name
        !           360:                                ))==NULL) {
        !           361:                                last_error=GetLastError();
        !           362:                                ReleaseMutex(exec_mutex);
        !           363:                                CloseHandle(vxd);
        !           364:                                SetLastError(last_error);
        !           365:                                errormsg(WHERE, ERR_CREATE, "exec start event", 0);
        !           366:                                return(GetLastError());
        !           367:                        }
        !           368: 
        !           369:                        if(OpenVxDHandle!=NULL)
        !           370:                                start.event=OpenVxDHandle(start_event);
        !           371:                        else
        !           372:                                start.event=start_event;
        !           373: 
        !           374:                        start.mode=SBBSEXEC_MODE_FOSSIL;
        !           375:                        if(mode&EX_INR)
        !           376:                        start.mode|=SBBSEXEC_MODE_DOS_IN;
        !           377:                        if(mode&EX_OUTR)
        !           378:                        start.mode|=SBBSEXEC_MODE_DOS_OUT;
        !           379: 
        !           380:                        if(!DeviceIoControl(
        !           381:                                vxd,                                    // handle to device of interest
        !           382:                                SBBSEXEC_IOCTL_START,   // control code of operation to perform
        !           383:                                &start,                                 // pointer to buffer to supply input data
        !           384:                                sizeof(start),                  // size of input buffer
        !           385:                                NULL,                                   // pointer to buffer to receive output data
        !           386:                                0,                                              // size of output buffer
        !           387:                                &rd,                                    // pointer to variable to receive output byte count
        !           388:                                NULL                                    // Overlapped I/O
        !           389:                                )) {
        !           390:                                last_error=GetLastError();
        !           391:                                ReleaseMutex(exec_mutex);
        !           392:                                CloseHandle(vxd);
        !           393:                                SetLastError(last_error);
        !           394:                                errormsg(WHERE, ERR_IOCTL, SBBSEXEC_VXD, SBBSEXEC_IOCTL_START);
        !           395:                                return(GetLastError());
        !           396:                        }
        !           397:                }
        !           398:     }
        !           399: 
        !           400:        if(startup_dir!=NULL && startup_dir[0])
        !           401:                p_startup_dir=startup_dir;
        !           402:        else
        !           403:                p_startup_dir=NULL;
        !           404:     STARTUPINFO startup_info={0};
        !           405:     startup_info.cb=sizeof(startup_info);
        !           406:        if(mode&EX_OFFLINE)
        !           407:                startup_info.lpTitle=NULL;
        !           408:        else {
        !           409:                sprintf(title,"%s running %s on node %d"
        !           410:                        ,useron.number ? useron.alias : "Event"
        !           411:                        ,realcmdline
        !           412:                        ,cfg.node_num);
        !           413:                startup_info.lpTitle=title;
        !           414:        }
        !           415:     if(cfg.startup->options&BBS_OPT_XTRN_MINIMIZED) {
        !           416:        startup_info.wShowWindow=SW_SHOWMINNOACTIVE;
        !           417:         startup_info.dwFlags|=STARTF_USESHOWWINDOW;
        !           418:     }
        !           419: 
        !           420:        if(native) {
        !           421:                /* temporary */
        !           422:                FILE* fp;
        !           423:                sprintf(fname,"%sDOOR32.SYS",cfg.node_dir);
        !           424:                fp=fopen(fname,"wb");
        !           425:                fprintf(fp,"2\r\n%d\r\n38400\r\nSynchronet %s%c\r\n%d\r\n%s\r\n%s\r\n%d\r\n%d\r\n"
        !           426:                        "%d\r\n%d\r\n"
        !           427:                        ,client_socket_dup
        !           428:                        ,VERSION,REVISION
        !           429:                        ,useron.number
        !           430:                        ,useron.name
        !           431:                        ,useron.alias
        !           432:                        ,useron.level
        !           433:                        ,timeleft/60
        !           434:                        ,useron.misc&ANSI ? 1 : 0
        !           435:                        ,cfg.node_num);
        !           436:                fclose(fp);
        !           437: 
        !           438:                /* not temporary */
        !           439: #if 0
        !           440:                SuspendThread(input_thread);
        !           441: #else
        !           442:                pthread_mutex_lock(&input_thread_mutex);
        !           443: #endif
        !           444:        }
        !           445: 
        !           446:     if(!CreateProcess(
        !           447:                NULL,                   // pointer to name of executable module
        !           448:                fullcmdline,    // pointer to command line string
        !           449:                NULL,                   // process security attributes
        !           450:                NULL,                   // thread security attributes
        !           451:                TRUE,                   // handle inheritance flag
        !           452:                CREATE_NEW_CONSOLE|CREATE_SEPARATE_WOW_VDM, // creation flags
        !           453:         NULL,                          // pointer to new environment block
        !           454:                p_startup_dir,  // pointer to current directory name
        !           455:                &startup_info,  // pointer to STARTUPINFO
        !           456:                &process_info   // pointer to PROCESS_INFORMATION
        !           457:                )) {
        !           458:                last_error=GetLastError();
        !           459:         ReleaseMutex(exec_mutex);
        !           460:                if(vxd!=INVALID_HANDLE_VALUE)
        !           461:                        CloseHandle(vxd);
        !           462:                if(hungup_event!=NULL)
        !           463:                        CloseHandle(hungup_event);
        !           464:                if(native)
        !           465:                        ResumeThread(input_thread);
        !           466:                SetLastError(last_error);
        !           467:         errormsg(WHERE, ERR_EXEC, realcmdline, mode);
        !           468:         return(GetLastError());
        !           469:     }
        !           470: 
        !           471:        if(!native) {
        !           472: 
        !           473:                if(!(mode&EX_OFFLINE) && !nt) {
        !           474:                // Wait for notification from VXD that new VM has started
        !           475:                        if((retval=WaitForSingleObject(start_event, 5000))!=WAIT_OBJECT_0) {
        !           476:                                last_error=GetLastError();
        !           477:                                ReleaseMutex(exec_mutex);
        !           478:                                CloseHandle(vxd);
        !           479:                                CloseHandle(start_event);
        !           480:                                SetLastError(last_error);
        !           481:                                errormsg(WHERE, ERR_TIMEOUT, "start_event", retval);
        !           482:                                return(GetLastError());
        !           483:                        }
        !           484: 
        !           485:                        CloseHandle(start_event);
        !           486: 
        !           487:                        if(!DeviceIoControl(
        !           488:                                vxd,                                    // handle to device of interest
        !           489:                                SBBSEXEC_IOCTL_COMPLETE,        // control code of operation to perform
        !           490:                                NULL,                                   // pointer to buffer to supply input data
        !           491:                                0,                                              // size of input buffer
        !           492:                                &hVM,                                   // pointer to buffer to receive output data
        !           493:                                sizeof(hVM),                    // size of output buffer
        !           494:                                &rd,                                    // pointer to variable to receive output byte count
        !           495:                                NULL                                    // Overlapped I/O
        !           496:                                )) {
        !           497:                                last_error=GetLastError();
        !           498:                                ReleaseMutex(exec_mutex);
        !           499:                                CloseHandle(vxd);
        !           500:                                SetLastError(last_error);
        !           501:                                errormsg(WHERE, ERR_IOCTL, SBBSEXEC_VXD, SBBSEXEC_IOCTL_COMPLETE);
        !           502:                                return(GetLastError());
        !           503:                        }
        !           504:                }
        !           505:         ReleaseMutex(exec_mutex);
        !           506:        }
        !           507: 
        !           508:     // Executing app, monitor
        !           509:     retval=STILL_ACTIVE;
        !           510:     while(1) {
        !           511:         if(!online && !(mode&EX_OFFLINE)) { // Tell VXD/VDD and external that user hung-up
        !           512:                if(was_online) {
        !           513:                                logline("X!","Hung-up in external program");
        !           514:                hungup=time(NULL);
        !           515:                                if(!native) {
        !           516:                                        if(nt)
        !           517:                                                SetEvent(hungup_event);
        !           518:                                        else if(!DeviceIoControl(
        !           519:                                                vxd,            // handle to device of interest
        !           520:                                                SBBSEXEC_IOCTL_DISCONNECT,      // operation to perform
        !           521:                                                &hVM,           // pointer to buffer to supply input data
        !           522:                                                sizeof(hVM),// size of input buffer
        !           523:                                                NULL,           // pointer to buffer to receive output data
        !           524:                                                0,                      // size of output buffer
        !           525:                                                &rd,            // pointer to variable to receive output byte count
        !           526:                                                NULL            // Overlapped I/O
        !           527:                                                )) {
        !           528:                                                errormsg(WHERE, ERR_IOCTL, SBBSEXEC_VXD, SBBSEXEC_IOCTL_DISCONNECT);
        !           529:                                                break;
        !           530:                                        }
        !           531:                                }
        !           532:                    was_online=false;
        !           533:             }
        !           534:             if(hungup && time(NULL)-hungup>5) 
        !           535:                 TerminateProcess(process_info.hProcess, 2112);
        !           536:         }
        !           537:                if(native || mode&EX_OFFLINE) {
        !           538:             if(GetExitCodeProcess(process_info.hProcess, &retval)==FALSE) {
        !           539:                 errormsg(WHERE, ERR_CHK, "ExitCodeProcess"
        !           540:                    ,(DWORD)process_info.hProcess);
        !           541:                 break;
        !           542:             }
        !           543:             if(retval!=STILL_ACTIVE)
        !           544:                 break;
        !           545:                Sleep(500);
        !           546:                } else {
        !           547: 
        !           548:                        if(nt) {        // Windows NT/2000
        !           549: 
        !           550:                                /* Write to VDD */
        !           551: 
        !           552:                                wr=RingBufPeek(&inbuf,buf,sizeof(buf));
        !           553:                                if(wr) {
        !           554:                                        if(wrslot==INVALID_HANDLE_VALUE) {
        !           555:                                                sprintf(str,"\\\\.\\mailslot\\sbbsexec\\wr%d"
        !           556:                                                        ,cfg.node_num);
        !           557:                                                wrslot=CreateFile(str
        !           558:                                                        ,GENERIC_WRITE
        !           559:                                                        ,FILE_SHARE_READ
        !           560:                                                        ,NULL
        !           561:                                                        ,OPEN_EXISTING
        !           562:                                                        ,FILE_ATTRIBUTE_NORMAL
        !           563:                                                        ,(HANDLE) NULL);
        !           564: #if 0
        !           565:                                                if(wrslot==INVALID_HANDLE_VALUE) {
        !           566:                                                        errormsg(WHERE,ERR_OPEN,str,0);
        !           567:                                                        break;
        !           568:                                                }
        !           569: #endif
        !           570:                                        }
        !           571:                                        if(wrslot!=INVALID_HANDLE_VALUE
        !           572:                                                && WriteFile(wrslot,buf,wr,&len,NULL)==TRUE) {
        !           573:                                                RingBufRead(&inbuf, NULL, len);
        !           574:                                                wr=len;
        !           575:                                        } else          // VDD not loaded yet
        !           576:                                                wr=0;
        !           577:                                }
        !           578: 
        !           579:                                /* Read from VDD */
        !           580: 
        !           581:                                len=sizeof(buf);
        !           582:                                avail=RingBufFree(&outbuf);
        !           583:                                if(len>avail)
        !           584:                        len=avail;
        !           585:                                if(ReadFile(rdslot,buf,len,&rd,NULL)==TRUE && rd>0) {
        !           586:                                        if(mode&EX_WWIV) {
        !           587:                                bp=wwiv_expand(buf, rd, wwiv_buf, rd, useron.misc, wwiv_flag);
        !           588:                                                if(rd>sizeof(wwiv_buf))
        !           589:                                                        errorlog("WWIV_BUF OVERRUN");
        !           590:                                        } else {
        !           591:                                bp=telnet_expand(buf, rd, telnet_buf, rd, telnet_flag);
        !           592:                                                if(rd>sizeof(telnet_buf))
        !           593:                                                        errorlog("TELNET_BUF OVERRUN");
        !           594:                                        }
        !           595:                                        RingBufWrite(&outbuf, bp, rd);
        !           596:                                        sem_post(&output_sem);
        !           597:                                }
        !           598:                        } else {        // Windows 9x
        !           599: 
        !           600:                                /* Write to VXD */
        !           601: 
        !           602:                                wr=RingBufPeek(&inbuf, buf+sizeof(hVM),sizeof(buf)-sizeof(hVM));
        !           603:                                if(wr) {
        !           604:                                        *(DWORD*)buf=hVM;
        !           605:                                        wr+=sizeof(hVM);
        !           606:                                        if(!DeviceIoControl(
        !           607:                                                vxd,                                    // handle to device of interest
        !           608:                                                SBBSEXEC_IOCTL_WRITE,   // control code of operation to perform
        !           609:                                                buf,                                    // pointer to buffer to supply input data
        !           610:                                                wr,                                             // size of input buffer
        !           611:                                                &rd,                                    // pointer to buffer to receive output data
        !           612:                                                sizeof(rd),                             // size of output buffer
        !           613:                                                &dummy,                                 // pointer to variable to receive output byte count
        !           614:                                                NULL                                    // Overlapped I/O
        !           615:                                                )) {
        !           616:                                                errormsg(WHERE, ERR_IOCTL, SBBSEXEC_VXD, SBBSEXEC_IOCTL_READ);
        !           617:                                                break;
        !           618:                                        }
        !           619:                                        RingBufRead(&inbuf, NULL, rd);
        !           620:                                        wr=rd;
        !           621:                                }
        !           622:                        /* Read from VXD */
        !           623:                                rd=0;
        !           624:                                len=sizeof(buf);
        !           625:                                avail=RingBufFree(&outbuf);
        !           626:                                if(len>avail)
        !           627:                        len=avail;
        !           628:                                if(len && avail>=RingBufFull(&outbuf)) {
        !           629:                                        if(!DeviceIoControl(
        !           630:                                                vxd,                                    // handle to device of interest
        !           631:                                                SBBSEXEC_IOCTL_READ,    // control code of operation to perform
        !           632:                                                &hVM,                                   // pointer to buffer to supply input data
        !           633:                                                sizeof(hVM),                    // size of input buffer
        !           634:                                                buf,                                    // pointer to buffer to receive output data
        !           635:                                                len,                                    // size of output buffer
        !           636:                                                &rd,                                    // pointer to variable to receive output byte count
        !           637:                                                NULL                                    // Overlapped I/O
        !           638:                                                )) {
        !           639:                                                errormsg(WHERE, ERR_IOCTL, SBBSEXEC_VXD, SBBSEXEC_IOCTL_READ);
        !           640:                                                break;
        !           641:                                        }
        !           642: #if 0
        !           643:                                        if(rd>1)
        !           644:                                lprintf("read %d bytes from xtrn", rd);
        !           645: #endif
        !           646: 
        !           647:                                        if(mode&EX_WWIV)
        !           648:                                bp=wwiv_expand(buf, rd, wwiv_buf, rd, useron.misc, wwiv_flag);
        !           649:                                        else
        !           650:                                bp=telnet_expand(buf, rd, telnet_buf, rd, telnet_flag);
        !           651:                                        RingBufWrite(&outbuf, bp, rd);
        !           652:                                        sem_post(&output_sem);
        !           653:                                }
        !           654:                        }
        !           655:             if(!rd && !wr) {
        !           656:                                if(++loop_since_io>=1000) {
        !           657:                        if(GetExitCodeProcess(process_info.hProcess, &retval)==FALSE) {
        !           658:                            errormsg(WHERE, ERR_CHK, "ExitCodeProcess"
        !           659:                                                ,(DWORD)process_info.hProcess);
        !           660:                                                break;
        !           661:                                        }
        !           662:                                        if(retval!=STILL_ACTIVE)  {
        !           663: #if 0
        !           664:                                                if(hungup)
        !           665:                                                        Sleep(5000);    // Give the application time to close files
        !           666: #endif
        !           667:                            break;
        !           668:                                        }
        !           669:                                        if(!(loop_since_io%3000)) {
        !           670: //                                             OutputDebugString(".");
        !           671:                                                getnodedat(cfg.node_num,&thisnode,0);
        !           672:                                                if(thisnode.misc&NODE_INTR)
        !           673:                                                        break;
        !           674:                                        }
        !           675:                                        Sleep(1);
        !           676:                                }
        !           677:             } else
        !           678:                                loop_since_io=0;
        !           679:         }
        !           680:        }
        !           681: 
        !           682:        if(!native && !(mode&EX_OFFLINE) && !nt) {
        !           683:                if(!DeviceIoControl(
        !           684:                        vxd,                                    // handle to device of interest
        !           685:                        SBBSEXEC_IOCTL_STOP,    // control code of operation to perform
        !           686:                        &hVM,                                   // pointer to buffer to supply input data
        !           687:                        sizeof(hVM),                    // size of input buffer
        !           688:                        NULL,                                   // pointer to buffer to receive output data
        !           689:                        0,                                              // size of output buffer
        !           690:                        &rd,                                    // pointer to variable to receive output byte count
        !           691:                        NULL                                    // Overlapped I/O
        !           692:                        )) {
        !           693:                        errormsg(WHERE, ERR_IOCTL, SBBSEXEC_VXD, SBBSEXEC_IOCTL_STOP);
        !           694:                }
        !           695:        }
        !           696: 
        !           697:     if(retval==STILL_ACTIVE)
        !           698:            TerminateProcess(process_info.hProcess, GetLastError());
        !           699: 
        !           700:     if(vxd!=INVALID_HANDLE_VALUE)
        !           701:                CloseHandle(vxd);
        !           702: 
        !           703:        if(rdslot!=INVALID_HANDLE_VALUE)
        !           704:                CloseHandle(rdslot);
        !           705: 
        !           706:        if(wrslot!=INVALID_HANDLE_VALUE)
        !           707:                CloseHandle(wrslot);
        !           708: 
        !           709:        if(hungup_event!=NULL)
        !           710:                CloseHandle(hungup_event);
        !           711: 
        !           712:        if(native)
        !           713: #if 0
        !           714:                ResumeThread(input_thread);
        !           715: #else
        !           716:                pthread_mutex_unlock(&input_thread_mutex);
        !           717: #endif
        !           718:        else {  // Get return value
        !           719:        sprintf(str,"%sDOSXTRN.RET", cfg.node_dir);
        !           720:         FILE* fp=fopen(str,"r");
        !           721:         if(fp!=NULL) {
        !           722:                        fscanf(fp,"%d",&retval);
        !           723:                        fclose(fp);
        !           724:                }
        !           725:        }
        !           726: 
        !           727:        curatr=0;       // Can't guarantee current attributes
        !           728: 
        !           729: //     lprintf("%s returned %d",realcmdline, retval);
        !           730: 
        !           731:        return(retval);
        !           732: }
        !           733: 
        !           734: #else  /* !WIN32 */
        !           735: 
        !           736: int sbbs_t::external(char* cmdline, long mode, char* startup_dir)
        !           737: {
        !           738:        char    str[256];
        !           739:        char    fname[128];
        !           740:        char*   argv[30];
        !           741:        char*   p;
        !           742:     bool       native=false;                   // DOS program by default
        !           743:        int             i;
        !           744:        int             argc;
        !           745:        pid_t   pid;
        !           746:                
        !           747:        if(cmdline[0]=='*') {   /* Baja module */
        !           748:                sprintf(str,"%.*s",sizeof(str)-1,cmdline+1);
        !           749:                p=strchr(str,SP);
        !           750:                if(p) {
        !           751:                        strcpy(main_csi.str,p+1);
        !           752:                        *p=0; }
        !           753:                return(exec_bin(str,&main_csi)); 
        !           754:        }
        !           755: 
        !           756:        attr(cfg.color[clr_external]);        /* setup default attributes */
        !           757: 
        !           758:     strcpy(str,cmdline);               /* Set str to program name only */
        !           759:     p=strchr(str,SP);
        !           760:     if(p) *p=0;
        !           761:     strcpy(fname,str);
        !           762: 
        !           763:     p=strrchr(fname,'/');
        !           764:     if(!p) p=strrchr(fname,'\\');
        !           765:     if(!p) p=strchr(fname,':');
        !           766:     if(!p) p=fname;
        !           767:     else   p++;
        !           768: 
        !           769:     for(i=0;i<cfg.total_natvpgms;i++)
        !           770:         if(!stricmp(p,cfg.natvpgm[i]->name))
        !           771:             break;
        !           772:     if(i<cfg.total_natvpgms || mode&EX_NATIVE)
        !           773:         native=true;
        !           774: 
        !           775:        if(!native) {
        !           776:                bprintf("\r\nExternal DOS programs are not yet supported in Synchronet for Linux\r\n");
        !           777:                return(-1);
        !           778:        }
        !           779: 
        !           780:        if(native) { // Native (32-bit) external
        !           781: 
        !           782:                // Current environment passed to child process
        !           783:                sprintf(dszlog,"DSZLOG=%sPROTOCOL.LOG",cfg.node_dir);
        !           784:                if(putenv(dszlog))              /* Makes the DSZ LOG active */
        !           785:                errormsg(WHERE,ERR_WRITE,"environment",0);
        !           786:                sprintf(sbbsnode,"SBBSNODE=%s",cfg.node_dir);
        !           787:                putenv(sbbsnode);               /* create environment var to contain node num */
        !           788:                sprintf(sbbsnnum,"SBBSNNUM=%d",cfg.node_num);
        !           789:                putenv(sbbsnnum);          /* create environment var to contain node num */
        !           790: 
        !           791:        } else {
        !           792:                /* setup DOSemu env here */
        !           793:        }
        !           794: 
        !           795:        pthread_mutex_lock(&input_thread_mutex);
        !           796: 
        !           797:        if((pid=fork())==-1) {
        !           798:                pthread_mutex_unlock(&input_thread_mutex);
        !           799:                errormsg(WHERE,ERR_EXEC,cmdline,0);
        !           800:                return(-1);
        !           801:        }
        !           802: 
        !           803:        if(pid==0) {    /* child process */
        !           804:                if(startup_dir!=NULL && startup_dir[0])
        !           805:                        chdir(startup_dir);
        !           806: 
        !           807:                lprintf("Node %02d executing external: %s",cfg.node_num,cmdline);
        !           808: 
        !           809:                argv[0]=cmdline;        /* point to the beginning of the string */
        !           810:                argc=1;
        !           811:                for(i=0;cmdline[i];i++) /* Break up command line */
        !           812:                        if(cmdline[i]==SP) {
        !           813:                                cmdline[i]=0;                   /* insert nulls */
        !           814:                                argv[argc++]=cmdline+i+1; /* point to the beginning of the next arg */
        !           815:                        }
        !           816:                argv[argc]=0;
        !           817: 
        !           818:                if(mode&EX_INR) 
        !           819:                        dup2(client_socket,0);  /* redirect stdin to socket */
        !           820: 
        !           821:                if(mode&EX_OUTR) {
        !           822:                        dup2(client_socket,1);  /* stdout */
        !           823:                        dup2(client_socket,2);  /* stderr */
        !           824:                }       
        !           825: 
        !           826:                execvp(argv[0],argv);
        !           827:                exit(-1);       /* should never get here */
        !           828:        }
        !           829: 
        !           830:        waitpid(pid, &i, 0);
        !           831: 
        !           832:        pthread_mutex_unlock(&input_thread_mutex);
        !           833: 
        !           834:        return(WEXITSTATUS(i));
        !           835: }
        !           836: 
        !           837: #endif /* !WIN32 */
        !           838: 
        !           839: uint fakeriobp=0xffff;
        !           840: 
        !           841: /*****************************************************************************/
        !           842: /* Returns command line generated from instr with %c replacments             */
        !           843: /*****************************************************************************/
        !           844: char * sbbs_t::cmdstr(char *instr, char *fpath, char *fspec, char *outstr)
        !           845: {
        !           846:        char    str[256],*cmd;
        !           847:     int                i,j,len;
        !           848: 
        !           849:     if(outstr==NULL)
        !           850:         cmd=cmdstr_output;
        !           851:     else
        !           852:         cmd=outstr;
        !           853:     len=strlen(instr);
        !           854:     for(i=j=0;i<len && j<sizeof(cmdstr_output);i++) {
        !           855:         if(instr[i]=='%') {
        !           856:             i++;
        !           857:             cmd[j]=0;
        !           858:             switch(toupper(instr[i])) {
        !           859:                 case 'A':   /* User alias */
        !           860:                     strcat(cmd,useron.alias);
        !           861:                     break;
        !           862:                 case 'B':   /* Baud (DTE) Rate */
        !           863:                     strcat(cmd,ultoa(dte_rate,str,10));
        !           864:                     break;
        !           865:                 case 'C':   /* Connect Description */
        !           866:                     strcat(cmd,connection);
        !           867:                     break;
        !           868:                 case 'D':   /* Connect (DCE) Rate */
        !           869:                     strcat(cmd,ultoa((ulong)cur_rate,str,10));
        !           870:                     break;
        !           871:                 case 'E':   /* Estimated Rate */
        !           872:                     strcat(cmd,ultoa((ulong)cur_cps*10,str,10));
        !           873:                     break;
        !           874:                 case 'F':   /* File path */
        !           875:                     strcat(cmd,fpath);
        !           876:                     break;
        !           877:                 case 'G':   /* Temp directory */
        !           878:                     strcat(cmd,cfg.temp_dir);
        !           879:                     break;
        !           880:                 case 'H':   /* Port Handle or Hardware Flow Control */
        !           881:                     strcat(cmd,ultoa(client_socket_dup,str,10));
        !           882:                     break;
        !           883:                 case 'I':   /* UART IRQ Line */
        !           884:                     strcat(cmd,ultoa(cfg.com_irq,str,10));
        !           885:                     break;
        !           886:                 case 'J':
        !           887:                     strcat(cmd,cfg.data_dir);
        !           888:                     break;
        !           889:                 case 'K':
        !           890:                     strcat(cmd,cfg.ctrl_dir);
        !           891:                     break;
        !           892:                 case 'L':   /* Lines per message */
        !           893:                     strcat(cmd,ultoa(cfg.level_linespermsg[useron.level],str,10));
        !           894:                     break;
        !           895:                 case 'M':   /* Minutes (credits) for user */
        !           896:                     strcat(cmd,ultoa(useron.min,str,10));
        !           897:                     break;
        !           898:                 case 'N':   /* Node Directory (same as SBBSNODE environment var) */
        !           899:                     strcat(cmd,cfg.node_dir);
        !           900:                     break;
        !           901:                 case 'O':   /* SysOp */
        !           902:                     strcat(cmd,cfg.sys_op);
        !           903:                     break;
        !           904:                 case 'P':   /* COM Port */
        !           905:                     strcat(cmd,ultoa(online==ON_LOCAL ? 0:cfg.com_port,str,10));
        !           906:                     break;
        !           907:                 case 'Q':   /* QWK ID */
        !           908:                     strcat(cmd,cfg.sys_id);
        !           909:                     break;
        !           910:                 case 'R':   /* Rows */
        !           911:                     strcat(cmd,ultoa(rows,str,10));
        !           912:                     break;
        !           913:                 case 'S':   /* File Spec */
        !           914:                     strcat(cmd,fspec);
        !           915:                     break;
        !           916:                 case 'T':   /* Time left in seconds */
        !           917:                     gettimeleft();
        !           918:                     strcat(cmd,ultoa(timeleft,str,10));
        !           919:                     break;
        !           920:                 case 'U':   /* UART I/O Address (in hex) */
        !           921:                     strcat(cmd,ultoa(cfg.com_base,str,16));
        !           922:                     break;
        !           923:                 case 'V':   /* Synchronet Version */
        !           924:                     sprintf(str,"%s%c",VERSION,REVISION);
        !           925:                     break;
        !           926:                 case 'W':   /* Time-slice API type (mswtype) */
        !           927: #if 0 //ndef __FLAT__
        !           928:                     strcat(cmd,ultoa(mswtyp,str,10));
        !           929: #endif
        !           930:                     break;
        !           931:                 case 'X':
        !           932:                     strcat(cmd,cfg.shell[useron.shell]->code);
        !           933:                     break;
        !           934:                 case '&':   /* Address of msr */
        !           935:                     sprintf(str,"%lu",&fakeriobp);
        !           936:                     strcat(cmd,str);
        !           937:                     break;
        !           938:                 case 'Y':
        !           939:                     strcat(cmd,
        !           940:                     comspec
        !           941:                     );
        !           942:                     break;
        !           943:                 case 'Z':
        !           944:                     strcat(cmd,cfg.text_dir);
        !           945:                     break;
        !           946:                 case '!':   /* EXEC Directory */
        !           947:                     strcat(cmd,cfg.exec_dir);
        !           948:                     break;
        !           949:                 case '#':   /* Node number (same as SBBSNNUM environment var) */
        !           950:                     sprintf(str,"%d",cfg.node_num);
        !           951:                     strcat(cmd,str);
        !           952:                     break;
        !           953:                 case '*':
        !           954:                     sprintf(str,"%03d",cfg.node_num);
        !           955:                     strcat(cmd,str);
        !           956:                     break;
        !           957:                 case '$':   /* Credits */
        !           958:                     strcat(cmd,ultoa(useron.cdt+useron.freecdt,str,10));
        !           959:                     break;
        !           960:                 case '%':   /* %% for percent sign */
        !           961:                     strcat(cmd,"%");
        !           962:                     break;
        !           963:                                case '?':       /* Platform */
        !           964: #ifdef __OS2__
        !           965:                                        strcpy(str,"OS2");
        !           966: #else
        !           967:                                        strcpy(str,PLATFORM_DESC);
        !           968: #endif
        !           969:                                        strlwr(str);
        !           970:                                        strcat(cmd,str);
        !           971:                                        break;
        !           972:                 default:    /* unknown specification */
        !           973:                     if(isdigit(instr[i])) {
        !           974:                         sprintf(str,"%0*d",instr[i]&0xf,useron.number);
        !           975:                         strcat(cmd,str); }
        !           976:                     break; }
        !           977:             j=strlen(cmd); }
        !           978:         else
        !           979:             cmd[j++]=instr[i]; }
        !           980:     cmd[j]=0;
        !           981: 
        !           982:     return(cmd);
        !           983: }
        !           984: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.