YARP  2.3.70.1
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  write(fd, &len, 4);
776  write(fd, str.c_str(), len);
777 }
778 
779 int yarp::os::Run::readFromPipe(int fd, char* &data, int& buffsize)
780 {
781  int len=0;
782  char* buff=(char*)&len;
783 
784  for (int c=4, r=0; c>0; c-=r)
785  {
786  r=read(fd, buff, c);
787 
788  if (r<1) return -1;
789 
790  buff+=r;
791  }
792 
793  if (len<=0) return 0;
794 
795  if (len>buffsize)
796  {
797  delete [] data;
798  data=new char[buffsize=1024+(len/1024)*1024];
799  }
800 
801  buff=data;
802 
803  for (int c=len, r=0; c>0; c-=r)
804  {
805  r=read(fd, buff, c);
806 
807  if (r<1) return -1;
808 
809  buff+=r;
810  }
811 
812  return len;
813 }
814 
815 static void sigchld_handler(int sig)
816 {
817  if (yarp::os::Run::mBraveZombieHunter)
818  {
819  yarp::os::Run::mBraveZombieHunter->sigchldHandler();
820  }
821 }
822 
823 int yarp::os::Run::server()
824 {
825  int pipe_server2manager[2];
826  int pipe_manager2server[2];
827 
828  if (yarp::os::impl::pipe(pipe_server2manager))
829  {
830  fprintf(stderr, "Can't open pipe because %s\n", strerror(errno));
831  fflush(stderr);
832 
833  return YARPRUN_ERROR;
834  }
835 
836  if (yarp::os::impl::pipe(pipe_manager2server))
837  {
838  fprintf(stderr, "Can't open pipe because %s\n", strerror(errno));
839  fflush(stderr);
840 
841  return YARPRUN_ERROR;
842  }
843 
844  int pid_process_manager=yarp::os::fork();
845 
846  if (IS_INVALID(pid_process_manager))
847  {
848  int error=errno;
849 
850  CLOSE(pipe_server2manager[WRITE_TO_PIPE]);
851  CLOSE(pipe_server2manager[READ_FROM_PIPE]);
852  CLOSE(pipe_manager2server[WRITE_TO_PIPE]);
853  CLOSE(pipe_manager2server[READ_FROM_PIPE]);
854 
855  fprintf(stderr, "Can't fork process manager because %s\n", strerror(error));
856  fflush(stderr);
857 
858  return YARPRUN_ERROR;
859  }
860 
861  if (IS_PARENT_OF(pid_process_manager))
862  {
863  yarp::os::impl::signal(SIGPIPE, SIG_IGN);
864 
865  CLOSE(pipe_server2manager[READ_FROM_PIPE]);
866  CLOSE(pipe_manager2server[WRITE_TO_PIPE]);
867 
868  //yarp::os::Network::init();
870 
871  yarp::os::RpcServer port;
872 
873  if (!port.open(mPortName.c_str()))
874  {
875  yError() << "Yarprun failed to open port: " << mPortName.c_str();
876 
877  if (mPortName[0]!='/') yError("Invalid port name '%s', it should start with '/'\n", mPortName.c_str());
878  return YARPRUN_ERROR;
879  }
880  yInfo() << "Yarprun succesfully started on port: " << mPortName.c_str();
881 
882  pServerPort=&port;
883 
886 
887  int rsp_size=1024;
888  char *rsp_str=new char[rsp_size];
889 
890  Bottle msg, response;
891 
892  while (pServerPort)
893  {
894  RUNLOG("<<<port.read(msg, true)")
895  if (!port.read(msg, true)) break;
896  RUNLOG(">>>port.read(msg, true)")
897 
898  if (!pServerPort) break;
899 
900  if (msg.check("sysinfo"))
901  {
903  port.reply(sysinfo);
904  continue;
905  }
906 
907  if (msg.check("which"))
908  {
909  ConstString fileName=msg.find("which").asString();
910  if (fileName!="")
911  {
913  for (int i=0; i<possiblePaths.size(); ++i)
914  {
915  ConstString guessString=possiblePaths.get(i).asString() + slash + fileName;
916  const char* guess=guessString.c_str();
917  if (fileExists (guess))
918  {
919  fileName = guess;
920  break;
921  }
922  }
923  }
924  yarp::os::Value fileNameWriter(fileName);
925  port.reply(fileNameWriter);
926  continue;
927  }
928 
929  if (msg.check("exit"))
930  {
931  pServerPort = YARP_NULLPTR;
932  Bottle result;
933  result.addString("exit OK");
934  port.reply(result);
935  port.close();
936  break;
937  }
938 
939  RUNLOG("<<<writeToPipe")
940  writeToPipe(pipe_server2manager[WRITE_TO_PIPE], msg.toString());
941  RUNLOG(">>>writeToPipe")
942 
943  RUNLOG("<<<readFromPipe")
944  int nread=readFromPipe(pipe_manager2server[READ_FROM_PIPE], rsp_str, rsp_size);
945  RUNLOG(">>>readFromPipe")
946 
947  if (nread<0)
948  {
949  fprintf(stderr, "ERROR: broken pipe between server and manager\n");
950  fflush(stderr);
951  break;
952  }
953 
954  if (nread)
955  {
956  response.fromString(rsp_str);
957  port.reply(response);
958  }
959  }
960 
961  //yarp::os::Network::fini();
962 
963  CLOSE(pipe_server2manager[WRITE_TO_PIPE]);
964  CLOSE(pipe_manager2server[READ_FROM_PIPE]);
965 
966  delete [] rsp_str;
967 
968  return 0;
969  }
970 
971  if (IS_NEW_PROCESS(pid_process_manager))
972  {
973  yarp::os::impl::signal(SIGPIPE, SIG_IGN);
974 
975  CLOSE(pipe_server2manager[WRITE_TO_PIPE]);
976  CLOSE(pipe_manager2server[READ_FROM_PIPE]);
977 
978  //yarp::os::Network::init();
979 
980  mProcessVector=new YarpRunInfoVector;
981  mStdioVector=new YarpRunInfoVector;
982 
983  mBraveZombieHunter=new ZombieHunterThread;
984  mBraveZombieHunter->start();
985 
987  //yarp::os::impl::signal(SIGINT, SIG_IGN);
988  //yarp::os::impl::signal(SIGTERM, SIG_IGN);
989 
990  int msg_size=1024;
991  char *msg_str=new char[msg_size];
992 
993  Bottle msg;
994 
995  //while(readFromPipe(pipe_server2manager[READ_FROM_PIPE], msg_str, msg_size)>0)
996  while (true)
997  {
998  RUNLOG("<<<readFromPipe")
999  if (readFromPipe(pipe_server2manager[READ_FROM_PIPE], msg_str, msg_size)<=0) break;
1000  RUNLOG(">>>readFromPipe")
1001 
1002  //printf("<<< %s >>>\n", msg_str);
1003  //fflush(stdout);
1004 
1005  msg.fromString(msg_str);
1006 
1007  // command with stdio management
1008  if (msg.check("stdio"))
1009  {
1010  yarp::os::ConstString strOnPort=msg.find("on").asString();
1011  yarp::os::ConstString strStdioPort=msg.find("stdio").asString();
1012 
1013  if (strOnPort==mPortName)
1014  {
1015  yarp::os::ConstString strUUID=mPortName+"/"+int2String(getpid())+"/"+msg.find("as").asString()+"-"+int2String(mProcCNT++);
1016  Bottle botUUID;
1017  botUUID.addString("stdiouuid");
1018  botUUID.addString(strUUID.c_str());
1019  msg.addList()=botUUID;
1020 
1021  if (mLogged || msg.check("log"))
1022  {
1023  yarp::os::ConstString strAlias=msg.find("as").asString();
1024  yarp::os::ConstString portName="/log";
1025  portName+=mPortName+"/";
1026  yarp::os::ConstString command=msg.findGroup("cmd").get(1).asString();
1027  size_t space=command.find(' ');
1028  if (space!=ConstString::npos) command=command.substr(0, space);
1029  portName+=command;
1030 
1031  Bottle botFwd;
1032  botFwd.addString("forward");
1033  botFwd.addString(portName.c_str());
1034  if (msg.check("log"))
1035  {
1036  yarp::os::Bottle botLogger=msg.findGroup("log");
1037 
1038  if (botLogger.size()>1)
1039  {
1040  botFwd.addString(botLogger.get(1).asString());
1041  }
1042  else
1043  {
1044  botFwd.addString(mLoggerPort);
1045  }
1046  }
1047  else
1048  {
1049  botFwd.addString(mLoggerPort);
1050  }
1051  msg.addList()=botFwd;
1052 
1053  yarp::os::ContactStyle style;
1054  style.persistent=true;
1055  yarp::os::Network::connect(portName.c_str(), mLoggerPort.c_str(), style);
1056  }
1057 
1058  Bottle cmdResult;
1059  if (executeCmdAndStdio(msg, cmdResult)>0)
1060  {
1061  if (strStdioPort==mPortName)
1062  {
1063  Bottle stdioResult;
1064  userStdio(msg, stdioResult);
1065  cmdResult.append(stdioResult);
1066  }
1067  else
1068  {
1069  cmdResult.append(sendMsg(msg, strStdioPort));
1070  }
1071  }
1072 
1073  RUNLOG("<<<writeToPipe")
1074  writeToPipe(pipe_manager2server[WRITE_TO_PIPE], cmdResult.toString());
1075  RUNLOG(">>>writeToPipe")
1076  }
1077  else
1078  {
1079  Bottle stdioResult;
1080  userStdio(msg, stdioResult);
1081  RUNLOG("<<<writeToPipe")
1082  writeToPipe(pipe_manager2server[WRITE_TO_PIPE], stdioResult.toString());
1083  RUNLOG(">>>writeToPipe")
1084  }
1085 
1086  continue;
1087  }
1088 
1089  // without stdio
1090  if (msg.check("cmd"))
1091  {
1092  Bottle cmdResult;
1093 
1094  if (msg.check("log"))
1095  {
1096  yarp::os::Bottle botLogger=msg.findGroup("log");
1097 
1098  if (botLogger.size()>1)
1099  {
1100  yarp::os::ConstString loggerName=botLogger.get(1).asString();
1101  executeCmdStdout(msg, cmdResult, loggerName);
1102  }
1103  else
1104  {
1105  executeCmdStdout(msg, cmdResult, mLoggerPort);
1106  }
1107  }
1108  else if (mLogged)
1109  {
1110  executeCmdStdout(msg, cmdResult, mLoggerPort);
1111  }
1112  else
1113  {
1114  executeCmd(msg, cmdResult);
1115  }
1116 
1117  RUNLOG("<<<writeToPipe")
1118  writeToPipe(pipe_manager2server[WRITE_TO_PIPE], cmdResult.toString());
1119  RUNLOG(">>>writeToPipe")
1120  continue;
1121  }
1122 
1123  if (msg.check("kill"))
1124  {
1125  yarp::os::ConstString alias(msg.findGroup("kill").get(1).asString());
1126  int sig=msg.findGroup("kill").get(2).asInt();
1127  Bottle result;
1128  result.addString(mProcessVector->Signal(alias, sig)?"kill OK":"kill FAILED");
1129  RUNLOG("<<<writeToPipe")
1130  writeToPipe(pipe_manager2server[WRITE_TO_PIPE], result.toString());
1131  RUNLOG(">>>writeToPipe")
1132  continue;
1133  }
1134 
1135  if (msg.check("sigterm"))
1136  {
1137  yarp::os::ConstString alias(msg.find("sigterm").asString());
1138  Bottle result;
1139  result.addString(mProcessVector->Signal(alias, SIGTERM)?"sigterm OK":"sigterm FAILED");
1140  RUNLOG("<<<writeToPipe")
1141  writeToPipe(pipe_manager2server[WRITE_TO_PIPE], result.toString());
1142  RUNLOG(">>>writeToPipe")
1143  continue;
1144  }
1145 
1146  if (msg.check("sigtermall"))
1147  {
1148  mProcessVector->Killall(SIGTERM);
1149  Bottle result;
1150  result.addString("sigtermall OK");
1151 
1152  RUNLOG("<<<writeToPipe")
1153  writeToPipe(pipe_manager2server[WRITE_TO_PIPE], result.toString());
1154  RUNLOG(">>>writeToPipe")
1155  continue;
1156  }
1157 
1158  if (msg.check("ps"))
1159  {
1160  Bottle result;
1161  result.append(mProcessVector->PS());
1162  RUNLOG("<<<writeToPipe")
1163  writeToPipe(pipe_manager2server[WRITE_TO_PIPE], result.toString());
1164  RUNLOG(">>>writeToPipe")
1165  continue;
1166  }
1167 
1168  if (msg.check("isrunning"))
1169  {
1170  yarp::os::ConstString alias(msg.find("isrunning").asString());
1171  Bottle result;
1172  result.addString(mProcessVector->IsRunning(alias)?"running":"not running");
1173  RUNLOG("<<<writeToPipe")
1174  writeToPipe(pipe_manager2server[WRITE_TO_PIPE], result.toString());
1175  RUNLOG(">>>writeToPipe")
1176  continue;
1177  }
1178 
1179  if (msg.check("killstdio"))
1180  {
1181  yarp::os::ConstString alias(msg.find("killstdio").asString());
1182  mStdioVector->Signal(alias, SIGTERM);
1183  Bottle result;
1184  result.addString("killstdio OK");
1185  RUNLOG("<<<writeToPipe")
1186  writeToPipe(pipe_manager2server[WRITE_TO_PIPE], result.toString());
1187  RUNLOG(">>>writeToPipe")
1188  continue;
1189  }
1190  }
1191 
1192  mStdioVector->Killall(SIGTERM);
1193 
1194  mProcessVector->Killall(SIGTERM);
1195 
1196  if (mBraveZombieHunter)
1197  {
1198  mBraveZombieHunter->stop();
1199  delete mBraveZombieHunter;
1200  mBraveZombieHunter = YARP_NULLPTR;
1201  }
1202 
1203  delete mProcessVector;
1204 
1205  delete mStdioVector;
1206 
1207  //yarp::os::Network::fini();
1208 
1209  CLOSE(pipe_server2manager[READ_FROM_PIPE]);
1210  CLOSE(pipe_manager2server[WRITE_TO_PIPE]);
1211 
1212  delete [] msg_str;
1213  }
1214 
1215  return 0;
1216 } // LINUX SERVER
1217 #endif
1218 
1219 
1220 
1221 
1222 // CLIENT
1224 {
1225  // WITH STDIO
1226  //
1227  if (config.check("cmd") && config.check("stdio"))
1228  {
1230  // syntax check
1231  if (config.find("stdio").asString()=="")
1232  {
1233  Help("SYNTAX ERROR: missing remote stdio server\n");
1234  return YARPRUN_ERROR;
1235  }
1236  if (config.find("cmd").asString()=="")
1237  {
1238  Help("SYNTAX ERROR: missing command\n");
1239  return YARPRUN_ERROR;
1240  }
1241  if (!config.check("as") || config.find("as").asString()=="")
1242  {
1243  Help("SYNTAX ERROR: missing tag\n");
1244  return YARPRUN_ERROR;
1245  }
1246  if (!config.check("on") || config.find("on").asString()=="")
1247  {
1248  Help("SYNTAX ERROR: missing remote server\n");
1249  return YARPRUN_ERROR;
1250  }
1251  //
1253 
1254  printf("*********** %s ************\n", config.toString().c_str());
1255 
1256  yarp::os::Bottle msg;
1257  msg.addList()=config.findGroup("stdio");
1258  msg.addList()=config.findGroup("cmd");
1259  msg.addList()=config.findGroup("as");
1260  msg.addList()=config.findGroup("on");
1261 
1262  if (config.check("workdir")) msg.addList()=config.findGroup("workdir");
1263  if (config.check("geometry")) msg.addList()=config.findGroup("geometry");
1264  if (config.check("hold")) msg.addList()=config.findGroup("hold");
1265  if (config.check("env")) msg.addList()=config.findGroup("env");
1266  if (config.check("log")) msg.addList()=config.findGroup("log");
1267  /*
1268  {
1269  Bottle log;
1270  log.addString("log");
1271  log.addString("log");
1272  msg.addList()=log;
1273  }
1274  */
1275 
1276  ConstString on=config.find("on").asString();
1277 
1278  Bottle response=sendMsg(msg, on);
1279 
1280  if (!response.size()) return YARPRUN_ERROR;
1281 
1282  if (response.get(0).asInt()<=0) return 2;
1283 
1284  return 0;
1285  }
1286 
1287  // NO STDIO
1288  //
1289  if (config.check("cmd"))
1290  {
1292  // syntax check
1293  if (config.find("cmd").asString()=="")
1294  {
1295  Help("SYNTAX ERROR: missing command\n");
1296  return YARPRUN_ERROR;
1297  }
1298  if (!config.check("as") || config.find("as").asString()=="")
1299  {
1300  Help("SYNTAX ERROR: missing tag\n");
1301  return YARPRUN_ERROR;
1302  }
1303  if (!config.check("on") || config.find("on").asString()=="")
1304  {
1305  Help("SYNTAX ERROR: missing remote server\n");
1306  return YARPRUN_ERROR;
1307  }
1308  //
1310 
1311  yarp::os::Bottle msg;
1312  msg.addList()=config.findGroup("cmd");
1313  msg.addList()=config.findGroup("as");
1314 
1315  if (config.check("workdir")) msg.addList()=config.findGroup("workdir");
1316  if (config.check("log")) msg.addList()=config.findGroup("log");
1317  /*
1318  {
1319  Bottle log;
1320  log.addString("log");
1321  log.addString("log");
1322  msg.addList()=log;
1323  }
1324  */
1325  if (config.check("env")) msg.addList()=config.findGroup("env");
1326 
1327  Bottle response=sendMsg(msg, config.find("on").asString());
1328 
1329  if (!response.size()) return YARPRUN_ERROR;
1330 
1331  if (response.get(0).asInt()<=0) return 2;
1332 
1333  return 0;
1334  }
1335 
1336 
1337 
1338 
1339 
1340  // client -> cmd server
1341  if (config.check("kill"))
1342  {
1343  if (!config.check("on") || config.find("on").asString()=="")
1344  {
1345  Help("SYNTAX ERROR: missing remote server\n");
1346  return YARPRUN_ERROR;
1347  }
1348  if (config.findGroup("kill").get(1).asString()=="")
1349  {
1350  Help("SYNTAX ERROR: missing tag\n");
1351  return YARPRUN_ERROR;
1352  }
1353  if (config.findGroup("kill").get(2).asInt()==0)
1354  {
1355  Help("SYNTAX ERROR: missing signum\n");
1356  return YARPRUN_ERROR;
1357  }
1358 
1359  yarp::os::Bottle msg;
1360  msg.addList()=config.findGroup("kill");
1361 
1362  Bottle response=sendMsg(msg, config.find("on").asString());
1363 
1364  if (!response.size())
1365  {
1366  return YARPRUN_ERROR;
1367  }
1368 
1369  return response.get(0).asString()=="kill OK"?0:2;
1370  }
1371 
1372  // client -> cmd server
1373  if (config.check("sigterm"))
1374  {
1375  if (config.find("sigterm").asString()=="")
1376  {
1377  Help("SYNTAX ERROR: missing tag");
1378  return YARPRUN_ERROR;
1379  }
1380  if (!config.check("on") || config.find("on").asString()=="")
1381  {
1382  Help("SYNTAX ERROR: missing remote server\n");
1383  return YARPRUN_ERROR;
1384  }
1385 
1386  yarp::os::Bottle msg;
1387  msg.addList()=config.findGroup("sigterm");
1388 
1389  Bottle response=sendMsg(msg, config.find("on").asString());
1390 
1391  if (!response.size())
1392  {
1393  return YARPRUN_ERROR;
1394  }
1395 
1396  return response.get(0).asString()=="sigterm OK"?0:2;
1397  }
1398 
1399  // client -> cmd server
1400  if (config.check("sigtermall"))
1401  {
1402  if (!config.check("on") || config.find("on").asString()=="")
1403  {
1404  Help("SYNTAX ERROR: missing remote server\n");
1405  return YARPRUN_ERROR;
1406  }
1407 
1408  yarp::os::Bottle msg;
1409  msg.addList()=config.findGroup("sigtermall");
1410 
1411  Bottle response=sendMsg(msg, config.find("on").asString());
1412 
1413  if (!response.size())
1414  {
1415  return YARPRUN_ERROR;
1416  }
1417 
1418  return 0;
1419  }
1420 
1421  if (config.check("ps"))
1422  {
1423  if (!config.check("on") || config.find("on").asString()=="")
1424  {
1425  Help("SYNTAX ERROR: missing remote server\n");
1426  return YARPRUN_ERROR;
1427  }
1428 
1429  yarp::os::Bottle msg;
1430  msg.addList()=config.findGroup("ps");
1431 
1432  Bottle response=sendMsg(msg, config.find("on").asString());
1433 
1434  if (!response.size())
1435  {
1436  return YARPRUN_ERROR;
1437  }
1438 
1439  return 0;
1440  }
1441 
1442  if (config.check("isrunning"))
1443  {
1444  if (!config.check("on") || config.find("on").asString()=="")
1445  {
1446  Help("SYNTAX ERROR: missing remote server\n");
1447  return YARPRUN_ERROR;
1448  }
1449 
1450  if (config.find("isrunning").asString()=="")
1451  {
1452  Help("SYNTAX ERROR: missing tag\n");
1453  return YARPRUN_ERROR;
1454  }
1455 
1456  yarp::os::Bottle msg;
1457  msg.addList()=config.findGroup("isrunning");
1458 
1459  Bottle response=sendMsg(msg, config.find("on").asString());
1460 
1461  if (!response.size())
1462  {
1463  return YARPRUN_ERROR;
1464  }
1465 
1466  return response.get(0).asString()=="running"?0:2;
1467  }
1468 
1469  if (config.check("sysinfo"))
1470  {
1471  if (!config.check("on") || config.find("on").asString()=="")
1472  {
1473  Help("SYNTAX ERROR: missing remote server\n");
1474  return YARPRUN_ERROR;
1475  }
1476 
1477  yarp::os::Bottle msg;
1478  msg.addList()=config.findGroup("sysinfo");
1479 
1480  yarp::os::RpcClient port;
1481  //port.setTimeout(5.0);
1482  if (!port.open("..."))
1483  {
1484  fprintf(stderr, "RESPONSE:\n=========\n");
1485  fprintf(stderr, "Cannot open port, aborting...\n");
1486 
1487  return YARPRUN_ERROR;
1488  }
1489 
1490  bool connected = yarp::os::Network::connect(port.getName(), config.find("on").asString());
1491 
1492  if (!connected)
1493  {
1494  fprintf(stderr, "RESPONSE:\n=========\n");
1495  fprintf(stderr, "Cannot connect to remote server, aborting...\n");
1496  port.close();
1497  //yarp::os::Network::unregisterName(port.getName());
1498  return YARPRUN_ERROR;
1499  }
1500 
1502 
1503  RUNLOG("<<<port.write(msg, info)")
1504  int ret = port.write(msg, info);
1505  RUNLOG(">>>port.write(msg, info)")
1506  yarp::os::Network::disconnect(port.getName().c_str(), config.find("on").asString());
1507  port.close();
1508  //yarp::os::Network::unregisterName(port.getName());
1509  fprintf(stdout, "RESPONSE:\n=========\n\n");
1510 
1511  if (!ret)
1512  {
1513  fprintf(stdout, "No response. (timeout)\n");
1514 
1515  return YARPRUN_ERROR;
1516  }
1517 
1518  fprintf(stdout, "Platform name : %s\n", info.platform.name.c_str());
1519  fprintf(stdout, "Platform dist : %s\n", info.platform.distribution.c_str());
1520  fprintf(stdout, "Platform release : %s\n", info.platform.release.c_str());
1521  fprintf(stdout, "Platform code : %s\n", info.platform.codename.c_str());
1522  fprintf(stdout, "Platform kernel : %s\n\n", info.platform.kernel.c_str());
1523 
1524  fprintf(stdout, "User Id : %d\n", info.user.userID);
1525  fprintf(stdout, "User name : %s\n", info.user.userName.c_str());
1526  fprintf(stdout, "User real name : %s\n", info.user.realName.c_str());
1527  fprintf(stdout, "User home dir : %s\n\n", info.user.homeDir.c_str());
1528 
1529  fprintf(stdout, "Cpu load Ins.: %d\n", info.load.cpuLoadInstant);
1530  fprintf(stdout, "Cpu load 1 : %.2lf\n", info.load.cpuLoad1);
1531  fprintf(stdout, "Cpu load 5 : %.2lf\n", info.load.cpuLoad5);
1532  fprintf(stdout, "Cpu load 15 : %.2lf\n\n", info.load.cpuLoad15);
1533 
1534  fprintf(stdout, "Memory total : %dM\n", info.memory.totalSpace);
1535  fprintf(stdout, "Memory free : %dM\n\n", info.memory.freeSpace);
1536 
1537  fprintf(stdout, "Storage total : %dM\n", info.storage.totalSpace);
1538  fprintf(stdout, "Storage free : %dM\n\n", info.storage.freeSpace);
1539 
1540  fprintf(stdout, "Processor model : %s\n", info.processor.model.c_str());
1541  fprintf(stdout, "Processor model num : %d\n", info.processor.modelNumber);
1542  fprintf(stdout, "Processor family : %d\n", info.processor.family);
1543  fprintf(stdout, "Processor vendor : %s\n", info.processor.vendor.c_str());
1544  fprintf(stdout, "Processor arch : %s\n", info.processor.architecture.c_str());
1545  fprintf(stdout, "Processor cores : %d\n", info.processor.cores);
1546  fprintf(stdout, "Processor siblings : %d\n", info.processor.siblings);
1547  fprintf(stdout, "Processor Mhz : %.2lf\n\n", info.processor.frequency);
1548 
1549  fprintf(stdout, "Environment variables :\n%s\n", info.platform.environmentVars.toString().c_str());
1550  //fprintf(stdout, "Network IP4 : %s\n", info.network.ip4.c_str());
1551  //fprintf(stdout, "Network IP6 : %s\n", info.network.ip6.c_str());
1552  //fprintf(stdout, "Network mac : %s\n\n", info.network.mac.c_str());
1553 
1554  return 0;
1555  }
1556 
1557  if (config.check("which"))
1558  {
1559  if (!config.check("on") || config.find("on").asString()=="")
1560  {
1561  Help("SYNTAX ERROR: missing remote server\n");
1562 
1563  return YARPRUN_ERROR;
1564  }
1565 
1566  yarp::os::Bottle msg;
1567  msg.addList()=config.findGroup("which");
1568 
1569  Bottle response=sendMsg(msg, config.find("on").asString());
1570 
1571  if (!response.size())
1572  {
1573  return YARPRUN_ERROR;
1574  }
1575  return 0;
1576  }
1577 
1578  if (config.check("exit"))
1579  {
1580  if (!config.check("on") || config.find("on").asString()=="")
1581  {
1582  Help("SYNTAX ERROR: missing remote server\n");
1583 
1584  return YARPRUN_ERROR;
1585  }
1586 
1587  yarp::os::Bottle msg;
1588  msg.addList()=config.findGroup("exit");
1589 
1590  Bottle response=sendMsg(msg, config.find("on").asString());
1591 
1592  if (!response.size())
1593  {
1594  return YARPRUN_ERROR;
1595  }
1596 
1597  return 0;
1598  }
1599 
1600  return 0;
1601 }
1602 
1603 void yarp::os::Run::Help(const char *msg)
1604 {
1605  fprintf(stderr, "%s", msg);
1606  fprintf(stderr, "\nUSAGE:\n\n");
1607  fprintf(stderr, "yarp run --server SERVERPORT\nrun a server on the local machine\n\n");
1608  fprintf(stderr, "yarp run --on SERVERPORT --as TAG --cmd COMMAND [ARGLIST] [--workdir WORKDIR] [--env ENVIRONMENT]\nrun a command on SERVERPORT server\n\n");
1609  fprintf(stderr, "yarp run --on SERVERPORT --as TAG --stdio STDIOSERVERPORT [--hold] [--geometry WxH+X+Y] --cmd COMMAND [ARGLIST] [--workdir WORKDIR] [--env ENVIRONMENT]\n");
1610  fprintf(stderr, "run a command on SERVERPORT server sending I/O to STDIOSERVERPORT server\n\n");
1611  fprintf(stderr, "yarp run --on SERVERPORT --kill TAG SIGNUM\nsend SIGNUM signal to TAG command\n\n");
1612  fprintf(stderr, "yarp run --on SERVERPORT --sigterm TAG\nterminate TAG command\n\n");
1613  fprintf(stderr, "yarp run --on SERVERPORT --sigtermall\nterminate all commands\n\n");
1614  fprintf(stderr, "yarp run --on SERVERPORT --ps\nreport commands running on SERVERPORT\n\n");
1615  fprintf(stderr, "yarp run --on SERVERPORT --isrunning TAG\nTAG command is running?\n\n");
1616  fprintf(stderr, "yarp run --on SERVERPORT --sysinfo\nreport system information of SERVERPORT\n\n");
1617  fprintf(stderr, "yarp run --on SERVERPORT --exit\nstop SERVERPORT server\n\n");
1618 }
1619 
1621 // OS DEPENDENT FUNCTIONS
1623 
1624 // WINDOWS
1625 
1626 #if defined(_WIN32)
1627 
1628 // CMD SERVER
1629 int yarp::os::Run::executeCmdAndStdio(Bottle& msg, Bottle& result)
1630 {
1631  yarp::os::ConstString strAlias=msg.find("as").asString();
1632  yarp::os::ConstString strStdio=msg.find("stdio").asString();
1633  yarp::os::ConstString strStdioUUID=msg.find("stdiouuid").asString();
1634  //yarp::os::ConstString strCmdUUID=mPortName+"/"+int2String(GetCurrentProcessId())+"/"+strAlias+"-"+int2String(mProcCNT++);
1635 
1636  // PIPES
1637  SECURITY_ATTRIBUTES pipe_sec_attr;
1638  pipe_sec_attr.nLength=sizeof(SECURITY_ATTRIBUTES);
1639  pipe_sec_attr.bInheritHandle=TRUE;
1640  pipe_sec_attr.lpSecurityDescriptor = YARP_NULLPTR;
1641  HANDLE read_from_pipe_stdin_to_cmd, write_to_pipe_stdin_to_cmd;
1642  CreatePipe(&read_from_pipe_stdin_to_cmd, &write_to_pipe_stdin_to_cmd, &pipe_sec_attr, 0);
1643  HANDLE read_from_pipe_cmd_to_stdout, write_to_pipe_cmd_to_stdout;
1644  CreatePipe(&read_from_pipe_cmd_to_stdout, &write_to_pipe_cmd_to_stdout, &pipe_sec_attr, 0);
1645 
1646  // RUN STDOUT
1647  PROCESS_INFORMATION stdout_process_info;
1648  ZeroMemory(&stdout_process_info, sizeof(PROCESS_INFORMATION));
1649  STARTUPINFO stdout_startup_info;
1650  ZeroMemory(&stdout_startup_info, sizeof(STARTUPINFO));
1651 
1652  stdout_startup_info.cb=sizeof(STARTUPINFO);
1653  stdout_startup_info.hStdError=GetStdHandle(STD_ERROR_HANDLE);
1654  stdout_startup_info.hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE);
1655  stdout_startup_info.hStdInput=read_from_pipe_cmd_to_stdout;
1656  stdout_startup_info.dwFlags|=STARTF_USESTDHANDLES;
1657 
1658  BOOL bSuccess=CreateProcess(YARP_NULLPTR, // command name
1659  (char*)(yarp::os::ConstString("yarprun --write ")+strStdioUUID).c_str(), // command line
1660  YARP_NULLPTR, // process security attributes
1661  YARP_NULLPTR, // primary thread security attributes
1662  TRUE, // handles are inherited
1663  CREATE_NEW_PROCESS_GROUP, // creation flags
1664  YARP_NULLPTR, // use parent's environment
1665  YARP_NULLPTR, // use parent's current directory
1666  &stdout_startup_info, // STARTUPINFO pointer
1667  &stdout_process_info); // receives PROCESS_INFORMATION
1668 
1669  if (!bSuccess)
1670  {
1671  yarp::os::ConstString strError=yarp::os::ConstString("ABORTED: server=")+mPortName
1672  +yarp::os::ConstString(" alias=")+strAlias
1673  +yarp::os::ConstString(" cmd=stdout\n")
1674  +yarp::os::ConstString("Can't execute stdout because ")+lastError2String()
1675  +yarp::os::ConstString("\n");
1676 
1677  result.addInt(YARPRUN_ERROR);
1678  result.addString(strError.c_str());
1679  fprintf(stderr, "%s", strError.c_str());
1680  fflush(stderr);
1681 
1682  CloseHandle(write_to_pipe_stdin_to_cmd);
1683  CloseHandle(read_from_pipe_stdin_to_cmd);
1684  CloseHandle(write_to_pipe_cmd_to_stdout);
1685  CloseHandle(read_from_pipe_cmd_to_stdout);
1686 
1687  return YARPRUN_ERROR;
1688  }
1689 
1690  // RUN STDIN
1691 
1692  PROCESS_INFORMATION stdin_process_info;
1693  ZeroMemory(&stdin_process_info, sizeof(PROCESS_INFORMATION));
1694  STARTUPINFO stdin_startup_info;
1695  ZeroMemory(&stdin_startup_info, sizeof(STARTUPINFO));
1696 
1697  stdin_startup_info.cb=sizeof(STARTUPINFO);
1698  stdin_startup_info.hStdError=write_to_pipe_stdin_to_cmd;
1699  stdin_startup_info.hStdOutput=write_to_pipe_stdin_to_cmd;
1700  stdin_startup_info.hStdInput=GetStdHandle(STD_INPUT_HANDLE);
1701  stdin_startup_info.dwFlags|=STARTF_USESTDHANDLES;
1702 
1703  bSuccess=CreateProcess(YARP_NULLPTR, // command name
1704  (char*)(yarp::os::ConstString("yarprun --read ")+strStdioUUID).c_str(), // command line
1705  YARP_NULLPTR, // process security attributes
1706  YARP_NULLPTR, // primary thread security attributes
1707  TRUE, // handles are inherited
1708  CREATE_NEW_PROCESS_GROUP, // creation flags
1709  YARP_NULLPTR, // use parent's environment
1710  YARP_NULLPTR, // use parent's current directory
1711  &stdin_startup_info, // STARTUPINFO pointer
1712  &stdin_process_info); // receives PROCESS_INFORMATION
1713 
1714  if (!bSuccess)
1715  {
1716  yarp::os::ConstString strError=yarp::os::ConstString("ABORTED: server=")+mPortName
1717  +yarp::os::ConstString(" alias=")+strAlias
1718  +yarp::os::ConstString(" cmd=stdin\n")
1719  +yarp::os::ConstString("Can't execute stdin because ")+lastError2String()
1720  +yarp::os::ConstString("\n");
1721 
1722  result.addInt(YARPRUN_ERROR);
1723  result.addString(strError.c_str());
1724  fprintf(stderr, "%s", strError.c_str());
1725 
1726  TerminateProcess(stdout_process_info.hProcess, YARPRUN_ERROR);
1727 
1728  CloseHandle(stdout_process_info.hProcess);
1729 
1730  CloseHandle(write_to_pipe_stdin_to_cmd);
1731  CloseHandle(read_from_pipe_stdin_to_cmd);
1732  CloseHandle(write_to_pipe_cmd_to_stdout);
1733  CloseHandle(read_from_pipe_cmd_to_stdout);
1734 
1735  return YARPRUN_ERROR;
1736  }
1737 
1738  // RUN COMMAND
1739 
1740  PROCESS_INFORMATION cmd_process_info;
1741  ZeroMemory(&cmd_process_info, sizeof(PROCESS_INFORMATION));
1742  STARTUPINFO cmd_startup_info;
1743  ZeroMemory(&cmd_startup_info, sizeof(STARTUPINFO));
1744 
1745  cmd_startup_info.cb=sizeof(STARTUPINFO);
1746  cmd_startup_info.hStdError=write_to_pipe_cmd_to_stdout;
1747  cmd_startup_info.hStdOutput=write_to_pipe_cmd_to_stdout;
1748  cmd_startup_info.hStdInput=read_from_pipe_stdin_to_cmd;
1749  cmd_startup_info.dwFlags|=STARTF_USESTDHANDLES;
1750 
1751  Bottle botCmd=msg.findGroup("cmd").tail();
1752 
1753  yarp::os::ConstString strCmd;
1754  for (int s=0; s<botCmd.size(); ++s)
1755  {
1756  strCmd+=botCmd.get(s).toString()+yarp::os::ConstString(" ");
1757  }
1758 
1759  /*
1760  * setting environment variable for child process
1761  */
1762  TCHAR chNewEnv[32767];
1763 
1764  // Get a pointer to the env block.
1765  LPTCH chOldEnv = GetEnvironmentStrings();
1766 
1767  // copying parent env variables
1768  LPTSTR lpOld = (LPTSTR) chOldEnv;
1769  LPTSTR lpNew = (LPTSTR) chNewEnv;
1770  while (*lpOld)
1771  {
1772  lstrcpy(lpNew, lpOld);
1773  lpOld += lstrlen(lpOld) + 1;
1774  lpNew += lstrlen(lpNew) + 1;
1775  }
1776 
1777  // adding new env variables
1778  yarp::os::ConstString cstrEnvName;
1779  if (msg.check("env"))
1780  {
1781  yarp::os::impl::SplitString ss(msg.find("env").asString().c_str(), ';');
1782  for(int i=0; i<ss.size(); i++) {
1783  lstrcpy(lpNew, (LPTCH) ss.get(i));
1784  lpNew += lstrlen(lpNew) + 1;
1785  }
1786  }
1787 
1788  // closing env block
1789  *lpNew = (TCHAR)0;
1790 
1791  bool bWorkdir=msg.check("workdir");
1792  yarp::os::ConstString strWorkdir=bWorkdir?msg.find("workdir").asString()+"\\":"";
1793 
1794  bSuccess=CreateProcess(YARP_NULLPTR, // command name
1795  (char*)(strWorkdir+strCmd).c_str(), // command line
1796  YARP_NULLPTR, // process security attributes
1797  YARP_NULLPTR, // primary thread security attributes
1798  TRUE, // handles are inherited
1799  CREATE_NEW_PROCESS_GROUP, // creation flags
1800  (LPVOID) chNewEnv, // use new environment list
1801  bWorkdir ? strWorkdir.c_str() : YARP_NULLPTR, // working directory
1802  &cmd_startup_info, // STARTUPINFO pointer
1803  &cmd_process_info); // receives PROCESS_INFORMATION
1804 
1805  if (!bSuccess && bWorkdir)
1806  {
1807  bSuccess=CreateProcess(YARP_NULLPTR, // command name
1808  (char*)(strCmd.c_str()), // command line
1809  YARP_NULLPTR, // process security attributes
1810  YARP_NULLPTR, // primary thread security attributes
1811  TRUE, // handles are inherited
1812  CREATE_NEW_PROCESS_GROUP, // creation flags
1813  (LPVOID) chNewEnv, // use new environment list
1814  strWorkdir.c_str(), // working directory
1815  &cmd_startup_info, // STARTUPINFO pointer
1816  &cmd_process_info); // receives PROCESS_INFORMATION
1817  }
1818 
1819  // deleting old environment variable
1820  FreeEnvironmentStrings(chOldEnv);
1821 
1822  if (!bSuccess)
1823  {
1824  result.addInt(YARPRUN_ERROR);
1825 
1826  DWORD nBytes;
1827  yarp::os::ConstString line1=yarp::os::ConstString("ABORTED: server=")+mPortName
1828  +yarp::os::ConstString(" alias=")+strAlias
1829  +yarp::os::ConstString(" cmd=")+strCmd
1830  +yarp::os::ConstString("pid=")+int2String(cmd_process_info.dwProcessId)
1831  +yarp::os::ConstString("\n");
1832 
1833  WriteFile(write_to_pipe_cmd_to_stdout, line1.c_str(), line1.length(), &nBytes, 0);
1834 
1835  yarp::os::ConstString line2=yarp::os::ConstString("Can't execute command because ")+lastError2String()+yarp::os::ConstString("\n");
1836  WriteFile(write_to_pipe_cmd_to_stdout, line1.c_str(), line2.length(), &nBytes, 0);
1837  FlushFileBuffers(write_to_pipe_cmd_to_stdout);
1838 
1839  yarp::os::ConstString out=line1+line2;
1840  result.addString(out.c_str());
1841  fprintf(stderr, "%s", out.c_str());
1842  fflush(stderr);
1843 
1844  CloseHandle(write_to_pipe_stdin_to_cmd);
1845  CloseHandle(read_from_pipe_stdin_to_cmd);
1846  CloseHandle(write_to_pipe_cmd_to_stdout);
1847  CloseHandle(read_from_pipe_cmd_to_stdout);
1848 
1849  TerminateProcess(stdout_process_info.hProcess, YARPRUN_ERROR);
1850 
1851  CloseHandle(stdout_process_info.hProcess);
1852 
1853  TerminateProcess(stdin_process_info.hProcess, YARPRUN_ERROR);
1854 
1855  CloseHandle(stdin_process_info.hProcess);
1856 
1857  return YARPRUN_ERROR;
1858  }
1859 
1860  FlushFileBuffers(write_to_pipe_cmd_to_stdout);
1861 
1862  // EVERYTHING IS ALL RIGHT
1863  YarpRunCmdWithStdioInfo* pInf = new YarpRunCmdWithStdioInfo(strAlias,
1864  mPortName,
1865  strStdio,
1866  cmd_process_info.dwProcessId,
1867  strStdioUUID,
1868  &mStdioVector,
1869  stdin_process_info.dwProcessId,
1870  stdout_process_info.dwProcessId,
1871  read_from_pipe_stdin_to_cmd,
1872  write_to_pipe_stdin_to_cmd,
1873  read_from_pipe_cmd_to_stdout,
1874  write_to_pipe_cmd_to_stdout,
1875  cmd_process_info.hProcess,
1876  false);
1877 
1878  pInf->setCmd(strCmd);
1879  if (msg.check("env"))
1880  {
1881  pInf->setEnv(msg.find("env").asString());
1882  }
1883  mProcessVector.Add(pInf);
1884 
1885  result.addInt(cmd_process_info.dwProcessId);
1886  yarp::os::ConstString out=yarp::os::ConstString("STARTED: server=")+mPortName
1887  +yarp::os::ConstString(" alias=")+strAlias
1888  +yarp::os::ConstString(" cmd=")+strCmd
1889  +yarp::os::ConstString("pid=")+int2String(cmd_process_info.dwProcessId)
1890  +yarp::os::ConstString("\n");
1891 
1892  result.addString(out.c_str());
1893  result.addString(strStdioUUID.c_str());
1894  fprintf(stderr, "%s", out.c_str());
1895 
1896  return cmd_process_info.dwProcessId;
1897 }
1898 
1899 int yarp::os::Run::executeCmdStdout(Bottle& msg, Bottle& result, yarp::os::ConstString& loggerName)
1900 {
1901  yarp::os::ConstString strAlias=msg.find("as").asString();
1902  yarp::os::ConstString portName="/log";
1903  portName+=mPortName+"/";
1904  yarp::os::ConstString command=msg.findGroup("cmd").get(1).asString();
1905  int space=command.find(" ");
1906  if (space!=ConstString::npos) command=command.substr(0, space);
1907  portName+=command;
1908 
1909  // PIPES
1910  SECURITY_ATTRIBUTES pipe_sec_attr;
1911  pipe_sec_attr.nLength=sizeof(SECURITY_ATTRIBUTES);
1912  pipe_sec_attr.bInheritHandle=TRUE;
1913  pipe_sec_attr.lpSecurityDescriptor = YARP_NULLPTR;
1914  HANDLE read_from_pipe_cmd_to_stdout, write_to_pipe_cmd_to_stdout;
1915  CreatePipe(&read_from_pipe_cmd_to_stdout, &write_to_pipe_cmd_to_stdout, &pipe_sec_attr, 0);
1916 
1917  // RUN STDOUT
1918  PROCESS_INFORMATION stdout_process_info;
1919  ZeroMemory(&stdout_process_info, sizeof(PROCESS_INFORMATION));
1920  STARTUPINFO stdout_startup_info;
1921  ZeroMemory(&stdout_startup_info, sizeof(STARTUPINFO));
1922 
1923  stdout_startup_info.cb=sizeof(STARTUPINFO);
1924  stdout_startup_info.hStdError=GetStdHandle(STD_ERROR_HANDLE);
1925  stdout_startup_info.hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE);
1926  stdout_startup_info.hStdInput=read_from_pipe_cmd_to_stdout;
1927  stdout_startup_info.dwFlags|=STARTF_USESTDHANDLES;
1928 
1929  BOOL bSuccess=CreateProcess(YARP_NULLPTR, // command name
1930  (char*)(yarp::os::ConstString("yarprun --log ")+loggerName+yarp::os::ConstString(" --write ")+portName).c_str(), // command line
1931  YARP_NULLPTR, // process security attributes
1932  YARP_NULLPTR, // primary thread security attributes
1933  TRUE, // handles are inherited
1934  CREATE_NEW_PROCESS_GROUP, // creation flags
1935  YARP_NULLPTR, // use parent's environment
1936  YARP_NULLPTR, // use parent's current directory
1937  &stdout_startup_info, // STARTUPINFO pointer
1938  &stdout_process_info); // receives PROCESS_INFORMATION
1939 
1940  if (!bSuccess)
1941  {
1942  yarp::os::ConstString strError=yarp::os::ConstString("ABORTED: server=")+mPortName
1943  +yarp::os::ConstString(" alias=")+strAlias
1944  +yarp::os::ConstString(" cmd=stdout\n")
1945  +yarp::os::ConstString("Can't execute stdout because ")+lastError2String()
1946  +yarp::os::ConstString("\n");
1947 
1948  result.addInt(YARPRUN_ERROR);
1949  result.addString(strError.c_str());
1950  fprintf(stderr, "%s", strError.c_str());
1951  fflush(stderr);
1952 
1953  CloseHandle(write_to_pipe_cmd_to_stdout);
1954  CloseHandle(read_from_pipe_cmd_to_stdout);
1955 
1956  return YARPRUN_ERROR;
1957  }
1958 
1959  // RUN COMMAND
1960 
1961  PROCESS_INFORMATION cmd_process_info;
1962  ZeroMemory(&cmd_process_info, sizeof(PROCESS_INFORMATION));
1963  STARTUPINFO cmd_startup_info;
1964  ZeroMemory(&cmd_startup_info, sizeof(STARTUPINFO));
1965 
1966  cmd_startup_info.cb=sizeof(STARTUPINFO);
1967  cmd_startup_info.hStdError=write_to_pipe_cmd_to_stdout;
1968  cmd_startup_info.hStdOutput=write_to_pipe_cmd_to_stdout;
1969  cmd_startup_info.hStdInput=GetStdHandle(STD_INPUT_HANDLE);
1970  cmd_startup_info.dwFlags|=STARTF_USESTDHANDLES;
1971 
1972  Bottle botCmd=msg.findGroup("cmd").tail();
1973 
1974  yarp::os::ConstString strCmd;
1975  for (int s=0; s<botCmd.size(); ++s)
1976  {
1977  strCmd+=botCmd.get(s).toString()+yarp::os::ConstString(" ");
1978  }
1979 
1980  /*
1981  * setting environment variable for child process
1982  */
1983  TCHAR chNewEnv[32767];
1984 
1985  // Get a pointer to the env block.
1986  LPTCH chOldEnv = GetEnvironmentStrings();
1987 
1988  // copying parent env variables
1989  LPTSTR lpOld = (LPTSTR) chOldEnv;
1990  LPTSTR lpNew = (LPTSTR) chNewEnv;
1991  while (*lpOld)
1992  {
1993  lstrcpy(lpNew, lpOld);
1994  lpOld += lstrlen(lpOld) + 1;
1995  lpNew += lstrlen(lpNew) + 1;
1996  }
1997 
1998  // adding new env variables
1999  yarp::os::ConstString cstrEnvName;
2000  if (msg.check("env"))
2001  {
2002  lstrcpy(lpNew, (LPTCH) msg.find("env").asString().c_str());
2003  lpNew += lstrlen(lpNew) + 1;
2004  }
2005 
2006  // closing env block
2007  *lpNew = (TCHAR)0;
2008 
2009  bool bWorkdir=msg.check("workdir");
2010  yarp::os::ConstString strWorkdir=bWorkdir?msg.find("workdir").asString()+"\\":"";
2011 
2012  bSuccess=CreateProcess(YARP_NULLPTR, // command name
2013  (char*)(strWorkdir+strCmd).c_str(), // command line
2014  YARP_NULLPTR, // process security attributes
2015  YARP_NULLPTR, // primary thread security attributes
2016  TRUE, // handles are inherited
2017  CREATE_NEW_PROCESS_GROUP, // creation flags
2018  (LPVOID) chNewEnv, // use new environment list
2019  bWorkdir?strWorkdir.c_str():YARP_NULLPTR, // working directory
2020  &cmd_startup_info, // STARTUPINFO pointer
2021  &cmd_process_info); // receives PROCESS_INFORMATION
2022 
2023  if (!bSuccess && bWorkdir)
2024  {
2025  bSuccess=CreateProcess(YARP_NULLPTR, // command name
2026  (char*)(strCmd.c_str()), // command line
2027  YARP_NULLPTR, // process security attributes
2028  YARP_NULLPTR, // primary thread security attributes
2029  TRUE, // handles are inherited
2030  CREATE_NEW_PROCESS_GROUP, // creation flags
2031  (LPVOID) chNewEnv, // use new environment list
2032  strWorkdir.c_str(), // working directory
2033  &cmd_startup_info, // STARTUPINFO pointer
2034  &cmd_process_info); // receives PROCESS_INFORMATION
2035  }
2036 
2037  // deleting old environment variable
2038  FreeEnvironmentStrings(chOldEnv);
2039 
2040  if (!bSuccess)
2041  {
2042  result.addInt(YARPRUN_ERROR);
2043 
2044  DWORD nBytes;
2045  yarp::os::ConstString line1=yarp::os::ConstString("ABORTED: server=")+mPortName
2046  +yarp::os::ConstString(" alias=")+strAlias
2047  +yarp::os::ConstString(" cmd=")+strCmd
2048  +yarp::os::ConstString("pid=")+int2String(cmd_process_info.dwProcessId)
2049  +yarp::os::ConstString("\n");
2050 
2051  WriteFile(write_to_pipe_cmd_to_stdout, line1.c_str(), line1.length(), &nBytes, 0);
2052 
2053  yarp::os::ConstString line2=yarp::os::ConstString("Can't execute command because ")+lastError2String()+yarp::os::ConstString("\n");
2054  WriteFile(write_to_pipe_cmd_to_stdout, line1.c_str(), line2.length(), &nBytes, 0);
2055  FlushFileBuffers(write_to_pipe_cmd_to_stdout);
2056 
2057  yarp::os::ConstString out=line1+line2;
2058  result.addString(out.c_str());
2059  fprintf(stderr, "%s", out.c_str());
2060  fflush(stderr);
2061 
2062  CloseHandle(write_to_pipe_cmd_to_stdout);
2063  CloseHandle(read_from_pipe_cmd_to_stdout);
2064 
2065  TerminateProcess(stdout_process_info.hProcess, YARPRUN_ERROR);
2066 
2067  CloseHandle(stdout_process_info.hProcess);
2068 
2069  return YARPRUN_ERROR;
2070  }
2071 
2072  FlushFileBuffers(write_to_pipe_cmd_to_stdout);
2073 
2074  // EVERYTHING IS ALL RIGHT
2075  YarpRunCmdWithStdioInfo* pInf = new YarpRunCmdWithStdioInfo(strAlias,
2076  mPortName,
2077  portName,
2078  cmd_process_info.dwProcessId,
2079  stdout_process_info.dwProcessId,
2080  read_from_pipe_cmd_to_stdout,
2081  write_to_pipe_cmd_to_stdout,
2082  cmd_process_info.hProcess,
2083  false);
2084 
2085 
2086 
2087 
2088  pInf->setCmd(strCmd);
2089  if (msg.check("env"))
2090  {
2091  pInf->setEnv(msg.find("env").asString());
2092  }
2093  mProcessVector.Add(pInf);
2094 
2095  result.addInt(cmd_process_info.dwProcessId);
2096  yarp::os::ConstString out=yarp::os::ConstString("STARTED: server=")+mPortName
2097  +yarp::os::ConstString(" alias=")+strAlias
2098  +yarp::os::ConstString(" cmd=")+strCmd
2099  +yarp::os::ConstString("pid=")+int2String(cmd_process_info.dwProcessId)
2100  +yarp::os::ConstString("\n");
2101 
2102  result.addString(out.c_str());
2103  result.addString(portName.c_str());
2104  fprintf(stderr, "%s", out.c_str());
2105 
2106  return cmd_process_info.dwProcessId;
2107 }
2108 
2109 
2110 int yarp::os::Run::executeCmd(yarp::os::Bottle& msg, Bottle& result)
2111 {
2112  yarp::os::ConstString strAlias=msg.find("as").asString().c_str();
2113 
2114  // RUN COMMAND
2115  PROCESS_INFORMATION cmd_process_info;
2116  ZeroMemory(&cmd_process_info, sizeof(PROCESS_INFORMATION));
2117  STARTUPINFO cmd_startup_info;
2118  ZeroMemory(&cmd_startup_info, sizeof(STARTUPINFO));
2119 
2120  cmd_startup_info.cb=sizeof(STARTUPINFO);
2121 
2122  Bottle botCmd=msg.findGroup("cmd").tail();
2123 
2124  yarp::os::ConstString strCmd;
2125  for (int s=0; s<botCmd.size(); ++s)
2126  {
2127  strCmd+=botCmd.get(s).toString()+yarp::os::ConstString(" ");
2128  }
2129 
2130  /*
2131  if (msg.check("env"))
2132  {
2133  int pos = msg.find("env").asString().find("=");
2134  if (pos)
2135  {
2136  yarp::os::ConstString cstrName = msg.find("env").asString().substr(0, pos);
2137  int nValue = msg.find("env").asString().length() -
2138  cstrName.length() - 1;
2139  yarp::os::ConstString cstrValue = msg.find("env").asString().substr(pos+1, nValue);
2140  SetEnvironmentVariable(cstrName.c_str(), cstrValue.c_str());
2141  }
2142 
2143  }
2144  */
2145 
2146  /*
2147  * setting environment variable for child process
2148  */
2149  TCHAR chNewEnv[32767];
2150 
2151  // Get a pointer to the env block.
2152  LPTCH chOldEnv = GetEnvironmentStrings();
2153 
2154  // copying parent env variables
2155  LPTSTR lpOld = (LPTSTR) chOldEnv;
2156  LPTSTR lpNew = (LPTSTR) chNewEnv;
2157  while (*lpOld)
2158  {
2159  lstrcpy(lpNew, lpOld);
2160  lpOld += lstrlen(lpOld) + 1;
2161  lpNew += lstrlen(lpNew) + 1;
2162  }
2163 
2164  // adding new env variables
2165  yarp::os::ConstString cstrEnvName;
2166  if (msg.check("env"))
2167  {
2168  lstrcpy(lpNew, (LPTCH) msg.find("env").asString().c_str());
2169  lpNew += lstrlen(lpNew) + 1;
2170  }
2171 
2172  // closing env block
2173  *lpNew = (TCHAR)0;
2174 
2175  bool bWorkdir=msg.check("workdir");
2176  yarp::os::ConstString strWorkdir=bWorkdir?msg.find("workdir").asString()+"\\":"";
2177 
2178  BOOL bSuccess=CreateProcess(YARP_NULLPTR, // command name
2179  (char*)(strWorkdir+strCmd).c_str(), // command line
2180  YARP_NULLPTR, // process security attributes
2181  YARP_NULLPTR, // primary thread security attributes
2182  TRUE, // handles are inherited
2183  CREATE_NEW_PROCESS_GROUP, // creation flags
2184  (LPVOID) chNewEnv, // use new environment
2185  bWorkdir ? strWorkdir.c_str() : YARP_NULLPTR, // working directory
2186  &cmd_startup_info, // STARTUPINFO pointer
2187  &cmd_process_info); // receives PROCESS_INFORMATION
2188 
2189  if (!bSuccess && bWorkdir)
2190  {
2191  bSuccess=CreateProcess(YARP_NULLPTR, // command name
2192  (char*)(strCmd.c_str()), // command line
2193  YARP_NULLPTR, // process security attributes
2194  YARP_NULLPTR, // primary thread security attributes
2195  TRUE, // handles are inherited
2196  CREATE_NEW_PROCESS_GROUP, // creation flags
2197  (LPVOID) chNewEnv, // use new environment
2198  strWorkdir.c_str(), // working directory
2199  &cmd_startup_info, // STARTUPINFO pointer
2200  &cmd_process_info); // receives PROCESS_INFORMATION
2201  }
2202 
2203  // deleting old environment variable
2204  FreeEnvironmentStrings(chOldEnv);
2205 
2206  if (!bSuccess)
2207  {
2208  result.addInt(YARPRUN_ERROR);
2209 
2210  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2211  +yarp::os::ConstString(" alias=")+strAlias
2212  +yarp::os::ConstString(" cmd=")+strCmd
2213  +yarp::os::ConstString(" pid=")+int2String(cmd_process_info.dwProcessId)
2214  +yarp::os::ConstString("\nCan't execute command because ")+lastError2String()
2215  +yarp::os::ConstString("\n");
2216 
2217  result.addString(out.c_str());
2218  fprintf(stderr, "%s", out.c_str());
2219  fflush(stderr);
2220 
2221  return YARPRUN_ERROR;
2222  }
2223 
2224  // EVERYTHING IS ALL RIGHT
2225  YarpRunProcInfo* pInf = new YarpRunProcInfo(strAlias,
2226  mPortName,
2227  cmd_process_info.dwProcessId,
2228  cmd_process_info.hProcess,
2229  false);
2230  pInf->setCmd(strCmd);
2231  if (msg.check("env"))
2232  pInf->setEnv(msg.find("env").asString());
2233 
2234  mProcessVector.Add(pInf);
2235 
2236  result.addInt(cmd_process_info.dwProcessId);
2237  yarp::os::ConstString out=yarp::os::ConstString("STARTED: server=")+mPortName
2238  +yarp::os::ConstString(" alias=")+strAlias
2239  +yarp::os::ConstString(" cmd=")+strCmd
2240  +yarp::os::ConstString("pid=")+int2String(cmd_process_info.dwProcessId)
2241  +yarp::os::ConstString("\n");
2242 
2243  fprintf(stderr, "%s", out.c_str());
2244 
2245  return cmd_process_info.dwProcessId;
2246 }
2247 
2248 // STDIO SERVER
2249 int yarp::os::Run::userStdio(Bottle& msg, Bottle& result)
2250 {
2251  PROCESS_INFORMATION stdio_process_info;
2252  ZeroMemory(&stdio_process_info, sizeof(PROCESS_INFORMATION));
2253 
2254  STARTUPINFO stdio_startup_info;
2255  ZeroMemory(&stdio_startup_info, sizeof(STARTUPINFO));
2256  stdio_startup_info.cb=sizeof(STARTUPINFO);
2257  stdio_startup_info.wShowWindow=SW_SHOWNOACTIVATE;
2258  stdio_startup_info.dwFlags=STARTF_USESHOWWINDOW;
2259 
2260  yarp::os::ConstString strAlias=msg.find("as").asString();
2261  yarp::os::ConstString strUUID=msg.find("stdiouuid").asString();
2262  yarp::os::ConstString strCmd=yarp::os::ConstString("yarprun --readwrite ")+strUUID;
2263  if (msg.check("forward")) strCmd+=yarp::os::ConstString(" --forward ")+msg.findGroup("forward").get(1).asString()+yarp::os::ConstString(" ")+msg.findGroup("forward").get(2).asString();
2264 
2265  BOOL bSuccess=CreateProcess(YARP_NULLPTR, // command name
2266  (char*)strCmd.c_str(), // command line
2267  YARP_NULLPTR, // process security attributes
2268  YARP_NULLPTR, // primary thread security attributes
2269  TRUE, // handles are inherited
2270  CREATE_NEW_CONSOLE, // creation flags
2271  YARP_NULLPTR, // use parent's environment
2272  YARP_NULLPTR, // use parent's current directory
2273  &stdio_startup_info, // STARTUPINFO pointer
2274  &stdio_process_info); // receives PROCESS_INFORMATION
2275 
2277 
2278  if (bSuccess)
2279  {
2280  mStdioVector.Add(new YarpRunProcInfo(strAlias,
2281  mPortName,
2282  stdio_process_info.dwProcessId,
2283  stdio_process_info.hProcess,
2284  false));
2285 
2286  out=yarp::os::ConstString("STARTED: server=")+mPortName
2287  +yarp::os::ConstString(" alias=")+strAlias
2288  +yarp::os::ConstString(" cmd=stdio pid=")+int2String(stdio_process_info.dwProcessId)
2289  +yarp::os::ConstString("\n");
2290  }
2291  else
2292  {
2293  stdio_process_info.dwProcessId=YARPRUN_ERROR;
2294 
2295  out=yarp::os::ConstString("ABORTED: server=")+mPortName
2296  +yarp::os::ConstString(" alias=")+strAlias
2297  +yarp::os::ConstString(" cmd=stdio\n")
2298  +yarp::os::ConstString("Can't open stdio window because ")+lastError2String()
2299  +yarp::os::ConstString("\n");
2300  }
2301 
2302  result.clear();
2303  result.addInt(stdio_process_info.dwProcessId);
2304  result.addString(out.c_str());
2305  fprintf(stderr, "%s", out.c_str());
2306  fflush(stderr);
2307 
2308  return stdio_process_info.dwProcessId;
2309 }
2310 
2312 #else // LINUX
2313 /*
2315 int CountArgs(char *str)
2316 {
2317  int nargs=0;
2318 
2319  for (bool bSpace=true; *str; ++str)
2320  {
2321  if (bSpace)
2322  {
2323  if (*str!=' ')
2324  {
2325  ++nargs;
2326  bSpace=false;
2327  }
2328  }
2329  else
2330  {
2331  if (*str==' ')
2332  {
2333  bSpace=true;
2334  }
2335  }
2336  }
2337 
2338  return nargs;
2339 }
2340 
2341 void ParseCmd(char* cmd_str, char** arg_str)
2342 {
2343  int nargs=0;
2344 
2345  for (bool bSpace=true; *cmd_str; ++cmd_str)
2346  {
2347  if (*cmd_str!=' ')
2348  {
2349  if (bSpace) arg_str[nargs++]=cmd_str;
2350  bSpace=false;
2351  }
2352  else
2353  {
2354  *cmd_str=0;
2355  bSpace=true;
2356  }
2357  }
2358 }
2359 */
2363 void splitLine(char *pLine, char **pArgs)
2364 {
2365  char *pTmp = strchr(pLine, ' ');
2366 
2367  if (pTmp) {
2368  *pTmp = '\0';
2369  pTmp++;
2370  while ((*pTmp) && (*pTmp == ' ')) {
2371  pTmp++;
2372  }
2373  if (*pTmp == '\0') {
2374  pTmp = YARP_NULLPTR;
2375  }
2376  }
2377  *pArgs = pTmp;
2378 }
2379 
2380 
2381 
2385 void parseArguments(char *io_pLine, int *o_pArgc, char **o_pArgv)
2386 {
2387  char *pNext = io_pLine;
2388  size_t i;
2389  int j;
2390  int quoted = 0;
2391  size_t len = strlen(io_pLine);
2392 
2393  // Protect spaces inside quotes, but lose the quotes
2394  for(i = 0; i < len; i++) {
2395  if ((!quoted) && ('"' == io_pLine[i])) {
2396  quoted = 1;
2397  io_pLine[i] = ' ';
2398  } else if ((quoted) && ('"' == io_pLine[i])) {
2399  quoted = 0;
2400  io_pLine[i] = ' ';
2401  } else if ((quoted) && (' ' == io_pLine[i])) {
2402  io_pLine[i] = '\1';
2403  }
2404  }
2405 
2406  // init
2407  memset(o_pArgv, 0x00, sizeof(char*) * C_MAXARGS);
2408  *o_pArgc = 1;
2409  o_pArgv[0] = io_pLine;
2410 
2411  while ((YARP_NULLPTR != pNext) && (*o_pArgc < C_MAXARGS)) {
2412  splitLine(pNext, &(o_pArgv[*o_pArgc]));
2413  pNext = o_pArgv[*o_pArgc];
2414 
2415  if (YARP_NULLPTR != o_pArgv[*o_pArgc]) {
2416  *o_pArgc += 1;
2417  }
2418  }
2419 
2420  for(j = 0; j < *o_pArgc; j++) {
2421  len = strlen(o_pArgv[j]);
2422  for(i = 0; i < len; i++) {
2423  if ('\1' == o_pArgv[j][i]) {
2424  o_pArgv[j][i] = ' ';
2425  }
2426  }
2427  }
2428 }
2429 
2430 void yarp::os::Run::CleanZombie(int pid)
2431 {
2432  bool bFound=mProcessVector && mProcessVector->CleanZombie(pid);
2433 
2434  if (!bFound) if (mStdioVector) mStdioVector->CleanZombie(pid);
2435 }
2436 
2438 
2439 int yarp::os::Run::executeCmdAndStdio(yarp::os::Bottle& msg, yarp::os::Bottle& result)
2440 {
2441  yarp::os::ConstString strAlias=msg.find("as").asString();
2442  yarp::os::ConstString strCmd=msg.find("cmd").asString();
2443  yarp::os::ConstString strStdio=msg.find("stdio").asString();
2444  yarp::os::ConstString strStdioUUID=msg.find("stdiouuid").asString();
2445 
2446  int pipe_stdin_to_cmd[2];
2447  int ret_stdin_to_cmd=yarp::os::impl::pipe(pipe_stdin_to_cmd);
2448 
2449  int pipe_cmd_to_stdout[2];
2450  int ret_cmd_to_stdout=yarp::os::impl::pipe(pipe_cmd_to_stdout);
2451 
2452  int pipe_child_to_parent[2];
2453  int ret_child_to_parent=yarp::os::impl::pipe(pipe_child_to_parent);
2454 
2455  if (ret_child_to_parent!=0 || ret_cmd_to_stdout!=0 || ret_stdin_to_cmd!=0)
2456  {
2457  int error=errno;
2458 
2459  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2460  +yarp::os::ConstString(" alias=")+strAlias
2461  +yarp::os::ConstString(" cmd=stdout\n")
2462  +yarp::os::ConstString("Can't create pipes ")+strerror(error)
2463  +yarp::os::ConstString("\n");
2464 
2465  result.addInt(YARPRUN_ERROR);
2466  result.addString(out.c_str());
2467  fprintf(stderr, "%s", out.c_str());
2468 
2469  return YARPRUN_ERROR;
2470  }
2471 
2472  int pid_stdout=yarp::os::fork();
2473 
2474  if (IS_INVALID(pid_stdout))
2475  {
2476  int error=errno;
2477 
2478  CLOSE(pipe_stdin_to_cmd[WRITE_TO_PIPE]);
2479  CLOSE(pipe_stdin_to_cmd[READ_FROM_PIPE]);
2480  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2481  CLOSE(pipe_cmd_to_stdout[READ_FROM_PIPE]);
2482  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2483  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2484 
2485  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2486  +yarp::os::ConstString(" alias=")+strAlias
2487  +yarp::os::ConstString(" cmd=stdout\n")
2488  +yarp::os::ConstString("Can't fork stdout process because ")+strerror(error)
2489  +yarp::os::ConstString("\n");
2490 
2491  result.addInt(YARPRUN_ERROR);
2492  result.addString(out.c_str());
2493  fprintf(stderr, "%s", out.c_str());
2494 
2495  return YARPRUN_ERROR;
2496  }
2497 
2498  if (IS_NEW_PROCESS(pid_stdout)) // STDOUT IMPLEMENTED HERE
2499  {
2500  REDIRECT_TO(STDIN_FILENO, pipe_cmd_to_stdout[READ_FROM_PIPE]);
2501 
2502  CLOSE(pipe_stdin_to_cmd[WRITE_TO_PIPE]);
2503  CLOSE(pipe_stdin_to_cmd[READ_FROM_PIPE]);
2504  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2505  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2506 
2507  //Why removing vectors and stop threads?
2508  //exec* never returns and memory is claimed by the system
2509  //furthermore after fork() only the thread which called fork() is forked!
2510  // cleanBeforeExec();
2511 
2512  //yarp::os::impl::signal(SIGPIPE, SIG_DFL);
2513 
2514  int ret = yarp::os::impl::execlp("yarprun", "yarprun", "--write", strStdioUUID.c_str(), static_cast<char*>(YARP_NULLPTR));
2515 
2516  CLOSE(pipe_cmd_to_stdout[READ_FROM_PIPE]);
2517 
2518  if (ret==YARPRUN_ERROR)
2519  {
2520  int error=errno;
2521 
2522  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2523  +yarp::os::ConstString(" alias=")+strAlias
2524  +yarp::os::ConstString(" cmd=stdout\n")
2525  +yarp::os::ConstString("Can't execute stdout because ")+strerror(error)
2526  +yarp::os::ConstString("\n");
2527 
2528  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
2529  fprintf(out_to_parent, "%s", out.c_str());
2530  fflush(out_to_parent);
2531  fclose(out_to_parent);
2532 
2533  fprintf(stderr, "%s", out.c_str());
2534  }
2535 
2536  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2537 
2538  std::exit(ret);
2539  }
2540 
2541  if (IS_PARENT_OF(pid_stdout))
2542  {
2543  CLOSE(pipe_cmd_to_stdout[READ_FROM_PIPE]);
2544 
2545  fprintf(stderr, "STARTED: server=%s alias=%s cmd=stdout pid=%d\n", mPortName.c_str(), strAlias.c_str(), pid_stdout);
2546 
2547  int pid_stdin=yarp::os::fork();
2548 
2549  if (IS_INVALID(pid_stdin))
2550  {
2551  int error=errno;
2552 
2553  CLOSE(pipe_stdin_to_cmd[WRITE_TO_PIPE]);
2554  CLOSE(pipe_stdin_to_cmd[READ_FROM_PIPE]);
2555  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2556  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2557  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2558 
2559  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2560  +yarp::os::ConstString(" alias=")+strAlias
2561  +yarp::os::ConstString(" cmd=stdin\n")
2562  +yarp::os::ConstString("Can't fork stdin process because ")+strerror(error)
2563  +yarp::os::ConstString("\n");
2564 
2565  result.addInt(YARPRUN_ERROR);
2566  result.addString(out.c_str());
2567  fprintf(stderr, "%s", out.c_str());
2568 
2569  SIGNAL(pid_stdout, SIGTERM);
2570  fprintf(stderr, "TERMINATING stdout (%d)\n", pid_stdout);
2571 
2572  return YARPRUN_ERROR;
2573  }
2574 
2575  if (IS_NEW_PROCESS(pid_stdin)) // STDIN IMPLEMENTED HERE
2576  {
2577  REDIRECT_TO(STDOUT_FILENO, pipe_stdin_to_cmd[WRITE_TO_PIPE]);
2578  REDIRECT_TO(STDERR_FILENO, pipe_stdin_to_cmd[WRITE_TO_PIPE]);
2579 
2580  CLOSE(pipe_stdin_to_cmd[READ_FROM_PIPE]);
2581  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2582  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2583 
2584  //Why removing vectors and stop threads?
2585  //exec* never returns and memory is claimed by the system
2586  //furthermore after fork() only the thread which called fork() is forked!
2587  // cleanBeforeExec();
2588 
2589  //yarp::os::impl::signal(SIGPIPE, SIG_DFL);
2590 
2591  int ret = yarp::os::impl::execlp("yarprun", "yarprun", "--read", strStdioUUID.c_str(), static_cast<char*>(YARP_NULLPTR));
2592 
2593  CLOSE(pipe_stdin_to_cmd[WRITE_TO_PIPE]);
2594 
2595  if (ret==YARPRUN_ERROR)
2596  {
2597  int error=errno;
2598 
2599  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2600  +yarp::os::ConstString(" alias=")+strAlias
2601  +yarp::os::ConstString(" cmd=stdin\n")
2602  +yarp::os::ConstString("Can't execute stdin because ")+strerror(error)
2603  +yarp::os::ConstString("\n");
2604 
2605 
2606  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
2607  fprintf(out_to_parent, "%s", out.c_str());
2608  fflush(out_to_parent);
2609  fclose(out_to_parent);
2610  fprintf(stderr, "%s", out.c_str());
2611  }
2612 
2613  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2614 
2615  std::exit(ret);
2616  }
2617 
2618  if (IS_PARENT_OF(pid_stdin))
2619  {
2620  // connect yarp read and write
2621  CLOSE(pipe_stdin_to_cmd[WRITE_TO_PIPE]);
2622 
2623  fprintf(stderr, "STARTED: server=%s alias=%s cmd=stdin pid=%d\n", mPortName.c_str(), strAlias.c_str(), pid_stdin);
2624 
2625  int pid_cmd=yarp::os::fork();
2626 
2627  if (IS_INVALID(pid_cmd))
2628  {
2629  int error=errno;
2630 
2631  CLOSE(pipe_stdin_to_cmd[READ_FROM_PIPE]);
2632  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2633  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2634 
2635  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2636  +yarp::os::ConstString(" alias=")+strAlias
2637  +yarp::os::ConstString(" cmd=")+strCmd
2638  +yarp::os::ConstString("\nCan't fork command process because ")+strerror(error)
2639  +yarp::os::ConstString("\n");
2640 
2641  result.addInt(YARPRUN_ERROR);
2642  result.addString(out.c_str());
2643  fprintf(stderr, "%s", out.c_str());
2644 
2645  FILE* to_yarp_stdout=fdopen(pipe_cmd_to_stdout[WRITE_TO_PIPE], "w");
2646  fprintf(to_yarp_stdout, "%s", out.c_str());
2647  fflush(to_yarp_stdout);
2648  fclose(to_yarp_stdout);
2649 
2650  SIGNAL(pid_stdout, SIGTERM);
2651  fprintf(stderr, "TERMINATING stdout (%d)\n", pid_stdout);
2652  SIGNAL(pid_stdin, SIGTERM);
2653  fprintf(stderr, "TERMINATING stdin (%d)\n", pid_stdin);
2654 
2655  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2656 
2657  return YARPRUN_ERROR;
2658  }
2659 
2660  if (IS_NEW_PROCESS(pid_cmd)) // RUN COMMAND HERE
2661  {
2662  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2663 
2664  char *cmd_str=new char[strCmd.length()+1];
2665  strcpy(cmd_str, strCmd.c_str());
2666  /*
2667  int nargs=CountArgs(cmd_str);
2668  char **arg_str=new char*[nargs+1];
2669  ParseCmd(cmd_str, arg_str);
2670  arg_str[nargs]=0;
2671  */
2672  int nargs = 0;
2673  char **arg_str = new char*[C_MAXARGS + 1];
2674  parseArguments(cmd_str, &nargs, arg_str);
2675  arg_str[nargs]=YARP_NULLPTR;
2676 
2677  setvbuf(stdout, YARP_NULLPTR, _IONBF, 0);
2678 
2679  REDIRECT_TO(STDIN_FILENO, pipe_stdin_to_cmd[READ_FROM_PIPE]);
2680  REDIRECT_TO(STDOUT_FILENO, pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2681  REDIRECT_TO(STDERR_FILENO, pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2682 
2683  if (msg.check("env"))
2684  {
2685  yarp::os::impl::SplitString ss(msg.find("env").asString().c_str(), ';');
2686  for(int i=0; i<ss.size(); i++) {
2687  char* szenv = new char[strlen(ss.get(i))+1];
2688  strcpy(szenv, ss.get(i));
2689  yarp::os::impl::putenv(szenv); // putenv doesn't make copy of the string
2690  }
2691  //delete [] szenv;
2692  }
2693 
2694  if (msg.check("workdir"))
2695  {
2696  int ret = yarp::os::impl::chdir(msg.find("workdir").asString().c_str());
2697 
2698  if (ret!=0)
2699  {
2700  int error=errno;
2701 
2702  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2703  +yarp::os::ConstString(" alias=")+strAlias
2704  +yarp::os::ConstString(" cmd=")+strCmd
2705  +yarp::os::ConstString("\nCan't execute command, cannot set working directory ")+strerror(error)
2706  +yarp::os::ConstString("\n");
2707 
2708  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
2709  fprintf(out_to_parent, "%s", out.c_str());
2710  fflush(out_to_parent);
2711  fclose(out_to_parent);
2712  fprintf(stderr, "%s", out.c_str());
2713 
2714  std::exit(ret);
2715  }
2716  }
2717 
2718  int ret=YARPRUN_ERROR;
2719 
2720  char currWorkDirBuff[1024];
2721  char *currWorkDir=yarp::os::impl::getcwd(currWorkDirBuff, 1024);
2722 
2723  if (currWorkDir)
2724  {
2725  char **cwd_arg_str=new char*[nargs+1];
2726  for (int i=1; i<nargs; ++i) cwd_arg_str[i]=arg_str[i];
2727  cwd_arg_str[nargs]=YARP_NULLPTR;
2728  cwd_arg_str[0]=new char[strlen(currWorkDir)+strlen(arg_str[0])+16];
2729 
2730  strcpy(cwd_arg_str[0], currWorkDir);
2731  strcat(cwd_arg_str[0], "/");
2732  strcat(cwd_arg_str[0], arg_str[0]);
2733 
2734  //Why removing vectors and stop threads?
2735  //exec* never returns and memory is claimed by the system
2736  //furthermore after fork() only the thread which called fork() is forked!
2737  // cleanBeforeExec();
2738 
2739  ret = yarp::os::impl::execvp(cwd_arg_str[0], cwd_arg_str);
2740 
2741  delete [] cwd_arg_str[0];
2742  delete [] cwd_arg_str;
2743  }
2744 
2745  if (ret==YARPRUN_ERROR)
2746  {
2747  //Why removing vectors and stop threads?
2748  //exec* never returns and memory is claimed by the system
2749  //furthermore after fork() only the thread which called fork() is forked!
2750  // cleanBeforeExec();
2751 
2752  ret = yarp::os::impl::execvp(arg_str[0], arg_str);
2753  }
2754 
2755  fflush(stdout);
2756 
2757  CLOSE(pipe_stdin_to_cmd[READ_FROM_PIPE]);
2758  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2759 
2760  if (ret==YARPRUN_ERROR)
2761  {
2762  int error=errno;
2763 
2764  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2765  +yarp::os::ConstString(" alias=")+strAlias
2766  +yarp::os::ConstString(" cmd=")+strCmd
2767  +yarp::os::ConstString("\nCan't execute command because ")+strerror(error)
2768  +yarp::os::ConstString("\n");
2769 
2770  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
2771  fprintf(out_to_parent, "%s", out.c_str());
2772  fflush(out_to_parent);
2773  fclose(out_to_parent);
2774  fprintf(stderr, "%s", out.c_str());
2775  }
2776 
2777  delete [] cmd_str;
2778  delete [] arg_str;
2779 
2780  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2781 
2782  std::exit(ret);
2783  }
2784 
2785 
2786  if (IS_PARENT_OF(pid_cmd))
2787  {
2788  CLOSE(pipe_stdin_to_cmd[READ_FROM_PIPE]);
2789  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2790  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2791 
2793  strAlias,
2794  mPortName,
2795  strStdio,
2796  pid_cmd,
2797  strStdioUUID,
2798  mStdioVector,
2799  pid_stdin,
2800  pid_stdout,
2801  pipe_stdin_to_cmd[READ_FROM_PIPE],
2802  pipe_stdin_to_cmd[WRITE_TO_PIPE],
2803  pipe_cmd_to_stdout[READ_FROM_PIPE],
2804  pipe_cmd_to_stdout[WRITE_TO_PIPE],
2805  YARP_NULLPTR,
2806  false
2807  );
2808 
2809  pInf->setCmd(strCmd);
2810 
2811  if (msg.check("env"))
2812  {
2813  pInf->setEnv(msg.find("env").asString());
2814  }
2815 
2816  mProcessVector->Add(pInf);
2817 
2818  yarp::os::Time::delay(0.01);
2819 
2820  FILE* in_from_child=fdopen(pipe_child_to_parent[READ_FROM_PIPE], "r");
2821  int flags=fcntl(pipe_child_to_parent[READ_FROM_PIPE], F_GETFL, 0);
2822  fcntl(pipe_child_to_parent[READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
2823 
2825 
2826  if (in_from_child)
2827  {
2828  char buff[1024];
2829 
2830  while(true)
2831  {
2832  if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) break;
2833 
2834  out+=yarp::os::ConstString(buff);
2835  }
2836 
2837  fclose(in_from_child);
2838  }
2839 
2840  if (out.length()>0)
2841  {
2842  pid_cmd=YARPRUN_ERROR;
2843  }
2844  else
2845  {
2846  out=yarp::os::ConstString("STARTED: server=")+mPortName
2847  +yarp::os::ConstString(" alias=")+strAlias
2848  +yarp::os::ConstString(" cmd=")+strCmd
2849  +yarp::os::ConstString(" pid=")+int2String(pid_cmd)
2850  +yarp::os::ConstString("\n");
2851  }
2852 
2853  result.addInt(pid_cmd);
2854  result.addString(out.c_str());
2855  result.addString(strStdioUUID.c_str());
2856 
2857  fprintf(stderr, "%s", out.c_str());
2858 
2859  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2860 
2861  return pid_cmd;
2862  }
2863  }
2864  }
2865 
2866  result.addInt(YARPRUN_ERROR);
2867  result.addString("I should never reach this point!!!\n");
2868 
2869  return YARPRUN_ERROR;
2870 }
2871 
2872 int yarp::os::Run::executeCmdStdout(yarp::os::Bottle& msg, yarp::os::Bottle& result, yarp::os::ConstString& loggerName)
2873 {
2874  yarp::os::ConstString strAlias=msg.find("as").asString();
2875  yarp::os::ConstString strCmd=msg.find("cmd").asString();
2876 
2877  yarp::os::ConstString portName="/log";
2878  portName+=mPortName+"/";
2879 
2880  yarp::os::ConstString command=strCmd;
2881  size_t space=command.find(' ');
2882  if (space!=ConstString::npos) command=command.substr(0, space);
2883  portName+=command;
2884 
2885 
2886 
2887  int pipe_cmd_to_stdout[2];
2888  int ret_cmd_to_stdout=yarp::os::impl::pipe(pipe_cmd_to_stdout);
2889 
2890  int pipe_child_to_parent[2];
2891  int ret_child_to_parent=yarp::os::impl::pipe(pipe_child_to_parent);
2892 
2893  if (ret_child_to_parent!=0 || ret_cmd_to_stdout!=0)
2894  {
2895  int error=errno;
2896 
2897  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2898  +yarp::os::ConstString(" alias=")+strAlias
2899  +yarp::os::ConstString(" cmd=stdout\n")
2900  +yarp::os::ConstString("Can't create pipes ")+strerror(error)
2901  +yarp::os::ConstString("\n");
2902 
2903  result.addInt(YARPRUN_ERROR);
2904  result.addString(out.c_str());
2905  fprintf(stderr, "%s", out.c_str());
2906 
2907  return YARPRUN_ERROR;
2908  }
2909 
2910  int pid_stdout=yarp::os::fork();
2911 
2912  if (IS_INVALID(pid_stdout))
2913  {
2914  int error=errno;
2915 
2916  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2917  CLOSE(pipe_cmd_to_stdout[READ_FROM_PIPE]);
2918  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2919  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2920 
2921  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2922  +yarp::os::ConstString(" alias=")+strAlias
2923  +yarp::os::ConstString(" cmd=stdout\n")
2924  +yarp::os::ConstString("Can't fork stdout process because ")+strerror(error)
2925  +yarp::os::ConstString("\n");
2926 
2927  result.addInt(YARPRUN_ERROR);
2928  result.addString(out.c_str());
2929  fprintf(stderr, "%s", out.c_str());
2930 
2931  return YARPRUN_ERROR;
2932  }
2933 
2934  if (IS_NEW_PROCESS(pid_stdout)) // STDOUT IMPLEMENTED HERE
2935  {
2936  REDIRECT_TO(STDIN_FILENO, pipe_cmd_to_stdout[READ_FROM_PIPE]);
2937 
2938  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
2939  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2940 
2941  //Why removing vectors and stop threads?
2942  //exec* never returns and memory is claimed by the system
2943  //furthermore after fork() only the thread which called fork() is forked!
2944  // cleanBeforeExec();
2945 
2946  //yarp::os::impl::signal(SIGPIPE, SIG_DFL);
2947 
2948  int ret = yarp::os::impl::execlp("yarprun", "yarprun", "--write", portName.c_str(), "--log", loggerName.c_str(), static_cast<char*>(YARP_NULLPTR));
2949 
2950  CLOSE(pipe_cmd_to_stdout[READ_FROM_PIPE]);
2951 
2952  if (ret==YARPRUN_ERROR)
2953  {
2954  int error=errno;
2955 
2956  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2957  +yarp::os::ConstString(" alias=")+strAlias
2958  +yarp::os::ConstString(" cmd=stdout\n")
2959  +yarp::os::ConstString("Can't execute stdout because ")+strerror(error)
2960  +yarp::os::ConstString("\n");
2961 
2962  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
2963  fprintf(out_to_parent, "%s", out.c_str());
2964  fflush(out_to_parent);
2965  fclose(out_to_parent);
2966 
2967  fprintf(stderr, "%s", out.c_str());
2968  }
2969 
2970  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2971 
2972  std::exit(ret);
2973  }
2974 
2975  if (IS_PARENT_OF(pid_stdout))
2976  {
2977  CLOSE(pipe_cmd_to_stdout[READ_FROM_PIPE]);
2978 
2979  fprintf(stderr, "STARTED: server=%s alias=%s cmd=stdout pid=%d\n", mPortName.c_str(), strAlias.c_str(), pid_stdout);
2980 
2982 
2983  //if (IS_PARENT_OF(pid_stdin))
2984  {
2985  int pid_cmd=yarp::os::fork();
2986 
2987  if (IS_INVALID(pid_cmd))
2988  {
2989  int error=errno;
2990 
2991  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
2992  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
2993 
2994  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
2995  +yarp::os::ConstString(" alias=")+strAlias
2996  +yarp::os::ConstString(" cmd=")+strCmd
2997  +yarp::os::ConstString("\nCan't fork command process because ")+strerror(error)
2998  +yarp::os::ConstString("\n");
2999 
3000  result.addInt(YARPRUN_ERROR);
3001  result.addString(out.c_str());
3002  fprintf(stderr, "%s", out.c_str());
3003 
3004  FILE* to_yarp_stdout=fdopen(pipe_cmd_to_stdout[WRITE_TO_PIPE], "w");
3005  fprintf(to_yarp_stdout, "%s", out.c_str());
3006  fflush(to_yarp_stdout);
3007  fclose(to_yarp_stdout);
3008 
3009  SIGNAL(pid_stdout, SIGTERM);
3010  fprintf(stderr, "TERMINATING stdout (%d)\n", pid_stdout);
3011  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
3012 
3013  return YARPRUN_ERROR;
3014  }
3015 
3016  if (IS_NEW_PROCESS(pid_cmd)) // RUN COMMAND HERE
3017  {
3018  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
3019 
3020  char *cmd_str=new char[strCmd.length()+1];
3021  strcpy(cmd_str, strCmd.c_str());
3022  /*
3023  int nargs=CountArgs(cmd_str);
3024  char **arg_str=new char*[nargs+1];
3025  ParseCmd(cmd_str, arg_str);
3026  arg_str[nargs]=0;
3027  */
3028  int nargs = 0;
3029  char **arg_str = new char*[C_MAXARGS + 1];
3030  parseArguments(cmd_str, &nargs, arg_str);
3031  arg_str[nargs]=YARP_NULLPTR;
3032 
3033  setvbuf(stdout, YARP_NULLPTR, _IONBF, 0);
3034 
3035  REDIRECT_TO(STDOUT_FILENO, pipe_cmd_to_stdout[WRITE_TO_PIPE]);
3036  REDIRECT_TO(STDERR_FILENO, pipe_cmd_to_stdout[WRITE_TO_PIPE]);
3037 
3038  if (msg.check("env"))
3039  {
3040  yarp::os::impl::SplitString ss(msg.find("env").asString().c_str(), ';');
3041  for(int i=0; i<ss.size(); i++) {
3042  char* szenv = new char[strlen(ss.get(i))+1];
3043  strcpy(szenv, ss.get(i));
3044  yarp::os::impl::putenv(szenv); // putenv doesn't make copy of the string
3045  }
3046  //delete [] szenv;
3047  }
3048 
3049  if (msg.check("workdir"))
3050  {
3051  int ret = yarp::os::impl::chdir(msg.find("workdir").asString().c_str());
3052 
3053  if (ret!=0)
3054  {
3055  int error=errno;
3056 
3057  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
3058  +yarp::os::ConstString(" alias=")+strAlias
3059  +yarp::os::ConstString(" cmd=")+strCmd
3060  +yarp::os::ConstString("\nCan't execute command, cannot set working directory ")+strerror(error)
3061  +yarp::os::ConstString("\n");
3062 
3063  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
3064  fprintf(out_to_parent, "%s", out.c_str());
3065  fflush(out_to_parent);
3066  fclose(out_to_parent);
3067  fprintf(stderr, "%s", out.c_str());
3068 
3069  std::exit(ret);
3070  }
3071  }
3072 
3073  int ret=YARPRUN_ERROR;
3074 
3075  char currWorkDirBuff[1024];
3076  char *currWorkDir=getcwd(currWorkDirBuff, 1024);
3077 
3078  if (currWorkDir)
3079  {
3080  char **cwd_arg_str=new char*[nargs+1];
3081  for (int i=1; i<nargs; ++i) cwd_arg_str[i]=arg_str[i];
3082  cwd_arg_str[nargs]=YARP_NULLPTR;
3083  cwd_arg_str[0]=new char[strlen(currWorkDir)+strlen(arg_str[0])+16];
3084 
3085  strcpy(cwd_arg_str[0], currWorkDir);
3086  strcat(cwd_arg_str[0], "/");
3087  strcat(cwd_arg_str[0], arg_str[0]);
3088 
3089  //Why removing vectors and stop threads?
3090  //exec* never returns and memory is claimed by the system
3091  //furthermore after fork() only the thread which called fork() is forked!
3092  // cleanBeforeExec();
3093 
3094  ret = yarp::os::impl::execvp(cwd_arg_str[0], cwd_arg_str);
3095 
3096  delete [] cwd_arg_str[0];
3097  delete [] cwd_arg_str;
3098  }
3099 
3100  if (ret==YARPRUN_ERROR)
3101  {
3102  //Why removing vectors and stop threads?
3103  //exec* never returns and memory is claimed by the system
3104  //furthermore after fork() only the thread which called fork() is forked!
3105  // cleanBeforeExec();
3106 
3107  ret = yarp::os::impl::execvp(arg_str[0], arg_str);
3108  }
3109 
3110  fflush(stdout);
3111 
3112  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
3113 
3114  if (ret==YARPRUN_ERROR)
3115  {
3116  int error=errno;
3117 
3118  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
3119  +yarp::os::ConstString(" alias=")+strAlias
3120  +yarp::os::ConstString(" cmd=")+strCmd
3121  +yarp::os::ConstString("\nCan't execute command because ")+strerror(error)
3122  +yarp::os::ConstString("\n");
3123 
3124  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
3125  fprintf(out_to_parent, "%s", out.c_str());
3126  fflush(out_to_parent);
3127  fclose(out_to_parent);
3128  fprintf(stderr, "%s", out.c_str());
3129  }
3130 
3131  delete [] cmd_str;
3132  delete [] arg_str;
3133 
3134  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
3135 
3136  std::exit(ret);
3137  }
3138 
3139 
3140  if (IS_PARENT_OF(pid_cmd))
3141  {
3142  CLOSE(pipe_cmd_to_stdout[WRITE_TO_PIPE]);
3143  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
3144 
3146  strAlias,
3147  mPortName,
3148  portName,
3149  pid_cmd,
3150  pid_stdout,
3151  pipe_cmd_to_stdout[READ_FROM_PIPE],
3152  pipe_cmd_to_stdout[WRITE_TO_PIPE],
3153  YARP_NULLPTR,
3154  false
3155  );
3156 
3157  pInf->setCmd(strCmd);
3158 
3159  if (msg.check("env"))
3160  {
3161  pInf->setEnv(msg.find("env").asString());
3162  }
3163 
3164  mProcessVector->Add(pInf);
3165 
3166  yarp::os::Time::delay(0.01);
3167 
3168  FILE* in_from_child=fdopen(pipe_child_to_parent[READ_FROM_PIPE], "r");
3169  int flags=fcntl(pipe_child_to_parent[READ_FROM_PIPE], F_GETFL, 0);
3170  fcntl(pipe_child_to_parent[READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
3171 
3173 
3174  if (in_from_child)
3175  {
3176  char buff[1024];
3177 
3178  while(true)
3179  {
3180  if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) break;
3181 
3182  out+=yarp::os::ConstString(buff);
3183  }
3184 
3185  fclose(in_from_child);
3186  }
3187 
3188  if (out.length()>0)
3189  {
3190  pid_cmd=YARPRUN_ERROR;
3191  }
3192  else
3193  {
3194  out=yarp::os::ConstString("STARTED: server=")+mPortName
3195  +yarp::os::ConstString(" alias=")+strAlias
3196  +yarp::os::ConstString(" cmd=")+strCmd
3197  +yarp::os::ConstString(" pid=")+int2String(pid_cmd)
3198  +yarp::os::ConstString("\n");
3199  }
3200 
3201  result.addInt(pid_cmd);
3202  result.addString(out.c_str());
3203 
3204  fprintf(stderr, "%s", out.c_str());
3205 
3206  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
3207 
3208  return pid_cmd;
3209  }
3210  }
3211  }
3212 
3213  result.addInt(YARPRUN_ERROR);
3214  result.addString("I should never reach this point!!!\n");
3215 
3216  return YARPRUN_ERROR;
3217 }
3218 
3219 int yarp::os::Run::userStdio(yarp::os::Bottle& msg, yarp::os::Bottle& result)
3220 {
3221  yarp::os::ConstString strAlias=msg.find("as").asString();
3222  yarp::os::ConstString strUUID=msg.find("stdiouuid").asString();
3223 
3224  yarp::os::ConstString strCmd;
3225 
3226  if (msg.check("forward"))
3227  {
3228  strCmd=yarp::os::ConstString("/bin/bash -l -c \"yarprun --readwrite ")+strUUID
3229  +yarp::os::ConstString(" --forward ")+msg.findGroup("forward").get(1).asString()+yarp::os::ConstString(" ")+msg.findGroup("forward").get(2).asString()+yarp::os::ConstString("\"");
3230  }
3231  else
3232  {
3233  strCmd=yarp::os::ConstString("/bin/bash -l -c \"yarprun --readwrite ")+strUUID+"\"";
3234  }
3235 
3236  int pipe_child_to_parent[2];
3237 
3238  if (yarp::os::impl::pipe(pipe_child_to_parent))
3239  {
3240  int error=errno;
3241 
3242  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
3243  +yarp::os::ConstString(" alias=")+strAlias
3244  +yarp::os::ConstString(" cmd=stdio\nCan't create pipe ")+strerror(error)
3245  +yarp::os::ConstString("\n");
3246 
3247  result.clear();
3248  result.addInt(YARPRUN_ERROR);
3249  result.addString(out.c_str());
3250  fprintf(stderr, "%s", out.c_str());
3251 
3252  return YARPRUN_ERROR;
3253  }
3254 
3255  int c=0;
3256  char *command[16];
3257  for (int i=0; i<16; ++i) {
3258  command[i] = YARP_NULLPTR;
3259  }
3260 
3261  cmdcpy(command[c++], "xterm");
3262  cmdcpy(command[c++], msg.check("hold")?"-hold":"+hold");
3263 
3264  if (msg.check("geometry"))
3265  {
3266  cmdcpy(command[c++], "-geometry");
3267  cmdcpy(command[c++], msg.find("geometry").asString().c_str());
3268  }
3269 
3270  cmdcpy(command[c++], "-title");
3271  cmdcpy(command[c++], strAlias.c_str());
3272 
3273  cmdcpy(command[c++], "-e");
3274  cmdcpy(command[c++], strCmd.c_str());
3275 
3276  int pid_cmd=yarp::os::fork();
3277 
3278  if (IS_INVALID(pid_cmd))
3279  {
3280  int error=errno;
3281 
3282  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
3283  +yarp::os::ConstString(" alias=")+strAlias
3284  +yarp::os::ConstString(" cmd=stdio\nCan't fork stdout process because ")+strerror(error)
3285  +yarp::os::ConstString("\n");
3286 
3287  result.clear();
3288  result.addInt(YARPRUN_ERROR);
3289  result.addString(out.c_str());
3290  fprintf(stderr, "%s", out.c_str());
3291 
3292  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
3293  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
3294 
3295  cmdclean(command);
3296 
3297  return YARPRUN_ERROR;
3298  }
3299 
3300  if (IS_NEW_PROCESS(pid_cmd)) // RUN COMMAND HERE
3301  {
3302  //yarp::os::impl::signal(SIGPIPE, SIG_IGN);
3303 
3304  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
3305 
3306  REDIRECT_TO(STDERR_FILENO, pipe_child_to_parent[WRITE_TO_PIPE]);
3307 
3308  //Why removing vectors and stop threads?
3309  //exec* never returns and memory is claimed by the system
3310  //furthermore after fork() only the thread which called fork() is forked!
3311  // cleanBeforeExec();
3312 
3313  //yarp::os::impl::signal(SIGHUP, rwSighupHandler);
3314 
3315  int ret = yarp::os::impl::execvp("xterm", command);
3316 
3317  cmdclean(command);
3318 
3319  if (ret==YARPRUN_ERROR)
3320  {
3321  int error=errno;
3322 
3323  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
3324  +yarp::os::ConstString(" alias=")+strAlias
3325  +yarp::os::ConstString(" cmd=xterm\nCan't execute command because ")+strerror(error)
3326  +yarp::os::ConstString("\n");
3327 
3328  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
3329 
3330  fprintf(out_to_parent, "%s", out.c_str());
3331  fflush(out_to_parent);
3332  fclose(out_to_parent);
3333 
3334  fprintf(stderr, "%s", out.c_str());
3335  }
3336 
3337  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
3338 
3339  std::exit(ret);
3340  }
3341 
3342  if (IS_PARENT_OF(pid_cmd))
3343  {
3344  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
3345 
3346  mStdioVector->Add(new YarpRunProcInfo(strAlias, mPortName, pid_cmd, YARP_NULLPTR, msg.check("hold")));
3347 
3348  result.clear();
3349 
3350  cmdclean(command);
3351 
3352  yarp::os::Time::delay(0.01);
3353 
3354  FILE* in_from_child=fdopen(pipe_child_to_parent[READ_FROM_PIPE], "r");
3355  int flags=fcntl(pipe_child_to_parent[READ_FROM_PIPE], F_GETFL, 0);
3356  fcntl(pipe_child_to_parent[READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
3358 
3359  if (in_from_child)
3360  {
3361  char buff[1024];
3362 
3363  while(true)
3364  {
3365  if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) break;
3366 
3367  out+=yarp::os::ConstString(buff);
3368  }
3369 
3370  fclose(in_from_child);
3371  }
3372 
3373  result.clear();
3374 
3375  //if (out.length()>0)
3376  if (out.substr(0, 14)=="xterm Xt error" || out.substr(0, 7)=="ABORTED")
3377  {
3378  pid_cmd=YARPRUN_ERROR;
3379  }
3380  else
3381  {
3382  out=yarp::os::ConstString("STARTED: server=")+mPortName
3383  +yarp::os::ConstString(" alias=")+strAlias
3384  +yarp::os::ConstString(" cmd=xterm pid=")+int2String(pid_cmd)
3385  +yarp::os::ConstString("\n");
3386 
3387  }
3388 
3389  fprintf(stderr, "%s", out.c_str());
3390 
3391  result.addInt(pid_cmd);
3392  result.addString(out.c_str());
3393 
3394  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
3395 
3396  return pid_cmd;
3397  }
3398 
3399  result.clear();
3400  result.addInt(YARPRUN_ERROR);
3401 
3402  return YARPRUN_ERROR;
3403 }
3404 
3405 int yarp::os::Run::executeCmd(yarp::os::Bottle& msg, yarp::os::Bottle& result)
3406 {
3407  yarp::os::ConstString strAlias(msg.find("as").asString());
3408  yarp::os::ConstString strCmd(msg.find("cmd").toString());
3409 
3410  int pipe_child_to_parent[2];
3411  int ret_pipe_child_to_parent=yarp::os::impl::pipe(pipe_child_to_parent);
3412 
3413  if (ret_pipe_child_to_parent!=0)
3414  {
3415  int error=errno;
3416 
3417  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
3418  +yarp::os::ConstString(" alias=")+strAlias
3419  +yarp::os::ConstString(" cmd=stdio\nCan't create pipe ")+strerror(error)
3420  +yarp::os::ConstString("\n");
3421 
3422 
3423  result.addInt(YARPRUN_ERROR);
3424  result.addString(out.c_str());
3425  fprintf(stderr, "%s", out.c_str());
3426 
3427  return YARPRUN_ERROR;
3428  }
3429 
3430  int pid_cmd=yarp::os::fork();
3431 
3432  if (IS_INVALID(pid_cmd))
3433  {
3434  int error=errno;
3435 
3436  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
3437  +yarp::os::ConstString(" alias=")+strAlias
3438  +yarp::os::ConstString(" cmd=")+strCmd
3439  +yarp::os::ConstString("\nCan't fork command process because ")+strerror(error)
3440  +yarp::os::ConstString("\n");
3441 
3442  result.addInt(YARPRUN_ERROR);
3443  result.addString(out.c_str());
3444  fprintf(stderr, "%s", out.c_str());
3445 
3446  return YARPRUN_ERROR;
3447  }
3448 
3449  if (IS_NEW_PROCESS(pid_cmd)) // RUN COMMAND HERE
3450  {
3451  int saved_stderr = yarp::os::impl::dup(STDERR_FILENO);
3452  int null_file=open("/dev/null", O_WRONLY);
3453  REDIRECT_TO(STDOUT_FILENO, null_file);
3454  REDIRECT_TO(STDERR_FILENO, null_file);
3455  close(null_file);
3456 
3457  char *cmd_str=new char[strCmd.length()+1];
3458  strcpy(cmd_str, strCmd.c_str());
3459  /*
3460  int nargs=CountArgs(cmd_str);
3461  char **arg_str=new char*[nargs+1];
3462  ParseCmd(cmd_str, arg_str);
3463  arg_str[nargs]=0;
3464  */
3465  int nargs = 0;
3466  char **arg_str = new char*[C_MAXARGS + 1];
3467  parseArguments(cmd_str, &nargs, arg_str);
3468  arg_str[nargs]=YARP_NULLPTR;
3469 
3470  if (msg.check("env"))
3471  {
3472  yarp::os::impl::SplitString ss(msg.find("env").asString().c_str(), ';');
3473  for(int i=0; i<ss.size(); i++) {
3474  char* szenv = new char[strlen(ss.get(i))+1];
3475  strcpy(szenv, ss.get(i));
3476  yarp::os::impl::putenv(szenv); // putenv doesn't make copy of the string
3477  }
3478  }
3479 
3480  if (msg.check("workdir"))
3481  {
3482  int ret = yarp::os::impl::chdir(msg.find("workdir").asString().c_str());
3483 
3484  if (ret!=0)
3485  {
3486  int error=errno;
3487 
3488  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
3489  +yarp::os::ConstString(" alias=")+strAlias
3490  +yarp::os::ConstString(" cmd=")+strCmd
3491  +yarp::os::ConstString("\nCan't execute command, cannot set working directory ")+strerror(error)
3492  +yarp::os::ConstString("\n");
3493 
3494  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
3495  fprintf(out_to_parent, "%s", out.c_str());
3496  fflush(out_to_parent);
3497  fclose(out_to_parent);
3498 
3499  REDIRECT_TO(STDERR_FILENO, saved_stderr);
3500  fprintf(stderr, "%s", out.c_str());
3501  }
3502  }
3503 
3504  int ret=YARPRUN_ERROR;
3505 
3506  char currWorkDirBuff[1024];
3507  char *currWorkDir=getcwd(currWorkDirBuff, 1024);
3508 
3509  if (currWorkDir)
3510  {
3511  char **cwd_arg_str=new char*[nargs+1];
3512  for (int i=1; i<nargs; ++i) cwd_arg_str[i]=arg_str[i];
3513  cwd_arg_str[nargs]=YARP_NULLPTR;
3514  cwd_arg_str[0]=new char[strlen(currWorkDir)+strlen(arg_str[0])+16];
3515 
3516 
3517  strcpy(cwd_arg_str[0], currWorkDir);
3518  strcat(cwd_arg_str[0], "/");
3519  strcat(cwd_arg_str[0], arg_str[0]);
3520 
3521  //Why removing vectors and stop threads?
3522  //exec* never returns and memory is claimed by the system
3523  //furthermore after fork() only the thread which called fork() is forked!
3524 // cleanBeforeExec();
3525 
3526  ret = yarp::os::impl::execvp(cwd_arg_str[0], cwd_arg_str);
3527 
3528  delete [] cwd_arg_str[0];
3529  delete [] cwd_arg_str;
3530  }
3531 
3532  if (ret==YARPRUN_ERROR)
3533  {
3534  //Why removing vectors and stop threads?
3535  //exec* never returns and memory is claimed by the system
3536  //furthermore after fork() only the thread which called fork() is forked!
3537  // cleanBeforeExec();
3538  ret = yarp::os::impl::execvp(arg_str[0], arg_str);
3539  }
3540 
3541  if (ret==YARPRUN_ERROR)
3542  {
3543  int error=errno;
3544 
3545  yarp::os::ConstString out=yarp::os::ConstString("ABORTED: server=")+mPortName
3546  +yarp::os::ConstString(" alias=")+strAlias
3547  +yarp::os::ConstString(" cmd=")+strCmd
3548  +yarp::os::ConstString("\nCan't execute command because ")+strerror(error)
3549  +yarp::os::ConstString("\n");
3550 
3551  FILE* out_to_parent=fdopen(pipe_child_to_parent[WRITE_TO_PIPE], "w");
3552  fprintf(out_to_parent, "%s", out.c_str());
3553  fflush(out_to_parent);
3554  fclose(out_to_parent);
3555 
3556  REDIRECT_TO(STDERR_FILENO, saved_stderr);
3557  fprintf(stderr, "%s", out.c_str());
3558  }
3559 
3560  delete [] cmd_str;
3561  delete [] arg_str;
3562 
3563  std::exit(ret);
3564  }
3565 
3566  if (IS_PARENT_OF(pid_cmd))
3567  {
3568  YarpRunProcInfo* pInf = new YarpRunProcInfo(strAlias, mPortName, pid_cmd, YARP_NULLPTR, false);
3569  pInf->setCmd(strCmd);
3570  if (msg.check("env")) pInf->setEnv(msg.find("env").asString());
3571  mProcessVector->Add(pInf);
3572  char pidstr[16];
3573  sprintf(pidstr, "%d", pid_cmd);
3574 
3575  yarp::os::Time::delay(0.01);
3576 
3577  FILE* in_from_child=fdopen(pipe_child_to_parent[READ_FROM_PIPE], "r");
3578  int flags=fcntl(pipe_child_to_parent[READ_FROM_PIPE], F_GETFL, 0);
3579  fcntl(pipe_child_to_parent[READ_FROM_PIPE], F_SETFL, flags|O_NONBLOCK);
3580 
3582 
3583  if (in_from_child)
3584  {
3585  char buff[1024];
3586 
3587  while(true)
3588  {
3589  if (!fgets(buff, 1024, in_from_child) || ferror(in_from_child) || feof(in_from_child)) break;
3590 
3591  out+=yarp::os::ConstString(buff);
3592  }
3593 
3594  fclose(in_from_child);
3595  }
3596 
3597  if (out.length()>0)
3598  {
3599  pid_cmd=YARPRUN_ERROR;
3600  }
3601  else
3602  {
3603  out=yarp::os::ConstString("STARTED: server=")+mPortName
3604  +yarp::os::ConstString(" alias=")+strAlias
3605  +yarp::os::ConstString(" cmd=")+strCmd
3606  +yarp::os::ConstString(" pid=")+int2String(pid_cmd)
3607  +yarp::os::ConstString("\n");
3608  }
3609 
3610  fprintf(stderr, "%s", out.c_str());
3611 
3612  result.addInt(pid_cmd);
3613  result.addString(out.c_str());
3614 
3615  CLOSE(pipe_child_to_parent[READ_FROM_PIPE]);
3616  CLOSE(pipe_child_to_parent[WRITE_TO_PIPE]);
3617 
3618  return pid_cmd;
3619  }
3620 
3621  result.addInt(YARPRUN_ERROR);
3622 
3623  return YARPRUN_ERROR;
3624 }
3625 
3626 #endif
3627 
3629 // API
3631 
3633 {
3634  yarp::os::Bottle msg, grp, response;
3635 
3636  grp.clear();
3637  grp.addString("on");
3638  grp.addString(node.c_str());
3639  msg.addList()=grp;
3640 
3641  yarp::os::ConstString dest_srv=node;
3642 
3643  if (command.check("stdio"))
3644  {
3645  dest_srv=yarp::os::ConstString(command.find("stdio").asString());
3646 
3647  grp.clear();
3648  grp.addString("stdio");
3649  grp.addString(dest_srv.c_str());
3650  msg.addList()=grp;
3651 
3652  if (command.check("geometry"))
3653  {
3654  grp.clear();
3655  grp.addString("geometry");
3656  grp.addString(command.find("geometry").asString().c_str());
3657  msg.addList()=grp;
3658  }
3659 
3660  if (command.check("hold"))
3661  {
3662  grp.clear();
3663  grp.addString("hold");
3664  msg.addList()=grp;
3665  }
3666  }
3667 
3668  grp.clear();
3669  grp.addString("as");
3670  grp.addString(keyv.c_str());
3671  msg.addList()=grp;
3672 
3673  grp.clear();
3674  grp.addString("cmd");
3675  grp.addString(command.find("name").asString().c_str());
3676  grp.addString(command.find("parameters").asString().c_str());
3677  msg.addList()=grp;
3678 
3679  printf(":: %s\n", msg.toString().c_str());
3680 
3681  response=sendMsg(msg, dest_srv.c_str());
3682 
3683  char buff[16];
3684  sprintf(buff, "%d", response.get(0).asInt());
3685  keyv=yarp::os::ConstString(buff);
3686 
3687  return response.get(0).asInt()>0?0:YARPRUN_ERROR;
3688 }
3689 
3691 {
3692  yarp::os::Bottle msg, grp, response;
3693 
3694  grp.clear();
3695  grp.addString("on");
3696  grp.addString(node.c_str());
3697  msg.addList()=grp;
3698 
3699  grp.clear();
3700  grp.addString("sigterm");
3701  grp.addString(keyv.c_str());
3702  msg.addList()=grp;
3703 
3704  printf(":: %s\n", msg.toString().c_str());
3705 
3706  response=sendMsg(msg, node.c_str());
3707 
3708  return response.get(0).asString()=="sigterm OK"?0:YARPRUN_ERROR;
3709 }
3710 
3712 {
3713  yarp::os::Bottle msg, grp, response;
3714 
3715  grp.clear();
3716  grp.addString("on");
3717  grp.addString(node.c_str());
3718  msg.addList()=grp;
3719 
3720  grp.clear();
3721  grp.addString("sigtermall");
3722  msg.addList()=grp;
3723 
3724  printf(":: %s\n", msg.toString().c_str());
3725 
3726  response=sendMsg(msg, node.c_str());
3727 
3728  return response.get(0).asString()=="sigtermall OK"?0:YARPRUN_ERROR;
3729 }
3730 
3732 {
3733  yarp::os::Bottle msg, grp, response;
3734 
3735  grp.clear();
3736  grp.addString("on");
3737  grp.addString(node.c_str());
3738  msg.addList()=grp;
3739 
3740  grp.clear();
3741  grp.addString("kill");
3742  grp.addString(keyv.c_str());
3743  grp.addInt(s);
3744  msg.addList()=grp;
3745 
3746  printf(":: %s\n", msg.toString().c_str());
3747 
3748  response=sendMsg(msg, node.c_str());
3749 
3750  return response.get(0).asString()=="kill OK"?0:YARPRUN_ERROR;
3751 }
3752 
3754 {
3755  yarp::os::Bottle msg, grp, response;
3756 
3757  grp.clear();
3758  grp.addString("on");
3759  grp.addString(node.c_str());
3760  msg.addList()=grp;
3761 
3762  grp.clear();
3763  grp.addString("isrunning");
3764  grp.addString(keyv.c_str());
3765  msg.addList()=grp;
3766 
3767  printf(":: %s\n", msg.toString().c_str());
3768 
3769  response=sendMsg(msg, node.c_str());
3770 
3771  if (!response.size()) return false;
3772 
3773  return response.get(0).asString()=="running";
3774 }
3775 
3776 // end API
static ConstString getDirectorySeparator()
Get an OS-appropriate directory separator (e.g.
Definition: Network.cpp:1075
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:1085
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:3690
void setEnv(const yarp::os::ConstString &env)
void setVerbosity(int verbose=0)
Definition: Logger.h:155
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:3731
#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:2385
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:1055
static bool getLocalMode()
Get current value of flag "localMode", see setLocalMode function.
Definition: Network.cpp:738
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:982
#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:81
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:2363
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:952
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:1026
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:1054
#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:3753
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:526
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:964
static int start(const ConstString &node, Property &command, ConstString &keyv)
Launch a yarprun server.
Definition: Run.cpp:3632
static void sigchld_handler(int sig)
Definition: Run.cpp:815
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:544
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:1223
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