38 # if !defined(WIN32_LEAN_AND_MEAN)
39 # define WIN32_LEAN_AND_MEAN
43 # define C_MAXARGS 128
49 inline std::string lastError2String()
51 int error=GetLastError();
53 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
nullptr, error, 0, buff, 1024,
nullptr);
55 return std::string(buff);
59 #define READ_FROM_PIPE 0
60 #define WRITE_TO_PIPE 1
61 #define REDIRECT_TO(from, to) yarp::run::impl::dup2(to, from)
71 std::string yarp::run::Run::mPortName;
73 int yarp::run::Run::mProcCNT=0;
74 bool yarp::run::Run::mStresstest=
false;
75 bool yarp::run::Run::mLogged=
false;
76 std::string yarp::run::Run::mLoggerPort(
"/yarplogger");
88 sprintf(msg,
"SIGNAL %d", sig);
104 const char *at = txt.c_str();
107 for (
char ch : txt) {
109 result.
addString(std::string(at, len-slash_tweak));
115 slash_tweak = (ch==
slash && len>0)?1:0;
119 result.
addString(std::string(at, len-slash_tweak));
127 fp = fopen(fname,
"r");
144 if (config.
check(
"server"))
146 mLogged=config.
check(
"log");
152 if (botPortLogger.
size()>1)
158 mPortName=std::string(config.
find(
"server").
asString());
168 fprintf(stderr,
"ERROR: no yarp network found.\n");
175 if (config.
check(
"readwrite"))
178 std::string fPortName;
179 std::string lPortName;
181 if (config.
check(
"forward"))
191 #elif defined(__APPLE__)
194 struct sigaction new_action;
196 sigfillset(&new_action.sa_mask);
197 new_action.sa_flags=0;
199 sigaction(SIGTERM, &new_action,
nullptr);
200 sigaction(SIGHUP, &new_action,
nullptr);
203 yarp::os::impl::signal(SIGPIPE, SIG_IGN);
205 if (getppid()==1)
return 0;
207 yarp::os::impl::prctl(PR_SET_PDEATHSIG, SIGTERM);
209 struct sigaction new_action;
211 yarp::os::impl::sigfillset(&new_action.sa_mask);
212 new_action.sa_flags=0;
214 yarp::os::impl::sigaction(SIGTERM, &new_action,
nullptr);
215 yarp::os::impl::signal(SIGHUP, SIG_IGN);
217 yarp::os::impl::signal(SIGPIPE, SIG_IGN);
233 if (config.
check(
"write"))
242 struct sigaction new_action;
244 yarp::os::impl::sigfillset(&new_action.sa_mask);
245 new_action.sa_flags=0;
246 yarp::os::impl::sigaction(SIGTERM, &new_action,
nullptr);
248 yarp::os::impl::signal(SIGPIPE, SIG_IGN);
249 yarp::os::impl::signal(SIGHUP, SIG_IGN);
252 if (config.
check(
"log"))
274 if (config.
check(
"read"))
285 yarp::os::impl::signal(SIGHUP, SIG_IGN);
297 if (config.
check(
"stresstest"))
299 fprintf(stderr,
"Yarprun stress test started.\n");
302 int max_interval_ms=config.
find(
"stresstest").
asInt32();
307 config.
unput(
"stresstest");
311 bool isCommand=
false;
313 if (config.
check(
"cmd"))
320 unsigned int t=0, u=0;
324 char cmd_and_name[512];
328 std::random_device rd;
329 std::mt19937 mt(rd());
330 std::uniform_int_distribution<int> dist0maxint(0, max_interval_ms -1);
338 sprintf(tag,
"%s_%u", tag_zero.c_str(),
t++);
339 stresser.
put(
"as", tag);
343 sprintf(cmd_and_name,
"%s --name /%s", cmd.c_str(), tag);
344 stresser.
put(
"cmd", cmd_and_name);
349 std::uniform_int_distribution<int> dist07(0, 7);
350 if (isCommand && ++term_cycle>=4)
354 int r =
t - (dist07(mt));
356 for (
int i=u; i<r; ++i)
358 sprintf(tag,
"%s_%u", tag_zero.c_str(), i);
379 if (config.
check(
"help"))
387 if (config.
check(
"stdio")
388 || config.
check(
"cmd")
389 || config.
check(
"kill")
390 || config.
check(
"sigterm")
391 || config.
check(
"sigtermall")
392 || config.
check(
"exit")
393 || config.
check(
"isrunning")
394 || config.
check(
"ps")
395 || config.
check(
"env")
396 || config.
check(
"sysinfo")
397 || config.
check(
"which"))
413 for (
int r=0; r<RETRY; ++r)
417 if (!port.
open(
"..."))
430 RUNLOG(
"<<<port.write(msg, response)")
431 if (!port.
write(msg, response))
437 RUNLOG(
">>>port.write(msg, response)")
439 yarp::os::Network::disconnect(port.getName(), target);
442 fprintf(stderr, "RESPONSE:\n=========\n");
443 for (
size_t s=0; s<response.size(); ++s)
445 fprintf(stderr,
"%s\n", response.get(s).toString().c_str());
453 response.
addString(
"Cannot connect to remote server, aborting...\n");
454 for (
size_t s=0; s<response.
size(); ++s)
456 fprintf(stderr,
"%s\n", response.
get(s).
toString().c_str());
464 yarp::run::Run::mStresstest=
false;
466 if (yarp::run::Run::pServerPort)
469 yarp::run::Run::pServerPort =
nullptr;
480 int yarp::run::Run::server()
486 if (!port.
open(mPortName.c_str()))
488 yError() <<
"Yarprun failed to open port: " << mPortName.c_str();
499 yInfo() <<
"Yarprun successfully started on port: " << mPortName.c_str();
513 RUNLOG(
"<<<port.read(msg, true)")
514 if (!port.
read(msg, true)) break;
517 if (!pServerPort) break;
525 if (msg.check("stdio"))
527 std::string strOnPort=msg.find(
"on").asString();
528 std::string strStdioPort=msg.find(
"stdio").asString();
530 if (strOnPort==mPortName)
536 msg.addList()=botUUID;
538 if (mLogged || msg.check(
"log"))
541 std::string portName=
"/log";
542 portName+=mPortName+
"/";
543 std::string command = msg.findGroup(
"cmd").get(1).asString();
544 command = command.substr(0, command.find(
' '));
545 command = command.substr(command.find_last_of(
"\\/") + 1);
551 if (msg.check(
"log"))
555 if (botLogger.
size()>1)
568 msg.addList()=botFwd;
572 if (executeCmdAndStdio(msg, cmdResult)>0)
574 if (strStdioPort==mPortName)
577 userStdio(msg, stdioResult);
578 cmdResult.
append(stdioResult);
582 cmdResult.
append(sendMsg(msg, strStdioPort));
586 port.
reply(cmdResult);
591 userStdio(msg, stdioResult);
592 port.
reply(stdioResult);
599 if (msg.check(
"cmd"))
603 if (msg.check(
"log"))
607 if (botLogger.
size()>1)
609 std::string loggerName=botLogger.
get(1).
asString();
610 executeCmdStdout(msg, cmdResult, loggerName);
614 executeCmdStdout(msg, cmdResult, mLoggerPort);
619 executeCmdStdout(msg, cmdResult, mLoggerPort);
623 executeCmd(msg, cmdResult);
625 port.
reply(cmdResult);
629 if (msg.check(
"kill"))
631 std::string alias(msg.findGroup(
"kill").get(1).asString());
632 int sig=msg.findGroup(
"kill").get(2).asInt32();
634 result.
addString(mProcessVector.Signal(alias, sig)?
"kill OK":
"kill FAILED");
639 if (msg.check(
"sigterm"))
641 std::string alias(msg.find(
"sigterm").asString());
643 result.
addString(mProcessVector.Signal(alias, SIGTERM)?
"sigterm OK":
"sigterm FAILED");
648 if (msg.check(
"sigtermall"))
650 mProcessVector.Killall(SIGTERM);
660 result.
append(mProcessVector.PS());
665 if (msg.check(
"isrunning"))
667 std::string alias(msg.find(
"isrunning").asString());
669 result.
addString(mProcessVector.IsRunning(alias)?
"running":
"not running");
674 if (msg.check(
"killstdio"))
676 std::string alias(msg.find(
"killstdio").asString());
677 mStdioVector.Signal(alias, SIGTERM);
686 if (msg.check(
"sysinfo"))
693 if (msg.check(
"which"))
695 std::string fileName=msg.find(
"which").asString();
699 for (
int i=0; i<possiblePaths.
size(); ++i)
701 std::string guessString=possiblePaths.
get(i).
asString() +
702 std::string{
slash} + fileName;
703 const char* guess=guessString.c_str();
706 fileName=
"\"" + std::string(guess) +
"\"";
712 port.
reply(fileNameWriter);
716 if (msg.check(
"exit"))
727 Run::mStdioVector.Killall(SIGTERM);
729 Run::mProcessVector.Killall(SIGTERM);
738 void yarp::run::Run::cleanBeforeExec()
750 mProcessVector =
nullptr;
756 mStdioVector =
nullptr;
759 if (mBraveZombieHunter)
762 mBraveZombieHunter =
nullptr;
770 void yarp::run::Run::writeToPipe(
int fd, std::string str)
772 int len = str.length() + 1;
775 if (
ret !=
sizeof(len)) {
776 fprintf(stderr,
"Warning: could not write string length to pipe.\n");
780 fprintf(stderr,
"Warning: could not write string to pipe.\n");
784 int yarp::run::Run::readFromPipe(
int fd,
char* &data,
int& buffsize)
787 char* buff=(
char*)&len;
789 for (
int c=4, r=0; c>0; c-=r)
807 data=
new char[buffsize=1024+(len/1024)*1024];
812 for (
int c=len, r=0; c>0; c-=r)
829 if (yarp::run::Run::mBraveZombieHunter)
835 int yarp::run::Run::server()
837 int pipe_server2manager[2];
838 int pipe_manager2server[2];
840 if (yarp::run::impl::pipe(pipe_server2manager))
842 fprintf(stderr,
"Can't open pipe because %s\n", strerror(errno));
848 if (yarp::run::impl::pipe(pipe_manager2server))
850 fprintf(stderr,
"Can't open pipe because %s\n", strerror(errno));
858 if (IS_INVALID(pid_process_manager))
867 fprintf(stderr,
"Can't fork process manager because %s\n", strerror(error));
873 if (IS_PARENT_OF(pid_process_manager))
875 yarp::os::impl::signal(SIGPIPE, SIG_IGN);
882 if (!port.
open(mPortName))
884 yError() <<
"Yarprun failed to open port: " << mPortName.c_str();
886 if (mPortName[0] !=
'/') {
887 yError(
"Invalid port name '%s', it should start with '/'\n", mPortName.c_str());
899 yInfo() <<
"Yarprun successfully started on port: " << mPortName.c_str();
907 char *rsp_str=
new char[rsp_size];
913 RUNLOG(
"<<<port.read(msg, true)")
914 if (!port.
read(msg, true)) {
917 RUNLOG(
">>>port.read(msg, true)")
923 if (msg.
check(
"sysinfo"))
930 if (msg.
check(
"which"))
936 for (
size_t i=0; i<possiblePaths.
size(); ++i)
939 const char* guess=guessString.c_str();
948 port.
reply(fileNameWriter);
952 if (msg.
check(
"exit"))
954 pServerPort =
nullptr;
967 int nread=readFromPipe(pipe_manager2server[
READ_FROM_PIPE], rsp_str, rsp_size);
972 fprintf(stderr,
"ERROR: broken pipe between server and manager\n");
980 port.
reply(response);
994 if (IS_NEW_PROCESS(pid_process_manager))
996 yarp::os::impl::signal(SIGPIPE, SIG_IGN);
1007 mBraveZombieHunter->
start();
1014 char *msg_str=
new char[msg_size];
1021 RUNLOG(
"<<<readFromPipe")
1022 if (readFromPipe(pipe_server2manager[
READ_FROM_PIPE], msg_str, msg_size) <= 0) {
1025 RUNLOG(
">>>readFromPipe")
1030 msg.fromString(msg_str);
1033 if (msg.check("stdio"))
1038 if (strOnPort==mPortName)
1046 if (mLogged || msg.
check(
"log"))
1049 std::string portName=
"/log";
1050 portName+=mPortName+
"/";
1052 command = command.substr(0, command.find(
' '));
1053 command = command.substr(command.find_last_of(
"\\/") + 1);
1059 if (msg.
check(
"log"))
1063 if (botLogger.
size()>1)
1084 if (executeCmdAndStdio(msg, cmdResult)>0)
1086 if (strStdioPort==mPortName)
1089 userStdio(msg, stdioResult);
1090 cmdResult.
append(stdioResult);
1094 cmdResult.
append(sendMsg(msg, strStdioPort));
1105 userStdio(msg, stdioResult);
1115 if (msg.check("cmd"))
1119 if (msg.
check(
"log"))
1123 if (botLogger.
size()>1)
1125 std::string loggerName=botLogger.
get(1).
asString();
1126 executeCmdStdout(msg, cmdResult, loggerName);
1130 executeCmdStdout(msg, cmdResult, mLoggerPort);
1135 executeCmdStdout(msg, cmdResult, mLoggerPort);
1139 executeCmd(msg, cmdResult);
1148 if (msg.check("kill"))
1153 result.
addString(mProcessVector->Signal(alias, sig)?
"kill OK":
"kill FAILED");
1160 if (msg.check("sigterm"))
1164 result.
addString(mProcessVector->Signal(alias, SIGTERM)?
"sigterm OK":
"sigterm FAILED");
1171 if (msg.check("sigtermall"))
1173 mProcessVector->Killall(SIGTERM);
1183 if (msg.check("ps"))
1186 result.
append(mProcessVector->PS());
1193 if (msg.check("isrunning"))
1197 result.
addString(mProcessVector->IsRunning(alias)?
"running":
"not running");
1204 if (msg.check("killstdio"))
1207 mStdioVector->Signal(alias, SIGTERM);
1217 mStdioVector->Killall(SIGTERM);
1219 mProcessVector->Killall(SIGTERM);
1221 if (mBraveZombieHunter)
1223 mBraveZombieHunter->stop();
1224 delete mBraveZombieHunter;
1225 mBraveZombieHunter =
nullptr;
1228 delete mProcessVector;
1230 delete mStdioVector;
1252 if (config.
check(
"cmd") && config.
check(
"stdio"))
1258 Help(
"SYNTAX ERROR: missing remote stdio server\n");
1263 Help(
"SYNTAX ERROR: missing command\n");
1268 Help(
"SYNTAX ERROR: missing tag\n");
1273 Help(
"SYNTAX ERROR: missing remote server\n");
1279 printf(
"*********** %s ************\n", config.
toString().c_str());
1287 if (config.
check(
"workdir")) {
1290 if (config.
check(
"geometry")) {
1293 if (config.
check(
"hold")) {
1296 if (config.
check(
"env")) {
1299 if (config.
check(
"log")) {
1315 if (!response.
size()) {
1328 if (config.
check(
"cmd"))
1334 Help(
"SYNTAX ERROR: missing command\n");
1339 Help(
"SYNTAX ERROR: missing tag\n");
1344 Help(
"SYNTAX ERROR: missing remote server\n");
1354 if (config.
check(
"workdir")) {
1357 if (config.
check(
"log")) {
1368 if (config.
check(
"env")) {
1374 if (!response.
size()) {
1390 if (config.
check(
"kill"))
1394 Help(
"SYNTAX ERROR: missing remote server\n");
1399 Help(
"SYNTAX ERROR: missing tag\n");
1404 Help(
"SYNTAX ERROR: missing signum\n");
1413 if (!response.
size())
1422 if (config.
check(
"sigterm"))
1426 Help(
"SYNTAX ERROR: missing tag");
1431 Help(
"SYNTAX ERROR: missing remote server\n");
1440 if (!response.
size())
1445 return response.
get(0).
asString()==
"sigterm OK"?0:2;
1449 if (config.
check(
"sigtermall"))
1453 Help(
"SYNTAX ERROR: missing remote server\n");
1462 if (!response.
size())
1470 if (config.
check(
"ps"))
1474 Help(
"SYNTAX ERROR: missing remote server\n");
1483 if (!response.
size())
1491 if (config.
check(
"isrunning"))
1495 Help(
"SYNTAX ERROR: missing remote server\n");
1501 Help(
"SYNTAX ERROR: missing tag\n");
1510 if (!response.
size())
1518 if (config.
check(
"sysinfo"))
1522 Help(
"SYNTAX ERROR: missing remote server\n");
1531 if (!port.
open(
"..."))
1533 fprintf(stderr,
"RESPONSE:\n=========\n");
1534 fprintf(stderr,
"Cannot open port, aborting...\n");
1543 fprintf(stderr,
"RESPONSE:\n=========\n");
1544 fprintf(stderr,
"Cannot connect to remote server, aborting...\n");
1552 RUNLOG(
"<<<port.write(msg, info)")
1554 RUNLOG(
">>>port.write(msg, info)")
1558 fprintf(stdout,
"RESPONSE:\n=========\n\n");
1562 fprintf(stdout,
"No response. (timeout)\n");
1567 fprintf(stdout,
"Platform name : %s\n", info.
platform.
name.c_str());
1569 fprintf(stdout,
"Platform release : %s\n", info.
platform.
release.c_str());
1571 fprintf(stdout,
"Platform kernel : %s\n\n", info.
platform.
kernel.c_str());
1573 fprintf(stdout,
"User Id : %d\n", info.
user.
userID);
1574 fprintf(stdout,
"User name : %s\n", info.
user.
userName.c_str());
1575 fprintf(stdout,
"User real name : %s\n", info.
user.
realName.c_str());
1576 fprintf(stdout,
"User home dir : %s\n\n", info.
user.
homeDir.c_str());
1579 fprintf(stdout,
"Cpu load 1 : %.2lf\n", info.
load.
cpuLoad1);
1580 fprintf(stdout,
"Cpu load 5 : %.2lf\n", info.
load.
cpuLoad5);
1581 fprintf(stdout,
"Cpu load 15 : %.2lf\n\n", info.
load.
cpuLoad15);
1589 fprintf(stdout,
"Processor model : %s\n", info.
processor.
model.c_str());
1592 fprintf(stdout,
"Processor vendor : %s\n", info.
processor.
vendor.c_str());
1606 if (config.
check(
"which"))
1610 Help(
"SYNTAX ERROR: missing remote server\n");
1620 if (!response.
size())
1627 if (config.
check(
"exit"))
1631 Help(
"SYNTAX ERROR: missing remote server\n");
1641 if (!response.
size())
1652 void yarp::run::Run::Help(
const char *msg)
1654 fprintf(stderr,
"%s", msg);
1655 fprintf(stderr,
"\nUSAGE:\n\n");
1656 fprintf(stderr,
"yarp run --server SERVERPORT\nrun a server on the local machine\n\n");
1657 fprintf(stderr,
"yarp run --on SERVERPORT --as TAG --cmd COMMAND [ARGLIST] [--workdir WORKDIR] [--env ENVIRONMENT]\nrun a command on SERVERPORT server\n\n");
1658 fprintf(stderr,
"yarp run --on SERVERPORT --as TAG --stdio STDIOSERVERPORT [--hold] [--geometry WxH+X+Y] --cmd COMMAND [ARGLIST] [--workdir WORKDIR] [--env ENVIRONMENT]\n");
1659 fprintf(stderr,
"run a command on SERVERPORT server sending I/O to STDIOSERVERPORT server\n\n");
1660 fprintf(stderr,
"yarp run --on SERVERPORT --kill TAG SIGNUM\nsend SIGNUM signal to TAG command\n\n");
1661 fprintf(stderr,
"yarp run --on SERVERPORT --sigterm TAG\nterminate TAG command\n\n");
1662 fprintf(stderr,
"yarp run --on SERVERPORT --sigtermall\nterminate all commands\n\n");
1663 fprintf(stderr,
"yarp run --on SERVERPORT --ps\nreport commands running on SERVERPORT\n\n");
1664 fprintf(stderr,
"yarp run --on SERVERPORT --isrunning TAG\nTAG command is running?\n\n");
1665 fprintf(stderr,
"yarp run --on SERVERPORT --sysinfo\nreport system information of SERVERPORT\n\n");
1666 fprintf(stderr,
"yarp run --on SERVERPORT --exit\nstop SERVERPORT server\n\n");
1682 std::string strStdioUUID=msg.
find(
"stdiouuid").
asString();
1686 SECURITY_ATTRIBUTES pipe_sec_attr;
1687 pipe_sec_attr.nLength=
sizeof(SECURITY_ATTRIBUTES);
1688 pipe_sec_attr.bInheritHandle=TRUE;
1689 pipe_sec_attr.lpSecurityDescriptor =
nullptr;
1690 HANDLE read_from_pipe_stdin_to_cmd, write_to_pipe_stdin_to_cmd;
1691 CreatePipe(&read_from_pipe_stdin_to_cmd, &write_to_pipe_stdin_to_cmd, &pipe_sec_attr, 0);
1692 HANDLE read_from_pipe_cmd_to_stdout, write_to_pipe_cmd_to_stdout;
1693 CreatePipe(&read_from_pipe_cmd_to_stdout, &write_to_pipe_cmd_to_stdout, &pipe_sec_attr, 0);
1696 PROCESS_INFORMATION stdout_process_info;
1697 ZeroMemory(&stdout_process_info,
sizeof(PROCESS_INFORMATION));
1698 STARTUPINFO stdout_startup_info;
1699 ZeroMemory(&stdout_startup_info,
sizeof(STARTUPINFO));
1701 stdout_startup_info.cb=
sizeof(STARTUPINFO);
1702 stdout_startup_info.hStdError=GetStdHandle(STD_ERROR_HANDLE);
1703 stdout_startup_info.hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE);
1704 stdout_startup_info.hStdInput=read_from_pipe_cmd_to_stdout;
1705 stdout_startup_info.dwFlags|=STARTF_USESTDHANDLES;
1707 BOOL bSuccess=CreateProcess(
nullptr,
1708 (
char*)(std::string(
"yarprun --write ")+strStdioUUID).c_str(),
1712 CREATE_NEW_PROCESS_GROUP,
1715 &stdout_startup_info,
1716 &stdout_process_info);
1720 std::string strError=std::string(
"ABORTED: server=")+mPortName
1721 +std::string(
" alias=")+strAlias
1722 +std::string(
" cmd=stdout\n")
1723 +std::string(
"Can't execute stdout because ")+lastError2String()
1728 fprintf(stderr,
"%s", strError.c_str());
1731 CloseHandle(write_to_pipe_stdin_to_cmd);
1732 CloseHandle(read_from_pipe_stdin_to_cmd);
1733 CloseHandle(write_to_pipe_cmd_to_stdout);
1734 CloseHandle(read_from_pipe_cmd_to_stdout);
1741 PROCESS_INFORMATION stdin_process_info;
1742 ZeroMemory(&stdin_process_info,
sizeof(PROCESS_INFORMATION));
1743 STARTUPINFO stdin_startup_info;
1744 ZeroMemory(&stdin_startup_info,
sizeof(STARTUPINFO));
1746 stdin_startup_info.cb=
sizeof(STARTUPINFO);
1747 stdin_startup_info.hStdError=write_to_pipe_stdin_to_cmd;
1748 stdin_startup_info.hStdOutput=write_to_pipe_stdin_to_cmd;
1749 stdin_startup_info.hStdInput=GetStdHandle(STD_INPUT_HANDLE);
1750 stdin_startup_info.dwFlags|=STARTF_USESTDHANDLES;
1752 bSuccess=CreateProcess(
nullptr,
1753 (
char*)(std::string(
"yarprun --read ")+strStdioUUID).c_str(),
1757 CREATE_NEW_PROCESS_GROUP,
1760 &stdin_startup_info,
1761 &stdin_process_info);
1765 std::string strError=std::string(
"ABORTED: server=")+mPortName
1766 +std::string(
" alias=")+strAlias
1767 +std::string(
" cmd=stdin\n")
1768 +std::string(
"Can't execute stdin because ")+lastError2String()
1773 fprintf(stderr,
"%s", strError.c_str());
1775 TerminateProcess(stdout_process_info.hProcess,
YARPRUN_ERROR);
1777 CloseHandle(stdout_process_info.hProcess);
1779 CloseHandle(write_to_pipe_stdin_to_cmd);
1780 CloseHandle(read_from_pipe_stdin_to_cmd);
1781 CloseHandle(write_to_pipe_cmd_to_stdout);
1782 CloseHandle(read_from_pipe_cmd_to_stdout);
1789 PROCESS_INFORMATION cmd_process_info;
1790 ZeroMemory(&cmd_process_info,
sizeof(PROCESS_INFORMATION));
1791 STARTUPINFO cmd_startup_info;
1792 ZeroMemory(&cmd_startup_info,
sizeof(STARTUPINFO));
1794 cmd_startup_info.cb=
sizeof(STARTUPINFO);
1795 cmd_startup_info.hStdError=write_to_pipe_cmd_to_stdout;
1796 cmd_startup_info.hStdOutput=write_to_pipe_cmd_to_stdout;
1797 cmd_startup_info.hStdInput=read_from_pipe_stdin_to_cmd;
1798 cmd_startup_info.dwFlags|=STARTF_USESTDHANDLES;
1803 for (
int s=0; s<botCmd.
size(); ++s)
1805 strCmd+=botCmd.
get(s).
toString()+std::string(
" ");
1811 TCHAR chNewEnv[32767];
1814 LPTCH chOldEnv = GetEnvironmentStrings();
1817 LPTSTR lpOld = (LPTSTR) chOldEnv;
1818 LPTSTR lpNew = (LPTSTR) chNewEnv;
1821 lstrcpy(lpNew, lpOld);
1822 lpOld += lstrlen(lpOld) + 1;
1823 lpNew += lstrlen(lpNew) + 1;
1828 lstrcpy(lpNew, (LPTCH)
"YARP_IS_YARPRUN=1");
1829 lpNew += lstrlen(lpNew) + 1;
1833 lstrcpy(lpNew, (LPTCH)
"YARPRUN_IS_FORWARDING_LOG=1");
1834 lpNew += lstrlen(lpNew) + 1;
1837 std::string cstrEnvName;
1838 if (msg.
check(
"env"))
1841 for (
const auto& s : ss) {
1842 lstrcpy(lpNew, (LPTCH) s.c_str());
1843 lpNew += lstrlen(lpNew) + 1;
1850 bool bWorkdir=msg.
check(
"workdir");
1851 std::string strWorkdir=bWorkdir?msg.
find(
"workdir").
asString()+
"\\":
"";
1853 bSuccess=CreateProcess(
nullptr,
1854 (
char*)(strWorkdir+strCmd).c_str(),
1858 CREATE_NEW_PROCESS_GROUP,
1860 bWorkdir ? strWorkdir.c_str() :
nullptr,
1864 if (!bSuccess && bWorkdir)
1866 bSuccess=CreateProcess(
nullptr,
1867 (
char*)(strCmd.c_str()),
1871 CREATE_NEW_PROCESS_GROUP,
1879 FreeEnvironmentStrings(chOldEnv);
1886 std::string line1=std::string(
"ABORTED: server=")+mPortName
1887 +std::string(
" alias=")+strAlias
1888 +std::string(
" cmd=")+strCmd
1889 +std::string(
"pid=")+
int2String(cmd_process_info.dwProcessId)
1892 WriteFile(write_to_pipe_cmd_to_stdout, line1.c_str(), line1.length(), &nBytes, 0);
1894 std::string line2=std::string(
"Can't execute command because ")+lastError2String()+std::string(
"\n");
1895 WriteFile(write_to_pipe_cmd_to_stdout, line1.c_str(), line2.length(), &nBytes, 0);
1896 FlushFileBuffers(write_to_pipe_cmd_to_stdout);
1898 std::string out=line1+line2;
1900 fprintf(stderr,
"%s", out.c_str());
1903 CloseHandle(write_to_pipe_stdin_to_cmd);
1904 CloseHandle(read_from_pipe_stdin_to_cmd);
1905 CloseHandle(write_to_pipe_cmd_to_stdout);
1906 CloseHandle(read_from_pipe_cmd_to_stdout);
1908 TerminateProcess(stdout_process_info.hProcess,
YARPRUN_ERROR);
1910 CloseHandle(stdout_process_info.hProcess);
1912 TerminateProcess(stdin_process_info.hProcess,
YARPRUN_ERROR);
1914 CloseHandle(stdin_process_info.hProcess);
1919 FlushFileBuffers(write_to_pipe_cmd_to_stdout);
1925 cmd_process_info.dwProcessId,
1928 stdin_process_info.dwProcessId,
1929 stdout_process_info.dwProcessId,
1930 read_from_pipe_stdin_to_cmd,
1931 write_to_pipe_stdin_to_cmd,
1932 read_from_pipe_cmd_to_stdout,
1933 write_to_pipe_cmd_to_stdout,
1934 cmd_process_info.hProcess,
1938 if (msg.
check(
"env"))
1942 mProcessVector.Add(pInf);
1944 result.
addInt32(cmd_process_info.dwProcessId);
1945 std::string out=std::string(
"STARTED: server=")+mPortName
1946 +std::string(
" alias=")+strAlias
1947 +std::string(
" cmd=")+strCmd
1948 +std::string(
" pid=")+
int2String(cmd_process_info.dwProcessId)
1953 fprintf(stderr,
"%s", out.c_str());
1955 return cmd_process_info.dwProcessId;
1961 std::string portName=
"/log";
1962 portName+=mPortName+
"/";
1964 command = command.substr(0, command.find(
' '));
1965 command = command.substr(command.find_last_of(
"\\/") + 1);
1969 SECURITY_ATTRIBUTES pipe_sec_attr;
1970 pipe_sec_attr.nLength=
sizeof(SECURITY_ATTRIBUTES);
1971 pipe_sec_attr.bInheritHandle=TRUE;
1972 pipe_sec_attr.lpSecurityDescriptor =
nullptr;
1973 HANDLE read_from_pipe_cmd_to_stdout, write_to_pipe_cmd_to_stdout;
1974 CreatePipe(&read_from_pipe_cmd_to_stdout, &write_to_pipe_cmd_to_stdout, &pipe_sec_attr, 0);
1977 PROCESS_INFORMATION stdout_process_info;
1978 ZeroMemory(&stdout_process_info,
sizeof(PROCESS_INFORMATION));
1979 STARTUPINFO stdout_startup_info;
1980 ZeroMemory(&stdout_startup_info,
sizeof(STARTUPINFO));
1982 stdout_startup_info.cb=
sizeof(STARTUPINFO);
1983 stdout_startup_info.hStdError=GetStdHandle(STD_ERROR_HANDLE);
1984 stdout_startup_info.hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE);
1985 stdout_startup_info.hStdInput=read_from_pipe_cmd_to_stdout;
1986 stdout_startup_info.dwFlags|=STARTF_USESTDHANDLES;
1988 BOOL bSuccess=CreateProcess(
nullptr,
1989 (
char*)(std::string(
"yarprun --log ")+loggerName+std::string(
" --write ")+portName).c_str(),
1993 CREATE_NEW_PROCESS_GROUP,
1996 &stdout_startup_info,
1997 &stdout_process_info);
2001 std::string strError=std::string(
"ABORTED: server=")+mPortName
2002 +std::string(
" alias=")+strAlias
2003 +std::string(
" cmd=stdout\n")
2004 +std::string(
"Can't execute stdout because ")+lastError2String()
2009 fprintf(stderr,
"%s", strError.c_str());
2012 CloseHandle(write_to_pipe_cmd_to_stdout);
2013 CloseHandle(read_from_pipe_cmd_to_stdout);
2020 PROCESS_INFORMATION cmd_process_info;
2021 ZeroMemory(&cmd_process_info,
sizeof(PROCESS_INFORMATION));
2022 STARTUPINFO cmd_startup_info;
2023 ZeroMemory(&cmd_startup_info,
sizeof(STARTUPINFO));
2025 cmd_startup_info.cb=
sizeof(STARTUPINFO);
2026 cmd_startup_info.hStdError=write_to_pipe_cmd_to_stdout;
2027 cmd_startup_info.hStdOutput=write_to_pipe_cmd_to_stdout;
2028 cmd_startup_info.hStdInput=GetStdHandle(STD_INPUT_HANDLE);
2029 cmd_startup_info.dwFlags|=STARTF_USESTDHANDLES;
2034 for (
int s=0; s<botCmd.
size(); ++s)
2036 strCmd+=botCmd.
get(s).
toString()+std::string(
" ");
2042 TCHAR chNewEnv[32767];
2045 LPTCH chOldEnv = GetEnvironmentStrings();
2048 LPTSTR lpOld = (LPTSTR) chOldEnv;
2049 LPTSTR lpNew = (LPTSTR) chNewEnv;
2052 lstrcpy(lpNew, lpOld);
2053 lpOld += lstrlen(lpOld) + 1;
2054 lpNew += lstrlen(lpNew) + 1;
2059 lstrcpy(lpNew, (LPTCH)
"YARP_IS_YARPRUN=1");
2060 lpNew += lstrlen(lpNew) + 1;
2064 lstrcpy(lpNew, (LPTCH)
"YARPRUN_IS_FORWARDING_LOG=1");
2065 lpNew += lstrlen(lpNew) + 1;
2068 std::string cstrEnvName;
2069 if (msg.
check(
"env"))
2072 for (
const auto& s : ss) {
2073 lstrcpy(lpNew, (LPTCH)s.c_str());
2074 lpNew += lstrlen(lpNew) + 1;
2081 bool bWorkdir=msg.
check(
"workdir");
2082 std::string strWorkdir=bWorkdir?msg.
find(
"workdir").
asString()+
"\\":
"";
2084 bSuccess=CreateProcess(
nullptr,
2085 (
char*)(strWorkdir+strCmd).c_str(),
2089 CREATE_NEW_PROCESS_GROUP,
2091 bWorkdir?strWorkdir.c_str():
nullptr,
2095 if (!bSuccess && bWorkdir)
2097 bSuccess=CreateProcess(
nullptr,
2098 (
char*)(strCmd.c_str()),
2102 CREATE_NEW_PROCESS_GROUP,
2110 FreeEnvironmentStrings(chOldEnv);
2117 std::string line1=std::string(
"ABORTED: server=")+mPortName
2118 +std::string(
" alias=")+strAlias
2119 +std::string(
" cmd=")+strCmd
2120 +std::string(
"pid=")+
int2String(cmd_process_info.dwProcessId)
2123 WriteFile(write_to_pipe_cmd_to_stdout, line1.c_str(), line1.length(), &nBytes, 0);
2125 std::string line2=std::string(
"Can't execute command because ")+lastError2String()+std::string(
"\n");
2126 WriteFile(write_to_pipe_cmd_to_stdout, line1.c_str(), line2.length(), &nBytes, 0);
2127 FlushFileBuffers(write_to_pipe_cmd_to_stdout);
2129 std::string out=line1+line2;
2131 fprintf(stderr,
"%s", out.c_str());
2134 CloseHandle(write_to_pipe_cmd_to_stdout);
2135 CloseHandle(read_from_pipe_cmd_to_stdout);
2137 TerminateProcess(stdout_process_info.hProcess,
YARPRUN_ERROR);
2139 CloseHandle(stdout_process_info.hProcess);
2144 FlushFileBuffers(write_to_pipe_cmd_to_stdout);
2150 cmd_process_info.dwProcessId,
2151 stdout_process_info.dwProcessId,
2152 read_from_pipe_cmd_to_stdout,
2153 write_to_pipe_cmd_to_stdout,
2154 cmd_process_info.hProcess,
2161 if (msg.
check(
"env"))
2165 mProcessVector.Add(pInf);
2167 result.
addInt32(cmd_process_info.dwProcessId);
2168 std::string out=std::string(
"STARTED: server=")+mPortName
2169 +std::string(
" alias=")+strAlias
2170 +std::string(
" cmd=")+strCmd
2171 +std::string(
" pid=")+
int2String(cmd_process_info.dwProcessId)
2176 fprintf(stderr,
"%s", out.c_str());
2178 return cmd_process_info.dwProcessId;
2184 std::string strAlias=msg.
find(
"as").
asString().c_str();
2187 PROCESS_INFORMATION cmd_process_info;
2188 ZeroMemory(&cmd_process_info,
sizeof(PROCESS_INFORMATION));
2189 STARTUPINFO cmd_startup_info;
2190 ZeroMemory(&cmd_startup_info,
sizeof(STARTUPINFO));
2192 cmd_startup_info.cb=
sizeof(STARTUPINFO);
2197 for (
int s=0; s<botCmd.
size(); ++s)
2199 strCmd+=botCmd.
get(s).
toString()+std::string(
" ");
2205 TCHAR chNewEnv[32767];
2208 LPTCH chOldEnv = GetEnvironmentStrings();
2211 LPTSTR lpOld = (LPTSTR) chOldEnv;
2212 LPTSTR lpNew = (LPTSTR) chNewEnv;
2215 lstrcpy(lpNew, lpOld);
2216 lpOld += lstrlen(lpOld) + 1;
2217 lpNew += lstrlen(lpNew) + 1;
2222 lstrcpy(lpNew, (LPTCH)
"YARP_IS_YARPRUN=1");
2223 lpNew += lstrlen(lpNew) + 1;
2227 lstrcpy(lpNew, (LPTCH)
"YARPRUN_IS_FORWARDING_LOG=0");
2228 lpNew += lstrlen(lpNew) + 1;
2231 std::string cstrEnvName;
2232 if (msg.
check(
"env"))
2235 for (
const auto& s : ss) {
2236 lstrcpy(lpNew, (LPTCH)s.c_str());
2237 lpNew += lstrlen(lpNew) + 1;
2244 bool bWorkdir=msg.
check(
"workdir");
2245 std::string strWorkdir=bWorkdir?msg.
find(
"workdir").
asString()+
"\\":
"";
2247 BOOL bSuccess=CreateProcess(
nullptr,
2248 (
char*)(strWorkdir+strCmd).c_str(),
2252 CREATE_NEW_PROCESS_GROUP,
2254 bWorkdir ? strWorkdir.c_str() :
nullptr,
2258 if (!bSuccess && bWorkdir)
2260 bSuccess=CreateProcess(
nullptr,
2261 (
char*)(strCmd.c_str()),
2265 CREATE_NEW_PROCESS_GROUP,
2273 FreeEnvironmentStrings(chOldEnv);
2279 std::string out=std::string(
"ABORTED: server=")+mPortName
2280 +std::string(
" alias=")+strAlias
2281 +std::string(
" cmd=")+strCmd
2282 +std::string(
" pid=")+
int2String(cmd_process_info.dwProcessId)
2283 +std::string(
"\nCan't execute command because ")+lastError2String()
2287 fprintf(stderr,
"%s", out.c_str());
2296 cmd_process_info.dwProcessId,
2297 cmd_process_info.hProcess,
2300 if (msg.
check(
"env"))
2303 mProcessVector.Add(pInf);
2305 result.
addInt32(cmd_process_info.dwProcessId);
2306 std::string out=std::string(
"STARTED: server=")+mPortName
2307 +std::string(
" alias=")+strAlias
2308 +std::string(
" cmd=")+strCmd
2309 +std::string(
" pid=")+
int2String(cmd_process_info.dwProcessId)
2312 fprintf(stderr,
"%s", out.c_str());
2314 return cmd_process_info.dwProcessId;
2320 PROCESS_INFORMATION stdio_process_info;
2321 ZeroMemory(&stdio_process_info,
sizeof(PROCESS_INFORMATION));
2323 STARTUPINFO stdio_startup_info;
2324 ZeroMemory(&stdio_startup_info,
sizeof(STARTUPINFO));
2325 stdio_startup_info.cb=
sizeof(STARTUPINFO);
2326 stdio_startup_info.wShowWindow=SW_SHOWNOACTIVATE;
2327 stdio_startup_info.dwFlags=STARTF_USESHOWWINDOW;
2331 std::string strCmd=std::string(
"yarprun --readwrite ")+strUUID;
2334 BOOL bSuccess=CreateProcess(
nullptr,
2335 (
char*)strCmd.c_str(),
2342 &stdio_startup_info,
2343 &stdio_process_info);
2351 stdio_process_info.dwProcessId,
2352 stdio_process_info.hProcess,
2355 out=std::string(
"STARTED: server=")+mPortName
2356 +std::string(
" alias=")+strAlias
2357 +std::string(
" cmd=stdio pid=")+
int2String(stdio_process_info.dwProcessId)
2364 out=std::string(
"ABORTED: server=")+mPortName
2365 +std::string(
" alias=")+strAlias
2366 +std::string(
" cmd=stdio\n")
2367 +std::string(
"Can't open stdio window because ")+lastError2String()
2372 result.
addInt32(stdio_process_info.dwProcessId);
2374 fprintf(stderr,
"%s", out.c_str());
2377 return stdio_process_info.dwProcessId;
2388 char *pTmp = strchr(pLine,
' ');
2393 while ((*pTmp) && (*pTmp ==
' ')) {
2396 if (*pTmp ==
'\0') {
2408 char *pNext = io_pLine;
2412 size_t len = strlen(io_pLine);
2415 for(i = 0; i < len; i++) {
2416 if ((!quoted) && (
'"' == io_pLine[i])) {
2419 }
else if ((quoted) && (
'"' == io_pLine[i])) {
2422 }
else if ((quoted) && (
' ' == io_pLine[i])) {
2428 memset(o_pArgv, 0x00,
sizeof(
char*) *
C_MAXARGS);
2430 o_pArgv[0] = io_pLine;
2432 while ((
nullptr != pNext) && (*o_pArgc <
C_MAXARGS)) {
2434 pNext = o_pArgv[*o_pArgc];
2436 if (
nullptr != o_pArgv[*o_pArgc]) {
2441 for(j = 0; j < *o_pArgc; j++) {
2442 len = strlen(o_pArgv[j]);
2443 for(i = 0; i < len; i++) {
2444 if (
'\1' == o_pArgv[j][i]) {
2445 o_pArgv[j][i] =
' ';
2451 void yarp::run::Run::CleanZombie(
int pid)
2453 bool bFound=mProcessVector && mProcessVector->CleanZombie(pid);
2457 mStdioVector->CleanZombie(pid);
2469 std::string strStdioUUID=msg.
find(
"stdiouuid").
asString();
2471 int pipe_stdin_to_cmd[2];
2472 int ret_stdin_to_cmd=yarp::run::impl::pipe(pipe_stdin_to_cmd);
2474 int pipe_cmd_to_stdout[2];
2475 int ret_cmd_to_stdout=yarp::run::impl::pipe(pipe_cmd_to_stdout);
2477 int pipe_child_to_parent[2];
2478 int ret_child_to_parent=yarp::run::impl::pipe(pipe_child_to_parent);
2480 if (ret_child_to_parent!=0 || ret_cmd_to_stdout!=0 || ret_stdin_to_cmd!=0)
2484 std::string out=std::string(
"ABORTED: server=")+mPortName
2485 +std::string(
" alias=")+strAlias
2486 +std::string(
" cmd=stdout\n")
2487 +std::string(
"Can't create pipes ")+strerror(error)
2492 fprintf(stderr,
"%s", out.c_str());
2499 if (IS_INVALID(pid_stdout))
2510 std::string out=std::string(
"ABORTED: server=")+mPortName
2511 +std::string(
" alias=")+strAlias
2512 +std::string(
" cmd=stdout\n")
2513 +std::string(
"Can't fork stdout process because ")+strerror(error)
2518 fprintf(stderr,
"%s", out.c_str());
2523 if (IS_NEW_PROCESS(pid_stdout))
2539 int ret = yarp::run::impl::execlp(
"yarprun",
"yarprun",
"--write", strStdioUUID.c_str(),
static_cast<char*
>(
nullptr));
2547 std::string out=std::string(
"ABORTED: server=")+mPortName
2548 +std::string(
" alias=")+strAlias
2549 +std::string(
" cmd=stdout\n")
2550 +std::string(
"Can't execute stdout because ")+strerror(error)
2553 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
2554 fprintf(out_to_parent,
"%s", out.c_str());
2555 fflush(out_to_parent);
2556 fclose(out_to_parent);
2558 fprintf(stderr,
"%s", out.c_str());
2566 if (IS_PARENT_OF(pid_stdout))
2570 fprintf(stderr,
"STARTED: server=%s alias=%s cmd=stdout pid=%d\n", mPortName.c_str(), strAlias.c_str(), pid_stdout);
2574 if (IS_INVALID(pid_stdin))
2584 std::string out=std::string(
"ABORTED: server=")+mPortName
2585 +std::string(
" alias=")+strAlias
2586 +std::string(
" cmd=stdin\n")
2587 +std::string(
"Can't fork stdin process because ")+strerror(error)
2592 fprintf(stderr,
"%s", out.c_str());
2594 SIGNAL(pid_stdout, SIGTERM);
2595 fprintf(stderr,
"TERMINATING stdout (%d)\n", pid_stdout);
2600 if (IS_NEW_PROCESS(pid_stdin))
2616 int ret = yarp::run::impl::execlp(
"yarprun",
"yarprun",
"--read", strStdioUUID.c_str(),
static_cast<char*
>(
nullptr));
2624 std::string out=std::string(
"ABORTED: server=")+mPortName
2625 +std::string(
" alias=")+strAlias
2626 +std::string(
" cmd=stdin\n")
2627 +std::string(
"Can't execute stdin because ")+strerror(error)
2631 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
2632 fprintf(out_to_parent,
"%s", out.c_str());
2633 fflush(out_to_parent);
2634 fclose(out_to_parent);
2635 fprintf(stderr,
"%s", out.c_str());
2643 if (IS_PARENT_OF(pid_stdin))
2648 fprintf(stderr,
"STARTED: server=%s alias=%s cmd=stdin pid=%d\n", mPortName.c_str(), strAlias.c_str(), pid_stdin);
2652 if (IS_INVALID(pid_cmd))
2660 std::string out=std::string(
"ABORTED: server=")+mPortName
2661 +std::string(
" alias=")+strAlias
2662 +std::string(
" cmd=")+strCmd
2663 +std::string(
"\nCan't fork command process because ")+strerror(error)
2668 fprintf(stderr,
"%s", out.c_str());
2670 FILE* to_yarp_stdout=fdopen(pipe_cmd_to_stdout[
WRITE_TO_PIPE],
"w");
2671 fprintf(to_yarp_stdout,
"%s", out.c_str());
2672 fflush(to_yarp_stdout);
2673 fclose(to_yarp_stdout);
2675 SIGNAL(pid_stdout, SIGTERM);
2676 fprintf(stderr,
"TERMINATING stdout (%d)\n", pid_stdout);
2677 SIGNAL(pid_stdin, SIGTERM);
2678 fprintf(stderr,
"TERMINATING stdin (%d)\n", pid_stdin);
2685 if (IS_NEW_PROCESS(pid_cmd))
2689 char *cmd_str=
new char[strCmd.length()+1];
2690 strcpy(cmd_str, strCmd.c_str());
2698 char **arg_str =
new char*[
C_MAXARGS + 1];
2700 arg_str[nargs]=
nullptr;
2702 setvbuf(stdout,
nullptr, _IONBF, 0);
2716 if (msg.
check(
"env"))
2719 for (
const auto& s : ss) {
2720 char* szenv =
new char[s.size()+1];
2721 strcpy(szenv, s.c_str());
2722 yarp::run::impl::putenv(szenv);
2727 if (msg.
check(
"workdir"))
2729 int ret = yarp::os::impl::chdir(msg.
find(
"workdir").
asString().c_str());
2735 std::string out=std::string(
"ABORTED: server=")+mPortName
2736 +std::string(
" alias=")+strAlias
2737 +std::string(
" cmd=")+strCmd
2738 +std::string(
"\nCan't execute command, cannot set working directory ")+strerror(error)
2741 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
2742 fprintf(out_to_parent,
"%s", out.c_str());
2743 fflush(out_to_parent);
2744 fclose(out_to_parent);
2745 fprintf(stderr,
"%s", out.c_str());
2753 char currWorkDirBuff[1024];
2758 char **cwd_arg_str=
new char*[nargs+1];
2759 for (
int i = 1; i < nargs; ++i) {
2760 cwd_arg_str[i] = arg_str[i];
2762 cwd_arg_str[nargs]=
nullptr;
2763 cwd_arg_str[0]=
new char[strlen(currWorkDir)+strlen(arg_str[0])+16];
2765 strcpy(cwd_arg_str[0], currWorkDir);
2766 strcat(cwd_arg_str[0],
"/");
2767 strcat(cwd_arg_str[0], arg_str[0]);
2774 ret = yarp::run::impl::execvp(cwd_arg_str[0], cwd_arg_str);
2776 delete [] cwd_arg_str[0];
2777 delete [] cwd_arg_str;
2787 ret = yarp::run::impl::execvp(arg_str[0], arg_str);
2799 std::string out=std::string(
"ABORTED: server=")+mPortName
2800 +std::string(
" alias=")+strAlias
2801 +std::string(
" cmd=")+strCmd
2802 +std::string(
"\nCan't execute command because ")+strerror(error)
2805 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
2806 fprintf(out_to_parent,
"%s", out.c_str());
2807 fflush(out_to_parent);
2808 fclose(out_to_parent);
2809 fprintf(stderr,
"%s", out.c_str());
2821 if (IS_PARENT_OF(pid_cmd))
2846 if (msg.
check(
"env"))
2851 mProcessVector->Add(pInf);
2855 FILE* in_from_child=fdopen(pipe_child_to_parent[
READ_FROM_PIPE],
"r");
2856 int flags=fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_GETFL, 0);
2857 fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
2867 if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) {
2871 out+=std::string(buff);
2874 fclose(in_from_child);
2883 out=std::string(
"STARTED: server=")+mPortName
2884 +std::string(
" alias=")+strAlias
2885 +std::string(
" cmd=")+strCmd
2894 fprintf(stderr,
"%s", out.c_str());
2904 result.
addString(
"I should never reach this point!!!\n");
2914 std::string portName=
"/log";
2915 portName+=mPortName+
"/";
2917 std::string command = strCmd;
2918 command = command.substr(0, command.find(
' '));
2919 command = command.substr(command.find_last_of(
"\\/") + 1);
2925 int pipe_cmd_to_stdout[2];
2926 int ret_cmd_to_stdout=yarp::run::impl::pipe(pipe_cmd_to_stdout);
2928 int pipe_child_to_parent[2];
2929 int ret_child_to_parent=yarp::run::impl::pipe(pipe_child_to_parent);
2931 if (ret_child_to_parent!=0 || ret_cmd_to_stdout!=0)
2935 std::string out=std::string(
"ABORTED: server=")+mPortName
2936 +std::string(
" alias=")+strAlias
2937 +std::string(
" cmd=stdout\n")
2938 +std::string(
"Can't create pipes ")+strerror(error)
2943 fprintf(stderr,
"%s", out.c_str());
2950 if (IS_INVALID(pid_stdout))
2959 std::string out=std::string(
"ABORTED: server=")+mPortName
2960 +std::string(
" alias=")+strAlias
2961 +std::string(
" cmd=stdout\n")
2962 +std::string(
"Can't fork stdout process because ")+strerror(error)
2967 fprintf(stderr,
"%s", out.c_str());
2972 if (IS_NEW_PROCESS(pid_stdout))
2986 int ret = yarp::run::impl::execlp(
"yarprun",
"yarprun",
"--write", portName.c_str(),
"--log", loggerName.c_str(),
static_cast<char*
>(
nullptr));
2994 std::string out=std::string(
"ABORTED: server=")+mPortName
2995 +std::string(
" alias=")+strAlias
2996 +std::string(
" cmd=stdout\n")
2997 +std::string(
"Can't execute stdout because ")+strerror(error)
3000 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
3001 fprintf(out_to_parent,
"%s", out.c_str());
3002 fflush(out_to_parent);
3003 fclose(out_to_parent);
3005 fprintf(stderr,
"%s", out.c_str());
3013 if (IS_PARENT_OF(pid_stdout))
3017 fprintf(stderr,
"STARTED: server=%s alias=%s cmd=stdout pid=%d\n", mPortName.c_str(), strAlias.c_str(), pid_stdout);
3025 if (IS_INVALID(pid_cmd))
3032 std::string out=std::string(
"ABORTED: server=")+mPortName
3033 +std::string(
" alias=")+strAlias
3034 +std::string(
" cmd=")+strCmd
3035 +std::string(
"\nCan't fork command process because ")+strerror(error)
3040 fprintf(stderr,
"%s", out.c_str());
3042 FILE* to_yarp_stdout=fdopen(pipe_cmd_to_stdout[
WRITE_TO_PIPE],
"w");
3043 fprintf(to_yarp_stdout,
"%s", out.c_str());
3044 fflush(to_yarp_stdout);
3045 fclose(to_yarp_stdout);
3047 SIGNAL(pid_stdout, SIGTERM);
3048 fprintf(stderr,
"TERMINATING stdout (%d)\n", pid_stdout);
3054 if (IS_NEW_PROCESS(pid_cmd))
3058 char *cmd_str=
new char[strCmd.length()+1];
3059 strcpy(cmd_str, strCmd.c_str());
3067 char **arg_str =
new char*[
C_MAXARGS + 1];
3069 arg_str[nargs]=
nullptr;
3071 setvbuf(stdout,
nullptr, _IONBF, 0);
3084 if (msg.
check(
"env"))
3087 for (
const auto& s : ss) {
3088 char* szenv =
new char[s.size()+1];
3089 strcpy(szenv, s.c_str());
3090 yarp::run::impl::putenv(szenv);
3095 if (msg.
check(
"workdir"))
3097 int ret = yarp::os::impl::chdir(msg.
find(
"workdir").
asString().c_str());
3103 std::string out=std::string(
"ABORTED: server=")+mPortName
3104 +std::string(
" alias=")+strAlias
3105 +std::string(
" cmd=")+strCmd
3106 +std::string(
"\nCan't execute command, cannot set working directory ")+strerror(error)
3109 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
3110 fprintf(out_to_parent,
"%s", out.c_str());
3111 fflush(out_to_parent);
3112 fclose(out_to_parent);
3113 fprintf(stderr,
"%s", out.c_str());
3121 char currWorkDirBuff[1024];
3122 char *currWorkDir=
getcwd(currWorkDirBuff, 1024);
3126 char **cwd_arg_str=
new char*[nargs+1];
3127 for (
int i = 1; i < nargs; ++i) {
3128 cwd_arg_str[i] = arg_str[i];
3130 cwd_arg_str[nargs]=
nullptr;
3131 cwd_arg_str[0]=
new char[strlen(currWorkDir)+strlen(arg_str[0])+16];
3133 strcpy(cwd_arg_str[0], currWorkDir);
3134 strcat(cwd_arg_str[0],
"/");
3135 strcat(cwd_arg_str[0], arg_str[0]);
3142 ret = yarp::run::impl::execvp(cwd_arg_str[0], cwd_arg_str);
3144 delete [] cwd_arg_str[0];
3145 delete [] cwd_arg_str;
3155 ret = yarp::run::impl::execvp(arg_str[0], arg_str);
3166 std::string out=std::string(
"ABORTED: server=")+mPortName
3167 +std::string(
" alias=")+strAlias
3168 +std::string(
" cmd=")+strCmd
3169 +std::string(
"\nCan't execute command because ")+strerror(error)
3172 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
3173 fprintf(out_to_parent,
"%s", out.c_str());
3174 fflush(out_to_parent);
3175 fclose(out_to_parent);
3176 fprintf(stderr,
"%s", out.c_str());
3188 if (IS_PARENT_OF(pid_cmd))
3207 if (msg.
check(
"env"))
3212 mProcessVector->Add(pInf);
3216 FILE* in_from_child=fdopen(pipe_child_to_parent[
READ_FROM_PIPE],
"r");
3217 int flags=fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_GETFL, 0);
3218 fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
3228 if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) {
3232 out+=std::string(buff);
3235 fclose(in_from_child);
3244 out=std::string(
"STARTED: server=")+mPortName
3245 +std::string(
" alias=")+strAlias
3246 +std::string(
" cmd=")+strCmd
3254 fprintf(stderr,
"%s", out.c_str());
3264 result.
addString(
"I should never reach this point!!!\n");
3276 if (msg.
check(
"forward"))
3278 strCmd=std::string(
"/bin/bash -l -c \"yarprun --readwrite ")+strUUID
3283 strCmd=std::string(
"/bin/bash -l -c \"yarprun --readwrite ")+strUUID+
"\"";
3286 int pipe_child_to_parent[2];
3288 if (yarp::run::impl::pipe(pipe_child_to_parent))
3292 std::string out=std::string(
"ABORTED: server=")+mPortName
3293 +std::string(
" alias=")+strAlias
3294 +std::string(
" cmd=stdio\nCan't create pipe ")+strerror(error)
3300 fprintf(stderr,
"%s", out.c_str());
3307 for (
auto & i : command) {
3311 cmdcpy(command[c++],
"xterm");
3312 cmdcpy(command[c++], msg.
check(
"hold")?
"-hold":
"+hold");
3314 if (msg.
check(
"geometry"))
3316 cmdcpy(command[c++],
"-geometry");
3317 cmdcpy(command[c++], msg.
find(
"geometry").
asString().c_str());
3320 cmdcpy(command[c++],
"-title");
3321 cmdcpy(command[c++], strAlias.c_str());
3323 cmdcpy(command[c++],
"-e");
3324 cmdcpy(command[c++], strCmd.c_str());
3328 if (IS_INVALID(pid_cmd))
3332 std::string out=std::string(
"ABORTED: server=")+mPortName
3333 +std::string(
" alias=")+strAlias
3334 +std::string(
" cmd=stdio\nCan't fork stdout process because ")+strerror(error)
3340 fprintf(stderr,
"%s", out.c_str());
3350 if (IS_NEW_PROCESS(pid_cmd))
3365 int ret = yarp::run::impl::execvp(
"xterm", command);
3373 std::string out=std::string(
"ABORTED: server=")+mPortName
3374 +std::string(
" alias=")+strAlias
3375 +std::string(
" cmd=xterm\nCan't execute command because ")+strerror(error)
3378 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
3380 fprintf(out_to_parent,
"%s", out.c_str());
3381 fflush(out_to_parent);
3382 fclose(out_to_parent);
3384 fprintf(stderr,
"%s", out.c_str());
3392 if (IS_PARENT_OF(pid_cmd))
3396 mStdioVector->Add(
new YarpRunProcInfo(strAlias, mPortName, pid_cmd,
nullptr, msg.
check(
"hold")));
3404 FILE* in_from_child=fdopen(pipe_child_to_parent[
READ_FROM_PIPE],
"r");
3405 int flags=fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_GETFL, 0);
3406 fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
3415 if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) {
3419 out+=std::string(buff);
3422 fclose(in_from_child);
3428 if (out.substr(0, 14)==
"xterm Xt error" || out.substr(0, 7)==
"ABORTED")
3434 out=std::string(
"STARTED: server=")+mPortName
3435 +std::string(
" alias=")+strAlias
3436 +std::string(
" cmd=xterm pid=")+
int2String(pid_cmd)
3441 fprintf(stderr,
"%s", out.c_str());
3462 int pipe_child_to_parent[2];
3463 int ret_pipe_child_to_parent=yarp::run::impl::pipe(pipe_child_to_parent);
3465 if (ret_pipe_child_to_parent!=0)
3469 std::string out=std::string(
"ABORTED: server=")+mPortName
3470 +std::string(
" alias=")+strAlias
3471 +std::string(
" cmd=stdio\nCan't create pipe ")+strerror(error)
3477 fprintf(stderr,
"%s", out.c_str());
3484 if (IS_INVALID(pid_cmd))
3488 std::string out=std::string(
"ABORTED: server=")+mPortName
3489 +std::string(
" alias=")+strAlias
3490 +std::string(
" cmd=")+strCmd
3491 +std::string(
"\nCan't fork command process because ")+strerror(error)
3496 fprintf(stderr,
"%s", out.c_str());
3501 if (IS_NEW_PROCESS(pid_cmd))
3503 int saved_stderr = yarp::run::impl::dup(STDERR_FILENO);
3504 int null_file=open(
"/dev/null", O_WRONLY);
3511 char *cmd_str=
new char[strCmd.length()+1];
3512 strcpy(cmd_str, strCmd.c_str());
3520 char **arg_str =
new char*[
C_MAXARGS + 1];
3522 arg_str[nargs]=
nullptr;
3532 if (msg.
check(
"env"))
3535 for (
const auto& s : ss) {
3536 char* szenv =
new char[s.size()+1];
3537 strcpy(szenv, s.c_str());
3538 yarp::run::impl::putenv(szenv);
3542 if (msg.
check(
"workdir"))
3544 int ret = yarp::os::impl::chdir(msg.
find(
"workdir").
asString().c_str());
3550 std::string out=std::string(
"ABORTED: server=")+mPortName
3551 +std::string(
" alias=")+strAlias
3552 +std::string(
" cmd=")+strCmd
3553 +std::string(
"\nCan't execute command, cannot set working directory ")+strerror(error)
3556 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
3557 fprintf(out_to_parent,
"%s", out.c_str());
3558 fflush(out_to_parent);
3559 fclose(out_to_parent);
3562 fprintf(stderr,
"%s", out.c_str());
3568 char currWorkDirBuff[1024];
3569 char *currWorkDir=
getcwd(currWorkDirBuff, 1024);
3573 char **cwd_arg_str=
new char*[nargs+1];
3574 for (
int i = 1; i < nargs; ++i) {
3575 cwd_arg_str[i] = arg_str[i];
3577 cwd_arg_str[nargs]=
nullptr;
3578 cwd_arg_str[0]=
new char[strlen(currWorkDir)+strlen(arg_str[0])+16];
3581 strcpy(cwd_arg_str[0], currWorkDir);
3582 strcat(cwd_arg_str[0],
"/");
3583 strcat(cwd_arg_str[0], arg_str[0]);
3590 ret = yarp::run::impl::execvp(cwd_arg_str[0], cwd_arg_str);
3592 delete [] cwd_arg_str[0];
3593 delete [] cwd_arg_str;
3602 ret = yarp::run::impl::execvp(arg_str[0], arg_str);
3609 std::string out=std::string(
"ABORTED: server=")+mPortName
3610 +std::string(
" alias=")+strAlias
3611 +std::string(
" cmd=")+strCmd
3612 +std::string(
"\nCan't execute command because ")+strerror(error)
3615 FILE* out_to_parent=fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
3616 fprintf(out_to_parent,
"%s", out.c_str());
3617 fflush(out_to_parent);
3618 fclose(out_to_parent);
3620 if (saved_stderr >= 0)
3624 fprintf(stderr,
"%s", out.c_str());
3633 if (IS_PARENT_OF(pid_cmd))
3635 auto* pInf =
new YarpRunProcInfo(strAlias, mPortName, pid_cmd,
nullptr,
false);
3637 if (msg.
check(
"env")) {
3640 mProcessVector->Add(pInf);
3642 sprintf(pidstr,
"%d", pid_cmd);
3646 FILE* in_from_child=fdopen(pipe_child_to_parent[
READ_FROM_PIPE],
"r");
3647 int flags=fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_GETFL, 0);
3648 fcntl(pipe_child_to_parent[
READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
3658 if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) {
3662 out+=std::string(buff);
3665 fclose(in_from_child);
3674 out=std::string(
"STARTED: server=")+mPortName
3675 +std::string(
" alias=")+strAlias
3676 +std::string(
" cmd=")+strCmd
3681 fprintf(stderr,
"%s", out.c_str());
3712 std::string dest_srv=node;
3714 if (command.
check(
"stdio"))
3716 dest_srv=std::string(command.
find(
"stdio").
asString());
3723 if (command.
check(
"geometry"))
3731 if (command.
check(
"hold"))
3750 printf(
":: %s\n", msg.
toString().c_str());
3752 response=sendMsg(msg, dest_srv);
3755 sprintf(buff,
"%d", response.
get(0).
asInt32());
3756 keyv=std::string(buff);
3775 printf(
":: %s\n", msg.
toString().c_str());
3777 response=sendMsg(msg, node);
3795 printf(
":: %s\n", msg.
toString().c_str());
3797 response=sendMsg(msg, node);
3817 printf(
":: %s\n", msg.
toString().c_str());
3819 response=sendMsg(msg, node);
3838 printf(
":: %s\n", msg.
toString().c_str());
3840 response=sendMsg(msg, node);
3842 if (!response.
size()) {
int SIGNAL(int pid, int signum)
std::string int2String(int x)
static yarp::os::Bottle parsePaths(const std::string &txt)
static void sigchld_handler(int sig)
void sigstdio_handler(int sig)
void sigint_handler(int sig)
constexpr fs::value_type slash
void parseArguments(char *io_pLine, int *o_pArgc, char **o_pArgv)
Breaks up a line into multiple arguments.
static bool fileExists(const char *fname)
void splitLine(char *pLine, char **pArgs)
Split a line into separate words.
#define REDIRECT_TO(from, to)
static RunTerminator * pTerminator
void setEnv(const std::string &env)
void setCmd(const std::string &cmd)
A simple collection of objects that can be described and transmitted in a portable way.
void fromString(const std::string &text)
Initializes bottle from a string.
void append(const Bottle &alt)
Append the content of the given bottle to the current list.
Bottle & addList()
Places an empty nested list in the bottle, at the end of the list.
size_type size() const
Gets the number of elements in the bottle.
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Bottle & findGroup(const std::string &key) const override
Gets a list corresponding to a given keyword.
bool check(const std::string &key) const override
Check if there exists a property of the given name.
Bottle tail() const
Get all but the first element of a bottle.
void clear()
Empties the bottle of any objects it contains.
void addInt32(std::int32_t x)
Places a 32-bit integer in the bottle, at the end of the list.
void addString(const char *str)
Places a string in the bottle, at the end of the list.
std::string toString() const override
Gives a human-readable textual representation of the bottle.
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
static bool getLocalMode()
Get current value of flag "localMode", see setLocalMode function.
static bool connect(const std::string &src, const std::string &dest, const std::string &carrier="", bool quiet=true)
Request that an output port connect to an input port.
static bool checkNetwork()
Check if the YARP Network is up and running.
static bool disconnect(const std::string &src, const std::string &dest, bool quiet)
Request that an output port disconnect from an input port.
A class for storing options and configuration information.
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
std::string toString() const override
Return a standard text representation of the content of the object.
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
bool check(const std::string &key) const override
Check if there exists a property of the given name.
Bottle & findGroup(const std::string &key) const override
Gets a list corresponding to a given keyword.
void unput(const std::string &key)
Remove the association from the given key to a value, if present.
void fromCommand(int argc, char *argv[], bool skipFirst=true, bool wipe=true)
Interprets a list of command arguments as a list of properties.
A port that is specialized as an RPC client.
A port that is specialized as an RPC server.
A class for thread synchronization and mutual exclusion.
static void delaySystem(double seconds)
A helper class to pass the SystemInfo object around the YARP network.
yarp::os::SystemInfo::LoadInfo load
current cpu load information
yarp::os::SystemInfo::UserInfo user
current user information
yarp::os::SystemInfo::StorageInfo storage
system storage information
yarp::os::SystemInfo::PlatformInfo platform
operating system information
yarp::os::SystemInfo::MemoryInfo memory
system memory information
yarp::os::SystemInfo::ProcessorInfo processor
system processor type information
bool stop()
Stop the thread.
bool start()
Start the new thread running.
A single value (typically within a Bottle).
virtual std::int32_t asInt32() const
Get 32-bit integer value.
std::string toString() const override
Return a standard text representation of the content of the object.
virtual std::string asString() const
Get string value.
static NameClient & getNameClient()
Get an instance of the name client.
std::string send(const std::string &cmd, bool multi=true, const ContactStyle &style=ContactStyle())
Send a text message to the nameserver, and return the result.
static int kill(const std::string &node, const std::string &keyv, int s)
Send a SIGNAL to an application running on a yarprun server (Linux only).
static int start(const std::string &node, yarp::os::Property &command, std::string &keyv)
Launch a yarprun server.
static bool isRunning(const std::string &node, std::string &keyv)
Get a report of all applications running on a yarprun server.
static int sigterm(const std::string &node, const std::string &keyv)
Terminate an application running on a yarprun server.
static int client(yarp::os::Property &config)
Send a property object to a run server, bundling up all the settings usually specified on the command...
std::string toString(const T &value)
convert an arbitrary type to string.
static constexpr char path_separator
bool set_string(const std::string &key, const std::string &value)
Set a string to an environment variable.
std::string get_string(const std::string &key, bool *found=nullptr)
Read a string from an environment variable.
static constexpr value_type preferred_separator
ContainerT split(const typename ContainerT::value_type &s, std::basic_regex< typename ContainerT::value_type::value_type > regex)
Utility to split a string by a separator, into a vector of strings.
void useSystemClock()
Configure YARP to use system time (this is the default).
char * getcwd(char *buf, size_t size)
Portable wrapper for the getcwd() function.
int getpid()
Portable wrapper for the getppid() function.
int fork()
Portable wrapper for the fork() function.
bool read(ImageOf< PixelRgb > &dest, const std::string &src, image_fileformat format=FORMAT_ANY)
bool write(const ImageOf< PixelRgb > &src, const std::string &dest, image_fileformat format=FORMAT_PPM)
The main, catch-all namespace for YARP.
int main(int argc, char *argv[])