bool parse_tintin_command(char *command, char *arg) { /* this lines almost totally rewrote to put all command functions into a struct array. Size of array defined in tintin.h; Array itself defined in cmds.h. Struct: char alias - with it you can easily add aliases with same function name void function_name - main stuff char hlpfile - this field is for help_command. do not forget to link aliases to one help file. would rely it would not crash... En. */ CharLower(command); if(isdigit(*command)) { int a1=0; int a2=0; sscanf(command,"%d:%d",&a1,&a2); get_arg_in_braces(arg, arg, WITH_SPACES); do_cycle( 1, a1, 1, a2, arg ); /* do_cycle( bound1, bound2, step, delay, command); */ return false; } if(*command == cCommandChar) return false; for(int i=0;i<JMC_CMDS_NUM;i++) if((command[0]==jmc_cmds[i].alias[0]) &&(is_abrev(command,jmc_cmds[i].alias))) { (*(jmc_cmds[i].jmcfn))(arg); return true; } tintin_puts2(rs::rs(1145)); return false; }
void systemexec_command(wchar_t *arg) { wchar_t cmd[BUFFER_SIZE]; //* en //* due to an error in tintin.h (messed up STOP_SPACES and WITH_SPACES) // get_arg_in_braces(arg,cmd,STOP_SPACES,sizeof(cmd)/sizeof(wchar_t)-1); get_arg_in_braces(arg,cmd,WITH_SPACES,sizeof(cmd)/sizeof(wchar_t)-1); //* /en if ( !*cmd ) { tintin_puts2(rs::rs(1224)); return; } HANDLE hOutRead = NULL, hOutDup = NULL; HANDLE hOutWrite = NULL, hErrWrite = NULL; SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; if (!CreatePipe(&hOutRead, &hOutWrite, &sa, BUFFER_SIZE)) { systemexec_error: CloseHandle(hErrWrite); CloseHandle(hOutWrite); CloseHandle(hOutRead); tintin_puts2(rs::rs(1195)); return; } if (!DuplicateHandle( GetCurrentProcess(), hOutWrite, GetCurrentProcess(), &hErrWrite , 0, TRUE, DUPLICATE_SAME_ACCESS)) goto systemexec_error; if (!DuplicateHandle( GetCurrentProcess(), hOutRead, GetCurrentProcess(), &hOutDup , 0, FALSE, DUPLICATE_SAME_ACCESS)) goto systemexec_error; CloseHandle(hOutRead); PROCESS_INFORMATION pi; STARTUPINFO si; ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); //si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; si.dwFlags = STARTF_USESTDHANDLES; si.wShowWindow = SW_HIDE; si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); si.hStdError = hErrWrite; si.hStdOutput = hOutWrite; if (!CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NO_WINDOW | DETACHED_PROCESS, NULL, NULL, &si, &pi)) { DWORD err = GetLastError(); wchar_t buf[256]; swprintf(buf, L"GetLastError() = %d", err); tintin_puts2(buf); goto systemexec_error; } CloseHandle(pi.hThread); CloseHandle(pi.hProcess); CloseHandle(hErrWrite); CloseHandle(hOutWrite); PS_ITEM* psi = new PS_ITEM(hOutDup, pi.dwProcessId, cmd); PS_ITEM* pParam = new PS_ITEM(psi); EnterCriticalSection(&secSystemList); PsList.push_front(psi); LeaveCriticalSection(&secSystemList); DWORD dwId; HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&systemexec_thread, (LPVOID)pParam, 0, &dwId); if (!hThread) { delete psi; systemlist_delete(pi.dwProcessId); return; } CloseHandle(hThread); }
unsigned long __stdcall ConnectThread(void * pParam) { USES_CONVERSION; CoInitialize ((void*)COINIT_MULTITHREADED); tintin_puts2(rs::rs(1184)); SOCKET sock; int connectresult; struct sockaddr_in sockaddr; if(iswdigit(*strConnectAddress)) { /* interprete host part */ sockaddr.sin_addr.s_addr=inet_addr(W2A(strConnectAddress)); struct hostent *hp; if((hp=gethostbyaddr((const char*)&sockaddr, sizeof(sockaddr), AF_INET))==NULL) { wcscpy(MUDHostName, strConnectAddress); } else { wcscpy(MUDHostName, A2W(hp->h_name)); } } else { wcscpy(MUDHostName, strConnectAddress); struct hostent *hp; if((hp=gethostbyname(W2A(strConnectAddress)))==NULL) { tintin_puts2(rs::rs(1185)); return 0; } else { struct in_addr inad; wchar_t ipaddr[256]; inad.S_un.S_addr = *(long*)hp->h_addr_list[0]; swprintf(ipaddr , rs::rs(1186) , A2W(inet_ntoa(inad))); tintin_puts2(ipaddr); } memcpy((char *)&sockaddr.sin_addr, hp->h_addr, sizeof(sockaddr.sin_addr)); } if(iswdigit(*strConnectPort)) sockaddr.sin_port=htons((short)_wtoi(strConnectPort)); /* inteprete port part */ else { tintin_puts2(rs::rs(1187)); return 0; } START1: if((sock=socket(AF_INET, SOCK_STREAM, 0))<0) tintin_puts2(rs::rs(1188)); BOOL enable_opt = TRUE; /* Something more than TCP_NODELAY should be done in case MUD server frequently sends tiny packets. For example, if server sends prompt-line and IAC-GA in separate calls of send() then the first packet (prompt) wouldn't ACKed by windows core for 200 milliseconds regardless of Nagle's algorithm, leading to IAC-GA delayed for the same time. It's not a problem for visualizing since now JMC prints out all incoming data immidiately; but processing of prompt line in described situation by #acion and jmc.Incoming handlers will be delayed for 200 ms or value of Uncomplete line delay setting in case it is less than 200. Setting registry value on the client's machine (TcpAckFrequency := 1) is ugly, but effective solution. No other solution (i.e. disabling delayed acknowledgement for particular socket) was found for WinSock/WinSock2, WinXP/Vista/Win7/Win8. So it is responsibility of MUD servers to do wise and accurate TCP bufferisation, though obviously it is possible only in MUDs where the smallest time period between events (game-state updating period, "tick", time-quant) is less than 200ms. At this point I giving up to solve this issue completely and mark it as part of global MUD problem called "Telnet Curse". */ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char*)&enable_opt, sizeof(enable_opt))) { tintin_puts2(L"#Can't disable Nagle's algorithm"); } sockaddr.sin_family=AF_INET; reset_telnet_protocol(); multiline_length = 0; if (ulProxyAddress) { wchar_t buf[BUFFER_SIZE]; swprintf(buf, rs::rs(1303), (ulProxyAddress >> 24) & 0xff, (ulProxyAddress >> 16) & 0xff, (ulProxyAddress >> 8) & 0xff, (ulProxyAddress >> 0) & 0xff); tintin_puts2(buf); } else {
void write_line_mud(const wchar_t *line) { int len, OriginalLen; char buff[BUFFER_SIZE*8], coded[BUFFER_SIZE*4]; int ret = 0; if ( !MUDSocket ) { tintin_puts(rs::rs(1182) ); } else { OriginalLen = len = wcslen(line); wcscpy(strLastCommand, line); int count; if (MudCodePageUsed == 1200) { count = len * 2; memcpy(coded, line, count); } else if (MudCodePageUsed == 1201) { count = len * 2; utf16le_to_utf16be((wchar_t*)coded, line, len); } else { count = WideCharToMultiByte(MudCodePageUsed, 0, &line[ret], len, coded, sizeof(coded) - 1, NULL, NULL); } if ( bIACSendSingle ) memcpy (buff, coded, count); else { char* ptr = buff; int nIACs = 0; for ( int i = 0; i < count; i ++ ) { if ( coded[i] == (char)0xff ) { *ptr++ = (char)0xff; nIACs ++; } *ptr++ = coded[i]; } count += nIACs; } if ( buff[count-1] != 0xA ) { buff[count] = 0xA; buff[count+1] = 0; count ++; } int sent = tls_send(MUDSocket, buff, count); if (sent < 0) ret = sent; else ret = len; } //* en wchar_t daaString[BUFFER_SIZE+2]; int daalen = 0; if (bDaaMessage) { daaString[daalen++] = L'<'; for(int i = 0; i < wcslen(line) && i < BUFFER_SIZE; i++) daaString[daalen++]=L'*'; daaString[daalen++] = L'>'; } daaString[daalen] = 0; if (bDisplayInput && !(SocketFlags & SOCKECHO) && wcslen(line) > 0) { std::wstring str; str = USER_INPUT_MARK; str += L"\x1B[0;33m"; str += bDaaMessage ? daaString : line; str += L"\x1B[0m"; tintin_puts2(str.c_str()); if (hLogFile) { log(processLine(bDaaMessage ? daaString : line)); log(L"\n"); } add_line_to_scrollbuffer(bDaaMessage ? daaString : line); } //* en bDaaMessage = FALSE; //* /en #ifdef _DEBUG_LOG // -------- Write external log if (hExLog ) { char exLogText[128]; DWORD Written; swprintf(exLogText , L"\r\n#SEND got %d bytes sent %d bytes#\r\n" , len, ret ); WriteFile(hExLog , exLogText , wcslen(exLogText) , &Written, NULL); WriteFile(hExLog , buff , len , &Written, NULL); } #endif if ( ret < 0 ) { tintin_puts2(rs::rs(1183) ); } }
void KillAll(int mode, char *arg) { int Show = 0; if ( arg && *arg != '0') { Show = 1; } GROUP_INDEX gind; // !!! delete groups here, GROUP should remove EVERY object in it, but later gind = GroupList.begin(); while ( gind != GroupList.end () ) { delete gind->second; gind ++; } GroupList.clear (); VAR_INDEX vind = VarList.begin(); while (vind != VarList.end() ) { delete vind->second; vind++; } VarList.clear (); HOTKEY_INDEX hind = HotkeyList.begin(); while ( hind != HotkeyList.end() ) { delete hind->second; hind++; } HotkeyList.clear (); GroupList[DEFAULT_GROUP_NAME] = new CGROUP(DEFAULT_GROUP_NAME); //vls-begin// script files SCRIPTFILE_INDEX sfind = ScriptFileList.begin(); while ( sfind != ScriptFileList.end() ) { delete (*sfind); sfind++; } ScriptFileList.clear(); //vls-end// switch (mode) { case CLEAN: kill_list(common_subs); common_subs=init_list(); kill_list(common_antisubs); common_antisubs=init_list(); /* CHANGED to kill path stuff as well */ kill_list(common_path); common_path=init_list(); kill_list(common_pathdirs); common_pathdirs=init_pathdir_list(); if ( Show ) tintin_puts2(rs::rs(1094)); acnum = subnum = hinum = antisubnum = 0; break; case END: kill_list(common_subs); kill_list(common_antisubs); kill_list(common_path); kill_list(common_pathdirs); break; } /* Switch */ }
void shownode_list(struct listnode *nptr) { char temp[BUFFER_SIZE]; sprintf(temp, "{%s}={%s}", nptr->left, nptr->right); tintin_puts2(temp); }
void tickon_command(wchar_t*arg) { bTickStatus=TRUE; tintin_puts2(rs::rs(1179)); }
void tickoff_command(wchar_t*arg) { bTickStatus=FALSE; tintin_puts2(rs::rs(1178)); }
int do_one_inside(int begin, int end) { /* int prev, ptr, highest, loc, ploc, next, nval, flag; */ int prev, ptr, highest, loc, ploc, next; while(1) { ptr=0; if (begin>-1) ptr=stacks[begin][0]; highest=16; loc= -1; ploc= -1; prev= -1; while (ptr<end) { if (stacks[ptr][1]<highest) { highest=stacks[ptr][1]; loc=ptr; ploc=prev; } prev=ptr; ptr=stacks[ptr][0]; } if (highest==15) { if (begin>-1) { stacks[begin][1]=15; stacks[begin][2]=stacks[loc][2]; stacks[begin][0]=stacks[end][0]; return 1; } else { stacks[0][0]=stacks[end][0]; stacks[0][1]=15; stacks[0][2]=stacks[loc][2]; return 1; } } else if (highest==2) { next=stacks[loc][0]; if (stacks[next][1]!=15 || stacks[next][0]==0) { return 0; } stacks[loc][0]=stacks[next][0]; stacks[loc][1]=15; stacks[loc][2]=!stacks[next][2]; } else { next=stacks[loc][0]; if (ploc== -1 || stacks[next][0]==0 || stacks[next][1]!=15) return 0; if (stacks[ploc][1]!=15) return 0; switch (highest) { case 3: /* highest priority is * */ stacks[ploc][0]=stacks[next][0]; stacks[ploc][2]*=stacks[next][2]; break; case 4: /* highest priority is / */ stacks[ploc][0]=stacks[next][0]; stacks[ploc][2]/=stacks[next][2]; break; case 5: /* highest priority is + */ stacks[ploc][0]=stacks[next][0]; stacks[ploc][2]+=stacks[next][2]; break; case 6: /* highest priority is - */ stacks[ploc][0]=stacks[next][0]; stacks[ploc][2]-=stacks[next][2]; break; case 7: /* highest priority is > */ stacks[ploc][0]=stacks[next][0]; stacks[ploc][2]=(stacks[ploc][2]>stacks[next][2]); break; case 8: /* highest priority is >= */ stacks[ploc][0]=stacks[next][0]; stacks[ploc][2]=(stacks[ploc][2]>=stacks[next][2]); break; case 9: /* highest priority is < */ stacks[ploc][0]=stacks[next][0]; stacks[ploc][2]=(stacks[ploc][2]<stacks[next][2]); break; case 10: /* highest priority is <= */ stacks[ploc][0]=stacks[next][0]; stacks[ploc][2]=(stacks[ploc][2]<=stacks[next][2]); break; case 11: /* highest priority is == */ stacks[ploc][0]=stacks[next][0]; stacks[ploc][2]=(stacks[ploc][2]==stacks[next][2]); break; case 12: /* highest priority is != */ stacks[ploc][0]=stacks[next][0]; stacks[ploc][2]=(stacks[ploc][2]!=stacks[next][2]); break; case 13: /* highest priority is && */ stacks[ploc][0]=stacks[next][0]; stacks[ploc][2]=(stacks[ploc][2]&&stacks[next][2]); break; case 14: /* highest priority is || */ stacks[ploc][0]=stacks[next][0]; stacks[ploc][2]=(stacks[ploc][2]||stacks[next][2]); break; default: tintin_puts2(rs::rs(1087)); return 0; } } } }
int conv_to_ints(wchar_t *arg) { int i, flag; wchar_t *ptr, *tptr; i=0; ptr=arg; while (*ptr) { if (*ptr==L' ') ; else if (*ptr==L'(') { stacks[i][1]=0; } else if(*ptr==L')') { stacks[i][1]=1; } else if(*ptr==L'!') { if (*(ptr+1)==L'=') { stacks[i][1]=12; ptr++; } else stacks[i][1]=2; } else if(*ptr==L'*') { stacks[i][1]=3; } else if(*ptr==L'/') { stacks[i][1]=4; } else if(*ptr==L'+') { stacks[i][1]=5; } else if(*ptr==L'-') { flag= -1; if (i>0) flag=stacks[i-1][1]; if (flag==15) stacks[i][1]=6; else { tptr=ptr; ptr++; while(iswdigit(*ptr)) ptr++; swscanf(tptr,L"%d",&stacks[i][2]); stacks[i][1]=15; ptr--; } } else if(*ptr==L'>') { if (*(ptr+1)==L'=') { stacks[i][1]=8; ptr++; } else stacks[i][1]=7; } else if(*ptr==L'<') { if (*(ptr+1)==L'=') { ptr++; stacks[i][1]=10; } else stacks[i][1]=9; } else if(*ptr==L'=') { stacks[i][1]=11; if (*(ptr+1)==L'=') ptr++; } else if(*ptr==L'&') { stacks[i][1]=13; if (*(ptr+1)==L'&') ptr++; } else if(*ptr==L'|') { stacks[i][1]=14; if (*(ptr+1)==L'|') ptr++; } else if (iswdigit(*ptr)) { stacks[i][1]=15; tptr=ptr; while (iswdigit(*ptr)) ptr++; swscanf(tptr,L"%d",&stacks[i][2]); ptr--; } else if (*ptr==L'T') { stacks[i][1]=15; stacks[i][2]=1; } else if(*ptr==L'F') { stacks[i][1]=15; stacks[i][2]=0; } else { tintin_puts2(rs::rs(1086)); return 0; } if (*ptr!=L' ') { stacks[i][0]=i+1; i++; } ptr++; } if (i>0) stacks[i][0]=0; return 1; }
//* en void spit_command(char *arg) { char filename[BUFFER_SIZE], spformat[BUFFER_SIZE], soptions[BUFFER_SIZE], buffer[BUFFER_SIZE], *cptr1/*,*cptr2,*cptr3*/; FILE *myfile; BOOL bPassSpace = FALSE; BOOL bSilent = FALSE; arg=get_arg_in_braces(arg, filename, STOP_SPACES); arg=get_arg_in_braces(arg, spformat, WITH_SPACES); arg=get_arg_in_braces(arg, soptions, STOP_SPACES); if ( !filename || !*filename ) { tintin_puts2(rs::rs(1173)); return; } if ( !spformat || !*spformat ) { strcpy(spformat,"%0"); } BOOL hasD = FALSE; for(cptr1=spformat;*cptr1&&*cptr1!='\0';cptr1++) if(*cptr1=='%'&&*(cptr1+1)=='0') hasD = TRUE; if(!hasD) strcpy(cptr1," %0\0"); for(cptr1=soptions;*cptr1&&*cptr1!='\0';cptr1++) { if(*cptr1=='n') bPassSpace = TRUE; if(*cptr1=='s') bSilent = TRUE; } if((myfile=fopen(filename, "r"))==NULL) { char buff[MAX_PATH]; sprintf(buff, rs::rs(1174), filename); tintin_puts2(buff); return; } while(fgets(buffer, sizeof(buffer), myfile)) { char cbuffer[BUFFER_SIZE]; if((*buffer=='\n'||strlen(buffer)<2)&&bPassSpace) continue; /* for(cptr1=spformat,cptr3=cbuffer; *cptr1 && *cptr1!='\0'; cptr1++,cptr3++) if(*cptr1=='@') { for(cptr2=buffer;*cptr2&&*cptr2!='\0'&&*cptr2!='\n';cptr2++,cptr3++) *cptr3=*cptr2; cptr3--; } else *cptr3=*cptr1; *cptr3='\0'; */ for(cptr1=buffer;*cptr1&&*cptr1!='\n';cptr1++); *cptr1='\0'; sprintf(vars[0], "%s", buffer); substitute_vars(spformat,cbuffer); parse_input(cbuffer); } fclose(myfile); if(!bSilent) tintin_puts2(rs::rs(1175)); }
void grab_command(char *arg) { char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE], arg3[BUFFER_SIZE], buffer[BUFFER_SIZE], result[BUFFER_SIZE], *cptr; FILE *myfile; int needLine = 0; BOOL wn = FALSE; arg=get_arg_in_braces(arg, arg1, STOP_SPACES); arg=get_arg_in_braces(arg, arg2, WITH_SPACES); arg=get_arg_in_braces(arg, arg3, WITH_SPACES); if(*arg1 && isdigit(*arg1)) { wn = TRUE; needLine = atoi(arg1); } else if(!strcmpi(arg1,lastGrab)) needLine = lastLine+1; else { needLine = 1; maxLines = count_lines(arg1); } if (((!wn)&&(!arg1||!*arg1))||((wn)&&(!arg2||!*arg2))) { tintin_puts2(rs::rs(1173)); return; } if (((!wn)&&(!arg2||!*arg2))||((wn)&&(!arg3||!*arg3))) { strcpy(wn?arg3:arg2,"%0\0"); } BOOL hasD = FALSE; cptr=wn?arg3:arg2; for(;*cptr&&*cptr!='\0';cptr++) if(*cptr=='%'&&*(cptr+1)=='0') hasD = TRUE; if(!hasD) strcpy(cptr," %0\0"); if((myfile=fopen(wn?arg2:arg1, "r"))==NULL) { char buff[MAX_PATH]; sprintf(buff, rs::rs(1174), wn?arg2:arg1); tintin_puts2(buff); return; } int currLine = 0; while(fgets(buffer, sizeof(buffer), myfile)) { currLine++; if(currLine == needLine) { for(cptr=buffer;*cptr&&*cptr!='\n';cptr++); *cptr='\0'; sprintf(vars[0], "%s", buffer); substitute_vars(wn?arg3:arg2,result); parse_input(result); break; } } lastLine = (needLine != maxLines)?needLine:0; strcpy(lastGrab,wn?arg2:arg1); fclose(myfile); }
void parse_input(char *input) { char command[BUFFER_SIZE], arg[BUFFER_SIZE], result[BUFFER_SIZE]; char *input2; bPasswordEcho = TRUE; if(*input=='\0') { write_line_mud(""); return ; } if ( verbatim && *input == cCommandChar && *(input+1) == 'v' ) {// check verbatim command char command[BUFFER_SIZE]; char* input2=get_arg_stop_spaces(input+1, command); if(command[0] == 'v' && is_abrev(command, "verbatim")){ char arg[BUFFER_SIZE]; get_arg_all(input2, arg); verbatim_command(arg); return; } } if (verbatim ) { write_line_mud(input); return ; } if (*input==verbatim_char) { input++; write_line_mud(input); return ; } substitute_myvars(input, result); input2=result; while(*input2) { //* en:colon // if(*input2==';') if(*input2==cCommandDelimiter||(bColon && *input2==';')&&*(input2-1)!='\\') input2++; //*/en input2=get_arg_stop_spaces(input2, command); input2=get_arg_all(input2, arg); //* en:prefix if(s_prefix[0] && command[0] != cCommandChar) { char p_command[BUFFER_SIZE]; strcpy(p_command,command); strcat(p_command," "); strcat(p_command,arg); strcpy(command,s_prefix); strcpy(arg,p_command); } //*/en if(*command==cCommandChar) { if (bDisplayCommands) { // output command in square brackets char strInputCommand[BUFFER_SIZE], strOutputBuffer[BUFFER_SIZE]; strcpy(strInputCommand, "\n["); strcat(strInputCommand, command); if (*arg != '\0') { strcat(strInputCommand, " "); strcat(strInputCommand, arg); } strcat(strInputCommand, "]"); add_codes(strInputCommand, strOutputBuffer, "brown", TRUE); tintin_puts2(strOutputBuffer); if (hLogFile.is_open()) { log(strInputCommand); } } parse_tintin_command(command+1, arg); } //* en:comments else if(*command==cCommentChar); //*/en else { //* en:waits if(iWaitState>0) { char *ptr1,*ptr2; for(ptr1=mQueue;*ptr1&&*ptr1!='\0';ptr1++); *ptr1++=cCommandDelimiter; for(ptr2=command;*ptr2&&*ptr2!='\0';ptr2++,ptr1++) *ptr1=*ptr2; if(*arg) *ptr1++=' '; for(ptr2=arg;*ptr2&&*ptr2!='\0';ptr2++,ptr1++) *ptr1=*ptr2; *ptr1++='\0'; continue; } //* en ALIAS_INDEX ind; if( (ind=AliasList.find(command)) != AliasList.end() && ind->second->m_pGroup->m_bEnabled ) { int i; char *cpsource, *cpsource2, newcommand[BUFFER_SIZE], end; strcpy(vars[0], arg); for(i=1, cpsource=arg; i<10; i++) { /* Next lines CHANGED to allow argument grouping with aliases */ while (*cpsource == ' ') cpsource++; end = (*cpsource == '{') ? '}' : ' '; cpsource = (*cpsource == '{') ? cpsource+1 : cpsource; for(cpsource2=cpsource; *cpsource2 && *cpsource2!=end; cpsource2++); strncpy(vars[i], cpsource, cpsource2-cpsource); *(vars[i]+(cpsource2-cpsource))='\0'; cpsource=(*cpsource2) ? cpsource2+1 : cpsource2; } ALIAS* pal = ind->second; prepare_actionalias((char*)pal->m_strRight.data(), newcommand); if(!strcmp(pal->m_strRight.data(), newcommand) && *arg) { strcat(newcommand, " "); strcat(newcommand, arg); } parse_input(newcommand); } else if(speedwalk && !*arg && is_speedwalk_dirs(command)) do_speedwalk(command); else { get_arg_with_spaces(arg,arg); write_com_arg_mud(command, arg); } } } return; }