--- sbbs/src/sbbs3/xtrn.cpp 2018/04/24 16:41:24 1.1 +++ sbbs/src/sbbs3/xtrn.cpp 2018/04/24 16:43:47 1.1.1.2 @@ -2,13 +2,13 @@ /* Synchronet external program support routines */ -/* $Id: xtrn.cpp,v 1.1 2018/04/24 16:41:24 root Exp $ */ +/* $Id: xtrn.cpp,v 1.1.1.2 2018/04/24 16:43:47 root Exp $ */ /**************************************************************************** * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * - * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * @@ -45,7 +45,7 @@ #include // WEXITSTATUS #define TTYDEFCHARS // needed for ttydefchars definition - + #include // Linux - it's motherfucked. #if defined(__FreeBSD__) #include // forkpty() #elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DARWIN__) @@ -279,13 +279,13 @@ static bool native_executable(scfg_t* cf return(itotal_natvpgms); } -#define XTRN_LOADABLE_MODULE \ +#define XTRN_LOADABLE_MODULE(cmdline,startup_dir) \ if(cmdline[0]=='*') /* Baja module or JavaScript */ \ - return(exec_bin(cmdline+1,&main_csi)) + return(exec_bin(cmdline+1,&main_csi,startup_dir)) #ifdef JAVASCRIPT - #define XTRN_LOADABLE_JS_MODULE \ + #define XTRN_LOADABLE_JS_MODULE(cmdline,startup_dir) \ if(cmdline[0]=='?') /* JavaScript */ \ - return(js_execfile(cmdline+1)) + return(js_execfile(cmdline+1,startup_dir)) #else #define XTRN_LOADABLE_JS_MODULE #endif @@ -385,13 +385,13 @@ int sbbs_t::external(const char* cmdline HANDLE wrinpipe; PROCESS_INFORMATION process_info; DWORD hVM; - DWORD rd; - DWORD wr; - DWORD len; + unsigned long rd; + unsigned long wr; + unsigned long len; DWORD avail; - DWORD dummy; - DWORD msglen; - DWORD retval; + unsigned long dummy; + unsigned long msglen; + unsigned long retval; DWORD last_error; DWORD loop_since_io=0; struct tm tm; @@ -399,13 +399,18 @@ int sbbs_t::external(const char* cmdline sbbsexec_start_t start; OPENVXDHANDLE OpenVxDHandle; - if(online==ON_LOCAL) - eprintf(LOG_INFO,"Executing external: %s",cmdline); + if(online!=ON_REMOTE || cfg.node_num==0) + eprintf(LOG_DEBUG,"Executing external: %s",cmdline); else - lprintf(LOG_INFO,"Node %d Executing external: %s",cfg.node_num,cmdline); + lprintf(LOG_DEBUG,"Node %d Executing external: %s",cfg.node_num,cmdline); + + if(startup_dir!=NULL && startup_dir[0] && !isdir(startup_dir)) { + errormsg(WHERE, ERR_CHK, startup_dir, 0); + return -1; + } - XTRN_LOADABLE_MODULE; - XTRN_LOADABLE_JS_MODULE; + XTRN_LOADABLE_MODULE(cmdline,startup_dir); + XTRN_LOADABLE_JS_MODULE(cmdline,startup_dir); attr(cfg.color[clr_external]); /* setup default attributes */ @@ -439,7 +444,7 @@ int sbbs_t::external(const char* cmdline return(GetLastError()); } - if(native && mode&EX_OUTR && !(mode&EX_OFFLINE)) + if(native && mode&EX_STDOUT && !(mode&EX_OFFLINE)) use_pipes=true; if(native) { // Native (32-bit) external @@ -530,9 +535,9 @@ int sbbs_t::external(const char* cmdline if(!(mode&EX_OFFLINE) && nt) { // Windows NT/2000 i=SBBSEXEC_MODE_FOSSIL; - if(mode&EX_INR) + if(mode&EX_STDIN) i|=SBBSEXEC_MODE_DOS_IN; - if(mode&EX_OUTR) + if(mode&EX_STDOUT) i|=SBBSEXEC_MODE_DOS_OUT; sprintf(str," NT %u %u" ,cfg.node_num,i); @@ -604,9 +609,9 @@ int sbbs_t::external(const char* cmdline start.event=start_event; start.mode=SBBSEXEC_MODE_FOSSIL; - if(mode&EX_INR) + if(mode&EX_STDIN) start.mode|=SBBSEXEC_MODE_DOS_IN; - if(mode&EX_OUTR) + if(mode&EX_STDOUT) start.mode|=SBBSEXEC_MODE_DOS_OUT; sprintf(str," 95 %u %u" @@ -686,12 +691,12 @@ int sbbs_t::external(const char* cmdline } if(native && !(mode&EX_OFFLINE)) { - if(!(mode&EX_INR) && input_thread_running) { + if(!(mode&EX_STDIN) && input_thread_running) { pthread_mutex_lock(&input_thread_mutex); input_thread_mutex_locked=true; } - if(!(mode&EX_OUTR)) { /* Native Socket I/O program */ + if(!(mode&EX_STDOUT)) { /* Native Socket I/O program */ /* Enable the Nagle algorithm */ BOOL nodelay=FALSE; setsockopt(client_socket,IPPROTO_TCP,TCP_NODELAY,(char*)&nodelay,sizeof(nodelay)); @@ -784,7 +789,7 @@ int sbbs_t::external(const char* cmdline if(!online && !(mode&EX_OFFLINE)) { // Tell VXD/VDD and external that user hung-up if(was_online) { sprintf(str,"%s hung-up in external program",useron.alias); - logline("X!",str); + logline(LOG_NOTICE,"X!",str); hungup=time(NULL); if(!native) { if(nt) @@ -872,7 +877,7 @@ int sbbs_t::external(const char* cmdline len=avail; while(rdsizeof(wwiv_buf)) - errorlog("WWIV_BUF OVERRUN"); + lprintf(LOG_ERR,"WWIV_BUF OVERRUN"); } else if(telnet_mode&TELNET_MODE_OFF) { bp=buf; } else { bp=telnet_expand(buf, rd, telnet_buf, rd); if(rd>sizeof(telnet_buf)) - errorlog("TELNET_BUF OVERRUN"); + lprintf(LOG_ERR,"TELNET_BUF OVERRUN"); } if(rd>RingBufFree(&outbuf)) { - errorlog("output buffer overflow"); + lprintf(LOG_ERR,"output buffer overflow"); rd=RingBufFree(&outbuf); } RingBufWrite(&outbuf, bp, rd); @@ -969,16 +974,16 @@ int sbbs_t::external(const char* cmdline if(mode&EX_WWIV) { bp=wwiv_expand(buf, rd, wwiv_buf, rd, useron.misc, wwiv_flag); if(rd>sizeof(wwiv_buf)) - errorlog("WWIV_BUF OVERRUN"); + lprintf(LOG_ERR,"WWIV_BUF OVERRUN"); } else if(telnet_mode&TELNET_MODE_OFF) { bp=buf; } else { bp=telnet_expand(buf, rd, telnet_buf, rd); if(rd>sizeof(telnet_buf)) - errorlog("TELNET_BUF OVERRUN"); + lprintf(LOG_ERR,"TELNET_BUF OVERRUN"); } if(rd>RingBufFree(&outbuf)) { - errorlog("output buffer overflow"); + lprintf(LOG_ERR,"output buffer overflow"); rd=RingBufFree(&outbuf); } RingBufWrite(&outbuf, bp, rd); @@ -1308,14 +1313,19 @@ int sbbs_t::external(const char* cmdline int high_fd; struct timeval timeout; - if(online==ON_LOCAL) - eprintf(LOG_INFO,"Executing external: %s",cmdline); + if(online!=ON_REMOTE || cfg.node_num==0) + eprintf(LOG_DEBUG,"Executing external: %s",cmdline); + + if(startup_dir!=NULL && startup_dir[0] && !isdir(startup_dir)) { + errormsg(WHERE, ERR_CHK, startup_dir, 0); + return -1; + } if(startup_dir==NULL) startup_dir=nulstr; - XTRN_LOADABLE_MODULE; - XTRN_LOADABLE_JS_MODULE; + XTRN_LOADABLE_MODULE(cmdline,startup_dir); + XTRN_LOADABLE_JS_MODULE(cmdline,startup_dir); attr(cfg.color[clr_external]); /* setup default attributes */ @@ -1569,7 +1579,7 @@ int sbbs_t::external(const char* cmdline * it's a timed event. */ - if (!(mode&(EX_INR|EX_OUTR)) && online!=ON_LOCAL) + if (!(mode&(EX_STDIO)) && online!=ON_LOCAL) SAFECOPY(virtualconf,"-I\"serial { virtual com 1 }\""); else virtualconf[0] = '\0'; @@ -1578,7 +1588,7 @@ int sbbs_t::external(const char* cmdline * to intercept dos programs under Unix. */ - mode |= (EX_INR|EX_OUTR); + mode |= EX_STDIO; /* See if we have the dosemu link in the door's dir. If so, use the dosemu * that it points to as our command to execute. If not, use DOSemuPath. @@ -1636,7 +1646,7 @@ int sbbs_t::external(const char* cmdline #endif } - if(!(mode&EX_INR) && input_thread_running) { + if(!(mode&EX_STDIN) && input_thread_running) { lprintf(LOG_DEBUG,"Locking input thread mutex"); if(pthread_mutex_lock(&input_thread_mutex)!=0) errormsg(WHERE,ERR_LOCK,"input_thread_mutex",0); @@ -1650,7 +1660,7 @@ int sbbs_t::external(const char* cmdline } #endif - if((mode&EX_INR) && (mode&EX_OUTR)) { + if((mode&EX_STDIO)==EX_STDIO) { struct winsize winsize; struct termios term; memset(&term,0,sizeof(term)); @@ -1679,12 +1689,12 @@ int sbbs_t::external(const char* cmdline out_pipe[0]=in_pipe[1]; } else { - if(mode&EX_INR) + if(mode&EX_STDIN) if(pipe(in_pipe)!=0) { errormsg(WHERE,ERR_CREATE,"in_pipe",0); return(-1); } - if(mode&EX_OUTR) + if(mode&EX_STDOUT) if(pipe(out_pipe)!=0) { errormsg(WHERE,ERR_CREATE,"out_pipe",0); return(-1); @@ -1723,11 +1733,14 @@ int sbbs_t::external(const char* cmdline else #endif if(startup_dir!=NULL && startup_dir[0]) - chdir(startup_dir); + if(chdir(startup_dir)!=0) { + errormsg(WHERE,ERR_CHDIR,startup_dir,0); + return(-1); + } if(mode&EX_SH || strcspn(fullcmdline,"<>|;\"")!=strlen(fullcmdline)) { argv[0]=comspec; - argv[1]="-c"; + argv[1]=(char*)"-c"; argv[2]=fullcmdline; argv[3]=NULL; } else { @@ -1741,13 +1754,13 @@ int sbbs_t::external(const char* cmdline argv[argc]=NULL; } - if(mode&EX_INR && !(mode&EX_OUTR)) { + if(mode&EX_STDIN && !(mode&EX_STDOUT)) { close(in_pipe[1]); /* close write-end of pipe */ dup2(in_pipe[0],0); /* redirect stdin */ close(in_pipe[0]); /* close excess file descriptor */ } - if(mode&EX_OUTR && !(mode&EX_INR)) { + if(mode&EX_STDOUT && !(mode&EX_STDIN)) { close(out_pipe[0]); /* close read-end of pipe */ dup2(out_pipe[1],1); /* stdout */ #ifndef XTERN_LOG_STDERR @@ -1768,12 +1781,11 @@ int sbbs_t::external(const char* cmdline #endif execvp(argv[0],argv); - sprintf(str,"!ERROR %d executing %s",errno,argv[0]); - errorlog(str); + lprintf(LOG_ERR,"Node %d !ERROR %d executing %s",cfg.node_num,errno,argv[0]); _exit(-1); /* should never get here */ } - if(online!=ON_LOCAL) + if(online==ON_REMOTE) lprintf(LOG_INFO,"Node %d executing external: %s",cfg.node_num,fullcmdline); /* Disable Ctrl-C checking */ @@ -1784,8 +1796,8 @@ int sbbs_t::external(const char* cmdline close(err_pipe[1]); /* close write-end of pipe */ #endif - if(mode&EX_OUTR) { - if(!(mode&EX_INR)) + if(mode&EX_STDOUT) { + if(!(mode&EX_STDIN)) close(out_pipe[1]); /* close write-end of pipe */ while(!terminated) { if(waitpid(pid, &i, WNOHANG)!=0) /* child exited */ @@ -1796,12 +1808,12 @@ int sbbs_t::external(const char* cmdline if(!online && !(mode&EX_OFFLINE)) { sprintf(str,"%s hung-up in external program",useron.alias); - logline("X!",str); + logline(LOG_NOTICE,"X!",str); break; } /* Input */ - if(mode&EX_INR && RingBufFull(&inbuf)) { + if(mode&EX_STDIN && RingBufFull(&inbuf)) { if((wr=RingBufRead(&inbuf,buf,sizeof(buf)))!=0) write(in_pipe[1],buf,wr); } @@ -1894,13 +1906,13 @@ int sbbs_t::external(const char* cmdline /* Did expansion overrun the output buffer? */ if(output_len>sizeof(output_buf)) { - errorlog("OUTPUT_BUF OVERRUN"); + lprintf(LOG_ERR,"OUTPUT_BUF OVERRUN"); output_len=sizeof(output_buf); } /* Does expanded size fit in the ring buffer? */ if(output_len>RingBufFree(&outbuf)) { - errorlog("output buffer overflow"); + lprintf(LOG_ERR,"output buffer overflow"); output_len=RingBufFree(&outbuf); } @@ -1920,7 +1932,7 @@ int sbbs_t::external(const char* cmdline kill(pid, SIGKILL); // terminate child process } /* close unneeded descriptors */ - if(mode&EX_INR) + if(mode&EX_STDIN) close(in_pipe[1]); close(out_pipe[0]); } @@ -2008,7 +2020,7 @@ const char* quoted_string(const char* st /*****************************************************************************/ /* Returns command line generated from instr with %c replacments */ /*****************************************************************************/ -char* sbbs_t::cmdstr(char *instr, char *fpath, char *fspec, char *outstr) +char* sbbs_t::cmdstr(const char *instr, const char *fpath, const char *fspec, char *outstr) { char str[MAX_PATH+1],*cmd; int i,j,len; @@ -2047,7 +2059,7 @@ char* sbbs_t::cmdstr(char *instr, char * case 'G': /* Temp directory */ strcat(cmd,cfg.temp_dir); break; - case 'H': /* Port Handle or Hardware Flow Control */ + case 'H': /* Socket Handle */ strcat(cmd,ultoa(client_socket_dup,str,10)); break; case 'I': /* IP address */ @@ -2092,8 +2104,10 @@ char* sbbs_t::cmdstr(char *instr, char * break; case 'V': /* Synchronet Version */ sprintf(str,"%s%c",VERSION,REVISION); + strcat(cmd,str); break; - case 'W': /* Time-slice API type (mswtype) */ + case 'W': /* Columns (width) */ + strcat(cmd,ultoa(cols,str,10)); break; case 'X': strcat(cmd,cfg.shell[useron.shell]->code); @@ -2193,6 +2207,8 @@ char* DLLCALL cmdstr(scfg_t* cfg, user_t case 'B': /* Baud (DTE) Rate */ break; case 'C': /* Connect Description */ + if(user!=NULL) + strcat(cmd,user->modem); break; case 'D': /* Connect (DCE) Rate */ break; @@ -2207,6 +2223,8 @@ char* DLLCALL cmdstr(scfg_t* cfg, user_t case 'H': /* Port Handle or Hardware Flow Control */ break; case 'I': /* IP address */ + if(user!=NULL) + strcat(cmd,user->note); break; case 'J': strcat(cmd,cfg->data_dir); @@ -2247,8 +2265,9 @@ char* DLLCALL cmdstr(scfg_t* cfg, user_t break; case 'V': /* Synchronet Version */ sprintf(str,"%s%c",VERSION,REVISION); + strcat(cmd,str); break; - case 'W': /* Time-slice API type (mswtype) */ + case 'W': /* Columns/width */ break; case 'X': if(user!=NULL)