/****************************************************************************** * Copyright (c) 2000-2019 Ericsson Telecom AB * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html * * Contributors: * Jozsef Gyurusi - initial implementation and initial documentation * Adam Delic * Antal Wuh.Hen.Chang * Attila Balasko * Gabor Szalai * Istvan Sandor * Peter Kremer * Zoltan Jasz ******************************************************************************/ // // File: PIPEasp_PT.cc // Description: Source code of PIPE testport implementation // Rev: R7D // Prodnr: CNL 113 334 // #include "PIPEasp_PT.hh" #include //kill #include //pipe #include //errno #include //isspace #include //FD_ZERO #include // sys_errlist #include //wait #include //wait #include //wait #include #ifndef PIPE_BUF_SIZE #define PIPE_BUF_SIZE 65534 #endif #if defined LINUX || defined FREEBSD || defined WIN32 #include #endif #if defined SOLARIS || defined SOLARIS8 #include #include #include #include #include ///////////////////////////////////// int forkpty_solaris (int *amaster, char *name, struct termios *termp, struct winsize *winp) { int fdm, fds; char *slavename; pid_t pid; fdm = open("/dev/ptmx", O_RDWR); /* open master */ grantpt(fdm); /* change permission of slave */ unlockpt(fdm); /* unlock slave */ slavename = ptsname(fdm); /* get name of slave */ if (name) strcpy(name, slavename); *amaster = fdm; if ((pid = fork()) < 0) { return pid; /* error */ } else if (pid != 0) { /* parent */ return pid; } else { /* child */ pid_t pgid; /* create a new session */ pgid = setsid(); if (pgid == -1) { perror("forkpty_solaris() setsid failed"); return -1; } fds = open(slavename, O_RDWR); /* open slave */ ioctl(fds, I_PUSH, "ptem"); /* push ptem */ ioctl(fds, I_PUSH, "ldterm"); /* push ldterm */ dup2(fds, 0); dup2(fds, 1); dup2(fds, 2); ioctl(fds, TIOCSPGRP, &pgid); /* magic */ if (termp) ioctl(fds, TCSETS, termp); if (winp) ioctl(fds, TIOCSWINSZ, winp); return pid; } } ///////////////////////////////////// #define forkpty forkpty_solaris #endif namespace PIPEasp__Types { BOOLEAN f__PIPE__WIFEXITED(const INTEGER& code){ int c=(int)code; return WIFEXITED(c); } INTEGER f__PIPE__WEXITSTATUS(const INTEGER& code){ int c=(int)code; return WEXITSTATUS(c); } ; BOOLEAN f__PIPE__WIFSIGNALED(const INTEGER& code){ int c=(int)code; return WIFSIGNALED(c); } INTEGER f__PIPE__WTERMSIG(const INTEGER& code){ int c=(int)code; return WTERMSIG(c); } } namespace PIPEasp__PortType { PIPEasp__PT::PIPEasp__PT(const char *par_port_name) : PIPEasp__PT_BASE(par_port_name) , maindata_len(0) , maindata_used(0) , threaddata_len(0) , main_data(NULL) , thread_data(NULL) , lineMode(true) // , processPid(-1) // pid of the process currently executing , debugAllowed(false) // debug disabled by default { FD_ZERO(&working_set); process_buffer.clear(); processServerPid=-1; pty_echo=false; waitforpidrelease=false; processServerDown=-1; processServerUp=-1; max_fd=-1; } PIPEasp__PT::~PIPEasp__PT() { //printf("processServerPid %d\r\n",processServerPid); if(processServerPid>0){ // char kill_msg[5]; // kill_msg[0]=1; // kill_msg[1]=0; // kill_msg[2]=0; // kill_msg[3]=0; // kill_msg[4]=0; // write(processServerDown,kill_msg,3); close(processServerDown); int status=0; wait(&status); } if(main_data){ for(int i=0;istdout_buffer){delete (main_data+i)->stdout_buffer;}; if((main_data+i)->stderr_buffer){delete (main_data+i)->stderr_buffer;}; } Free(main_data); } if(thread_data){ Free(thread_data); } } void PIPEasp__PT::set_parameter(const char *parameter_name, const char *parameter_value) { if (!strcasecmp(parameter_name, "debug")) { if (!strcasecmp(parameter_value,"YES")) { debugAllowed = true; } } if (!strcasecmp(parameter_name, "suppress_pty_echo")) { if (!strcasecmp(parameter_value,"YES")) { pty_echo = true; } } if (!strcasecmp(parameter_name, "auto_pid_release")) { if (!strcasecmp(parameter_value,"no")) { waitforpidrelease = true; } else { waitforpidrelease = false; } } } /*void PIPEasp__PT::Event_Handler(const fd_set *read_fds, const fd_set *write_fds, const fd_set *error_fds, double time_since_last_call)*/ void PIPEasp__PT::Handle_Fd_Event_Readable(int /*fd*/) { log("PIPEasp__PT::Event_Handler called"); long nBytes; int r; nBytes = PIPE_BUF_SIZE; unsigned char* buffer; size_t end_len = nBytes; process_buffer.get_end(buffer, end_len); r = read(processServerUp,buffer,(int)nBytes); log("read returned %d",r); if (r <= 0) { log("ttcn_pipe_port: read problem from server process. %d, %d, %s\n", r, errno, strerror(errno)); close(processServerUp); close(processServerDown); Uninstall_Handler(); int status=0; wait(&status); processServerPid=-1; } else { process_buffer.increase_length(r); int msg_len; int buff_len=process_buffer.get_len(); const unsigned char* buff_data=process_buffer.get_data(); // log("process buffer length %d",buff_len); // if(buff_len>=3) { // const unsigned char* data=process_buffer.get_data(); // log("buffer data %02x %02x %02x", data[0],data[1],data[2]); // } log_buffer(buff_data,buff_len); while((msg_len=get_len(process_buffer))!=-1){ const unsigned char* msg=process_buffer.get_data(); int p_id; switch(msg[0]){ case 4: // stdout p_id=((int)msg[5]<<8) + (int)msg[6]; if (!((main_data+p_id)->processExecuting)) { TTCN_warning("Unexpected message from stdout, no command is executing"); } else { log("Incoming stdout message received from process: %d",msg_len); } (main_data+p_id)->stdout_buffer->put_s(msg_len-2,msg+7); sendStdout(p_id); break; case 5: // stderr p_id=((int)msg[5]<<8) + (int)msg[6]; if (!((main_data+p_id)->processExecuting)) { TTCN_warning("Unexpected message from stderr, no command is executing"); } else { log("Incoming stderr message received from process"); } (main_data+p_id)->stderr_buffer->put_s(msg_len-2,msg+7); sendStderr(p_id); break; case 6: // end of process p_id=((int)msg[5]<<8) + (int)msg[6]; (main_data+p_id)->processExitCode=((int)msg[7]<<24) + ((int)msg[8]<<16) + ((int)msg[9]<<8) + (int)msg[10]; handle_childDeath(p_id); break; default: break; } process_buffer.set_pos(5+msg_len); process_buffer.cut(); buff_len=process_buffer.get_len(); buff_data=process_buffer.get_data(); // log("process buffer length %d",buff_len); // if(buff_len>=3) { // const unsigned char* data=process_buffer.get_data(); // log("buffer data %02x %02x %02x", data[0],data[1],data[2]); // } log_buffer(buff_data,buff_len); } } } void PIPEasp__PT::user_map(const char *system_port) { log("%s mapping, child pid: %d",system_port, processServerPid); Handler_Add_Fd_Read(processServerUp); maindata_len=1; maindata_used=1; main_data=(pipedata_main*)Malloc(sizeof(pipedata_main)); setup_pipedata_main(0); main_data[0].reuse=true; send_p_id_to_thread(0); unsigned char msg[6]; msg[0]=11; msg[1]=0; msg[2]=0; msg[3]=0; msg[4]=1; msg[5]= pty_echo; write(processServerDown,msg,6); } void PIPEasp__PT::setup_pipedata_main(int idx){ main_data[idx].state=1; // 0- free, 1-allocated main_data[idx].reuse=false; main_data[idx].processExecuting=false; // true if process is executing: disable new processes main_data[idx].binaryMode=false; // true if result should be returned in as binary data main_data[idx].disableSend=false; // if true sendStdout/err is disabled main_data[idx].ptyMode=false; // pty mode main_data[idx].stdout_buffer=new TTCN_Buffer; // data sent to stdout main_data[idx].stderr_buffer=new TTCN_Buffer; // data sent to stderr main_data[idx].processExitCode=-1; // exit code of the process } void PIPEasp__PT::send_p_id_to_thread(const int p_id){ unsigned char msg[7]; msg[0]=12; msg[1]=0; msg[2]=0; msg[3]=0; msg[4]=2; msg[5]= (p_id >> 8) & 0xFF; msg[6]= p_id & 0xFF; write(processServerDown,msg,7); } void PIPEasp__PT::user_unmap(const char *system_port) { log("user_unmap started %s",system_port); //printf("****user_unmap started %s",system_port); Uninstall_Handler(); log("Sending unmap to processServer"); TTCN_Buffer out_buff; out_buff.clear(); process_buffer.clear(); int write_len=put_msg(out_buff,9,0,NULL,-1); // Sending unmap to processServer log("Sending unmap message to the fork server %d",write_len); int res=write(processServerDown,out_buff.get_data(),write_len); log("Message sent %d",res); if(main_data){ for(int i=0;istdout_buffer){delete (main_data+i)->stdout_buffer;}; if((main_data+i)->stderr_buffer){delete (main_data+i)->stderr_buffer;}; } Free(main_data); main_data=NULL; } log("user_unmap finsihed"); } void PIPEasp__PT::user_start() { start_child(); } void PIPEasp__PT::start_child() { if(processServerPid != -1) return; int pipefd[2]; int pipefd2[2]; if (pipe(pipefd) != 0) { return; } if (pipe(pipefd2) != 0) { return; } processServerPid=fork(); if (processServerPid < 0) { // // Error // // close the pipes close(pipefd[0]); close(pipefd[1]); close(pipefd2[0]); close(pipefd2[1]); processServerUp=-1; processServerDown=-1; } else if (processServerPid == 0) { // // Child process // // close the parent end of the pipes processServerUp=pipefd2[1]; processServerDown=pipefd[0]; // This is a hack // All fds (except the pipe) should be closed in order to avoid some "funny" communication lost between the mctr and PTC // There is no easy way to get the list of the open fds // The start_child called when the test port is started first time // which is right after the component initialization/first test case start // fd 0-3 are the standard io fds // there are only 2 or 3 fd opened by the TITAN run time (they should be closed) // So it is assummed the max value of the fd below 42 for(int i=4;i<42;i++){ if((i!=processServerUp) && (i!=processServerDown)){ close(i); } } close(pipefd[1]); close(pipefd2[0]); processHandler(); //printf("exit\r\n"); //throw TC_Error(); _exit(0); // end of child process } else { // // Parent process // // TTCN_warning("Process started with pid: %d\r\n", processServerPid); // close child end of the pipes processServerUp=pipefd2[0]; processServerDown=pipefd[1]; close(pipefd[0]); close(pipefd2[1]); } } void PIPEasp__PT::user_stop() { } /************************************* * Specific outgoing_send functions *************************************/ void PIPEasp__PT::handle_message(const int p_id, const PIPEasp__Types::ASP__PExecute& send_par) { if(!pipe_id_valid(p_id)){ sendError("Pipe Test Port: Pipe execution id (p_id) is not valid",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): Pipe execution id (p_id=%d) is not valid: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } if ((main_data+p_id)->processExecuting) { sendError("Pipe Test Port: Command already executing",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): Command already executing (p_id=%d). Following ASP is ignored: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } PIPEasp__Types::ASP__PExecuteBackground message_PExecuteBackground; // starting command message_PExecuteBackground.command() = send_par.command(); handle_message(p_id,message_PExecuteBackground); // sending input PIPEasp__Types::ASP__PStdin message_PStdin; message_PStdin.stdin_() = send_par.stdin_(); handle_message(p_id,message_PStdin); main_data[p_id].disableSend = true; // closing stdin pipe: handle_message(p_id,PIPEasp__Types::ASP__PEndOfInput()); } void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PExecute& send_par) { log("PIPEasp__PT::outgoing_send_PExecute called"); handle_message(0,send_par); log("PIPEasp__PT::outgoing_send_PExecute exited"); } void PIPEasp__PT::handle_message(const int p_id,const PIPEasp__Types::ASP__PExecutePty& send_par) { if(!pipe_id_valid(p_id)){ sendError("Pipe Test Port: Pipe execution id (p_id) is not valid",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): Pipe execution id (p_id=%d) is not valid: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } if ((main_data+p_id)->processExecuting) { sendError("Pipe Test Port: Command already executing",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): Command already executing (p_id=%d). Following ASP is ignored: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } PIPEasp__Types::ASP__PExecuteBackgroundPty message_PExecuteBackgroundPty; // starting command message_PExecuteBackgroundPty.command() = send_par.command(); handle_message(p_id,message_PExecuteBackgroundPty); // sending input PIPEasp__Types::ASP__PStdin message_PStdin; message_PStdin.stdin_() = send_par.stdin_(); handle_message(p_id,message_PStdin); (main_data+p_id)->disableSend = true; // closing stdin pipe: handle_message(p_id,PIPEasp__Types::ASP__PEndOfInput()); } void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PExecutePty& send_par) { log("PIPEasp__PT::outgoing_send_PExecutePty called"); handle_message(0,send_par); log("PIPEasp__PT::outgoing_send_PExecutePty exited"); } void PIPEasp__PT::handle_message(const int p_id,const PIPEasp__Types::ASP__PExecuteBinary& send_par) { if(!pipe_id_valid(p_id)){ sendError("Pipe Test Port: Pipe execution id (p_id) is not valid",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): Pipe execution id (p_id=%d) is not valid: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } if (main_data[p_id].processExecuting) { sendError("Pipe Test Port: Command already executing",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): Command already executing (p_id=%d). Following ASP is ignored: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } PIPEasp__Types::ASP__PExecuteBackground message_PExecuteBackground; // starting command message_PExecuteBackground.command() = send_par.command(); handle_message(p_id,message_PExecuteBackground); // sending input PIPEasp__Types::ASP__PStdinBinary message_PStdinBinary; message_PStdinBinary.stdin_() = send_par.stdin_(); handle_message(p_id,message_PStdinBinary); main_data[p_id].disableSend = true; // closing stdin pipe: handle_message(p_id,PIPEasp__Types::ASP__PEndOfInput()); log("PIPEasp__PT::outgoing_send_PExecuteBinary exited"); } void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PExecuteBinary& send_par) { log("PIPEasp__PT::outgoing_send_PExecuteBinary called"); handle_message(0,send_par); log("PIPEasp__PT::outgoing_send_PExecuteBinary exited"); } void PIPEasp__PT::handle_message(const int p_id,const PIPEasp__Types::ASP__PExecuteBinaryPty& send_par) { if(!pipe_id_valid(p_id)){ sendError("Pipe Test Port: Pipe execution id (p_id) is not valid",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): Pipe execution id (p_id=%d) is not valid: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } if (main_data[p_id].processExecuting) { sendError("Pipe Test Port: Command already executing",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): Command already executing (p_id=%d). Following ASP is ignored: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } PIPEasp__Types::ASP__PExecuteBackgroundPty message_PExecuteBackgroundPty; // starting command message_PExecuteBackgroundPty.command() = send_par.command(); handle_message(p_id,message_PExecuteBackgroundPty); // sending input PIPEasp__Types::ASP__PStdinBinary message_PStdinBinary; message_PStdinBinary.stdin_() = send_par.stdin_(); handle_message(p_id,message_PStdinBinary); main_data[p_id].disableSend = true; // closing stdin pipe: handle_message(p_id,PIPEasp__Types::ASP__PEndOfInput()); } void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PExecuteBinaryPty& send_par) { log("PIPEasp__PT::outgoing_send_PExecuteBinaryPty called"); handle_message(0,send_par); log("PIPEasp__PT::outgoing_send_PExecuteBinaryPty exited"); } void PIPEasp__PT::handle_message(const int p_id,const PIPEasp__Types::ASP__PExecuteBackground& send_par) { if(!pipe_id_valid(p_id)){ sendError("Pipe Test Port: Pipe execution id (p_id) is not valid",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): Pipe execution id (p_id=%d) is not valid: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } if (main_data[p_id].processExecuting) { sendError("Pipe Test Port: Command already executing",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): Command already executing (p_id=%d). Following ASP is ignored: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } TTCN_Buffer out_buff; out_buff.clear(); int write_len=put_msg(out_buff,2,send_par.command().lengthof(),(const unsigned char*)(const char*)send_par.command(),p_id); write(processServerDown,out_buff.get_data(),write_len); main_data[p_id].processExecuting=true; log("PIPEasp__PT::outgoing_send_PExecuteBackground exited"); } void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PExecuteBackground& send_par) { log("PIPEasp__PT::outgoing_send_PExecuteBackground called"); handle_message(0,send_par); log("PIPEasp__PT::outgoing_send_PExecuteBackground exited"); } void PIPEasp__PT::handle_message(const int p_id,const PIPEasp__Types::ASP__PExecuteBackgroundPty& send_par) { if(!pipe_id_valid(p_id)){ sendError("Pipe Test Port: Pipe execution id (p_id) is not valid",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): Pipe execution id (p_id=%d) is not valid: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } if (main_data[p_id].processExecuting) { sendError("Pipe Test Port: Command already executing",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): Command already executing (p_id=%d). Following ASP is ignored: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } TTCN_Buffer out_buff; out_buff.clear(); int write_len=put_msg(out_buff,10,send_par.command().lengthof(),(const unsigned char*)(const char*)send_par.command(),p_id); write(processServerDown,out_buff.get_data(),write_len); main_data[p_id].processExecuting=true; log("PIPEasp__PT::outgoing_send_PExecuteBackgroundPty exited"); } void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PExecuteBackgroundPty& send_par) { log("PIPEasp__PT::outgoing_send_PExecuteBackgroundPty called"); handle_message(0,send_par); log("PIPEasp__PT::outgoing_send_PExecuteBackgroundPty exited"); } void PIPEasp__PT::handle_message(const int p_id, const PIPEasp__Types::ASP__PStdin& send_par) { if(!pipe_id_valid(p_id)){ sendError("Pipe Test Port: Pipe execution id (p_id) is not valid",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): Pipe execution id (p_id=%d) is not valid: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } if (!main_data[p_id].processExecuting) { sendError("Pipe Test Port: No command executing",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): No command executing (p_id=%d). Following ASP is ignored: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } if (main_data[p_id].disableSend) { sendError("ipe Test Port: PStdinBinary is not sent: current process is not started with PExecuteBackground!",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): ipe Test Port: PStdinBinary is not sent: current process is not started with PExecuteBackground! (p_id=%d). Following ASP is ignored: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } log("will now write to stdin: '%s'", (const char*)(send_par.stdin_()+((lineMode)?"\n":""))); TTCN_Buffer out_buff; out_buff.clear(); int write_len=put_msg(out_buff,3,send_par.stdin_().lengthof()+((lineMode)?1:0), (const unsigned char*)(const char*)(send_par.stdin_()+((lineMode)?"\n":"")),p_id); write(processServerDown,out_buff.get_data(),write_len); } void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PStdin& send_par) { log("PIPEasp__PT::outgoing_send_PStdin called"); handle_message(0,send_par); log("PIPEasp__PT::outgoing_send_PStdin exited"); } void PIPEasp__PT::handle_message(const int p_id, const PIPEasp__Types::ASP__PStdinBinary& send_par) { if(!pipe_id_valid(p_id)){ sendError("Pipe Test Port: Pipe execution id (p_id) is not valid",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): Pipe execution id (p_id=%d) is not valid: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } if (!main_data[p_id].processExecuting) { sendError("Pipe Test Port: No command executing",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): No command executing (p_id=%d). Following ASP is ignored: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } if (main_data[p_id].disableSend) { sendError("ipe Test Port: PStdinBinary is not sent: current process is not started with PExecuteBackground!",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): ipe Test Port: PStdinBinary is not sent: current process is not started with PExecuteBackground! (p_id=%d). Following ASP is ignored: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } main_data[p_id].binaryMode = true; if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): will now write binary data to stdin: ", get_name()); send_par.stdin_().log(); TTCN_Logger::end_event(); } TTCN_Buffer out_buff; out_buff.clear(); int write_len=put_msg(out_buff,3,send_par.stdin_().lengthof(), (const unsigned char*)(send_par.stdin_()),p_id); write(processServerDown,out_buff.get_data(),write_len); } void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PStdinBinary& send_par) { log("PIPEasp__PT::outgoing_send_PStdinBinary called"); handle_message(0,send_par); log("PIPEasp__PT::outgoing_send_PStdinBinary exited"); } void PIPEasp__PT::handle_message(const int p_id, const PIPEasp__Types::ASP__PKill& send_par) { if(!pipe_id_valid(p_id)){ sendError("Pipe Test Port: Pipe execution id (p_id) is not valid",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): Pipe execution id (p_id=%d) is not valid: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } if (!main_data[p_id].processExecuting) { sendError("Pipe Test Port: No command executing",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): No command executing (p_id=%d). Following ASP is ignored: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } int signo = (int)send_par.signal(); if (signo<1 || signo>31) { // signo out of range; log("Signo out of range."); sendError( "Pipe Test port: Signal number should be " "between 1 and 31",p_id); log("PIPEasp__PT::outgoing_send_PKill exited"); return; } // killing process log("Killing process with signo: %d", signo); unsigned char msg[8]; msg[0]=7; msg[1]=0; msg[2]=0; msg[3]=0; msg[4]=3; msg[5]= (p_id >> 8) & 0xFF; msg[6]= p_id & 0xFF; msg[7]= signo; write(processServerDown,msg,8); } void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PKill& send_par) { log("PIPEasp__PT::outgoing_send_PKill called"); handle_message(0,send_par); log("PIPEasp__PT::outgoing_send_PKill exited"); } void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PLineMode& send_par) { log("PIPEasp__PT::outgoing_send_PLineMode called"); lineMode = (bool)send_par.lineMode(); log("LineMode is set to %s", (lineMode)?"TRUE":"FALSE"); log("PIPEasp__PT::outgoing_send_PLineMode exited"); } void PIPEasp__PT::handle_message(const int p_id, const PIPEasp__Types::ASP__PEndOfInput& send_par) { if(!pipe_id_valid(p_id)){ sendError("Pipe Test Port: Pipe execution id (p_id) is not valid",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): Pipe execution id (p_id=%d) is not valid: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } if (!main_data[p_id].processExecuting) { sendError("Pipe Test Port: No command executing",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): No command executing (p_id=%d). Following ASP is ignored: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } return; } unsigned char msg[7]; msg[0]=8; msg[1]=0; msg[2]=0; msg[3]=0; msg[4]=2; msg[5]= (p_id >> 8) & 0xFF; msg[6]= p_id & 0xFF; write(processServerDown,msg,7); } void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PEndOfInput& send_par) { log("PIPEasp__PT::outgoing_send_PEndOfInput called"); handle_message(0,send_par); log("PIPEasp__PT::outgoing_send_PEndOfInput exited"); } void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__Parallel__Command& send_par) { log("PIPEasp__PT::ASP__Parallel__Command called"); int p_id=send_par.p__id(); if(p_id==0){ sendError("Pipe Test Port: Pipe execution id (p_id) is not valid",p_id); if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): Pipe execution id (p_id=%d) is not valid: ", get_name(),p_id); send_par.log(); TTCN_Logger::end_event(); } } else { switch (send_par.command().get_selection()) { case PIPEasp__Types::ASP__Commands::ALT_pexecute: handle_message(p_id,send_par.command().pexecute()); break; case PIPEasp__Types::ASP__Commands::ALT_pexecutePty: handle_message(p_id,send_par.command().pexecutePty()); break; case PIPEasp__Types::ASP__Commands::ALT_pexecuteBinary: handle_message(p_id,send_par.command().pexecuteBinary()); break; case PIPEasp__Types::ASP__Commands::ALT_pexecuteBinaryPty: handle_message(p_id,send_par.command().pexecuteBinaryPty()); break; case PIPEasp__Types::ASP__Commands::ALT_pexecuteBackground: handle_message(p_id,send_par.command().pexecuteBackground()); break; case PIPEasp__Types::ASP__Commands::ALT_pexecuteBackgroundPty: handle_message(p_id,send_par.command().pexecuteBackgroundPty()); break; case PIPEasp__Types::ASP__Commands::ALT_pStdin: handle_message(p_id,send_par.command().pStdin()); break; case PIPEasp__Types::ASP__Commands::ALT_pStdinBinary: handle_message(p_id,send_par.command().pStdinBinary()); break; case PIPEasp__Types::ASP__Commands::ALT_pKill: handle_message(p_id,send_par.command().pKill()); break; case PIPEasp__Types::ASP__Commands::ALT_pEndOfInput: handle_message(p_id,send_par.command().pEndOfInput()); break; default: break; } } log("PIPEasp__PT::ASP__Parallel__Command exited"); } /*********************************** * if the the child process died, gets * the exit code and sends it to TTCN * should be called when stdout/err are closed ************************************/ void PIPEasp__PT::handle_childDeath(const int p_id) { log("Child process exit status is: %d", main_data[p_id].processExitCode); // send code to TTCN: sendExitCode(p_id); // send result to TTCN sendResult(p_id); main_data[p_id].processExecuting = false; main_data[p_id].disableSend = false; if(!main_data[p_id].reuse && !waitforpidrelease){ main_data[p_id].state=0; Free(main_data[p_id].stdout_buffer); main_data[p_id].stdout_buffer=NULL; Free(main_data[p_id].stderr_buffer); main_data[p_id].stderr_buffer=NULL; maindata_used--; } } /*************************** * Send stdout msg to TTCN ***************************/ void PIPEasp__PT::sendStdout(const int p_id) { if (main_data[p_id].disableSend) return; PIPEasp__Types::ASP__PStdout message_PStdout; PIPEasp__Types::ASP__PStdoutBinary message_PStdoutBinary; if (lineMode && !main_data[p_id].binaryMode) { // send complete lines from buffer const unsigned char* pos = main_data[p_id].stdout_buffer->get_read_data(); for(unsigned int i=0; i < main_data[p_id].stdout_buffer->get_read_len() ; i++) { // not end of line: if (pos[i] != '\n') { continue; } // at end of line // length of data is i (+1 is for \n and is not sent) message_PStdout.stdout_() = CHARSTRING(i, (const char*)pos); // send message if(p_id){ // p_id == 0 means old interface PIPEasp__Types::ASP__Parrallel__Result message_PR; message_PR.p__id()=p_id; message_PR.result().pStdout()=message_PStdout; incoming_message(message_PR); } else { incoming_message(message_PStdout); } // remove the complete line from buffer, // also set i and pos to the beginning of buffer main_data[p_id].stdout_buffer->set_pos(i+1); main_data[p_id].stdout_buffer->cut(); i = 0; pos = main_data[p_id].stdout_buffer->get_read_data(); } } else { // lineMode false or binaryMode true if (main_data[p_id].binaryMode) { message_PStdoutBinary.stdout_() = OCTETSTRING(main_data[p_id].stdout_buffer->get_read_len(), main_data[p_id].stdout_buffer->get_read_data()); main_data[p_id].stdout_buffer->clear(); if(p_id){ // p_id == 0 means old interface PIPEasp__Types::ASP__Parrallel__Result message_PR; message_PR.p__id()=p_id; message_PR.result().pStdoutBinary()=message_PStdoutBinary; incoming_message(message_PR); } else { incoming_message(message_PStdoutBinary); } } else { message_PStdout.stdout_() = CHARSTRING(main_data[p_id].stdout_buffer->get_read_len(), (const char*)main_data[p_id].stdout_buffer->get_read_data()); main_data[p_id].stdout_buffer->clear(); if(p_id){ // p_id == 0 means old interface PIPEasp__Types::ASP__Parrallel__Result message_PR; message_PR.p__id()=p_id; message_PR.result().pStdout()=message_PStdout; incoming_message(message_PR); } else { incoming_message(message_PStdout); } } // incoming_message(message); } } /*************************** * Send stderr msg to TTCN ***************************/ void PIPEasp__PT::sendStderr(const int p_id) { if (main_data[p_id].disableSend) return; PIPEasp__Types::ASP__PStderr message_PStderr; PIPEasp__Types::ASP__PStderrBinary message_PStderrBinary; if (lineMode && !main_data[p_id].binaryMode) { // send complete lines from buffer const unsigned char* pos = main_data[p_id].stderr_buffer->get_read_data(); for(unsigned int i=0; iget_read_len(); i++) { // not end of line: if (pos[i] != '\n') { continue; } // at end of line // length of data is i (+1 is for \n and is not sent) message_PStderr.stderr_() = CHARSTRING(i, (const char*)pos); // send message if(p_id){ // p_id == 0 means old interface PIPEasp__Types::ASP__Parrallel__Result message_PR; message_PR.p__id()=p_id; message_PR.result().pStderr()=message_PStderr; incoming_message(message_PR); } else { incoming_message(message_PStderr); } // remove the complete line from buffer, // also set i and pos to the beginning of buffer main_data[p_id].stderr_buffer->set_pos(i+1); main_data[p_id].stderr_buffer->cut(); i = 0; pos = main_data[p_id].stderr_buffer->get_read_data(); } } else { // lineMode false or binaryMode true if (main_data[p_id].binaryMode) { message_PStderrBinary.stderr_() = OCTETSTRING(main_data[p_id].stderr_buffer->get_read_len(), main_data[p_id].stderr_buffer->get_read_data()); main_data[p_id].stderr_buffer->clear(); if(p_id){ // p_id == 0 means old interface PIPEasp__Types::ASP__Parrallel__Result message_PR; message_PR.p__id()=p_id; message_PR.result().pStedrrBinary()=message_PStderrBinary; incoming_message(message_PR); } else { incoming_message(message_PStderr); } } else { message_PStderr.stderr_() = CHARSTRING(main_data[p_id].stderr_buffer->get_read_len(), (const char*)main_data[p_id].stderr_buffer->get_read_data()); main_data[p_id].stderr_buffer->clear(); if(p_id){ // p_id == 0 means old interface PIPEasp__Types::ASP__Parrallel__Result message_PR; message_PR.p__id()=p_id; message_PR.result().pStderr()=message_PStderr; incoming_message(message_PR); } else { incoming_message(message_PStderr); } } // incoming_message(message); } } /*************************** * Send exitcode msg to TTCN ***************************/ void PIPEasp__PT::sendExitCode(const int p_id) { if (main_data[p_id].disableSend) return; log("Sending ExitCode to TTCN"); PIPEasp__Types::ASP__PExit message_PExit; message_PExit.code() = main_data[p_id].processExitCode; if(p_id){ // p_id == 0 means old interface PIPEasp__Types::ASP__Parrallel__Result message_PR; message_PR.p__id()=p_id; message_PR.result().pExit()=message_PExit; incoming_message(message_PR); } else { incoming_message(message_PExit); } } /*************************** * Send error msg to TTCN ***************************/ void PIPEasp__PT::sendError(const char* error_msg,const int p_id) { PIPEasp__Types::ASP__PError message_PError; message_PError.errorMessage() = error_msg; if(p_id){ // p_id == 0 means old interface PIPEasp__Types::ASP__Parrallel__Result message_PR; message_PR.p__id()=p_id; message_PR.result().pError()=message_PError; incoming_message(message_PR); } else { incoming_message(message_PError); } } /*************************** * Send Result msg to TTCN ***************************/ void PIPEasp__PT::sendResult(const int p_id) { if (!main_data[p_id].disableSend) return; // do not send result if process was started by PExecuteBackground log("Sending result to TTCN..."); PIPEasp__Types::ASP__PResult message_PResult; PIPEasp__Types::ASP__PResultBinary message_PResultBinary; if (main_data[p_id].binaryMode) { message_PResultBinary.stdout_() = OCTETSTRING(main_data[p_id].stdout_buffer->get_read_len(), main_data[p_id].stdout_buffer->get_read_data()); message_PResultBinary.stderr_() = OCTETSTRING(main_data[p_id].stderr_buffer->get_read_len(), main_data[p_id].stderr_buffer->get_read_data()); message_PResultBinary.code() = main_data[p_id].processExitCode; if(p_id){ // p_id == 0 means old interface PIPEasp__Types::ASP__Parrallel__Result message_PR; message_PR.p__id()=p_id; message_PR.result().pResultBinary()=message_PResultBinary; incoming_message(message_PR); } else { incoming_message(message_PResultBinary); } } else { int messageLen = main_data[p_id].stdout_buffer->get_read_len(); const char* messageData = (const char*)main_data[p_id].stdout_buffer->get_read_data(); if (messageLen>0 && lineMode && messageData[messageLen-1]=='\n') { messageLen--; // remove newline from the end } message_PResult.stdout_() = CHARSTRING(messageLen, messageData); messageLen = main_data[p_id].stderr_buffer->get_read_len(); messageData = (const char*)main_data[p_id].stderr_buffer->get_read_data(); if (messageLen>0 && lineMode && messageData[messageLen-1]=='\n') { messageLen--; // remove newline from the end } message_PResult.stderr_() = CHARSTRING(messageLen, messageData); message_PResult.code() = main_data[p_id].processExitCode; if(p_id){ // p_id == 0 means old interface PIPEasp__Types::ASP__Parrallel__Result message_PR; message_PR.p__id()=p_id; message_PR.result().pResult()=message_PResult; incoming_message(message_PR); } else { incoming_message(message_PResult); } } // clearing the buffers main_data[p_id].stdout_buffer->clear(); main_data[p_id].stderr_buffer->clear(); //incoming_message(message); } //////////////// // Log function //////////////// void PIPEasp__PT::log(const char *fmt, ...) { if(debugAllowed) { TTCN_Logger::begin_event(TTCN_DEBUG); TTCN_Logger::log_event("PIPE test port (%s): ", get_name()); va_list ap; va_start(ap, fmt); TTCN_Logger::log_event_va_list(fmt, ap); va_end(ap); TTCN_Logger::end_event(); } } void PIPEasp__PT::log_buffer(const unsigned char * buf, size_t buflen) { if(debugAllowed) { TTCN_logger.log(TTCN_DEBUG,"------------------------ PIPE test port (%s) Logging process buffer -----------------------------\n", get_name()); TTCN_logger.log(TTCN_DEBUG,"Process buffer in hexstring format:\n"); for(size_t j=0;j>24)&0xFF); buff.put_c(((len+2)>>16)&0xFF); buff.put_c(((len+2)>>8)&0xFF); buff.put_c((len+2)&0xFF); buff.put_c((p_id>>8)&0xFF); buff.put_c(p_id&0xFF); buff.put_s(len,msg); return whole_len; } void PIPEasp__PT::processHandler(){ bool executing=true; int nBytes; int r; fd_set select_set; FD_ZERO(&working_set); FD_ZERO(&select_set); //printf("PIPEasp__PT::processHandler() started %d\r\n",getpid()); FD_SET(processServerDown, &working_set); max_fd=processServerDown; while(executing){ //printf("while(executing)\r\n"); /* if(processStdout!=-1){ FD_SET(processStdout, &readfds); max_fd=max_fd>processStdout?max_fd:processStdout; } if(processStderr!=-1){ FD_SET(processStderr, &readfds); max_fd=max_fd>processStderr?max_fd:processStderr; } if(processPty!=-1){ FD_SET(processPty, &readfds); max_fd=max_fd>processPty?max_fd:processPty; }*/ //printf("call select, %d\r\n",max_fd); select_set = working_set; int result = select(max_fd+1,&select_set,NULL,NULL,NULL); //printf("result = select(max_fd+1,&readfds,NULL,NULL,NULL), %d,%d,%s\r\n",result,errno, strerror(errno)); if(result<0){ if(errno != EINTR) { close(processServerDown); close(processServerUp); return; } } else { if(FD_ISSET(processServerDown,&select_set)){ result--; nBytes = PIPE_BUF_SIZE; unsigned char* buffer; size_t end_len = nBytes; process_buffer.get_end(buffer, end_len); r = read(processServerDown,buffer,(int)nBytes); //printf("messages read from ttcn, %d\r\n",r); if(r>0){ process_buffer.increase_length(r); int msg_len; int sig_no; //int a; int p_id; while((msg_len=get_len(process_buffer))!=-1){ const unsigned char* msg=process_buffer.get_data(); //printf("messages from ttcn, %d, %d,%d,%d\n", msg[0], msg_len, msg[1], msg[2]); switch(msg[0]){ case 1: // kill the server close(processServerDown); close(processServerUp); free_thread_data(); return; break; case 2: // execute command p_id=((int)msg[5]<<8) + (int)msg[6]; thread_data[p_id].ptyMode = false; newcmd(p_id,CHARSTRING(msg_len-2,(const char*)msg+7)); break; case 10: // execute command in pty mode p_id=((int)msg[5]<<8) + (int)msg[6]; thread_data[p_id].ptyMode = true; newcmd_pty(p_id,CHARSTRING(msg_len-2,(const char*)msg+7)); break; case 3: // stdin or pty p_id=((int)msg[5]<<8) + (int)msg[6]; if (!thread_data[p_id].ptyMode) { if(thread_data[p_id].processStdin!=-1){ write(thread_data[p_id].processStdin,msg+7,msg_len-2); } } else { if(thread_data[p_id].processPty!=-1){ write(thread_data[p_id].processPty,msg+7,msg_len-2); } } break; case 8: // end of input p_id=((int)msg[5]<<8) + (int)msg[6]; if (!thread_data[p_id].ptyMode) { close(thread_data[p_id].processStdin); thread_data[p_id].processStdin=-1; } else { shutdown(thread_data[p_id].processPty,SHUT_WR); } break; case 7: // kill command p_id=((int)msg[5]<<8) + (int)msg[6]; sig_no=msg[7]; kill(thread_data[p_id].pid,sig_no); //printf("kill(%d,%d) returned %d\r\n", processPid,sig_no,a); break; case 9: // unmap command for(int i=0;i0 && p_id0){ TTCN_Buffer msg; int msg_len=put_msg(msg,4,r,buffer,p_id); write(processServerUp,msg.get_data(),msg_len); } else { close_and_remove_fd(thread_data[p_id].processStdout); thread_data[p_id].processStdout=-1; if(thread_data[p_id].processStderr==-1) handle_childDeath_inprocess(p_id); //printf("handle_childDeath_inprocess end, %d \r\n", executing); } } if(thread_data[p_id].processStderr!=-1 && FD_ISSET(thread_data[p_id].processStderr,&select_set)){ result--; nBytes = PIPE_BUF_SIZE; unsigned char buffer[PIPE_BUF_SIZE]; r = read(thread_data[p_id].processStderr,buffer,(int)nBytes); //printf("processStderr end, %d\r\n",r); if(r>0){ TTCN_Buffer msg; int msg_len=put_msg(msg,5,r,buffer,p_id); write(processServerUp,msg.get_data(),msg_len); } else { close_and_remove_fd(thread_data[p_id].processStderr); thread_data[p_id].processStderr=-1; if(thread_data[p_id].processStdout==-1) handle_childDeath_inprocess(p_id); // printf("handle_childDeath_inprocess end, \r\n"); } } if(thread_data[p_id].processPty!=-1 && FD_ISSET(thread_data[p_id].processPty,&select_set)){ result--; nBytes = PIPE_BUF_SIZE; unsigned char buffer[PIPE_BUF_SIZE]; r = read(thread_data[p_id].processPty,buffer,(int)nBytes); //printf("processPty end, %d\r\n",r); if(r>0){ TTCN_Buffer msg; // sent as STDIN int msg_len=put_msg(msg,4,r,buffer,p_id); write(processServerUp,msg.get_data(),msg_len); } else { close_and_remove_fd(thread_data[p_id].processPty); thread_data[p_id].processPty=-1; handle_childDeath_inprocess(p_id); // printf("handle_childDeath_inprocess end, %d \r\n", executing); } } } } //printf("while end, %d\r\n",executing); } } void PIPEasp__PT::newcmd(const int p_id,const char* command){ // creating pipes for process int pipesStdin[2]; int pipesStdout[2]; int pipesStderr[2]; int processPid; if (pipe(pipesStdin) != 0) { return; } if (pipe(pipesStdout) != 0) { return; } if (pipe(pipesStderr) != 0) { return; } thread_data[p_id].processStdin = pipesStdin[1]; thread_data[p_id].processStdout = pipesStdout[0]; thread_data[p_id].processStderr = pipesStderr[0]; processPid = fork(); if (processPid < 0) { // // Error // // close the pipes close(pipesStdin[0]); close(pipesStdout[1]); close(pipesStderr[1]); close(thread_data[p_id].processStdin); close(thread_data[p_id].processStdout); close(thread_data[p_id].processStderr); } else if (processPid == 0) { // // Child process // // close the parent end of the pipes close(thread_data[p_id].processStdin); close(thread_data[p_id].processStdout); close(thread_data[p_id].processStderr); int r; // redirect pipeStdin to stdin r = dup2(pipesStdin[0], 0); if (r<0) { exit(errno); } // redirect pipeStdout to stdout r = dup2(pipesStdout[1], 1); if (r<0) { exit(errno); } // redirect pipeStderr to stderr r = dup2(pipesStderr[1], 2); if (r<0) { exit(errno); } int processExitCode = execCommand(command); // There is a problem executing the command // Exiting... fflush(stdout); fflush(stderr); //closing pipes: close(pipesStdin[0]); close(pipesStdout[1]); close(pipesStderr[1]); exit(processExitCode); // end of child process } else { // // Parent process // //printf("PIPEasp__PT::newcmd(%s) started, %d\r\n",command,processPid); // close child end of the pipes close(pipesStdin[0]); close(pipesStdout[1]); close(pipesStderr[1]); FD_SET(thread_data[p_id].processStdout,&working_set); max_fd=max_fd>thread_data[p_id].processStdout?max_fd:thread_data[p_id].processStdout; FD_SET(thread_data[p_id].processStderr,&working_set); max_fd=max_fd>thread_data[p_id].processStderr?max_fd:thread_data[p_id].processStderr; thread_data[p_id].processExecuting = true; thread_data[p_id].pid=processPid; } } void PIPEasp__PT::newcmd_pty(const int p_id,const char* command){ int processPid; processPid = forkpty(&thread_data[p_id].processPty,NULL,NULL,NULL); if (processPid < 0) { // // Error // thread_data[p_id].processPty=-1; } else if (processPid == 0) { // // Child process // int processExitCode; processExitCode = execCommand(command); exit(processExitCode); // end of child process } else { // // Parent process // if(pty_echo){ struct termio tty, oldtty; ioctl(thread_data[p_id].processPty, TCGETA, &oldtty); tty = oldtty; tty.c_lflag &= ~ECHO; ioctl(thread_data[p_id].processPty, TCSETA, &tty); } FD_SET(thread_data[p_id].processPty,&working_set); max_fd=max_fd>thread_data[p_id].processPty?max_fd:thread_data[p_id].processPty; thread_data[p_id].processExecuting = true; thread_data[p_id].pid=processPid; } } /******************************** * Execute the given command * returns the exitcode of the process *********************************/ int PIPEasp__PT::execCommand(const char* command) { // log("PIPEasp__PT::execCommand called"); // log("Executing command: %s", command); // with this it is not possible to access the pid of the process //return system(command); int argc = 0; char* argv[1024]; CHARSTRING temp = ""; for (int i = 0; command[i] != 0; i++) { if (isspace(command[i])) { argv[argc++] = strdup(temp); // log("command argument added: %s", (const char*)temp); while (command[i] != '0' && isspace(command[i])) i++; i--; temp = ""; } else { temp = temp + CHARSTRING(1, command+i); } } if (temp != "") { argv[argc++] = strdup(temp); // log("command argument added: %s", (const char*)temp); } argv[argc++] = (char*)NULL; // log("execCommand(%s,%d)\n", argv[0], argc); int retval=execvp(argv[0],argv); // f// int store_errno=errno; fprintf(stderr,"Executing command failed (retval=%d) %s (%d): %s\r\n",retval, argv[0],store_errno , strerror(store_errno)); // fflush(stderr); // exit(errno); return store_errno; } void PIPEasp__PT::handle_childDeath_inprocess(const int p_id) { thread_data[p_id].processExitCode = 0; // reset the exitcode int pid = waitpid(thread_data[p_id].pid,&thread_data[p_id].processExitCode, 0); //printf("processExitCode %d\n",processExitCode); if (pid!=thread_data[p_id].pid) { return; } if (!thread_data[p_id].ptyMode) { if(thread_data[p_id].processStdin!=-1){ close(thread_data[p_id].processStdin); thread_data[p_id].processStdin=-1; } } else { if(thread_data[p_id].processPty!=-1){ close_and_remove_fd(thread_data[p_id].processPty); thread_data[p_id].processPty=-1; } } // send code to TTCN: unsigned char msg[11]; msg[0]=6; msg[1]=0; msg[2]=0; msg[3]=0; msg[4]=6; msg[5]= (p_id >> 8) & 0xFF; msg[6]= p_id & 0xFF; msg[7]=(thread_data[p_id].processExitCode>>24)&0xFF; msg[8]=(thread_data[p_id].processExitCode>>16)&0xFF; msg[9]=(thread_data[p_id].processExitCode>>8)&0xFF; msg[10]=thread_data[p_id].processExitCode&0xFF; write(processServerUp,msg,11); //printf("write\n"); thread_data[p_id].processExecuting = false; thread_data[p_id].pid=-1; } void PIPEasp__PT::init_pipedata(int idx){ thread_data[idx].processExecuting=false; // true if process is executing: disable new processes thread_data[idx].processStdin=-1; // fd of stdin of the process thread_data[idx].processStdout=-1; // fd of stdout of the process thread_data[idx].processStderr=-1; // fd of stderr of the process thread_data[idx].pid=-1; thread_data[idx].ptyMode=false; // pty mode thread_data[idx].processPty=-1; // pty of the process (in pty mode) thread_data[idx].processExitCode=-1; // exit code of the process } void PIPEasp__PT::close_and_remove_fd(int fd){ close(fd); FD_CLR(fd,&working_set); if(fd==max_fd){ max_fd=processServerDown; for(int i=0;ithread_data[i].processStdout?max_fd:thread_data[i].processStdout; } if(thread_data[i].processStderr!=-1 && thread_data[i].processStderr!=fd){ max_fd=max_fd>thread_data[i].processStderr?max_fd:thread_data[i].processStderr; } if(thread_data[i].processPty!=-1 && thread_data[i].processPty!=fd){ max_fd=max_fd>thread_data[i].processPty?max_fd:thread_data[i].processPty; } } } } INTEGER f__PIPE__request__p__id(PIPEasp__PortType::PIPEasp__PT& pl__port, BOOLEAN const&pl__reuse){ int return_value=-1; if((pl__port.maindata_used+1)>pl__port.maindata_len){ return_value=pl__port.maindata_len; pl__port.maindata_len++; pl__port.main_data=(PIPEasp__PT::pipedata_main*)Realloc(pl__port.main_data,pl__port.maindata_len*sizeof(PIPEasp__PT::pipedata_main)); } else { for(int i=0;i=0) && (p_id