YARP  2.3.70
Yet Another Robot Platform
Run.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007-2009 RobotCub Consortium
3  * Author: Alessandro Scalzo <alessandro.scalzo@iit.it>
4  * CopyPolicy: Released under the terms of the LGPLv2.1 or later, see LGPL.TXT
5  */
6 
7 #include <yarp/os/Run.h>
8 
9 #include <yarp/os/Network.h>
10 #include <yarp/os/Os.h>
11 #include <yarp/os/LogStream.h>
12 #include <yarp/os/RpcClient.h>
13 #include <yarp/os/SystemInfo.h>
15 #include <yarp/os/Time.h>
16 
17 #include <yarp/os/impl/Logger.h>
27 
28 #include <cstdio>
29 #include <string>
30 #include <cstring>
31 
32 #if defined(_WIN32)
33 # if !defined(WIN32_LEAN_AND_MEAN)
34 # define WIN32_LEAN_AND_MEAN
35 # endif
36 # include <windows.h>
37 #else
38 # define C_MAXARGS 128 // the max number of command parameters. rational?
39 #endif
40 
41 #if defined(_WIN32)
42 YarpRunInfoVector yarp::os::Run::mProcessVector;
43 YarpRunInfoVector yarp::os::Run::mStdioVector;
44 inline yarp::os::ConstString lastError2String()
45 {
46  int error=GetLastError();
47  char buff[1024];
48  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, YARP_NULLPTR, error, 0, buff, 1024, YARP_NULLPTR);
49 
50  return yarp::os::ConstString(buff);
51 }
52 #else
53 //#define SIGSTDIO SIGHUP
54 #define READ_FROM_PIPE 0
55 #define WRITE_TO_PIPE 1
56 #define REDIRECT_TO(from, to) yarp::os::impl::dup2(to, from)
57 YarpRunInfoVector* yarp::os::Run::mProcessVector = YARP_NULLPTR;
58 YarpRunInfoVector* yarp::os::Run::mStdioVector = YARP_NULLPTR;
59 ZombieHunterThread* yarp::os::Run::mBraveZombieHunter = YARP_NULLPTR;
60 #endif
61 
63 // OS INDEPENDENT FUNCTIONS
65 
66 yarp::os::ConstString yarp::os::Run::mPortName;
67 yarp::os::RpcServer* yarp::os::Run::pServerPort=YARP_NULLPTR;
68 int yarp::os::Run::mProcCNT=0;
69 bool yarp::os::Run::mStresstest=false;
70 bool yarp::os::Run::mLogged=false;
71 yarp::os::ConstString yarp::os::Run::mLoggerPort("/yarplogger");
72 
74 
75 static RunTerminator *pTerminator = YARP_NULLPTR;
76 
77 void sigstdio_handler(int sig)
78 {
79  char msg[16];
80  sprintf(msg, "SIGNAL %d", sig);
81  RUNLOG(msg);
82 
83  if (pTerminator) pTerminator->exit();
84 }
85 
87 
93  yarp::os::Bottle result;
94  const char *at = txt.c_str();
95  int slash_tweak = 0;
96  int len = 0;
97  for (yarp::os::ConstString::size_type i=0; i<txt.length(); i++) {
98  char ch = txt[i];
99  if (ch==sep) {
100  result.addString(yarp::os::ConstString(at, len-slash_tweak));
101  at += len+1;
102  len = 0;
103  slash_tweak = 0;
104  continue;
105  }
106  slash_tweak = (ch==slash && len>0)?1:0;
107  len++;
108  }
109  if (len>0) {
110  result.addString(yarp::os::ConstString(at, len-slash_tweak));
111  }
112  return result;
113 }
114 
115 static bool fileExists(const char *fname) {
116  FILE *fp = YARP_NULLPTR;
117  fp = fopen(fname, "r");
118  if (!fp) {
119  return false;
120  } else {
121  fclose(fp);
122  return true;
123  }
124  }
125 
126 
128 int yarp::os::Run::main(int argc, char *argv[])
129 {
130  Property config;
131  config.fromCommand(argc, argv, false);
132 
133  // SERVER
134  if (config.check("server"))
135  {
136  mLogged=config.check("log");
137 
138  if (mLogged)
139  {
140  Bottle botPortLogger=config.findGroup("log");
141 
142  if (botPortLogger.size()>1)
143  {
144  mLoggerPort=botPortLogger.get(1).asString();
145  }
146  }
147 
148  mPortName=yarp::os::ConstString(config.find("server").asString());
149 
150  return server();
151  }
152 
153  if (config.check("echo"))
154  {
155  char line[1024];
156  fprintf(stderr, "Program echo started.\n");
157  fflush(stderr);
158 
159  while(true)
160  {
161  int ret=scanf("%s", line);
162 
163  if (ret>0)
164  {
165  fprintf(stderr, "%s\n", line);
166  fflush(stderr);
167  }
168  }
169 
170  return 0;
171  }
172 
173  //yarp::os::Network yarp;
174 
175  mPortName="";
176 
178  {
180  {
181  fprintf(stderr, "ERROR: no yarp network found.\n");
182 
183  return YARPRUN_ERROR;
184  }
185  }
186 
188 
189  if (config.check("readwrite"))
190  {
192  yarp::os::ConstString uuid=config.findGroup("readwrite").get(1).asString();
193  yarp::os::ConstString fPortName("");
194  yarp::os::ConstString lPortName("");
195 
196  if (config.check("forward"))
197  {
198  fPortName=config.findGroup("forward").get(1).asString();
199  lPortName=config.findGroup("forward").get(2).asString();
200  }
201 
202 #if defined(_WIN32)
206 #elif defined(__APPLE__)
207  //prctl(PR_SET_PDEATHSIG, SIGTERM);
208 
209  struct sigaction new_action;
210  new_action.sa_handler=sigstdio_handler;
211  sigfillset(&new_action.sa_mask);
212  new_action.sa_flags=0;
213 
214  sigaction(SIGTERM, &new_action, YARP_NULLPTR);
215  sigaction(SIGHUP, &new_action, YARP_NULLPTR);
216  //yarp::os::impl::signal(SIGHUP, SIG_IGN);
217  //yarp::os::impl::signal(SIGINT, SIG_IGN);
218  yarp::os::impl::signal(SIGPIPE, SIG_IGN);
219 
220  if (getppid()==1) return 0;
221 #else
222  yarp::os::impl::prctl(PR_SET_PDEATHSIG, SIGTERM);
223 
224  struct sigaction new_action;
225  new_action.sa_handler=sigstdio_handler;
226  yarp::os::impl::sigfillset(&new_action.sa_mask);
227  new_action.sa_flags=0;
228 
229  yarp::os::impl::sigaction(SIGTERM, &new_action, YARP_NULLPTR);
230  yarp::os::impl::signal(SIGHUP, SIG_IGN);
231  //yarp::os::impl::signal(SIGINT, SIG_IGN);
232  yarp::os::impl::signal(SIGPIPE, SIG_IGN);
233 
234  if (yarp::os::getpid() == 1) {
235  return 0;
236  }
237 #endif
238 
239  RunReadWrite rw(uuid, fPortName, lPortName);
240  RunTerminator rt(&rw);
241  pTerminator=&rt;
242  rt.start();
243 
244  return rw.loop();
245  }
246 
247  if (config.check("write"))
248  {
250  yarp::os::ConstString portName=config.findGroup("write").get(1).asString();
251 
252 #if defined(_WIN32)
256 #else
257  struct sigaction new_action;
258  new_action.sa_handler=sigstdio_handler;
259  yarp::os::impl::sigfillset(&new_action.sa_mask);
260  new_action.sa_flags=0;
261  yarp::os::impl::sigaction(SIGTERM, &new_action, YARP_NULLPTR);
262  //yarp::os::impl::signal(SIGINT, SIG_IGN);
263  yarp::os::impl::signal(SIGPIPE, SIG_IGN);
264  yarp::os::impl::signal(SIGHUP, SIG_IGN);
265 #endif
266 
267  if (config.check("log"))
268  {
269  yarp::os::ConstString loggerName=config.find("log").asString();
270  RunWrite w(portName, loggerName);
271  RunTerminator rt(&w);
272  pTerminator=&rt;
273  rt.start();
274  return w.loop();
275  }
276  else
277  {
278  RunWrite w(portName);
279  RunTerminator rt(&w);
280  pTerminator=&rt;
281  rt.start();
282  return w.loop();
283  }
284 
285  return 0;
286  }
287 
288  if (config.check("read"))
289  {
291  yarp::os::ConstString uuid=config.findGroup("read").get(1).asString();
292 
293  #if defined(_WIN32)
297  #else
298  //yarp::os::impl::signal(SIGINT, SIG_IGN);
300  yarp::os::impl::signal(SIGHUP, SIG_IGN);
301  #endif
302 
303  RunRead r(uuid);
304  RunTerminator rt(&r);
305  pTerminator=&rt;
306  rt.start();
307 
308  return r.loop();
309  }
310 
312 
313  if (config.check("stresstest"))
314  {
315  fprintf(stderr, "Yarprun stress test started.\n");
316  fflush(stderr);
317 
318  int max_interval_ms=config.find("stresstest").asInt();
319  yarp::os::ConstString tag_zero=config.find("as").asString();
320  yarp::os::Bottle srv=config.findGroup("on");
321 
322  config.unput("as");
323  config.unput("stresstest");
324 
326 
327  bool isCommand=false;
328 
329  if (config.check("cmd"))
330  {
331  isCommand=true;
332  cmd=config.find("cmd").asString();
333  config.unput("cmd");
334  }
335 
336  unsigned int t=0, u=0;
337  int term_cycle=0;
338 
339  char tag[256];
340  char cmd_and_name[512];
341 
342  mStresstest=true;
343 
344  while (mStresstest)
345  {
346  yarp::os::Time::delay(0.001*(rand() % max_interval_ms));
347 
348  Property stresser=config;
349 
350  sprintf(tag, "%s_%u", tag_zero.c_str(), t++);
351  stresser.put("as", tag);
352 
353  if (isCommand)
354  {
355  sprintf(cmd_and_name, "%s --name /%s", cmd.c_str(), tag);
356  stresser.put("cmd", cmd_and_name);
357  }
358 
359  client(stresser);
360 
361  if (isCommand && ++term_cycle>=4)
362  {
363  term_cycle=0;
364 
365  int r=t-(rand()%8);
366 
367  for (int i=u; i<r; ++i)
368  {
369  sprintf(tag, "%s_%u", tag_zero.c_str(), i);
370 
371  Bottle as;
372  as.addString("sigterm");
373  as.addString(tag);
374 
375  Bottle term;
376  term.addList()=srv;
377  term.addList()=as;
378 
379  sendMsg(term, srv.get(1).asString());
380 
381  ++u;
382  }
383  }
384  }
385 
386  return 0;
387  }
388 
389  // HELP
390  if (config.check("help"))
391  {
392  Help();
393 
394  return 0;
395  }
396 
397  // CLIENT (config is from keyboard)
398  if (config.check("stdio")
399  || config.check("cmd")
400  || config.check("kill")
401  || config.check("sigterm")
402  || config.check("sigtermall")
403  || config.check("exit")
404  || config.check("isrunning")
405  || config.check("ps")
406  || config.check("env")
407  || config.check("sysinfo")
408  || config.check("which"))
409  {
410  int ret=client(config);
411 
412  return ret;
413  }
414 
415  Help();
416 
417  return 0;
418 }
419 
420 yarp::os::Bottle yarp::os::Run::sendMsg(Bottle& msg, yarp::os::ConstString target, int RETRY, double DELAY)
421 {
422  Bottle response;
423 
424  for (int r=0; r<RETRY; ++r)
425  {
426  yarp::os::RpcClient port;
427 
428  if (!port.open("..."))
429  {
430  yarp::os::Time::delay(DELAY);
431  continue;
432  }
433 
434  if (!yarp::os::Network::connect(port.getName(), target))
435  {
436  port.close();
437  yarp::os::Time::delay(DELAY);
438  continue;
439  }
440 
441  RUNLOG("<<<port.write(msg, response)")
442  if (!port.write(msg, response))
443  {
444  port.close();
445  yarp::os::Time::delay(DELAY);
446  continue;
447  }
448  RUNLOG(">>>port.write(msg, response)")
449 
450  yarp::os::Network::disconnect(port.getName().c_str(), target.c_str());
451  port.close();
452 
453  fprintf(stderr, "RESPONSE:\n=========\n");
454  for (int s=0; s<response.size(); ++s)
455  {
456  fprintf(stderr, "%s\n", response.get(s).toString().c_str());
457  }
458 
459  return response;
460  }
461 
462  response.addString("RESPONSE:\n");
463  response.addString("=========\n");
464  response.addString("Cannot connect to remote server, aborting...\n");
465  for (int s=0; s<response.size(); ++s)
466  {
467  fprintf(stderr, "%s\n", response.get(s).toString().c_str());
468  }
469  return response;
470 }
471 
472 void sigint_handler(int sig)
473 {
474  yarp::os::Run::mStresstest=false;
475 
476  if (yarp::os::Run::pServerPort)
477  {
478  yarp::os::RpcServer *pClose=yarp::os::Run::pServerPort;
479  yarp::os::Run::pServerPort = YARP_NULLPTR;
480  pClose->close();
481  }
482  //else
483  //{
484  //}
485 }
486 
488 // WINDOWS SERVER
489 #if defined(_WIN32)
490 int yarp::os::Run::server()
491 {
492  yarp::os::Semaphore serializer(1);
493 
494  RpcServer port;
495 
496  if (!port.open(mPortName.c_str()))
497  {
498  yError() << "Yarprun failed to open port: " << mPortName.c_str();
499  return YARPRUN_ERROR;
500  }
501  yInfo() << "Yarprun succesfully started on port: " << mPortName.c_str();
502 
503  pServerPort=&port;
504 
507 
508  // Enabling cpu load collector on windows
509  //yarp::os::impl::SystemInfo::enableCpuLoadCollector();
510 
511  while (pServerPort)
512  {
513  Bottle msg;
514 
515  RUNLOG("<<<port.read(msg, true)")
516  if (!port.read(msg, true)) break;
517  RUNLOG(">>>port.read(msg, true)")
518 
519  if (!pServerPort) break;
520 
521  //printf("<<< %s >>>\n", msg.toString().c_str());
522  //fflush(stdout);
523 
525 
526  // command with stdio management
527  if (msg.check("stdio"))
528  {
529  yarp::os::ConstString strOnPort=msg.find("on").asString();
530  yarp::os::ConstString strStdioPort=msg.find("stdio").asString();
531 
532  if (strOnPort==mPortName)
533  {
534  yarp::os::ConstString strUUID=mPortName+"/"+int2String(getpid())+"/"+msg.find("as").asString()+"-"+int2String(mProcCNT++);
535  Bottle botUUID;
536  botUUID.addString("stdiouuid");
537  botUUID.addString(strUUID.c_str());
538  msg.addList()=botUUID;
539 
540  if (mLogged || msg.check("log"))
541  {
542  yarp::os::ConstString strAlias=msg.find("as").asString();
543  yarp::os::ConstString portName="/log";
544  portName+=mPortName+"/";
545  yarp::os::ConstString command=msg.findGroup("cmd").get(1).asString();
546  int space=command.find(" ");
547  if (space!=ConstString::npos) command=command.substr(0, space);
548  portName+=command;
549 
550  Bottle botFwd;
551  botFwd.addString("forward");
552  botFwd.addString(portName.c_str());
553  if (msg.check("log"))
554  {
555  yarp::os::Bottle botLogger=msg.findGroup("log");
556 
557  if (botLogger.size()>1)
558  {
559  botFwd.addString(botLogger.get(1).asString());
560  }
561  else
562  {
563  botFwd.addString(mLoggerPort);
564  }
565  }
566  else
567  {
568  botFwd.addString(mLoggerPort);
569  }
570  msg.addList()=botFwd;
571  }
572 
573  Bottle cmdResult;
574  if (executeCmdAndStdio(msg, cmdResult)>0)
575  {
576  if (strStdioPort==mPortName)
577  {
578  Bottle stdioResult;
579  userStdio(msg, stdioResult);
580  cmdResult.append(stdioResult);
581  }
582  else
583  {
584  cmdResult.append(sendMsg(msg, strStdioPort));
585  }
586  }
587 
588  port.reply(cmdResult);
589  }
590  else
591  {
592  Bottle stdioResult;
593  userStdio(msg, stdioResult);
594  port.reply(stdioResult);
595  }
596 
597  continue;
598  }
599 
600  // without stdio
601  if (msg.check("cmd"))
602  {
603  Bottle cmdResult;
604 
605  if (msg.check("log"))
606  {
607  yarp::os::Bottle botLogger=msg.findGroup("log");
608 
609  if (botLogger.size()>1)
610  {
611  yarp::os::ConstString loggerName=botLogger.get(1).asString();
612  executeCmdStdout(msg, cmdResult, loggerName);
613  }
614  else
615  {
616  executeCmdStdout(msg, cmdResult, mLoggerPort);
617  }
618  }
619  else if (mLogged)
620  {
621  executeCmdStdout(msg, cmdResult, mLoggerPort);
622  }
623  else
624  {
625  executeCmd(msg, cmdResult);
626  }
627  port.reply(cmdResult);
628  continue;
629  }
630 
631  if (msg.check("kill"))
632  {
633  yarp::os::ConstString alias(msg.findGroup("kill").get(1).asString());
634  int sig=msg.findGroup("kill").get(2).asInt();
635  Bottle result;
636  result.addString(mProcessVector.Signal(alias, sig)?"kill OK":"kill FAILED");
637  port.reply(result);
638  continue;
639  }
640 
641  if (msg.check("sigterm"))
642  {
643  yarp::os::ConstString alias(msg.find("sigterm").asString());
644  Bottle result;
645  result.addString(mProcessVector.Signal(alias, SIGTERM)?"sigterm OK":"sigterm FAILED");
646  port.reply(result);
647  continue;
648  }
649 
650  if (msg.check("sigtermall"))
651  {
652  mProcessVector.Killall(SIGTERM);
653  Bottle result;
654  result.addString("sigtermall OK");
655  port.reply(result);
656  continue;
657  }
658 
659  if (msg.check("ps"))
660  {
661  Bottle result;
662  result.append(mProcessVector.PS());
663  port.reply(result);
664  continue;
665  }
666 
667  if (msg.check("isrunning"))
668  {
669  yarp::os::ConstString alias(msg.find("isrunning").asString());
670  Bottle result;
671  result.addString(mProcessVector.IsRunning(alias)?"running":"not running");
672  port.reply(result);
673  continue;
674  }
675 
676  if (msg.check("killstdio"))
677  {
678  yarp::os::ConstString alias(msg.find("killstdio").asString());
679  mStdioVector.Signal(alias, SIGTERM);
680  Bottle result;
681  result.addString("killstdio OK");
682  port.reply(result);
683  continue;
684  }
685 
687 
688  if (msg.check("sysinfo"))
689  {
691  port.reply(sysinfo);
692  continue;
693  }
694 
695  if (msg.check("which"))
696  {
697  ConstString fileName=msg.find("which").asString();
698  if (fileName!="")
699  {
701  for (int i=0; i<possiblePaths.size(); ++i)
702  {
703  ConstString guessString=possiblePaths.get(i).asString() + slash + fileName;
704  const char* guess=guessString.c_str();
705  if (fileExists (guess))
706  {
707  fileName= "\"" + std::string(guess) + "\"";
708  break;
709  }
710  }
711  }
712  yarp::os::Value fileNameWriter(fileName);
713  port.reply(fileNameWriter);
714  continue;
715  }
716 
717  if (msg.check("exit"))
718  {
719  pServerPort=0;
720  Bottle result;
721  result.addString("exit OK");
722  port.reply(result);
723  port.close();
724  }
725  }
726 
727 
728  Run::mStdioVector.Killall(SIGTERM);
729 
730  Run::mProcessVector.Killall(SIGTERM);
731 
732  return 0;
733 }
734 
736 #else // LINUX SERVER
737 
739 void yarp::os::Run::cleanBeforeExec()
740 {
741  // zombie hunter stop
742 
743  //yarp::os::impl::signal(SIGPIPE, SIG_IGN);
744  //yarp::os::impl::signal(SIGCHLD, SIG_DFL);
745  //yarp::os::impl::signal(SIGINT, SIG_DFL);
746  //yarp::os::impl::signal(SIGTERM, SIG_DFL);
747 
748  if (mProcessVector)
749  {
750  YarpRunInfoVector *p=mProcessVector;
751  mProcessVector = YARP_NULLPTR;
752  delete p;
753  }
754  if (mStdioVector)
755  {
756  YarpRunInfoVector *p=mStdioVector;
757  mStdioVector = YARP_NULLPTR;
758  delete p;
759  }
760  if (mBraveZombieHunter)
761  {
762  ZombieHunterThread *p=mBraveZombieHunter;
763  mBraveZombieHunter = YARP_NULLPTR;
764  p->stop();
765  delete p;
766  }
767 
768  //yarp::os::Network::fini();
769 }
770 
771 void yarp::os::Run::writeToPipe(int fd, yarp::os::ConstString str)
772 {
773  int len=str.length()+1;
774 
775  ssize_t warn_suppress = write(fd, &len, 4);
776  warn_suppress = write(fd, str.c_str(), len);
777  YARP_UNUSED(warn_suppress);
778 }
779 
780 int yarp::os::Run::readFromPipe(int fd, char* &data, int& buffsize)
781 {
782  int len=0;
783  char* buff=(char*)&len;
784 
785  for (int c=4, r=0; c>0; c-=r)
786  {
787  r=read(fd, buff, c);
788 
789  if (r<1) return -1;
790 
791  buff+=r;
792  }
793 
794  if (len<=0) return 0;
795 
796  if (len>buffsize)
797  {
798  delete [] data;
799  data=new char[buffsize=1024+(len/1024)*1024];
800  }
801 
802  buff=data;
803 
804  for (int c=len, r=0; c>0; c-=r)
805  {
806  r=read(fd, buff, c);
807 
808  if (r<1) return -1;
809 
810  buff+=r;
811  }
812 
813  return len;
814 }
815 
816 static void sigchld_handler(int sig)
817 {
818  if (yarp::os::Run::mBraveZombieHunter)
819  {
820  yarp::os::Run::mBraveZombieHunter->sigchldHandler();
821  }
822 }
823 
824 int yarp::os::Run::server()
825 {
826  int pipe_server2manager[2];
827  int pipe_manager2server[2];
828 
829  if (yarp::os::impl::pipe(pipe_server2manager))
830  {
831  fprintf(stderr, "Can't open pipe because %s\n", strerror(errno));
832  fflush(stderr);
833 
834  return YARPRUN_ERROR;
835  }
836 
837  if (yarp::os::impl::pipe(pipe_manager2server))
838  {
839  fprintf(stderr, "Can't open pipe because %s\n", strerror(errno));
840  fflush(stderr);
841 
842  return YARPRUN_ERROR;
843  }
844 
845  int pid_process_manager=yarp::os::fork();
846 
847  if (IS_INVALID(pid_process_manager))
848  {
849  int error=errno;
850 
851  CLOSE(pipe_server2manager[WRITE_TO_PIPE]);
852  CLOSE(pipe_server2manager[READ_FROM_PIPE]);
853  CLOSE(pipe_manager2server[WRITE_TO_PIPE]);
854  CLOSE(pipe_manager2server[READ_FROM_PIPE]);
855 
856  fprintf(stderr, "Can't fork process manager because %s\n", strerror(error));
857  fflush(stderr);
858 
859  return YARPRUN_ERROR;
860  }
861 
862  if (IS_PARENT_OF(pid_process_manager))
863  {
864  yarp::os::impl::signal(SIGPIPE, SIG_IGN);
865 
866  CLOSE(pipe_server2manager[READ_FROM_PIPE]);
867  CLOSE(pipe_manager2server[WRITE_TO_PIPE]);
868 
869  //yarp::os::Network::init();
871 
872  yarp::os::RpcServer port;
873 
874  if (!port.open(mPortName.c_str()))
875  {
876  yError() << "Yarprun failed to open port: " << mPortName.c_str();
877 
878  if (mPortName[0]!='/') yError("Invalid port name '%s', it should start with '/'\n", mPortName.c_str());
879  return YARPRUN_ERROR;
880  }
881  yInfo() << "Yarprun succesfully started on port: " << mPortName.c_str();
882 
883  pServerPort=&port;
884 
887 
888  int rsp_size=1024;
889  char *rsp_str=new char[rsp_size];
890 
891  Bottle msg, response;
892 
893  while (pServerPort)
894  {
895  RUNLOG("<<<port.read(msg, true)")
896  if (!port.read(msg, true)) break;
897  RUNLOG(">>>port.read(msg, true)")
898 
899  if (!pServerPort) break;
900 
901  if (msg.check("sysinfo"))
902  {
904  port.reply(sysinfo);
905  continue;
906  }
907 
908  if (msg.check("which"))
909  {
910  ConstString fileName=msg.find("which").asString();
911  if (fileName!="")
912  {
914  for (int i=0; i<possiblePaths.size(); ++i)
915  {
916  ConstString guessString=possiblePaths.get(i).asString() + slash + fileName;
917  const char* guess=guessString.c_str();
918  if (fileExists (guess))
919  {
920  fileName = guess;
921  break;
922  }
923  }
924  }
925  yarp::os::Value fileNameWriter(fileName);
926  port.reply(fileNameWriter);
927  continue;
928  }
929 
930  if (msg.check("exit"))
931  {
932  pServerPort = YARP_NULLPTR;
933  Bottle result;
934  result.addString("exit OK");
935  port.reply(result);
936  port.close();
937  break;
938  }
939 
940  RUNLOG("<<<writeToPipe")
941  writeToPipe(pipe_server2manager[WRITE_TO_PIPE], msg.toString());
942  RUNLOG(">>>writeToPipe")
943 
944  RUNLOG("<<<readFromPipe")
945  int nread=readFromPipe(pipe_manager2server[READ_FROM_PIPE], rsp_str, rsp_size);
946  RUNLOG(">>>readFromPipe")
947 
948  if (nread<0)
949  {
950  fprintf(stderr, "ERROR: broken pipe between server and manager\n");
951  fflush(stderr);
952  break;
953  }
954 
955  if (nread)
956  {
957  response.fromString(rsp_str);
958  port.reply(response);
959  }
960  }
961 
962  //yarp::os::Network::fini();
963 
964  CLOSE(pipe_server2manager[WRITE_TO_PIPE]);
965  CLOSE(pipe_manager2server[READ_FROM_PIPE]);
966 
967  delete [] rsp_str;
968 
969  return 0;
970  }
971 
972  if (IS_NEW_PROCESS(pid_process_manager))
973  {
974  yarp::os::impl::signal(SIGPIPE, SIG_IGN);
975 
976  CLOSE(pipe_server2manager[WRITE_TO_PIPE]);
977  CLOSE(pipe_manager2server[READ_FROM_PIPE]);
978 
979  //yarp::os::Network::init();
980 
981  mProcessVector=new YarpRunInfoVector;
982  mStdioVector=new YarpRunInfoVector;
983 
984  mBraveZombieHunter=new ZombieHunterThread;
985  mBraveZombieHunter->start();
986 
988  //yarp::os::impl::signal(SIGINT, SIG_IGN);
989  //yarp::os::impl::signal(SIGTERM, SIG_IGN);
990 
991  int msg_size=1024;
992  char *msg_str=new char[msg_size];
993 
994  Bottle msg;
995 
996  //while(readFromPipe(pipe_server2manager[READ_FROM_PIPE], msg_str, msg_size)>0)
997  while (true)
998  {
999  RUNLOG("<<<readFromPipe")
1000  if (readFromPipe(pipe_server2manager[READ_FROM_PIPE], msg_str, msg_size)<=0) break;
1001  RUNLOG(">>>readFromPipe")
1002 
1003  //printf("<<< %s >>>\n", msg_str);
1004  //fflush(stdout);
1005 
1006  msg.fromString(msg_str);
1007 
1008  // command with stdio management
1009  if (msg.check("stdio"))
1010  {
1011  yarp::os::ConstString strOnPort=msg.find("on").asString();
1012  yarp::os::ConstString strStdioPort=msg.find("stdio").asString();
1013 
1014  if (strOnPort==mPortName)
1015  {
1016  yarp::os::ConstString strUUID=mPortName+"/"+int2String(getpid())+"/"+msg.find("as").asString()+"-"+int2String(mProcCNT++);
1017  Bottle botUUID;
1018  botUUID.addString("stdiouuid");
1019  botUUID.addString(strUUID.c_str());
1020  msg.addList()=botUUID;
1021 
1022  if (mLogged || msg.check("log"))
1023  {
1024  yarp::os::ConstString strAlias=msg.find("as").asString();
1025  yarp::os::ConstString portName="/log";
1026  portName+=mPortName+"/";
1027  yarp::os::ConstString command=msg.findGroup("cmd").get(1).asString();
1028  size_t space=command.find(' ');
1029  if (space!=ConstString::npos) command=command.substr(0, space);
1030  portName+=command;
1031 
1032  Bottle botFwd;
1033  botFwd.addString("forward");
1034  botFwd.addString(portName.c_str());
1035  if (msg.check("log"))
1036  {
1037  yarp::os::Bottle botLogger=msg.findGroup("log");
1038 
1039  if (botLogger.size()>1)
1040  {
1041  botFwd.addString(botLogger.get(1).asString());
1042  }
1043  else
1044  {
1045  botFwd.addString(mLoggerPort);
1046  }
1047  }
1048  else
1049  {
1050  botFwd.addString(mLoggerPort);
1051  }
1052  msg.addList()=botFwd;
1053 
1054  yarp::os::ContactStyle style;
1055  style.persistent=true;
1056  yarp::os::Network::connect(portName.c_str(), mLoggerPort.c_str(), style);
1057  }
1058 
1059  Bottle cmdResult;
1060  if (executeCmdAndStdio(msg, cmdResult)>0)
1061  {
1062  if (strStdioPort==mPortName)
1063  {
1064  Bottle stdioResult;
1065  userStdio(msg, stdioResult);
1066  cmdResult.append(stdioResult);
1067  }
1068  else
1069  {
1070  cmdResult.append(sendMsg(msg, strStdioPort));
1071  }
1072  }
1073 
1074  RUNLOG("<<<writeToPipe")
1075  writeToPipe(pipe_manager2server[WRITE_TO_PIPE], cmdResult.toString());
1076  RUNLOG(">>>writeToPipe")
1077  }
1078  else
1079  {
1080  Bottle stdioResult;
1081  userStdio(msg, stdioResult);
1082  RUNLOG("<<<writeToPipe")
1083  writeToPipe(pipe_manager2server[WRITE_TO_PIPE], stdioResult.toString());
1084  RUNLOG(">>>writeToPipe")
1085  }
1086 
1087  continue;
1088  }
1089 
1090  // without stdio
1091  if (msg.check("cmd"))
1092  {
1093  Bottle cmdResult;
1094 
1095  if (msg.check("log"))
1096  {
1097  yarp::os::Bottle botLogger=msg.findGroup("log");
1098 
1099  if (botLogger.size()>1)
1100  {
1101  yarp::os::ConstString loggerName=botLogger.get(1).asString();
1102  executeCmdStdout(msg, cmdResult, loggerName);
1103  }
1104  else
1105  {
1106  executeCmdStdout(msg, cmdResult, mLoggerPort);
1107  }
1108  }
1109  else if (mLogged)
1110  {
1111  executeCmdStdout(msg, cmdResult, mLoggerPort);
1112  }
1113  else
1114  {
1115  executeCmd(msg, cmdResult);
1116  }
1117 
1118  RUNLOG("<<<writeToPipe")
1119  writeToPipe(pipe_manager2server[WRITE_TO_PIPE], cmdResult.toString());
1120  RUNLOG(">>>writeToPipe")
1121  continue;
1122  }
1123 
1124  if (msg.check("kill"))
1125  {
1126  yarp::os::ConstString alias(msg.findGroup("kill").get(1).asString());
1127  int sig=msg.findGroup("kill").get(2).asInt();
1128  Bottle result;
1129  result.addString(mProcessVector->Signal(alias, sig)?"kill OK":"kill FAILED");
1130  RUNLOG("<<<writeToPipe")
1131  writeToPipe(pipe_manager2server[WRITE_TO_PIPE], result.toString());
1132  RUNLOG(">>>writeToPipe")
1133  continue;
1134  }
1135 
1136  if (msg.check("sigterm"))
1137  {
1138  yarp::os::ConstString alias(msg.find("sigterm").asString());
1139  Bottle result;
1140  result.addString(mProcessVector->Signal(alias, SIGTERM)?"sigterm OK":"sigterm FAILED");
1141  RUNLOG("<<<writeToPipe")
1142  writeToPipe(pipe_manager2server[WRITE_TO_PIPE], result.toString());
1143  RUNLOG(">>>writeToPipe")
1144  continue;
1145  }
1146 
1147  if (msg.check("sigtermall"))
1148  {
1149  mProcessVector->Killall(SIGTERM);
1150  Bottle result;
1151  result.addString("sigtermall OK");
1152 
1153  RUNLOG("<<<writeToPipe")
1154  writeToPipe(pipe_manager2server[WRITE_TO_PIPE], result.toString());
1155  RUNLOG(">>>writeToPipe")
1156  continue;
1157  }
1158 
1159  if (msg.check("ps"))
1160  {
1161  Bottle result;
1162  result.append(mProcessVector->PS());
1163  RUNLOG("<<<writeToPipe")
1164  writeToPipe(pipe_manager2server[WRITE_TO_PIPE], result.toString());
1165  RUNLOG(">>>writeToPipe")
1166  continue;
1167  }
1168 
1169  if (msg.check("isrunning"))
1170  {
1171  yarp::os::ConstString alias(msg.find("isrunning").asString());
1172  Bottle result;
1173  result.addString(mProcessVector->IsRunning(alias)?"running":"not running");
1174  RUNLOG("<<<writeToPipe")
1175  writeToPipe(pipe_manager2server[WRITE_TO_PIPE], result.toString());
1176  RUNLOG(">>>writeToPipe")
1177  continue;
1178  }
1179 
1180  if (msg.check("killstdio"))
1181  {
1182  yarp::os::ConstString alias(msg.find("killstdio").asString());
1183  mStdioVector->Signal(alias, SIGTERM);
1184  Bottle result;
1185  result.addString("killstdio OK");
1186  RUNLOG("<<<writeToPipe")
1187  writeToPipe(pipe_manager2server[WRITE_TO_PIPE], result.toString());
1188  RUNLOG(">>>writeToPipe")
1189  continue;
1190  }
1191  }
1192 
1193  mStdioVector->Killall(SIGTERM);
1194 
1195  mProcessVector->Killall(SIGTERM);
1196 
1197  if (mBraveZombieHunter)
1198  {
1199  mBraveZombieHunter->stop();
1200  delete mBraveZombieHunter;
1201  mBraveZombieHunter = YARP_NULLPTR;
1202  }
1203 
1204  delete mProcessVector;
1205 
1206  delete mStdioVector;
1207 
1208  //yarp::os::Network::fini();
1209 
1210  CLOSE(pipe_server2manager[READ_FROM_PIPE]);
1211  CLOSE(pipe_manager2server[WRITE_TO_PIPE]);
1212 
1213  delete [] msg_str;
1214  }
1215 
1216  return 0;
1217 } // LINUX SERVER
1218 #endif
1219 
1220 
1221 
1222 
1223 // CLIENT
1225 {
1226  // WITH STDIO
1227  //
1228  if (config.check("cmd") && config.check("stdio"))
1229  {
1231  // syntax check
1232  if (config.find("stdio").asString()=="")
1233  {
1234  Help("SYNTAX ERROR: missing remote stdio server\n");
1235  return YARPRUN_ERROR;
1236  }
1237  if (config.find("cmd").asString()=="")
1238  {
1239  Help("SYNTAX ERROR: missing command\n");
1240  return YARPRUN_ERROR;
1241  }
1242  if (!config.check("as") || config.find("as").asString()=="")
1243  {
1244  Help("SYNTAX ERROR: missing tag\n");
1245  return YARPRUN_ERROR;
1246  }
1247  if (!config.check("on") || config.find("on").asString()=="")
1248  {
1249  Help("SYNTAX ERROR: missing remote server\n");
1250  return YARPRUN_ERROR;
1251  }
1252  //
1254 
1255  printf("*********** %s ************\n", config.toString().c_str());
1256 
1257  yarp::os::Bottle msg;
1258  msg.addList()=config.findGroup("stdio");
1259  msg.addList()=config.findGroup("cmd");
1260  msg.addList()=config.findGroup("as");
1261  msg.addList()=config.findGroup("on");
1262 
1263  if (config.check("workdir")) msg.addList()=config.findGroup("workdir");
1264  if (config.check("geometry")) msg.addList()=config.findGroup("geometry");
1265  if (config.check("hold")) msg.addList()=config.findGroup("hold");
1266  if (config.check("env")) msg.addList()=config.findGroup("env");
1267  if (config.check("log")) msg.addList()=config.findGroup("log");
1268  /*
1269  {
1270  Bottle log;
1271  log.addString("log");
1272  log.addString("log");
1273  msg.addList()=log;
1274  }
1275  */
1276 
1277  ConstString on=config.find("on").asString();
1278 
1279  Bottle response=sendMsg(msg, on);
1280 
1281  if (!response.size()) return YARPRUN_ERROR;
1282 
1283  if (response.get(0).asInt()<=0) return 2;
1284 
1285  return 0;
1286  }
1287 
1288  // NO STDIO
1289  //
1290  if (config.check("cmd"))
1291  {
1293  // syntax check
1294  if (config.find("cmd").asString()=="")
1295  {
1296  Help("SYNTAX ERROR: missing command\n");
1297  return YARPRUN_ERROR;
1298  }
1299  if (!config.check("as") || config.find("as").asString()=="")
1300  {
1301  Help("SYNTAX ERROR: missing tag\n");
1302  return YARPRUN_ERROR;
1303  }
1304  if (!config.check("on") || config.find("on").asString()=="")
1305  {
1306  Help("SYNTAX ERROR: missing remote server\n");
1307  return YARPRUN_ERROR;
1308  }
1309  //
1311 
1312  yarp::os::Bottle msg;
1313  msg.addList()=config.findGroup("cmd");
1314  msg.addList()=config.findGroup("as");
1315 
1316  if (config.check("workdir")) msg.addList()=config.findGroup("workdir");
1317  if (config.check("log")) msg.addList()=config.findGroup("log");
1318  /*
1319  {
1320  Bottle log;
1321  log.addString("log");
1322  log.addString("log");
1323  msg.addList()=log;
1324  }
1325  */
1326  if (config.check("env")) msg.addList()=config.findGroup("env");
1327 
1328  Bottle response=sendMsg(msg, config.find("on").asString());
1329 
1330  if (!response.size()) return YARPRUN_ERROR;
1331 
1332  if (response.get(0).asInt()<=0) return 2;
1333 
1334  return 0;
1335  }
1336 
1337 
1338 
1339 
1340 
1341  // client -> cmd server
1342  if (config.check("kill"))
1343  {
1344  if (!config.check("on") || config.find("on").asString()=="")
1345  {
1346  Help("SYNTAX ERROR: missing remote server\n");
1347  return YARPRUN_ERROR;
1348  }
1349  if (config.findGroup("kill").get(1).asString()=="")
1350  {
1351  Help("SYNTAX ERROR: missing tag\n");
1352  return YARPRUN_ERROR;
1353  }
1354  if (config.findGroup("kill").get(2).asInt()==0)
1355  {
1356  Help("SYNTAX ERROR: missing signum\n");
1357  return YARPRUN_ERROR;
1358  }
1359 
1360  yarp::os::Bottle msg;
1361  msg.addList()=config.findGroup("kill");
1362 
1363  Bottle response=sendMsg(msg, config.find("on").asString());
1364 
1365  if (!response.size())
1366  {
1367  return YARPRUN_ERROR;
1368  }
1369 
1370  return response.get(0).asString()=="kill OK"?0:2;
1371  }
1372 
1373  // client -> cmd server
1374  if (config.check("sigterm"))
1375  {
1376  if (config.find("sigterm").asString()=="")
1377  {
1378  Help("SYNTAX ERROR: missing tag");
1379  return YARPRUN_ERROR;
1380  }
1381  if (!config.check("on") || config.find("on").asString()=="")
1382  {
1383  Help("SYNTAX ERROR: missing remote server\n");
1384  return YARPRUN_ERROR;
1385  }
1386 
1387  yarp::os::Bottle msg;
1388  msg.addList()=config.findGroup("sigterm");
1389 
1390  Bottle response=sendMsg(msg, config.find("on").asString());
1391 
1392  if (!response.size())
1393  {
1394  return YARPRUN_ERROR;
1395  }
1396 
1397  return response.get(0).asString()=="sigterm OK"?0:2;
1398  }
1399 
1400  // client -> cmd server
1401  if (config.check("sigtermall"))
1402  {
1403  if (!config.check("on") || config.find("on").asString()=="")
1404  {
1405  Help("SYNTAX ERROR: missing remote server\n");
1406  return YARPRUN_ERROR;
1407  }
1408 
1409  yarp::os::Bottle msg;
1410  msg.addList()=config.findGroup("sigtermall");
1411 
1412  Bottle response=sendMsg(msg, config.find("on").asString());
1413 
1414  if (!response.size())
1415  {
1416  return YARPRUN_ERROR;
1417  }
1418 
1419  return 0;
1420  }
1421 
1422  if (config.check("ps"))
1423  {
1424  if (!config.check("on") || config.find("on").asString()=="")
1425  {
1426  Help("SYNTAX ERROR: missing remote server\n");
1427  return YARPRUN_ERROR;
1428  }
1429 
1430  yarp::os::Bottle msg;
1431  msg.addList()=config.findGroup("ps");
1432 
1433  Bottle response=sendMsg(msg, config.find("on").asString());
1434 
1435  if (!response.size())
1436  {
1437  return YARPRUN_ERROR;
1438  }
1439 
1440  return 0;
1441  }
1442 
1443  if (config.check("isrunning"))
1444  {
1445  if (!config.check("on") || config.find("on").asString()=="")
1446  {
1447  Help("SYNTAX ERROR: missing remote server\n");
1448  return YARPRUN_ERROR;
1449  }
1450 
1451  if (config.find("isrunning").asString()=="")
1452  {
1453  Help("SYNTAX ERROR: missing tag\n");
1454  return YARPRUN_ERROR;
1455  }
1456 
1457  yarp::os::Bottle msg;
1458  msg.addList()=config.findGroup("isrunning");
1459 
1460  Bottle response=sendMsg(msg, config.find("on").asString());
1461 
1462  if (!response.size())
1463  {
1464  return YARPRUN_ERROR;
1465  }
1466 
1467  return response.get(0).asString()=="running"?0:2;
1468  }
1469 
1470  if (config.check("sysinfo"))
1471  {
1472  if (!config.check("on") || config.find("on").asString()=="")
1473  {
1474  Help("SYNTAX ERROR: missing remote server\n");
1475  return YARPRUN_ERROR;
1476  }
1477 
1478  yarp::os::Bottle msg;
1479  msg.addList()=config.findGroup("sysinfo");
1480 
1481  yarp::os::RpcClient port;
1482  //port.setTimeout(5.0);
1483  if (!port.open("..."))
1484  {
1485  fprintf(stderr, "RESPONSE:\n=========\n");
1486  fprintf(stderr, "Cannot open port, aborting...\n");
1487 
1488  return YARPRUN_ERROR;
1489  }
1490 
1491  bool connected = yarp::os::Network::connect(port.getName(), config.find("on").asString());
1492 
1493  if (!connected)
1494  {
1495  fprintf(stderr, "RESPONSE:\n=========\n");
1496  fprintf(stderr, "Cannot connect to remote server, aborting...\n");
1497  port.close();
1498  //yarp::os::Network::unregisterName(port.getName());
1499  return YARPRUN_ERROR;
1500  }
1501 
1503 
1504  RUNLOG("<<<port.write(msg, info)")
1505  int ret = port.write(msg, info);
1506  RUNLOG(">>>port.write(msg, info)")
1507  yarp::os::Network::disconnect(port.getName().c_str(), config.find("on").asString());
1508  port.close();
1509  //yarp::os::Network::unregisterName(port.getName());
1510  fprintf(stdout, "RESPONSE:\n=========\n\n");
1511 
1512  if (!ret)
1513  {
1514  fprintf(stdout, "No response. (timeout)\n");
1515 
1516  return YARPRUN_ERROR;
1517  }
1518 
1519  fprintf(stdout, "Platform name : %s\n", info.platform.name.c_str());
1520  fprintf(stdout, "Platform dist : %s\n", info.platform.distribution.c_str());
1521  fprintf(stdout, "Platform release : %s\n", info.platform.release.c_str());
1522  fprintf(stdout, "Platform code : %s\n", info.platform.codename.c_str());
1523  fprintf(stdout, "Platform kernel : %s\n\n", info.platform.kernel.c_str());
1524 
1525  fprintf(stdout, "User Id : %d\n", info.user.userID);
1526  fprintf(stdout, "User name : %s\n", info.user.userName.c_str());
1527  fprintf(stdout, "User real name : %s\n", info.user.realName.c_str());
1528  fprintf(stdout, "User home dir : %s\n\n", info.user.homeDir.c_str());
1529 
1530  fprintf(stdout, "Cpu load Ins.: %d\n", info.load.cpuLoadInstant);
1531  fprintf(stdout, "Cpu load 1 : %.2lf\n", info.load.cpuLoad1);
1532  fprintf(stdout, "Cpu load 5 : %.2lf\n", info.load.cpuLoad5);
1533  fprintf(stdout, "Cpu load 15 : %.2lf\n\n", info.load.cpuLoad15);
1534 
1535  fprintf(stdout, "Memory total : %dM\n", info.memory.totalSpace);
1536  fprintf(stdout, "Memory free : %dM\n\n", info.memory.freeSpace);
1537 
1538  fprintf(stdout, "Storage total : %dM\n", info.storage.totalSpace);
1539  fprintf(stdout, "Storage free : %dM\n\n", info.storage.freeSpace);
1540 
1541  fprintf(stdout, "Processor model : %s\n", info.processor.model.c_str());
1542  fprintf(stdout, "Processor model num : %d\n", info.processor.modelNumber);
1543  fprintf(stdout, "Processor family : %d\n", info.processor.family);
1544  fprintf(stdout, "Processor vendor : %s\n", info.processor.vendor.c_str());
1545  fprintf(stdout, "Processor arch : %s\n", info.processor.architecture.c_str());
1546  fprintf(stdout, "Processor cores : %d\n", info.processor.cores);
1547  fprintf(stdout, "Processor siblings : %d\n", info.processor.siblings);
1548  fprintf(stdout, "Processor Mhz : %.2lf\n\n", info.processor.frequency);
1549 
1550  fprintf(stdout, "Environment variables :\n%s\n", info.platform.environmentVars.toString().c_str());
1551  //fprintf(stdout, "Network IP4 : %s\n", info.network.ip4.c_str());
1552  //fprintf(stdout, "Network IP6 : %s\n", info.network.ip6.c_str());
1553  //fprintf(stdout, "Network mac : %s\n\n", info.network.mac.c_str());
1554 
1555  return 0;
1556  }
1557 
1558  if (config.check("which"))
1559  {
1560  if (!config.check("on") || config.find("on").asString()=="")
1561  {
1562  Help("SYNTAX ERROR: missing remote server\n");
1563 
1564  return YARPRUN_ERROR;
1565  }
1566 
1567  yarp::os::Bottle msg;
1568  msg.addList()=config.findGroup("which");
1569 
1570  Bottle response=sendMsg(msg, config.find("on").asString());
1571 
1572  if (!response.size())
1573  {
1574  return YARPRUN_ERROR;
1575  }
1576  return 0;
1577  }
1578 
1579  if (config.check("exit"))
1580  {
1581  if (!config.check("on") || config.find("on").asString()=="")
1582  {
1583  Help("SYNTAX ERROR: missing remote server\n");
1584 
1585  return YARPRUN_ERROR;
1586  }
1587 
1588  yarp::os::Bottle msg;
1589  msg.addList()=config.findGroup("exit");
1590 
1591  Bottle response=sendMsg(msg, config.find("on").asString());
1592 
1593  if (!response.size())
1594  {
1595  return YARPRUN_ERROR;
1596  }
1597 
1598  return 0;
1599  }
1600 
1601  return 0;
1602 }
1603 
1604 void yarp::os::Run::Help(const char *msg)
1605 {
1606  fprintf(stderr, "%s", msg);
1607  fprintf(stderr, "\nUSAGE:\n\n");
1608  fprintf(stderr, "yarp run --server SERVERPORT\nrun a server on the local machine\n\n");
1609  fprintf(stderr, "yarp run --on SERVERPORT --as TAG --cmd COMMAND [ARGLIST] [--workdir WORKDIR] [--env ENVIRONMENT]\nrun a command on SERVERPORT server\n\n");
1610  fprintf(stderr, "yarp run --on SERVERPORT --as TAG --stdio STDIOSERVERPORT [--hold] [--geometry WxH+X+Y] --cmd COMMAND [ARGLIST] [--workdir WORKDIR] [--env ENVIRONMENT]\n");
1611  fprintf(stderr, "run a command on SERVERPORT server sending I/O to STDIOSERVERPORT server\n\n");
1612  fprintf(stderr, "yarp run --on SERVERPORT --kill TAG SIGNUM\nsend SIGNUM signal to TAG command\n\n");
1613  fprintf(stderr, "yarp run --on SERVERPORT --sigterm TAG\nterminate TAG command\n\n");
1614  fprintf(stderr, "yarp run --on SERVERPORT --sigtermall\nterminate all commands\n\n");
1615  fprintf(stderr, "yarp run --on SERVERPORT --ps\nreport commands running on SERVERPORT\n\n");
1616  fprintf(stderr, "yarp run --on SERVERPORT --isrunning TAG\nTAG command is running?\n\n");
1617  fprintf(stderr, "yarp run --on SERVERPORT --sysinfo\nreport system information of SERVERPORT\n\n");
1618  fprintf(stderr, "yarp run --on SERVERPORT --exit\nstop SERVERPORT server\n\n");
1619 }
1620 
1622 // OS DEPENDENT FUNCTIONS
1624 
1625 // WINDOWS
1626 
1627 #if defined(_WIN32)
1628 
1629 // CMD SERVER
1630 int yarp::os::Run::executeCmdAndStdio(Bottle& msg, Bottle& result)
1631 {
1632  yarp::os::ConstString strAlias=msg.find("as").asString();
1633  yarp::os::ConstString strStdio=msg.find("stdio").asString();
1634  yarp::os::ConstString strStdioUUID=msg.find("stdiouuid").asString();
1635  //yarp::os::ConstString strCmdUUID=mPortName+"/"+int2String(GetCurrentProcessId())+"/"+strAlias+"-"+int2String(mProcCNT++);
1636 
1637  // PIPES
1638  SECURITY_ATTRIBUTES pipe_sec_attr;
1639  pipe_sec_attr.nLength=sizeof(SECURITY_ATTRIBUTES);
1640  pipe_sec_attr.bInheritHandle=TRUE;
1641  pipe_sec_attr.lpSecurityDescriptor = YARP_NULLPTR;
1642  HANDLE read_from_pipe_stdin_to_cmd, write_to_pipe_stdin_to_cmd;
1643  CreatePipe(&read_from_pipe_stdin_to_cmd, &write_to_pipe_stdin_to_cmd, &pipe_sec_attr, 0);
1644  HANDLE read_from_pipe_cmd_to_stdout, write_to_pipe_cmd_to_stdout;
1645  CreatePipe(&read_from_pipe_cmd_to_stdout, &write_to_pipe_cmd_to_stdout, &pipe_sec_attr, 0);
1646 
1647  // RUN STDOUT
1648  PROCESS_INFORMATION stdout_process_info;
1649  ZeroMemory(&stdout_process_info, sizeof(PROCESS_INFORMATION));
1650  STARTUPINFO stdout_startup_info;
1651  ZeroMemory(&stdout_startup_info, sizeof(STARTUPINFO));
1652 
1653  stdout_startup_info.cb=sizeof(STARTUPINFO);
1654  stdout_startup_info.hStdError=GetStdHandle(STD_ERROR_HANDLE);
1655  stdout_startup_info.hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE);
1656  stdout_startup_info.hStdInput=read_from_pipe_cmd_to_stdout;
1657  stdout_startup_info.dwFlags|=STARTF_USESTDHANDLES;
1658 
1659  BOOL bSuccess=CreateProcess(YARP_NULLPTR, // command name
1660  (char*)(yarp::os::ConstString("yarprun --write ")+strStdioUUID).c_str(), // command line
1661  YARP_NULLPTR, // process security attributes
1662  YARP_NULLPTR, // primary thread security attributes
1663  TRUE, // handles are inherited
1664  CREATE_NEW_PROCESS_GROUP, // creation flags
1665  YARP_NULLPTR, // use parent's environment
1666  YARP_NULLPTR, // use parent's current directory
1667  &stdout_startup_info, // STARTUPINFO pointer
1668  &stdout_process_info); // receives PROCESS_INFORMATION
1669 
1670  if (!bSuccess)
1671  {
1672  yarp::os::ConstString strError=yarp::os::ConstString("ABORTED: server=")+mPortName
1673  +yarp::os::ConstString(" alias=")+strAlias
1674  +yarp::os::ConstString(" cmd=stdout\n")
1675  +yarp::os::ConstString("Can't execute stdout because ")+lastError2String()
1676  +yarp::os::ConstString("\n");
1677 
1678  result.addInt(YARPRUN_ERROR);
1679  result.addString(strError.c_str());
1680  fprintf(stderr, "%s", strError.c_str());
1681  fflush(stderr);
1682 
1683  CloseHandle(write_to_pipe_stdin_to_cmd);
1684  CloseHandle(read_from_pipe_stdin_to_cmd);
1685  CloseHandle(write_to_pipe_cmd_to_stdout);
1686  CloseHandle(read_from_pipe_cmd_to_stdout);
1687 
1688  return YARPRUN_ERROR;
1689  }
1690 
1691  // RUN STDIN
1692 
1693  PROCESS_INFORMATION stdin_process_info;
1694  ZeroMemory(&stdin_process_info, sizeof(PROCESS_INFORMATION));
1695  STARTUPINFO stdin_startup_info;
1696  ZeroMemory(&stdin_startup_info, sizeof(STARTUPINFO));
1697 
1698  stdin_startup_info.cb=sizeof(STARTUPINFO);
1699  stdin_startup_info.hStdError=write_to_pipe_stdin_to_cmd;
1700  stdin_startup_info.hStdOutput=write_to_pipe_stdin_to_cmd;
1701  stdin_startup_info.hStdInput=GetStdHandle(STD_INPUT_HANDLE);
1702  stdin_startup_info.dwFlags|=STARTF_USESTDHANDLES;
1703 
1704  bSuccess=CreateProcess(YARP_NULLPTR, // command name
1705  (char*)(yarp::os::ConstString("yarprun --read ")+strStdioUUID).c_str(), // command line
1706  YARP_NULLPTR, // process security attributes
1707  YARP_NULLPTR, // primary thread security attributes
1708  TRUE, // handles are inherited
1709  CREATE_NEW_PROCESS_GROUP, // creation flags
1710  YARP_NULLPTR, // use parent's environment
1711  YARP_NULLPTR, // use parent's current directory
1712  &stdin_startup_info, // STARTUPINFO pointer
1713  &stdin_process_info); // receives PROCESS_INFORMATION
1714 
1715  if (!bSuccess)
1716  {
1717  yarp::os::ConstString strError=yarp::os::ConstString("ABORTED: server=")+mPortName
1718  +yarp::os::ConstString(" alias=")+strAlias
1719  +yarp::os::ConstString(" cmd=stdin\n")
1720  +yarp::os::ConstString("Can't execute stdin because ")+lastError2String()
1721  +yarp::os::ConstString("\n");
1722 
1723  result.addInt(YARPRUN_ERROR);
1724  result.addString(strError.c_str());
1725  fprintf(stderr, "%s", strError.c_str());
1726 
1727  TerminateProcess(stdout_process_info.hProcess, YARPRUN_ERROR);
1728 
1729  CloseHandle(stdout_process_info.hProcess);
1730 
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);
1735 
1736  return YARPRUN_ERROR;
1737  }
1738 
1739  // RUN COMMAND
1740 
1741  PROCESS_INFORMATION cmd_process_info;
1742  ZeroMemory(&cmd_process_info, sizeof(PROCESS_INFORMATION));
1743  STARTUPINFO cmd_startup_info;
1744  ZeroMemory(&cmd_startup_info, sizeof(STARTUPINFO));
1745 
1746  cmd_startup_info.cb=sizeof(STARTUPINFO);
1747  cmd_startup_info.hStdError=write_to_pipe_cmd_to_stdout;
1748  cmd_startup_info.hStdOutput=write_to_pipe_cmd_to_stdout;
1749  cmd_startup_info.hStdInput=read_from_pipe_stdin_to_cmd;
1750  cmd_startup_info.dwFlags|=STARTF_USESTDHANDLES;
1751 
1752  Bottle botCmd=msg.findGroup("cmd").tail();
1753 
1754  yarp::os::ConstString strCmd;
1755  for (int s=0; s<botCmd.size(); ++s)
1756  {
1757  strCmd+=botCmd.get(s).toString()+yarp::os::ConstString(" ");
1758  }
1759 
1760  /*
1761  * setting environment variable for child process
1762  */
1763  TCHAR chNewEnv[32767];
1764 
1765  // Get a pointer to the env block.
1766  LPTCH chOldEnv = GetEnvironmentStrings();
1767 
1768  // copying parent env variables
1769  LPTSTR lpOld = (LPTSTR) chOldEnv;
1770  LPTSTR lpNew = (LPTSTR) chNewEnv;
1771  while (*lpOld)
1772  {
1773  lstrcpy(lpNew, lpOld);
1774  lpOld += lstrlen(lpOld) + 1;
1775  lpNew += lstrlen(lpNew) + 1;
1776  }
1777 
1778  // adding new env variables
1779  yarp::os::ConstString cstrEnvName;
1780  if (msg.check("env"))
1781  {
1782  yarp::os::impl::SplitString ss(msg.find("env").asString().c_str(), ';');
1783  for(int i=0; i<ss.size(); i++) {
1784  lstrcpy(lpNew, (LPTCH) ss.get(i));
1785  lpNew += lstrlen(lpNew) + 1;
1786  }
1787  }
1788 
1789  // closing env block
1790  *lpNew = (TCHAR)0;
1791 
1792  bool bWorkdir=msg.check("workdir");
1793  yarp::os::ConstString strWorkdir=bWorkdir?msg.find("workdir").asString()+"\\":"";
1794 
1795  bSuccess=CreateProcess(YARP_NULLPTR, // command name
1796  (char*)(strWorkdir+strCmd).c_str(), // command line
1797  YARP_NULLPTR, // process security attributes
1798  YARP_NULLPTR, // primary thread security attributes
1799  TRUE, // handles are inherited
1800  CREATE_NEW_PROCESS_GROUP, // creation flags
1801  (LPVOID) chNewEnv, // use new environment list
1802  bWorkdir ? strWorkdir.c_str() : YARP_NULLPTR, // working directory
1803  &cmd_startup_info, // STARTUPINFO pointer
1804  &cmd_process_info); // receives PROCESS_INFORMATION
1805 
1806  if (!bSuccess && bWorkdir)
1807  {
1808  bSuccess=CreateProcess(YARP_NULLPTR, // command name
1809  (char*)(strCmd.c_str()), // command line
1810  YARP_NULLPTR, // process security attributes
1811  YARP_NULLPTR, // primary thread security attributes
1812  TRUE, // handles are inherited
1813  CREATE_NEW_PROCESS_GROUP, // creation flags
1814  (LPVOID) chNewEnv, // use new environment list
1815  strWorkdir.c_str(), // working directory
1816  &cmd_startup_info, // STARTUPINFO pointer
1817  &cmd_process_info); // receives PROCESS_INFORMATION
1818  }
1819 
1820  // deleting old environment variable
1821  FreeEnvironmentStrings(chOldEnv);
1822 
1823  if (!bSuccess)
1824  {
1825  result.addInt(YARPRUN_ERROR);
1826 
1827  DWORD nBytes;
1828  yarp::os::ConstString line1=yarp::os::ConstString("ABORTED: server=")+mPortName
1829  +yarp::os::ConstString(" alias=")+strAlias
1830  +yarp::os::ConstString(" cmd=")+strCmd
1831  +yarp::os::ConstString("pid=")+int2String(cmd_process_info.dwProcessId)
1832  +yarp::os::ConstString("\n");
1833 
1834  WriteFile(write_to_pipe_cmd_to_stdout, line1.c_str(), line1.length(), &nBytes, 0);
1835 
1836  yarp::os::ConstString line2=yarp::os::ConstString("Can't execute command because ")+lastError2String()+yarp::os::ConstString("\n");
1837  WriteFile(write_to_pipe_cmd_to_stdout, line1.c_str(), line2.length(), &nBytes, 0);
1838  FlushFileBuffers(write_to_pipe_cmd_to_stdout);
1839 
1840  yarp::os::ConstString out=line1+line2;
1841  result.addString(out.c_str());
1842  fprintf(stderr, "%s", out.c_str());
1843  fflush(stderr);
1844 
1845  CloseHandle(write_to_pipe_stdin_to_cmd);
1846  CloseHandle(read_from_pipe_stdin_to_cmd);
1847  CloseHandle(write_to_pipe_cmd_to_stdout);
1848  CloseHandle(read_from_pipe_cmd_to_stdout);
1849 
1850  TerminateProcess(stdout_process_info.hProcess, YARPRUN_ERROR);
1851 
1852  CloseHandle(stdout_process_info.hProcess);
1853 
1854  TerminateProcess(stdin_process_info.hProcess, YARPRUN_ERROR);
1855 
1856  CloseHandle(stdin_process_info.hProcess);
1857 
1858  return YARPRUN_ERROR;
1859  }
1860 
1861  FlushFileBuffers(write_to_pipe_cmd_to_stdout);
1862 
1863  // EVERYTHING IS ALL RIGHT
1864  YarpRunCmdWithStdioInfo* pInf = new YarpRunCmdWithStdioInfo(strAlias,
1865  mPortName,
1866  strStdio,
1867  cmd_process_info.dwProcessId,
1868  strStdioUUID,
1869  &mStdioVector,
1870  stdin_process_info.dwProcessId,
1871  stdout_process_info.dwProcessId,
1872  read_from_pipe_stdin_to_cmd,
1873  write_to_pipe_stdin_to_cmd,
1874  read_from_pipe_cmd_to_stdout,
1875  write_to_pipe_cmd_to_stdout,
1876  cmd_process_info.hProcess,
1877  false);
1878 
1879  pInf->setCmd(strCmd);
1880  if (msg.check("env"))
1881  {
1882  pInf->setEnv(msg.find("env").asString());
1883  }
1884  mProcessVector.Add(pInf);
1885 
1886  result.addInt(cmd_process_info.dwProcessId);
1887  yarp::os::ConstString out=yarp::os::ConstString("STARTED: server=")+mPortName
1888  +yarp::os::ConstString(" alias=")+strAlias
1889  +yarp::os::ConstString(" cmd=")+strCmd
1890  +yarp::os::ConstString("pid=")+int2String(cmd_process_info.dwProcessId)
1891  +yarp::os::ConstString("\n");
1892 
1893  result.addString(out.c_str());
1894  result.addString(strStdioUUID.c_str());
1895  fprintf(stderr, "%s", out.c_str());
1896 
1897  return cmd_process_info.dwProcessId;
1898 }
1899 
1900 int yarp::os::Run::executeCmdStdout(Bottle& msg, Bottle& result, yarp::os::ConstString& loggerName)
1901 {
1902  yarp::os::ConstString strAlias=msg.find("as").asString();
1903  yarp::os::ConstString portName="/log";
1904  portName+=mPortName+"/";
1905  yarp::os::ConstString command=msg.findGroup("cmd").get(1).asString();
1906  int space=command.find(" ");
1907  if (space!=ConstString::npos) command=command.substr(0, space);
1908  portName+=command;
1909 
1910  // PIPES
1911  SECURITY_ATTRIBUTES pipe_sec_attr;
1912  pipe_sec_attr.nLength=sizeof(SECURITY_ATTRIBUTES);
1913  pipe_sec_attr.bInheritHandle=TRUE;
1914  pipe_sec_attr.lpSecurityDescriptor = YARP_NULLPTR;
1915  HANDLE read_from_pipe_cmd_to_stdout, write_to_pipe_cmd_to_stdout;
1916  CreatePipe(&read_from_pipe_cmd_to_stdout, &write_to_pipe_cmd_to_stdout, &pipe_sec_attr, 0);
1917 
1918  // RUN STDOUT
1919  PROCESS_INFORMATION stdout_process_info;
1920  ZeroMemory(&stdout_process_info, sizeof(PROCESS_INFORMATION));
1921  STARTUPINFO stdout_startup_info;
1922  ZeroMemory(&stdout_startup_info, sizeof(STARTUPINFO));
1923 
1924  stdout_startup_info.cb=sizeof(STARTUPINFO);
1925  stdout_startup_info.hStdError=GetStdHandle(STD_ERROR_HANDLE);
1926  stdout_startup_info.hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE);
1927  stdout_startup_info.hStdInput=read_from_pipe_cmd_to_stdout;
1928  stdout_startup_info.dwFlags|=STARTF_USESTDHANDLES;
1929 
1930  BOOL bSuccess=CreateProcess(YARP_NULLPTR, // command name
1931  (char*)(yarp::os::ConstString("yarprun --log ")+loggerName+yarp::os::ConstString(" --write ")+portName).c_str(), // command line
1932  YARP_NULLPTR, // process security attributes
1933  YARP_NULLPTR, // primary thread security attributes
1934  TRUE, // handles are inherited
1935  CREATE_NEW_PROCESS_GROUP, // creation flags
1936  YARP_NULLPTR, // use parent's environment
1937  YARP_NULLPTR, // use parent's current directory
1938  &stdout_startup_info, // STARTUPINFO pointer
1939  &stdout_process_info); // receives PROCESS_INFORMATION
1940 
1941  if (!bSuccess)
1942  {
1943  yarp::os::ConstString strError=yarp::os::ConstString("ABORTED: server=")+mPortName
1944  +yarp::os::ConstString(" alias=")+strAlias
1945  +yarp::os::ConstString(" cmd=stdout\n")
1946  +yarp::os::ConstString("Can't execute stdout because ")+lastError2String()
1947  +yarp::os::ConstString("\n");
1948 
1949  result.addInt(YARPRUN_ERROR);
1950  result.addString(strError.c_str());
1951  fprintf(stderr, "%s", strError.c_str());
1952  fflush(stderr);
1953 
1954  CloseHandle(write_to_pipe_cmd_to_stdout);
1955  CloseHandle(read_from_pipe_cmd_to_stdout);
1956 
1957  return YARPRUN_ERROR;
1958  }
1959 
1960  // RUN COMMAND
1961 
1962  PROCESS_INFORMATION cmd_process_info;
1963  ZeroMemory(&cmd_process_info, sizeof(PROCESS_INFORMATION));
1964  STARTUPINFO cmd_startup_info;
1965  ZeroMemory(&cmd_startup_info, sizeof(STARTUPINFO));
1966 
1967  cmd_startup_info.cb=sizeof(STARTUPINFO);
1968  cmd_startup_info.hStdError=write_to_pipe_cmd_to_stdout;
1969  cmd_startup_info.hStdOutput=write_to_pipe_cmd_to_stdout;
1970  cmd_startup_info.hStdInput=GetStdHandle(STD_INPUT_HANDLE);
1971  cmd_startup_info.dwFlags|=STARTF_USESTDHANDLES;
1972 
1973  Bottle botCmd=msg.findGroup("cmd").tail();
1974 
1975  yarp::os::ConstString strCmd;
1976  for (int s=0; s<botCmd.size(); ++s)
1977  {
1978  strCmd+=botCmd.get(s).toString()+yarp::os::ConstString(" ");
1979  }
1980 
1981  /*
1982  * setting environment variable for child process
1983  */
1984  TCHAR chNewEnv[32767];
1985 
1986  // Get a pointer to the env block.
1987  LPTCH chOldEnv = GetEnvironmentStrings();
1988 
1989  // copying parent env variables
1990  LPTSTR lpOld = (LPTSTR) chOldEnv;
1991  LPTSTR lpNew = (LPTSTR) chNewEnv;
1992  while (*lpOld)
1993  {
1994  lstrcpy(lpNew, lpOld);
1995  lpOld += lstrlen(lpOld) + 1;
1996  lpNew += lstrlen(lpNew) + 1;
1997  }
1998 
1999  // adding new env variables
2000  yarp::os::ConstString cstrEnvName;
2001  if (msg.check("env"))
2002  {
2003  lstrcpy(lpNew, (LPTCH) msg.find("env").asString().c_str());
2004  lpNew += lstrlen(lpNew) + 1;
2005  }
2006 
2007  // closing env block
2008  *lpNew = (TCHAR)0;
2009 
2010  bool bWorkdir=msg.check("workdir");
2011  yarp::os::ConstString strWorkdir=bWorkdir?msg.find("workdir").asString()+"\\":"";
2012 
2013  bSuccess=CreateProcess(YARP_NULLPTR, // command name
2014  (char*)(strWorkdir+strCmd).c_str(), // command line
2015  YARP_NULLPTR, // process security attributes
2016  YARP_NULLPTR, // primary thread security attributes
2017  TRUE, // handles are inherited
2018  CREATE_NEW_PROCESS_GROUP, // creation flags
2019  (LPVOID) chNewEnv, // use new environment list
2020  bWorkdir?strWorkdir.c_str():YARP_NULLPTR, // working directory
2021  &cmd_startup_info, // STARTUPINFO pointer
2022  &cmd_process_info); // receives PROCESS_INFORMATION
2023 
2024  if (!bSuccess && bWorkdir)
2025  {
2026  bSuccess=CreateProcess(YARP_NULLPTR, // command name
2027  (char*)(strCmd.c_str()), // command line
2028  YARP_NULLPTR, // process security attributes
2029  YARP_NULLPTR, // primary thread security attributes
2030  TRUE, // handles are inherited
2031  CREATE_NEW_PROCESS_GROUP, // creation flags
2032  (LPVOID) chNewEnv, // use new environment list
2033  strWorkdir.c_str(), // working directory
2034  &cmd_startup_info, // STARTUPINFO pointer
2035  &cmd_process_info); // receives PROCESS_INFORMATION
2036  }
2037 
2038  // deleting old environment variable
2039  FreeEnvironmentStrings(chOldEnv);
2040 
2041  if (!bSuccess)
2042  {
2043  result.addInt(YARPRUN_ERROR);
2044 
2045  DWORD nBytes;
2046  yarp::os::ConstString line1=yarp::os::ConstString("ABORTED: server=")+mPortName
2047  +yarp::os::ConstString(" alias=")+strAlias
2048  +yarp::os::ConstString(" cmd=")+strCmd
2049  +yarp::os::ConstString("pid=")+int2String(cmd_process_info.dwProcessId)
2050  +yarp::os::ConstString("\n");
2051 
2052  WriteFile(write_to_pipe_cmd_to_stdout, line1.c_str(), line1.length(), &nBytes, 0);
2053 
2054  yarp::os::ConstString line2=yarp::os::ConstString("Can't execute command because ")+lastError2String()+yarp::os::ConstString("\n");
2055  WriteFile(write_to_pipe_cmd_to_stdout, line1.c_str(), line2.length(), &nBytes, 0);
2056  FlushFileBuffers(write_to_pipe_cmd_to_stdout);
2057 
2058  yarp::os::ConstString out=line1+line2;
2059  result.addString(out.c_str());
2060  fprintf(stderr, "%s", out.c_str());
2061  fflush(stderr);
2062 
2063  CloseHandle(write_to_pipe_cmd_to_stdout);
2064  CloseHandle(read_from_pipe_cmd_to_stdout);
2065 
2066  TerminateProcess(stdout_process_info.hProcess, YARPRUN_ERROR);
2067 
2068  CloseHandle(stdout_process_info.hProcess);
2069 
2070  return YARPRUN_ERROR;
2071  }
2072 
2073  FlushFileBuffers(write_to_pipe_cmd_to_stdout);
2074 
2075  // EVERYTHING IS ALL RIGHT
2076  YarpRunCmdWithStdioInfo* pInf = new YarpRunCmdWithStdioInfo(strAlias,
2077  mPortName,
2078  portName,
2079  cmd_process_info.dwProcessId,
2080  stdout_process_info.dwProcessId,
2081  read_from_pipe_cmd_to_stdout,
2082  write_to_pipe_cmd_to_stdout,
2083  cmd_process_info.hProcess,
2084  false);
2085 
2086 
2087 
2088 
2089  pInf->setCmd(strCmd);
2090  if (msg.check("env"))
2091  {
2092  pInf->setEnv(msg.find("env").asString());
2093  }
2094  mProcessVector.Add(pInf);
2095 
2096  result.addInt(cmd_process_info.dwProcessId);
2097  yarp::os::ConstString out=yarp::os::ConstString("STARTED: server=")+mPortName
2098  +yarp::os::ConstString(" alias=")+strAlias
2099  +yarp::os::ConstString(" cmd=")+strCmd
2100  +yarp::os::ConstString("pid=")+int2String(cmd_process_info.dwProcessId)
2101  +yarp::os::ConstString("\n");
2102 
2103  result.addString(out.c_str());
2104  result.addString(portName.c_str());
2105  fprintf(stderr, "%s", out.c_str());
2106 
2107  return cmd_process_info.dwProcessId;
2108 }
2109 
2110 
2111 int yarp::os::Run::executeCmd(yarp::os::Bottle& msg, Bottle& result)
2112 {
2113  yarp::os::ConstString strAlias=msg.find("as").asString().c_str();
2114 
2115  // RUN COMMAND
2116  PROCESS_INFORMATION cmd_process_info;
2117  ZeroMemory(&cmd_process_info, sizeof(PROCESS_INFORMATION));
2118  STARTUPINFO cmd_startup_info;
2119  ZeroMemory(&cmd_startup_info, sizeof(STARTUPINFO));
2120 
2121  cmd_startup_info.cb=sizeof(STARTUPINFO);
2122 
2123  Bottle botCmd=msg.findGroup("cmd").tail();
2124 
2125  yarp::os::ConstString strCmd;
2126  for (int s=0; s<botCmd.size(); ++s)
2127  {
2128  strCmd+=botCmd.get(s).toString()+yarp::os::ConstString(" ");
2129  }
2130 
2131  /*
2132  if (msg.check("env"))
2133  {
2134  int pos = msg.find("env").asString().find("=");
2135  if (pos)
2136  {
2137  yarp::os::ConstString cstrName = msg.find("env").asString().substr(0, pos);
2138  int nValue = msg.find("env").asString().length() -
2139  cstrName.length() - 1;
2140  yarp::os::ConstString cstrValue = msg.find("env").asString().substr(pos+1, nValue);
2141  SetEnvironmentVariable(cstrName.c_str(), cstrValue.c_str());
2142  }
2143 
2144  }
2145  */
2146 
2147  /*
2148  * setting environment variable for child process
2149  */
2150  TCHAR chNewEnv[32767];
2151 
2152  // Get a pointer to the env block.
2153  LPTCH chOldEnv = GetEnvironmentStrings();
2154 
2155  // copying parent env variables
2156  LPTSTR lpOld = (LPTSTR) chOldEnv;
2157  LPTSTR lpNew = (LPTSTR) chNewEnv;
2158  while (*lpOld)
2159  {
2160  lstrcpy(lpNew, lpOld);
2161  lpOld += lstrlen(lpOld) + 1;
2162  lpNew += lstrlen(lpNew) + 1;
2163  }
2164 
2165  // adding new env variables
2166  yarp::os::ConstString cstrEnvName;
2167  if (msg.check("env"))
2168  {
2169  lstrcpy(lpNew, (LPTCH) msg.find("env").asString().c_str());
2170  lpNew += lstrlen(lpNew) + 1;
2171  }
2172 
2173  // closing env block
2174  *lpNew = (TCHAR)0;
2175 
2176  bool bWorkdir=msg.check("workdir");
2177  yarp::os::ConstString strWorkdir=bWorkdir?msg.find("workdir").asString()+"\\":"";
2178 
2179  BOOL bSuccess=CreateProcess(YARP_NULLPTR, // command name
2180  (char*)(strWorkdir+strCmd).c_str(), // command line
2181  YARP_NULLPTR, // process security attributes
2182  YARP_NULLPTR, // primary thread security attributes
2183  TRUE, // handles are inherited
2184  CREATE_NEW_PROCESS_GROUP, // creation flags
2185  (LPVOID) chNewEnv, // use new environment
2186  bWorkdir ? strWorkdir.c_str() : YARP_NULLPTR, // working directory
2187  &cmd_startup_info, // STARTUPINFO pointer
2188  &cmd_process_info); // receives PROCESS_INFORMATION
2189 
2190  if (!bSuccess && bWorkdir)
2191  {
2192  bSuccess=CreateProcess(YARP_NULLPTR, // command name
2193  (char*)(strCmd.c_str()), // command line
2194  YARP_NULLPTR, // process security attributes
2195  YARP_NULLPTR, // primary thread security attributes
2196  TRUE, // handles are inherited
2197  CREATE_NEW_PROCESS_GROUP, // creation flags
2198  (LPVOID) chNewEnv, // use new environment
2199  strWorkdir.c_str(), // working directory
2200  &cmd_startup_info, // STARTUPINFO pointer
2201  &cmd_process_info); // receives PROCESS_INFORMATION
2202  }
2203 
2204  // deleting old environment variable
2205  FreeEnvironmentStrings(chOldEnv);
2206 
2207  if (!bSuccess)
2208  {
2209  result.addInt(YARPRUN_ERROR);
2210 
2211  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2212  +yarp::os::ConstString(" alias=")+strAlias
2213  +yarp::os::ConstString(" cmd=")+strCmd
2214  +yarp::os::ConstString(" pid=")+int2String(cmd_process_info.dwProcessId)
2215  +yarp::os::ConstString("\nCan't execute command because ")+lastError2String()
2216  +yarp::os::ConstString("\n");
2217 
2218  result.addString(out.c_str());
2219  fprintf(stderr, "%s", out.c_str());
2220  fflush(stderr);
2221 
2222  return YARPRUN_ERROR;
2223  }
2224 
2225  // EVERYTHING IS ALL RIGHT
2226  YarpRunProcInfo* pInf = new YarpRunProcInfo(strAlias,
2227  mPortName,
2228  cmd_process_info.dwProcessId,
2229  cmd_process_info.hProcess,
2230  false);
2231  pInf->setCmd(strCmd);
2232  if (msg.check("env"))
2233  pInf->setEnv(msg.find("env").asString());
2234 
2235  mProcessVector.Add(pInf);
2236 
2237  result.addInt(cmd_process_info.dwProcessId);
2238  yarp::os::ConstString out=yarp::os::ConstString("STARTED: server=")+mPortName
2239  +yarp::os::ConstString(" alias=")+strAlias
2240  +yarp::os::ConstString(" cmd=")+strCmd
2241  +yarp::os::ConstString("pid=")+int2String(cmd_process_info.dwProcessId)
2242  +yarp::os::ConstString("\n");
2243 
2244  fprintf(stderr, "%s", out.c_str());
2245 
2246  return cmd_process_info.dwProcessId;
2247 }
2248 
2249 // STDIO SERVER
2250 int yarp::os::Run::userStdio(Bottle& msg, Bottle& result)
2251 {
2252  PROCESS_INFORMATION stdio_process_info;
2253  ZeroMemory(&stdio_process_info, sizeof(PROCESS_INFORMATION));
2254 
2255  STARTUPINFO stdio_startup_info;
2256  ZeroMemory(&stdio_startup_info, sizeof(STARTUPINFO));
2257  stdio_startup_info.cb=sizeof(STARTUPINFO);
2258  stdio_startup_info.wShowWindow=SW_SHOWNOACTIVATE;
2259  stdio_startup_info.dwFlags=STARTF_USESHOWWINDOW;
2260 
2261  yarp::os::ConstString strAlias=msg.find("as").asString();
2262  yarp::os::ConstString strUUID=msg.find("stdiouuid").asString();
2263  yarp::os::ConstString strCmd=yarp::os::ConstString("yarprun --readwrite ")+strUUID;
2264  if (msg.check("forward")) strCmd+=yarp::os::ConstString(" --forward ")+msg.findGroup("forward").get(1).asString()+yarp::os::ConstString(" ")+msg.findGroup("forward").get(2).asString();
2265 
2266  BOOL bSuccess=CreateProcess(YARP_NULLPTR, // command name
2267  (char*)strCmd.c_str(), // command line
2268  YARP_NULLPTR, // process security attributes
2269  YARP_NULLPTR, // primary thread security attributes
2270  TRUE, // handles are inherited
2271  CREATE_NEW_CONSOLE, // creation flags
2272  YARP_NULLPTR, // use parent's environment
2273  YARP_NULLPTR, // use parent's current directory
2274  &stdio_startup_info, // STARTUPINFO pointer
2275  &stdio_process_info); // receives PROCESS_INFORMATION
2276 
2278 
2279  if (bSuccess)
2280  {
2281  mStdioVector.Add(new YarpRunProcInfo(strAlias,
2282  mPortName,
2283  stdio_process_info.dwProcessId,
2284  stdio_process_info.hProcess,
2285  false));
2286 
2287  out=yarp::os::ConstString("STARTED: server=")+mPortName
2288  +yarp::os::ConstString(" alias=")+strAlias
2289  +yarp::os::ConstString(" cmd=stdio pid=")+int2String(stdio_process_info.dwProcessId)
2290  +yarp::os::ConstString("\n");
2291  }
2292  else
2293  {
2294  stdio_process_info.dwProcessId=YARPRUN_ERROR;
2295 
2296  out=yarp::os::ConstString("ABORTED: server=")+mPortName
2297  +yarp::os::ConstString(" alias=")+strAlias
2298  +yarp::os::ConstString(" cmd=stdio\n")
2299  +yarp::os::ConstString("Can't open stdio window because ")+lastError2String()
2300  +yarp::os::ConstString("\n");
2301  }
2302 
2303  result.clear();
2304  result.addInt(stdio_process_info.dwProcessId);
2305  result.addString(out.c_str());
2306  fprintf(stderr, "%s", out.c_str());
2307  fflush(stderr);
2308 
2309  return stdio_process_info.dwProcessId;
2310 }
2311 
2313 #else // LINUX
2314 /*
2316 int CountArgs(char *str)
2317 {
2318  int nargs=0;
2319 
2320  for (bool bSpace=true; *str; ++str)
2321  {
2322  if (bSpace)
2323  {
2324  if (*str!=' ')
2325  {
2326  ++nargs;
2327  bSpace=false;
2328  }
2329  }
2330  else
2331  {
2332  if (*str==' ')
2333  {
2334  bSpace=true;
2335  }
2336  }
2337  }
2338 
2339  return nargs;
2340 }
2341 
2342 void ParseCmd(char* cmd_str, char** arg_str)
2343 {
2344  int nargs=0;
2345 
2346  for (bool bSpace=true; *cmd_str; ++cmd_str)
2347  {
2348  if (*cmd_str!=' ')
2349  {
2350  if (bSpace) arg_str[nargs++]=cmd_str;
2351  bSpace=false;
2352  }
2353  else
2354  {
2355  *cmd_str=0;
2356  bSpace=true;
2357  }
2358  }
2359 }
2360 */
2364 void splitLine(char *pLine, char **pArgs)
2365 {
2366  char *pTmp = strchr(pLine, ' ');
2367 
2368  if (pTmp) {
2369  *pTmp = '\0';
2370  pTmp++;
2371  while ((*pTmp) && (*pTmp == ' ')) {
2372  pTmp++;
2373  }
2374  if (*pTmp == '\0') {
2375  pTmp = YARP_NULLPTR;
2376  }
2377  }
2378  *pArgs = pTmp;
2379 }
2380 
2381 
2382 
2386 void parseArguments(char *io_pLine, int *o_pArgc, char **o_pArgv)
2387 {
2388  char *pNext = io_pLine;
2389  size_t i;
2390  int j;
2391  int quoted = 0;
2392  size_t len = strlen(io_pLine);
2393 
2394  // Protect spaces inside quotes, but lose the quotes
2395  for(i = 0; i < len; i++) {
2396  if ((!quoted) && ('"' == io_pLine[i])) {
2397  quoted = 1;
2398  io_pLine[i] = ' ';
2399  } else if ((quoted) && ('"' == io_pLine[i])) {
2400  quoted = 0;
2401  io_pLine[i] = ' ';
2402  } else if ((quoted) && (' ' == io_pLine[i])) {
2403  io_pLine[i] = '\1';
2404  }
2405  }
2406 
2407  // init
2408  memset(o_pArgv, 0x00, sizeof(char*) * C_MAXARGS);
2409  *o_pArgc = 1;
2410  o_pArgv[0] = io_pLine;
2411 
2412  while ((YARP_NULLPTR != pNext) && (*o_pArgc < C_MAXARGS)) {
2413  splitLine(pNext, &(o_pArgv[*o_pArgc]));
2414  pNext = o_pArgv[*o_pArgc];
2415 
2416  if (YARP_NULLPTR != o_pArgv[*o_pArgc]) {
2417  *o_pArgc += 1;
2418  }
2419  }
2420 
2421  for(j = 0; j < *o_pArgc; j++) {
2422  len = strlen(o_pArgv[j]);
2423  for(i = 0; i < len; i++) {
2424  if ('\1' == o_pArgv[j][i]) {
2425  o_pArgv[j][i] = ' ';
2426  }
2427  }
2428  }
2429 }
2430 
2431 void yarp::os::Run::CleanZombie(int pid)
2432 {
2433  bool bFound=mProcessVector && mProcessVector->CleanZombie(pid);
2434 
2435  if (!bFound) if (mStdioVector) mStdioVector->CleanZombie(pid);
2436 }
2437 
2439 
2440 int yarp::os::Run::executeCmdAndStdio(yarp::os::Bottle& msg, yarp::os::Bottle& result)
2441 {
2442  yarp::os::ConstString strAlias=msg.find("as").asString();
2443  yarp::os::ConstString strCmd=msg.find("cmd").asString();
2444  yarp::os::ConstString strStdio=msg.find("stdio").asString();
2445  yarp::os::ConstString strStdioUUID=msg.find("stdiouuid").asString();
2446 
2447  int pipe_stdin_to_cmd[2];
2448  int ret_stdin_to_cmd=yarp::os::impl::pipe(pipe_stdin_to_cmd);
2449 
2450  int pipe_cmd_to_stdout[2];
2451  int ret_cmd_to_stdout=yarp::os::impl::pipe(pipe_cmd_to_stdout);
2452 
2453  int pipe_child_to_parent[2];
2454  int ret_child_to_parent=yarp::os::impl::pipe(pipe_child_to_parent);
2455 
2456  if (ret_child_to_parent!=0 || ret_cmd_to_stdout!=0 || ret_stdin_to_cmd!=0)
2457  {
2458  int error=errno;
2459 
2460  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2461  +yarp::os::ConstString(" alias=")+strAlias
2462  +yarp::os::ConstString(" cmd=stdout\n")
2463  +yarp::os::ConstString("Can't create pipes ")+strerror(error)
2464  +yarp::os::ConstString("\n");
2465 
2466  result.addInt(YARPRUN_ERROR);
2467  result.addString(out.c_str());
2468  fprintf(stderr, "%s", out.c_str());
2469 
2470  return YARPRUN_ERROR;
2471  }
2472 
2473  int pid_stdout=yarp::os::fork();
2474 
2475  if (IS_INVALID(pid_stdout))
2476  {
2477  int error=errno;
2478 
2479  CLOSE(pipe_stdin_to_cmd[WRITE_TO_PIPE]);
2480  CLOSE(pipe_stdin_to_cmd[READ_FROM_PIPE]);
2481  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2482  CLOSE(pipe_cmd_to_stdout[READ_FROM_PIPE]);
2483  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2484  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2485 
2486  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2487  +yarp::os::ConstString(" alias=")+strAlias
2488  +yarp::os::ConstString(" cmd=stdout\n")
2489  +yarp::os::ConstString("Can't fork stdout process because ")+strerror(error)
2490  +yarp::os::ConstString("\n");
2491 
2492  result.addInt(YARPRUN_ERROR);
2493  result.addString(out.c_str());
2494  fprintf(stderr, "%s", out.c_str());
2495 
2496  return YARPRUN_ERROR;
2497  }
2498 
2499  if (IS_NEW_PROCESS(pid_stdout)) // STDOUT IMPLEMENTED HERE
2500  {
2501  REDIRECT_TO(STDIN_FILENO, pipe_cmd_to_stdout[READ_FROM_PIPE]);
2502 
2503  CLOSE(pipe_stdin_to_cmd[WRITE_TO_PIPE]);
2504  CLOSE(pipe_stdin_to_cmd[READ_FROM_PIPE]);
2505  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2506  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2507 
2508  //Why removing vectors and stop threads?
2509  //exec* never returns and memory is claimed by the system
2510  //furthermore after fork() only the thread which called fork() is forked!
2511  // cleanBeforeExec();
2512 
2513  //yarp::os::impl::signal(SIGPIPE, SIG_DFL);
2514 
2515  int ret = yarp::os::impl::execlp("yarprun", "yarprun", "--write", strStdioUUID.c_str(), static_cast<char*>(YARP_NULLPTR));
2516 
2517  CLOSE(pipe_cmd_to_stdout[READ_FROM_PIPE]);
2518 
2519  if (ret==YARPRUN_ERROR)
2520  {
2521  int error=errno;
2522 
2523  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2524  +yarp::os::ConstString(" alias=")+strAlias
2525  +yarp::os::ConstString(" cmd=stdout\n")
2526  +yarp::os::ConstString("Can't execute stdout because ")+strerror(error)
2527  +yarp::os::ConstString("\n");
2528 
2529  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
2530  fprintf(out_to_parent, "%s", out.c_str());
2531  fflush(out_to_parent);
2532  fclose(out_to_parent);
2533 
2534  fprintf(stderr, "%s", out.c_str());
2535  }
2536 
2537  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2538 
2539  std::exit(ret);
2540  }
2541 
2542  if (IS_PARENT_OF(pid_stdout))
2543  {
2544  CLOSE(pipe_cmd_to_stdout[READ_FROM_PIPE]);
2545 
2546  fprintf(stderr, "STARTED: server=%s alias=%s cmd=stdout pid=%d\n", mPortName.c_str(), strAlias.c_str(), pid_stdout);
2547 
2548  int pid_stdin=yarp::os::fork();
2549 
2550  if (IS_INVALID(pid_stdin))
2551  {
2552  int error=errno;
2553 
2554  CLOSE(pipe_stdin_to_cmd[WRITE_TO_PIPE]);
2555  CLOSE(pipe_stdin_to_cmd[READ_FROM_PIPE]);
2556  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2557  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2558  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2559 
2560  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2561  +yarp::os::ConstString(" alias=")+strAlias
2562  +yarp::os::ConstString(" cmd=stdin\n")
2563  +yarp::os::ConstString("Can't fork stdin process because ")+strerror(error)
2564  +yarp::os::ConstString("\n");
2565 
2566  result.addInt(YARPRUN_ERROR);
2567  result.addString(out.c_str());
2568  fprintf(stderr, "%s", out.c_str());
2569 
2570  SIGNAL(pid_stdout, SIGTERM);
2571  fprintf(stderr, "TERMINATING stdout (%d)\n", pid_stdout);
2572 
2573  return YARPRUN_ERROR;
2574  }
2575 
2576  if (IS_NEW_PROCESS(pid_stdin)) // STDIN IMPLEMENTED HERE
2577  {
2578  REDIRECT_TO(STDOUT_FILENO, pipe_stdin_to_cmd[WRITE_TO_PIPE]);
2579  REDIRECT_TO(STDERR_FILENO, pipe_stdin_to_cmd[WRITE_TO_PIPE]);
2580 
2581  CLOSE(pipe_stdin_to_cmd[READ_FROM_PIPE]);
2582  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2583  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2584 
2585  //Why removing vectors and stop threads?
2586  //exec* never returns and memory is claimed by the system
2587  //furthermore after fork() only the thread which called fork() is forked!
2588  // cleanBeforeExec();
2589 
2590  //yarp::os::impl::signal(SIGPIPE, SIG_DFL);
2591 
2592  int ret = yarp::os::impl::execlp("yarprun", "yarprun", "--read", strStdioUUID.c_str(), static_cast<char*>(YARP_NULLPTR));
2593 
2594  CLOSE(pipe_stdin_to_cmd[WRITE_TO_PIPE]);
2595 
2596  if (ret==YARPRUN_ERROR)
2597  {
2598  int error=errno;
2599 
2600  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2601  +yarp::os::ConstString(" alias=")+strAlias
2602  +yarp::os::ConstString(" cmd=stdin\n")
2603  +yarp::os::ConstString("Can't execute stdin because ")+strerror(error)
2604  +yarp::os::ConstString("\n");
2605 
2606 
2607  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
2608  fprintf(out_to_parent, "%s", out.c_str());
2609  fflush(out_to_parent);
2610  fclose(out_to_parent);
2611  fprintf(stderr, "%s", out.c_str());
2612  }
2613 
2614  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2615 
2616  std::exit(ret);
2617  }
2618 
2619  if (IS_PARENT_OF(pid_stdin))
2620  {
2621  // connect yarp read and write
2622  CLOSE(pipe_stdin_to_cmd[WRITE_TO_PIPE]);
2623 
2624  fprintf(stderr, "STARTED: server=%s alias=%s cmd=stdin pid=%d\n", mPortName.c_str(), strAlias.c_str(), pid_stdin);
2625 
2626  int pid_cmd=yarp::os::fork();
2627 
2628  if (IS_INVALID(pid_cmd))
2629  {
2630  int error=errno;
2631 
2632  CLOSE(pipe_stdin_to_cmd[READ_FROM_PIPE]);
2633  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2634  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2635 
2636  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2637  +yarp::os::ConstString(" alias=")+strAlias
2638  +yarp::os::ConstString(" cmd=")+strCmd
2639  +yarp::os::ConstString("\nCan't fork command process because ")+strerror(error)
2640  +yarp::os::ConstString("\n");
2641 
2642  result.addInt(YARPRUN_ERROR);
2643  result.addString(out.c_str());
2644  fprintf(stderr, "%s", out.c_str());
2645 
2646  FILE* to_yarp_stdout=fdopen(pipe_cmd_to_stdout[WRITE_TO_PIPE], "w");
2647  fprintf(to_yarp_stdout, "%s", out.c_str());
2648  fflush(to_yarp_stdout);
2649  fclose(to_yarp_stdout);
2650 
2651  SIGNAL(pid_stdout, SIGTERM);
2652  fprintf(stderr, "TERMINATING stdout (%d)\n", pid_stdout);
2653  SIGNAL(pid_stdin, SIGTERM);
2654  fprintf(stderr, "TERMINATING stdin (%d)\n", pid_stdin);
2655 
2656  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2657 
2658  return YARPRUN_ERROR;
2659  }
2660 
2661  if (IS_NEW_PROCESS(pid_cmd)) // RUN COMMAND HERE
2662  {
2663  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2664 
2665  char *cmd_str=new char[strCmd.length()+1];
2666  strcpy(cmd_str, strCmd.c_str());
2667  /*
2668  int nargs=CountArgs(cmd_str);
2669  char **arg_str=new char*[nargs+1];
2670  ParseCmd(cmd_str, arg_str);
2671  arg_str[nargs]=0;
2672  */
2673  int nargs = 0;
2674  char **arg_str = new char*[C_MAXARGS + 1];
2675  parseArguments(cmd_str, &nargs, arg_str);
2676  arg_str[nargs]=YARP_NULLPTR;
2677 
2678  setvbuf(stdout, YARP_NULLPTR, _IONBF, 0);
2679 
2680  REDIRECT_TO(STDIN_FILENO, pipe_stdin_to_cmd[READ_FROM_PIPE]);
2681  REDIRECT_TO(STDOUT_FILENO, pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2682  REDIRECT_TO(STDERR_FILENO, pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2683 
2684  if (msg.check("env"))
2685  {
2686  yarp::os::impl::SplitString ss(msg.find("env").asString().c_str(), ';');
2687  for(int i=0; i<ss.size(); i++) {
2688  char* szenv = new char[strlen(ss.get(i))+1];
2689  strcpy(szenv, ss.get(i));
2690  yarp::os::impl::putenv(szenv); // putenv doesn't make copy of the string
2691  }
2692  //delete [] szenv;
2693  }
2694 
2695  if (msg.check("workdir"))
2696  {
2697  int ret = yarp::os::impl::chdir(msg.find("workdir").asString().c_str());
2698 
2699  if (ret!=0)
2700  {
2701  int error=errno;
2702 
2703  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2704  +yarp::os::ConstString(" alias=")+strAlias
2705  +yarp::os::ConstString(" cmd=")+strCmd
2706  +yarp::os::ConstString("\nCan't execute command, cannot set working directory ")+strerror(error)
2707  +yarp::os::ConstString("\n");
2708 
2709  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
2710  fprintf(out_to_parent, "%s", out.c_str());
2711  fflush(out_to_parent);
2712  fclose(out_to_parent);
2713  fprintf(stderr, "%s", out.c_str());
2714 
2715  std::exit(ret);
2716  }
2717  }
2718 
2719  int ret=YARPRUN_ERROR;
2720 
2721  char currWorkDirBuff[1024];
2722  char *currWorkDir=yarp::os::impl::getcwd(currWorkDirBuff, 1024);
2723 
2724  if (currWorkDir)
2725  {
2726  char **cwd_arg_str=new char*[nargs+1];
2727  for (int i=1; i<nargs; ++i) cwd_arg_str[i]=arg_str[i];
2728  cwd_arg_str[nargs]=YARP_NULLPTR;
2729  cwd_arg_str[0]=new char[strlen(currWorkDir)+strlen(arg_str[0])+16];
2730 
2731  strcpy(cwd_arg_str[0], currWorkDir);
2732  strcat(cwd_arg_str[0], "/");
2733  strcat(cwd_arg_str[0], arg_str[0]);
2734 
2735  //Why removing vectors and stop threads?
2736  //exec* never returns and memory is claimed by the system
2737  //furthermore after fork() only the thread which called fork() is forked!
2738  // cleanBeforeExec();
2739 
2740  ret = yarp::os::impl::execvp(cwd_arg_str[0], cwd_arg_str);
2741 
2742  delete [] cwd_arg_str[0];
2743  delete [] cwd_arg_str;
2744  }
2745 
2746  if (ret==YARPRUN_ERROR)
2747  {
2748  //Why removing vectors and stop threads?
2749  //exec* never returns and memory is claimed by the system
2750  //furthermore after fork() only the thread which called fork() is forked!
2751  // cleanBeforeExec();
2752 
2753  ret = yarp::os::impl::execvp(arg_str[0], arg_str);
2754  }
2755 
2756  fflush(stdout);
2757 
2758  CLOSE(pipe_stdin_to_cmd[READ_FROM_PIPE]);
2759  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2760 
2761  if (ret==YARPRUN_ERROR)
2762  {
2763  int error=errno;
2764 
2765  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2766  +yarp::os::ConstString(" alias=")+strAlias
2767  +yarp::os::ConstString(" cmd=")+strCmd
2768  +yarp::os::ConstString("\nCan't execute command because ")+strerror(error)
2769  +yarp::os::ConstString("\n");
2770 
2771  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
2772  fprintf(out_to_parent, "%s", out.c_str());
2773  fflush(out_to_parent);
2774  fclose(out_to_parent);
2775  fprintf(stderr, "%s", out.c_str());
2776  }
2777 
2778  delete [] cmd_str;
2779  delete [] arg_str;
2780 
2781  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2782 
2783  std::exit(ret);
2784  }
2785 
2786 
2787  if (IS_PARENT_OF(pid_cmd))
2788  {
2789  CLOSE(pipe_stdin_to_cmd[READ_FROM_PIPE]);
2790  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2791  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2792 
2794  strAlias,
2795  mPortName,
2796  strStdio,
2797  pid_cmd,
2798  strStdioUUID,
2799  mStdioVector,
2800  pid_stdin,
2801  pid_stdout,
2802  pipe_stdin_to_cmd[READ_FROM_PIPE],
2803  pipe_stdin_to_cmd[WRITE_TO_PIPE],
2804  pipe_cmd_to_stdout[READ_FROM_PIPE],
2805  pipe_cmd_to_stdout[WRITE_TO_PIPE],
2806  YARP_NULLPTR,
2807  false
2808  );
2809 
2810  pInf->setCmd(strCmd);
2811 
2812  if (msg.check("env"))
2813  {
2814  pInf->setEnv(msg.find("env").asString());
2815  }
2816 
2817  mProcessVector->Add(pInf);
2818 
2819  yarp::os::Time::delay(0.01);
2820 
2821  FILE* in_from_child=fdopen(pipe_child_to_parent[READ_FROM_PIPE], "r");
2822  int flags=fcntl(pipe_child_to_parent[READ_FROM_PIPE], F_GETFL, 0);
2823  fcntl(pipe_child_to_parent[READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
2824 
2826 
2827  if (in_from_child)
2828  {
2829  char buff[1024];
2830 
2831  while(true)
2832  {
2833  if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) break;
2834 
2835  out+=yarp::os::ConstString(buff);
2836  }
2837 
2838  fclose(in_from_child);
2839  }
2840 
2841  if (out.length()>0)
2842  {
2843  pid_cmd=YARPRUN_ERROR;
2844  }
2845  else
2846  {
2847  out=yarp::os::ConstString("STARTED: server=")+mPortName
2848  +yarp::os::ConstString(" alias=")+strAlias
2849  +yarp::os::ConstString(" cmd=")+strCmd
2850  +yarp::os::ConstString(" pid=")+int2String(pid_cmd)
2851  +yarp::os::ConstString("\n");
2852  }
2853 
2854  result.addInt(pid_cmd);
2855  result.addString(out.c_str());
2856  result.addString(strStdioUUID.c_str());
2857 
2858  fprintf(stderr, "%s", out.c_str());
2859 
2860  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2861 
2862  return pid_cmd;
2863  }
2864  }
2865  }
2866 
2867  result.addInt(YARPRUN_ERROR);
2868  result.addString("I should never reach this point!!!\n");
2869 
2870  return YARPRUN_ERROR;
2871 }
2872 
2873 int yarp::os::Run::executeCmdStdout(yarp::os::Bottle& msg, yarp::os::Bottle& result, yarp::os::ConstString& loggerName)
2874 {
2875  yarp::os::ConstString strAlias=msg.find("as").asString();
2876  yarp::os::ConstString strCmd=msg.find("cmd").asString();
2877 
2878  yarp::os::ConstString portName="/log";
2879  portName+=mPortName+"/";
2880 
2881  yarp::os::ConstString command=strCmd;
2882  size_t space=command.find(' ');
2883  if (space!=ConstString::npos) command=command.substr(0, space);
2884  portName+=command;
2885 
2886 
2887 
2888  int pipe_cmd_to_stdout[2];
2889  int ret_cmd_to_stdout=yarp::os::impl::pipe(pipe_cmd_to_stdout);
2890 
2891  int pipe_child_to_parent[2];
2892  int ret_child_to_parent=yarp::os::impl::pipe(pipe_child_to_parent);
2893 
2894  if (ret_child_to_parent!=0 || ret_cmd_to_stdout!=0)
2895  {
2896  int error=errno;
2897 
2898  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2899  +yarp::os::ConstString(" alias=")+strAlias
2900  +yarp::os::ConstString(" cmd=stdout\n")
2901  +yarp::os::ConstString("Can't create pipes ")+strerror(error)
2902  +yarp::os::ConstString("\n");
2903 
2904  result.addInt(YARPRUN_ERROR);
2905  result.addString(out.c_str());
2906  fprintf(stderr, "%s", out.c_str());
2907 
2908  return YARPRUN_ERROR;
2909  }
2910 
2911  int pid_stdout=yarp::os::fork();
2912 
2913  if (IS_INVALID(pid_stdout))
2914  {
2915  int error=errno;
2916 
2917  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2918  CLOSE(pipe_cmd_to_stdout[READ_FROM_PIPE]);
2919  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2920  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2921 
2922  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2923  +yarp::os::ConstString(" alias=")+strAlias
2924  +yarp::os::ConstString(" cmd=stdout\n")
2925  +yarp::os::ConstString("Can't fork stdout process because ")+strerror(error)
2926  +yarp::os::ConstString("\n");
2927 
2928  result.addInt(YARPRUN_ERROR);
2929  result.addString(out.c_str());
2930  fprintf(stderr, "%s", out.c_str());
2931 
2932  return YARPRUN_ERROR;
2933  }
2934 
2935  if (IS_NEW_PROCESS(pid_stdout)) // STDOUT IMPLEMENTED HERE
2936  {
2937  REDIRECT_TO(STDIN_FILENO, pipe_cmd_to_stdout[READ_FROM_PIPE]);
2938 
2939  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2940  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2941 
2942  //Why removing vectors and stop threads?
2943  //exec* never returns and memory is claimed by the system
2944  //furthermore after fork() only the thread which called fork() is forked!
2945  // cleanBeforeExec();
2946 
2947  //yarp::os::impl::signal(SIGPIPE, SIG_DFL);
2948 
2949  int ret = yarp::os::impl::execlp("yarprun", "yarprun", "--write", portName.c_str(), "--log", loggerName.c_str(), static_cast<char*>(YARP_NULLPTR));
2950 
2951  CLOSE(pipe_cmd_to_stdout[READ_FROM_PIPE]);
2952 
2953  if (ret==YARPRUN_ERROR)
2954  {
2955  int error=errno;
2956 
2957  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2958  +yarp::os::ConstString(" alias=")+strAlias
2959  +yarp::os::ConstString(" cmd=stdout\n")
2960  +yarp::os::ConstString("Can't execute stdout because ")+strerror(error)
2961  +yarp::os::ConstString("\n");
2962 
2963  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
2964  fprintf(out_to_parent, "%s", out.c_str());
2965  fflush(out_to_parent);
2966  fclose(out_to_parent);
2967 
2968  fprintf(stderr, "%s", out.c_str());
2969  }
2970 
2971  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2972 
2973  std::exit(ret);
2974  }
2975 
2976  if (IS_PARENT_OF(pid_stdout))
2977  {
2978  CLOSE(pipe_cmd_to_stdout[READ_FROM_PIPE]);
2979 
2980  fprintf(stderr, "STARTED: server=%s alias=%s cmd=stdout pid=%d\n", mPortName.c_str(), strAlias.c_str(), pid_stdout);
2981 
2983 
2984  //if (IS_PARENT_OF(pid_stdin))
2985  {
2986  int pid_cmd=yarp::os::fork();
2987 
2988  if (IS_INVALID(pid_cmd))
2989  {
2990  int error=errno;
2991 
2992  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2993  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2994 
2995  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2996  +yarp::os::ConstString(" alias=")+strAlias
2997  +yarp::os::ConstString(" cmd=")+strCmd
2998  +yarp::os::ConstString("\nCan't fork command process because ")+strerror(error)
2999  +yarp::os::ConstString("\n");
3000 
3001  result.addInt(YARPRUN_ERROR);
3002  result.addString(out.c_str());
3003  fprintf(stderr, "%s", out.c_str());
3004 
3005  FILE* to_yarp_stdout=fdopen(pipe_cmd_to_stdout[WRITE_TO_PIPE], "w");
3006  fprintf(to_yarp_stdout, "%s", out.c_str());
3007  fflush(to_yarp_stdout);
3008  fclose(to_yarp_stdout);
3009 
3010  SIGNAL(pid_stdout, SIGTERM);
3011  fprintf(stderr, "TERMINATING stdout (%d)\n", pid_stdout);
3012  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
3013 
3014  return YARPRUN_ERROR;
3015  }
3016 
3017  if (IS_NEW_PROCESS(pid_cmd)) // RUN COMMAND HERE
3018  {
3019  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
3020 
3021  char *cmd_str=new char[strCmd.length()+1];
3022  strcpy(cmd_str, strCmd.c_str());
3023  /*
3024  int nargs=CountArgs(cmd_str);
3025  char **arg_str=new char*[nargs+1];
3026  ParseCmd(cmd_str, arg_str);
3027  arg_str[nargs]=0;
3028  */
3029  int nargs = 0;
3030  char **arg_str = new char*[C_MAXARGS + 1];
3031  parseArguments(cmd_str, &nargs, arg_str);
3032  arg_str[nargs]=YARP_NULLPTR;
3033 
3034  setvbuf(stdout, YARP_NULLPTR, _IONBF, 0);
3035 
3036  REDIRECT_TO(STDOUT_FILENO, pipe_cmd_to_stdout[WRITE_TO_PIPE]);
3037  REDIRECT_TO(STDERR_FILENO, pipe_cmd_to_stdout[WRITE_TO_PIPE]);
3038 
3039  if (msg.check("env"))
3040  {
3041  yarp::os::impl::SplitString ss(msg.find("env").asString().c_str(), ';');
3042  for(int i=0; i<ss.size(); i++) {
3043  char* szenv = new char[strlen(ss.get(i))+1];
3044  strcpy(szenv, ss.get(i));
3045  yarp::os::impl::putenv(szenv); // putenv doesn't make copy of the string
3046  }
3047  //delete [] szenv;
3048  }
3049 
3050  if (msg.check("workdir"))
3051  {
3052  int ret = yarp::os::impl::chdir(msg.find("workdir").asString().c_str());
3053 
3054  if (ret!=0)
3055  {
3056  int error=errno;
3057 
3058  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
3059  +yarp::os::ConstString(" alias=")+strAlias
3060  +yarp::os::ConstString(" cmd=")+strCmd
3061  +yarp::os::ConstString("\nCan't execute command, cannot set working directory ")+strerror(error)
3062  +yarp::os::ConstString("\n");
3063 
3064  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
3065  fprintf(out_to_parent, "%s", out.c_str());
3066  fflush(out_to_parent);
3067  fclose(out_to_parent);
3068  fprintf(stderr, "%s", out.c_str());
3069 
3070  std::exit(ret);
3071  }
3072  }
3073 
3074  int ret=YARPRUN_ERROR;
3075 
3076  char currWorkDirBuff[1024];
3077  char *currWorkDir=getcwd(currWorkDirBuff, 1024);
3078 
3079  if (currWorkDir)
3080  {
3081  char **cwd_arg_str=new char*[nargs+1];
3082  for (int i=1; i<nargs; ++i) cwd_arg_str[i]=arg_str[i];
3083  cwd_arg_str[nargs]=YARP_NULLPTR;
3084  cwd_arg_str[0]=new char[strlen(currWorkDir)+strlen(arg_str[0])+16];
3085 
3086  strcpy(cwd_arg_str[0], currWorkDir);
3087  strcat(cwd_arg_str[0], "/");
3088  strcat(cwd_arg_str[0], arg_str[0]);
3089 
3090  //Why removing vectors and stop threads?
3091  //exec* never returns and memory is claimed by the system
3092  //furthermore after fork() only the thread which called fork() is forked!
3093  // cleanBeforeExec();
3094 
3095  ret = yarp::os::impl::execvp(cwd_arg_str[0], cwd_arg_str);
3096 
3097  delete [] cwd_arg_str[0];
3098  delete [] cwd_arg_str;
3099  }
3100 
3101  if (ret==YARPRUN_ERROR)
3102  {
3103  //Why removing vectors and stop threads?
3104  //exec* never returns and memory is claimed by the system
3105  //furthermore after fork() only the thread which called fork() is forked!
3106  // cleanBeforeExec();
3107 
3108  ret = yarp::os::impl::execvp(arg_str[0], arg_str);
3109  }
3110 
3111  fflush(stdout);
3112 
3113  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
3114 
3115  if (ret==YARPRUN_ERROR)
3116  {
3117  int error=errno;
3118 
3119  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
3120  +yarp::os::ConstString(" alias=")+strAlias
3121  +yarp::os::ConstString(" cmd=")+strCmd
3122  +yarp::os::ConstString("\nCan't execute command because ")+strerror(error)
3123  +yarp::os::ConstString("\n");
3124 
3125  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
3126  fprintf(out_to_parent, "%s", out.c_str());
3127  fflush(out_to_parent);
3128  fclose(out_to_parent);
3129  fprintf(stderr, "%s", out.c_str());
3130  }
3131 
3132  delete [] cmd_str;
3133  delete [] arg_str;
3134 
3135  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
3136 
3137  std::exit(ret);
3138  }
3139 
3140 
3141  if (IS_PARENT_OF(pid_cmd))
3142  {
3143  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
3144  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
3145 
3147  strAlias,
3148  mPortName,
3149  portName,
3150  pid_cmd,
3151  pid_stdout,
3152  pipe_cmd_to_stdout[READ_FROM_PIPE],
3153  pipe_cmd_to_stdout[WRITE_TO_PIPE],
3154  YARP_NULLPTR,
3155  false
3156  );
3157 
3158  pInf->setCmd(strCmd);
3159 
3160  if (msg.check("env"))
3161  {
3162  pInf->setEnv(msg.find("env").asString());
3163  }
3164 
3165  mProcessVector->Add(pInf);
3166 
3167  yarp::os::Time::delay(0.01);
3168 
3169  FILE* in_from_child=fdopen(pipe_child_to_parent[READ_FROM_PIPE], "r");
3170  int flags=fcntl(pipe_child_to_parent[READ_FROM_PIPE], F_GETFL, 0);
3171  fcntl(pipe_child_to_parent[READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
3172 
3174 
3175  if (in_from_child)
3176  {
3177  char buff[1024];
3178 
3179  while(true)
3180  {
3181  if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) break;
3182 
3183  out+=yarp::os::ConstString(buff);
3184  }
3185 
3186  fclose(in_from_child);
3187  }
3188 
3189  if (out.length()>0)
3190  {
3191  pid_cmd=YARPRUN_ERROR;
3192  }
3193  else
3194  {
3195  out=yarp::os::ConstString("STARTED: server=")+mPortName
3196  +yarp::os::ConstString(" alias=")+strAlias
3197  +yarp::os::ConstString(" cmd=")+strCmd
3198  +yarp::os::ConstString(" pid=")+int2String(pid_cmd)
3199  +yarp::os::ConstString("\n");
3200  }
3201 
3202  result.addInt(pid_cmd);
3203  result.addString(out.c_str());
3204 
3205  fprintf(stderr, "%s", out.c_str());
3206 
3207  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
3208 
3209  return pid_cmd;
3210  }
3211  }
3212  }
3213 
3214  result.addInt(YARPRUN_ERROR);
3215  result.addString("I should never reach this point!!!\n");
3216 
3217  return YARPRUN_ERROR;
3218 }
3219 
3220 int yarp::os::Run::userStdio(yarp::os::Bottle& msg, yarp::os::Bottle& result)
3221 {
3222  yarp::os::ConstString strAlias=msg.find("as").asString();
3223  yarp::os::ConstString strUUID=msg.find("stdiouuid").asString();
3224 
3225  yarp::os::ConstString strCmd;
3226 
3227  if (msg.check("forward"))
3228  {
3229  strCmd=yarp::os::ConstString("/bin/bash -l -c \"yarprun --readwrite ")+strUUID
3230  +yarp::os::ConstString(" --forward ")+msg.findGroup("forward").get(1).asString()+yarp::os::ConstString(" ")+msg.findGroup("forward").get(2).asString()+yarp::os::ConstString("\"");
3231  }
3232  else
3233  {
3234  strCmd=yarp::os::ConstString("/bin/bash -l -c \"yarprun --readwrite ")+strUUID+"\"";
3235  }
3236 
3237  int pipe_child_to_parent[2];
3238 
3239  if (yarp::os::impl::pipe(pipe_child_to_parent))
3240  {
3241  int error=errno;
3242 
3243  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
3244  +yarp::os::ConstString(" alias=")+strAlias
3245  +yarp::os::ConstString(" cmd=stdio\nCan't create pipe ")+strerror(error)
3246  +yarp::os::ConstString("\n");
3247 
3248  result.clear();
3249  result.addInt(YARPRUN_ERROR);
3250  result.addString(out.c_str());
3251  fprintf(stderr, "%s", out.c_str());
3252 
3253  return YARPRUN_ERROR;
3254  }
3255 
3256  int c=0;
3257  char *command[16];
3258  for (int i=0; i<16; ++i) {
3259  command[i] = YARP_NULLPTR;
3260  }
3261 
3262  cmdcpy(command[c++], "xterm");
3263  cmdcpy(command[c++], msg.check("hold")?"-hold":"+hold");
3264 
3265  if (msg.check("geometry"))
3266  {
3267  cmdcpy(command[c++], "-geometry");
3268  cmdcpy(command[c++], msg.find("geometry").asString().c_str());
3269  }
3270 
3271  cmdcpy(command[c++], "-title");
3272  cmdcpy(command[c++], strAlias.c_str());
3273 
3274  cmdcpy(command[c++], "-e");
3275  cmdcpy(command[c++], strCmd.c_str());
3276 
3277  int pid_cmd=yarp::os::fork();
3278 
3279  if (IS_INVALID(pid_cmd))
3280  {
3281  int error=errno;
3282 
3283  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
3284  +yarp::os::ConstString(" alias=")+strAlias
3285  +yarp::os::ConstString(" cmd=stdio\nCan't fork stdout process because ")+strerror(error)
3286  +yarp::os::ConstString("\n");
3287 
3288  result.clear();
3289  result.addInt(YARPRUN_ERROR);
3290  result.addString(out.c_str());
3291  fprintf(stderr, "%s", out.c_str());
3292 
3293  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
3294  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
3295 
3296  cmdclean(command);
3297 
3298  return YARPRUN_ERROR;
3299  }
3300 
3301  if (IS_NEW_PROCESS(pid_cmd)) // RUN COMMAND HERE
3302  {
3303  //yarp::os::impl::signal(SIGPIPE, SIG_IGN);
3304 
3305  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
3306 
3307  REDIRECT_TO(STDERR_FILENO, pipe_child_to_parent[WRITE_TO_PIPE]);
3308 
3309  //Why removing vectors and stop threads?
3310  //exec* never returns and memory is claimed by the system
3311  //furthermore after fork() only the thread which called fork() is forked!
3312  // cleanBeforeExec();
3313 
3314  //yarp::os::impl::signal(SIGHUP, rwSighupHandler);
3315 
3316  int ret = yarp::os::impl::execvp("xterm", command);
3317 
3318  cmdclean(command);
3319 
3320  if (ret==YARPRUN_ERROR)
3321  {
3322  int error=errno;
3323 
3324  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
3325  +yarp::os::ConstString(" alias=")+strAlias
3326  +yarp::os::ConstString(" cmd=xterm\nCan't execute command because ")+strerror(error)
3327  +yarp::os::ConstString("\n");
3328 
3329  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
3330 
3331  fprintf(out_to_parent, "%s", out.c_str());
3332  fflush(out_to_parent);
3333  fclose(out_to_parent);
3334 
3335  fprintf(stderr, "%s", out.c_str());
3336  }
3337 
3338  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
3339 
3340  std::exit(ret);
3341  }
3342 
3343  if (IS_PARENT_OF(pid_cmd))
3344  {
3345  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
3346 
3347  mStdioVector->Add(new YarpRunProcInfo(strAlias, mPortName, pid_cmd, YARP_NULLPTR, msg.check("hold")));
3348 
3349  result.clear();
3350 
3351  cmdclean(command);
3352 
3353  yarp::os::Time::delay(0.01);
3354 
3355  FILE* in_from_child=fdopen(pipe_child_to_parent[READ_FROM_PIPE], "r");
3356  int flags=fcntl(pipe_child_to_parent[READ_FROM_PIPE], F_GETFL, 0);
3357  fcntl(pipe_child_to_parent[READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
3359 
3360  if (in_from_child)
3361  {
3362  char buff[1024];
3363 
3364  while(true)
3365  {
3366  if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) break;
3367 
3368  out+=yarp::os::ConstString(buff);
3369  }
3370 
3371  fclose(in_from_child);
3372  }
3373 
3374  result.clear();
3375 
3376  //if (out.length()>0)
3377  if (out.substr(0, 14)=="xterm Xt error" || out.substr(0, 7)=="ABORTED")
3378  {
3379  pid_cmd=YARPRUN_ERROR;
3380  }
3381  else
3382  {
3383  out=yarp::os::ConstString("STARTED: server=")+mPortName
3384  +yarp::os::ConstString(" alias=")+strAlias
3385  +yarp::os::ConstString(" cmd=xterm pid=")+int2String(pid_cmd)
3386  +yarp::os::ConstString("\n");
3387 
3388  }
3389 
3390  fprintf(stderr, "%s", out.c_str());
3391 
3392  result.addInt(pid_cmd);
3393  result.addString(out.c_str());
3394 
3395  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
3396 
3397  return pid_cmd;
3398  }
3399 
3400  result.clear();
3401  result.addInt(YARPRUN_ERROR);
3402 
3403  return YARPRUN_ERROR;
3404 }
3405 
3406 int yarp::os::Run::executeCmd(yarp::os::Bottle& msg, yarp::os::Bottle& result)
3407 {
3408  yarp::os::ConstString strAlias(msg.find("as").asString());
3409  yarp::os::ConstString strCmd(msg.find("cmd").toString());
3410 
3411  int pipe_child_to_parent[2];
3412  int ret_pipe_child_to_parent=yarp::os::impl::pipe(pipe_child_to_parent);
3413 
3414  if (ret_pipe_child_to_parent!=0)
3415  {
3416  int error=errno;
3417 
3418  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
3419  +yarp::os::ConstString(" alias=")+strAlias
3420  +yarp::os::ConstString(" cmd=stdio\nCan't create pipe ")+strerror(error)
3421  +yarp::os::ConstString("\n");
3422 
3423 
3424  result.addInt(YARPRUN_ERROR);
3425  result.addString(out.c_str());
3426  fprintf(stderr, "%s", out.c_str());
3427 
3428  return YARPRUN_ERROR;
3429  }
3430 
3431  int pid_cmd=yarp::os::fork();
3432 
3433  if (IS_INVALID(pid_cmd))
3434  {
3435  int error=errno;
3436 
3437  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
3438  +yarp::os::ConstString(" alias=")+strAlias
3439  +yarp::os::ConstString(" cmd=")+strCmd
3440  +yarp::os::ConstString("\nCan't fork command process because ")+strerror(error)
3441  +yarp::os::ConstString("\n");
3442 
3443  result.addInt(YARPRUN_ERROR);
3444  result.addString(out.c_str());
3445  fprintf(stderr, "%s", out.c_str());
3446 
3447  return YARPRUN_ERROR;
3448  }
3449 
3450  if (IS_NEW_PROCESS(pid_cmd)) // RUN COMMAND HERE
3451  {
3452  int saved_stderr = yarp::os::impl::dup(STDERR_FILENO);
3453  int null_file=open("/dev/null", O_WRONLY);
3454  REDIRECT_TO(STDOUT_FILENO, null_file);
3455  REDIRECT_TO(STDERR_FILENO, null_file);
3456  close(null_file);
3457 
3458  char *cmd_str=new char[strCmd.length()+1];
3459  strcpy(cmd_str, strCmd.c_str());
3460  /*
3461  int nargs=CountArgs(cmd_str);
3462  char **arg_str=new char*[nargs+1];
3463  ParseCmd(cmd_str, arg_str);
3464  arg_str[nargs]=0;
3465  */
3466  int nargs = 0;
3467  char **arg_str = new char*[C_MAXARGS + 1];
3468  parseArguments(cmd_str, &nargs, arg_str);
3469  arg_str[nargs]=YARP_NULLPTR;
3470 
3471  if (msg.check("env"))
3472  {
3473  yarp::os::impl::SplitString ss(msg.find("env").asString().c_str(), ';');
3474  for(int i=0; i<ss.size(); i++) {
3475  char* szenv = new char[strlen(ss.get(i))+1];
3476  strcpy(szenv, ss.get(i));
3477  yarp::os::impl::putenv(szenv); // putenv doesn't make copy of the string
3478  }
3479  }
3480 
3481  if (msg.check("workdir"))
3482  {
3483  int ret = yarp::os::impl::chdir(msg.find("workdir").asString().c_str());
3484 
3485  if (ret!=0)
3486  {
3487  int error=errno;
3488 
3489  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
3490  +yarp::os::ConstString(" alias=")+strAlias
3491  +yarp::os::ConstString(" cmd=")+strCmd
3492  +yarp::os::ConstString("\nCan't execute command, cannot set working directory ")+strerror(error)
3493  +yarp::os::ConstString("\n");
3494 
3495  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
3496  fprintf(out_to_parent, "%s", out.c_str());
3497  fflush(out_to_parent);
3498  fclose(out_to_parent);
3499 
3500  REDIRECT_TO(STDERR_FILENO, saved_stderr);
3501  fprintf(stderr, "%s", out.c_str());
3502  }
3503  }
3504 
3505  int ret=YARPRUN_ERROR;
3506 
3507  char currWorkDirBuff[1024];
3508  char *currWorkDir=getcwd(currWorkDirBuff, 1024);
3509 
3510  if (currWorkDir)
3511  {
3512  char **cwd_arg_str=new char*[nargs+1];
3513  for (int i=1; i<nargs; ++i) cwd_arg_str[i]=arg_str[i];
3514  cwd_arg_str[nargs]=YARP_NULLPTR;
3515  cwd_arg_str[0]=new char[strlen(currWorkDir)+strlen(arg_str[0])+16];
3516 
3517 
3518  strcpy(cwd_arg_str[0], currWorkDir);
3519  strcat(cwd_arg_str[0], "/");
3520  strcat(cwd_arg_str[0], arg_str[0]);
3521 
3522  //Why removing vectors and stop threads?
3523  //exec* never returns and memory is claimed by the system
3524  //furthermore after fork() only the thread which called fork() is forked!
3525 // cleanBeforeExec();
3526 
3527  ret = yarp::os::impl::execvp(cwd_arg_str[0], cwd_arg_str);
3528 
3529  delete [] cwd_arg_str[0];
3530  delete [] cwd_arg_str;
3531  }
3532 
3533  if (ret==YARPRUN_ERROR)
3534  {
3535  //Why removing vectors and stop threads?
3536  //exec* never returns and memory is claimed by the system
3537  //furthermore after fork() only the thread which called fork() is forked!
3538  // cleanBeforeExec();
3539  ret = yarp::os::impl::execvp(arg_str[0], arg_str);
3540  }
3541 
3542  if (ret==YARPRUN_ERROR)
3543  {
3544  int error=errno;
3545 
3546  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
3547  +yarp::os::ConstString(" alias=")+strAlias
3548  +yarp::os::ConstString(" cmd=")+strCmd
3549  +yarp::os::ConstString("\nCan't execute command because ")+strerror(error)
3550  +yarp::os::ConstString("\n");
3551 
3552  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
3553  fprintf(out_to_parent, "%s", out.c_str());
3554  fflush(out_to_parent);
3555  fclose(out_to_parent);
3556 
3557  REDIRECT_TO(STDERR_FILENO, saved_stderr);
3558  fprintf(stderr, "%s", out.c_str());
3559  }
3560 
3561  delete [] cmd_str;
3562  delete [] arg_str;
3563 
3564  std::exit(ret);
3565  }
3566 
3567  if (IS_PARENT_OF(pid_cmd))
3568  {
3569  YarpRunProcInfo* pInf = new YarpRunProcInfo(strAlias, mPortName, pid_cmd, YARP_NULLPTR, false);
3570  pInf->setCmd(strCmd);
3571  if (msg.check("env")) pInf->setEnv(msg.find("env").asString());
3572  mProcessVector->Add(pInf);
3573  char pidstr[16];
3574  sprintf(pidstr, "%d", pid_cmd);
3575 
3576  yarp::os::Time::delay(0.01);
3577 
3578  FILE* in_from_child=fdopen(pipe_child_to_parent[READ_FROM_PIPE], "r");
3579  int flags=fcntl(pipe_child_to_parent[READ_FROM_PIPE], F_GETFL, 0);
3580  fcntl(pipe_child_to_parent[READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
3581 
3583 
3584  if (in_from_child)
3585  {
3586  char buff[1024];
3587 
3588  while(true)
3589  {
3590  if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) break;
3591 
3592  out+=yarp::os::ConstString(buff);
3593  }
3594 
3595  fclose(in_from_child);
3596  }
3597 
3598  if (out.length()>0)
3599  {
3600  pid_cmd=YARPRUN_ERROR;
3601  }
3602  else
3603  {
3604  out=yarp::os::ConstString("STARTED: server=")+mPortName
3605  +yarp::os::ConstString(" alias=")+strAlias
3606  +yarp::os::ConstString(" cmd=")+strCmd
3607  +yarp::os::ConstString(" pid=")+int2String(pid_cmd)
3608  +yarp::os::ConstString("\n");
3609  }
3610 
3611  fprintf(stderr, "%s", out.c_str());
3612 
3613  result.addInt(pid_cmd);
3614  result.addString(out.c_str());
3615 
3616  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
3617  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
3618 
3619  return pid_cmd;
3620  }
3621 
3622  result.addInt(YARPRUN_ERROR);
3623 
3624  return YARPRUN_ERROR;
3625 }
3626 
3627 #endif
3628 
3630 // API
3632 
3634 {
3635  yarp::os::Bottle msg, grp, response;
3636 
3637  grp.clear();
3638  grp.addString("on");
3639  grp.addString(node.c_str());
3640  msg.addList()=grp;
3641 
3642  yarp::os::ConstString dest_srv=node;
3643 
3644  if (command.check("stdio"))
3645  {
3646  dest_srv=yarp::os::ConstString(command.find("stdio").asString());
3647 
3648  grp.clear();
3649  grp.addString("stdio");
3650  grp.addString(dest_srv.c_str());
3651  msg.addList()=grp;
3652 
3653  if (command.check("geometry"))
3654  {
3655  grp.clear();
3656  grp.addString("geometry");
3657  grp.addString(command.find("geometry").asString().c_str());
3658  msg.addList()=grp;
3659  }
3660 
3661  if (command.check("hold"))
3662  {
3663  grp.clear();
3664  grp.addString("hold");
3665  msg.addList()=grp;
3666  }
3667  }
3668 
3669  grp.clear();
3670  grp.addString("as");
3671  grp.addString(keyv.c_str());
3672  msg.addList()=grp;
3673 
3674  grp.clear();
3675  grp.addString("cmd");
3676  grp.addString(command.find("name").asString().c_str());
3677  grp.addString(command.find("parameters").asString().c_str());
3678  msg.addList()=grp;
3679 
3680  printf(":: %s\n", msg.toString().c_str());
3681 
3682  response=sendMsg(msg, dest_srv.c_str());
3683 
3684  char buff[16];
3685  sprintf(buff, "%d", response.get(0).asInt());
3686  keyv=yarp::os::ConstString(buff);
3687 
3688  return response.get(0).asInt()>0?0:YARPRUN_ERROR;
3689 }
3690 
3692 {
3693  yarp::os::Bottle msg, grp, response;
3694 
3695  grp.clear();
3696  grp.addString("on");
3697  grp.addString(node.c_str());
3698  msg.addList()=grp;
3699 
3700  grp.clear();
3701  grp.addString("sigterm");
3702  grp.addString(keyv.c_str());
3703  msg.addList()=grp;
3704 
3705  printf(":: %s\n", msg.toString().c_str());
3706 
3707  response=sendMsg(msg, node.c_str());
3708 
3709  return response.get(0).asString()=="sigterm OK"?0:YARPRUN_ERROR;
3710 }
3711 
3713 {
3714  yarp::os::Bottle msg, grp, response;
3715 
3716  grp.clear();
3717  grp.addString("on");
3718  grp.addString(node.c_str());
3719  msg.addList()=grp;
3720 
3721  grp.clear();
3722  grp.addString("sigtermall");
3723  msg.addList()=grp;
3724 
3725  printf(":: %s\n", msg.toString().c_str());
3726 
3727  response=sendMsg(msg, node.c_str());
3728 
3729  return response.get(0).asString()=="sigtermall OK"?0:YARPRUN_ERROR;
3730 }
3731 
3733 {
3734  yarp::os::Bottle msg, grp, response;
3735 
3736  grp.clear();
3737  grp.addString("on");
3738  grp.addString(node.c_str());
3739  msg.addList()=grp;
3740 
3741  grp.clear();
3742  grp.addString("kill");
3743  grp.addString(keyv.c_str());
3744  grp.addInt(s);
3745  msg.addList()=grp;
3746 
3747  printf(":: %s\n", msg.toString().c_str());
3748 
3749  response=sendMsg(msg, node.c_str());
3750 
3751  return response.get(0).asString()=="kill OK"?0:YARPRUN_ERROR;
3752 }
3753 
3755 {
3756  yarp::os::Bottle msg, grp, response;
3757 
3758  grp.clear();
3759  grp.addString("on");
3760  grp.addString(node.c_str());
3761  msg.addList()=grp;
3762 
3763  grp.clear();
3764  grp.addString("isrunning");
3765  grp.addString(keyv.c_str());
3766  msg.addList()=grp;
3767 
3768  printf(":: %s\n", msg.toString().c_str());
3769 
3770  response=sendMsg(msg, node.c_str());
3771 
3772  if (!response.size()) return false;
3773 
3774  return response.get(0).asString()=="running";
3775 }
3776 
3777 // end API
static ConstString getDirectorySeparator()
Get an OS-appropriate directory separator (e.g.
Definition: Network.cpp:1071
int CLOSE(int h)
virtual YARP_SSIZE_T read(const Bytes &b) override
static RunTerminator * pTerminator
Definition: Run.cpp:75
ConstString substr(size_t start=0, size_t n=npos) const
Generate a substring.
A port that is specialized as an RPC server.
Definition: RpcServer.h:26
static ConstString getPathSeparator()
Get an OS-appropriate path separator (e.g.
Definition: Network.cpp:1081
yarp::os::SystemInfo::MemoryInfo memory
system memory information
static int sigterm(const ConstString &node, const ConstString &keyv)
Terminate an application running on a yarprun server.
Definition: Run.cpp:3691
void setEnv(const yarp::os::ConstString &env)
void setVerbosity(int verbose=0)
Definition: Logger.h:153
int size() const
Gets the number of elements in the bottle.
Definition: Bottle.cpp:186
yarp::os::ConstString realName
Definition: SystemInfo.h:94
static int kill(const ConstString &node, const ConstString &keyv, int s)
Send a SIGNAL to an application running on a yarprun server (Linux only).
Definition: Run.cpp:3732
#define C_MAXARGS
Definition: Run.cpp:38
#define RUNLOG(msg)
virtual bool write(PortWriter &writer, PortWriter *callback=YARP_NULLPTR) const YARP_OVERRIDE
Write an object to the port.
yarp::os::SystemInfo::PlatformInfo platform
operating system information
virtual bool reply(PortWriter &writer) YARP_OVERRIDE
Send an object as a reply to an object read from the port.
char * getcwd(char *buf, size_t size)
Portable wrapper for the getcwd() function.
Definition: Os.cpp:133
A class for storing options and configuration information.
Definition: Property.h:32
bool start()
Start the new thread running.
Definition: Thread.cpp:85
static bool fileExists(const char *fname)
Definition: Run.cpp:115
yarp::os::ConstString codename
Definition: SystemInfo.h:84
virtual bool open(const ConstString &name) YARP_OVERRIDE
Start port operation, with a specific name, with automatically-chosen network parameters.
void addString(const char *str)
Places a string in the bottle, at the end of the list.
Definition: Bottle.cpp:105
yarp::os::ConstString architecture
Definition: SystemInfo.h:55
void parseArguments(char *io_pLine, int *o_pArgc, char **o_pArgv)
Breaks up a line into multiple arguments.
Definition: Run.cpp:2386
bool stop()
Stop the thread.
Definition: Thread.cpp:74
virtual ConstString getName() const YARP_OVERRIDE
Get name of port.
virtual int asInt() const
Get integer value.
Definition: Value.cpp:172
A port that is specialized as an RPC client.
Definition: RpcClient.h:25
void sigstdio_handler(int sig)
Definition: Run.cpp:77
static char slash
Definition: Run.cpp:88
virtual bool read(PortReader &reader, bool willReply=true) YARP_OVERRIDE
Read an object from the port.
Definition: RpcServer.cpp:34
yarp::os::SystemInfo::LoadInfo load
current cpu load information
yarp::os::ConstString release
Definition: SystemInfo.h:83
A string with almost the same api as std::string.
Definition: ConstString.h:44
static const size_t npos
Definition: ConstString.h:47
static ConstString getEnvironment(const char *key, bool *found=YARP_NULLPTR)
Read a variable from the environment.
Definition: Network.cpp:1051
static bool getLocalMode()
Get current value of flag "localMode", see setLocalMode function.
Definition: Network.cpp:734
void setCmd(const yarp::os::ConstString &cmd)
ConstString toString() const YARP_OVERRIDE
Return a standard text representation of the content of the object.
Definition: Property.cpp:987
#define yInfo
Definition: Log.h:113
virtual ConstString asString() const
Get string value.
Definition: Value.cpp:196
virtual void close() YARP_OVERRIDE
Stop port activity.
void exit(int exit_code)
Portable wrapper for the exit() function.
Definition: Os.cpp:40
static void delay(double seconds)
Wait for a certain number of seconds.
Definition: Time.cpp:82
float t
yarp::os::ConstString homeDir
Definition: SystemInfo.h:95
void clear()
Empties the bottle of any objects it contains.
Definition: Bottle.cpp:74
A helper class to pass the SystemInfo object around the YARP network.
void splitLine(char *pLine, char **pArgs)
Split a line into separate words.
Definition: Run.cpp:2364
bool persistent
Specify whether a requested connection should be persistent.
Definition: ContactStyle.h:78
yarp::os::ConstString name
Definition: SystemInfo.h:81
ConstString toString() const YARP_OVERRIDE
Gives a human-readable textual representation of the bottle.
Definition: Bottle.cpp:146
Preferences for how to communicate with a contact.
Definition: ContactStyle.h:25
yarp::os::ConstString userName
Definition: SystemInfo.h:93
Split a string into pieces.
Definition: SplitString.h:29
int SIGNAL(int pid, int signum)
bool check(const ConstString &key) const YARP_OVERRIDE
Check if there exists a property of the given name.
Definition: Property.cpp:957
ConstString toString() const YARP_OVERRIDE
Return a standard text representation of the content of the object.
Definition: Value.cpp:303
A simple collection of objects that can be described and transmitted in a portable way...
Definition: Bottle.h:57
yarp::os::SystemInfo::ProcessorInfo processor
system processor type information
YarpSignalHandler signal(int signum, YarpSignalHandler sighandler)
Portable wrapper for the signal() function.
Definition: Os.cpp:26
A class for thread synchronization and mutual exclusion.
Definition: Semaphore.h:28
static bool checkNetwork()
Check if the YARP Network is up and running.
Definition: Network.cpp:1022
static yarp::os::Bottle parsePaths(const yarp::os::ConstString &txt)
Definition: Run.cpp:90
Bottle & findGroup(const ConstString &key) const YARP_OVERRIDE
Gets a list corresponding to a given keyword.
Definition: Bottle.cpp:237
Bottle tail() const
Get all but the first element of a bottle.
Definition: Bottle.cpp:333
yarp::os::ConstString vendor
Definition: SystemInfo.h:57
Bottle & addList()
Places an empty nested list in the bottle, at the end of the list.
Definition: Bottle.cpp:117
virtual Bottle & findGroup(const ConstString &key) const YARP_OVERRIDE
Gets a list corresponding to a given keyword.
Definition: Property.cpp:1059
#define REDIRECT_TO(from, to)
Definition: Run.cpp:56
#define yError
Definition: Log.h:115
size_t length() const
yarp::os::SystemInfo::UserInfo user
current user information
int getpid()
Portable wrapper for the getppid() function.
Definition: Os.cpp:91
static bool isRunning(const ConstString &node, ConstString &keyv)
Get a report of all applications running on a yarprun server.
Definition: Run.cpp:3754
void addInt(int x)
Places an integer in the bottle, at the end of the list.
Definition: Bottle.cpp:81
void * HANDLE
virtual void close() override
Definition: TcpRosStream.h:95
yarp::os::SystemInfo::StorageInfo storage
system storage information
yarp::os::Property environmentVars
Definition: SystemInfo.h:86
void sigint_handler(int sig)
Definition: Run.cpp:472
yarp::os::ConstString model
Definition: SystemInfo.h:56
yarp::os::ConstString kernel
Definition: SystemInfo.h:85
virtual Value & find(const ConstString &key) const YARP_OVERRIDE
Gets a value corresponding to a given keyword.
Definition: Bottle.cpp:222
#define YARPRUN_ERROR
int fork(void)
Portable wrapper for the fork() function.
Definition: Os.cpp:138
int main()
yarp::os::ConstString distribution
Definition: SystemInfo.h:82
int loop()
A single value (typically within a Bottle).
Definition: Value.h:36
const char * c_str() const
Accesses the character sequence stored in this object.
Definition: ConstString.cpp:88
return ret
Definition: IplImage.cpp:876
static bool connect(const ConstString &src, const ConstString &dest, const ConstString &carrier="", bool quiet=true)
Request that an output port connect to an input port.
Definition: Network.cpp:522
SPECIAL_COPY_BEGIN dest r
Definition: ImageCopy.cpp:50
size_t find(const ConstString &needle, size_t start=0) const
Find content in string.
virtual Value & find(const ConstString &key) const YARP_OVERRIDE
Gets a value corresponding to a given keyword.
Definition: Property.cpp:969
static int start(const ConstString &node, Property &command, ConstString &keyv)
Launch a yarprun server.
Definition: Run.cpp:3633
static void sigchld_handler(int sig)
Definition: Run.cpp:816
int loop()
static Logger & get()
Definition: Logger.cpp:19
#define WRITE_TO_PIPE
Definition: Run.cpp:55
static bool disconnect(const ConstString &src, const ConstString &dest, bool quiet=true)
Request that an output port disconnect from an input port.
Definition: Network.cpp:540
yarp::os::ConstString int2String(int x)
static int client(Property &config)
Send a property object to a run server, bundling up all the settings usually specified on the command...
Definition: Run.cpp:1224
virtual bool check(const ConstString &key) const YARP_OVERRIDE
Check if there exists a property of the given name.
Definition: Bottle.cpp:212
#define READ_FROM_PIPE
Definition: Run.cpp:54
Value & get(int index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:181
virtual void write(const Bytes &b) override