Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

ExecutableCommPort.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_ExecutableCommPort_h_
00003 #define INCLUDED_ExecutableCommPort_h_
00004 
00005 #include "local/CommPort.h"
00006 #include "Wireless/netstream.h"
00007 
00008 //! Run a specified executable, with the comm port connected to its stdin and stdout
00009 /*! This can be handy for testing with a device simulator, or if you want to
00010  *  interface with a device as an external process.  It's more efficient to run your
00011  *  driver as an DeviceDriver subclass than to spawn an external process however.
00012  *
00013  *  If you need to keep your external program running across instances of the
00014  *  simulator (or just want to launch it externally), you'll need to use file system
00015  *  fifos (see mkfifo command), probably separate ones for reading and writing
00016  *  with a RedirectionCommPort to combine them (unless your platform supports
00017  *  bidirectional pipes... most don't) */
00018 class ExecutableCommPort : public CommPort, public virtual plist::PrimitiveListener {
00019 public:
00020   explicit ExecutableCommPort(const std::string& name)
00021     : CommPort(autoRegisterExecutableCommPort,name),
00022     command(), shell("sh"), child(0), rbuf(), wbuf(), openedCnt(0)
00023   {
00024     addEntry("Command",command,"Specifies the shell command to run, stdio from this process will be piped through the comm port");
00025     addEntry("Shell",shell,"The shell executable to use for executing the command, can be found via PATH, or explicit path\n"
00026              "The shell will be passed '-c' and then your command");
00027   }
00028   
00029   //! destructor, checks that child process is no longer running, kills it if it is (after some delay)
00030   virtual ~ExecutableCommPort();
00031   
00032   virtual std::string getClassName() const { return autoRegisterExecutableCommPort; }
00033   
00034   virtual streambuf& getReadStreambuf() { return rbuf; }
00035   virtual streambuf& getWriteStreambuf() { return wbuf; }
00036   virtual bool isWriteable() { wbuf.update_status(); return wbuf.is_open(); }
00037   virtual bool isReadable() { rbuf.update_status(); return rbuf.is_open(); }
00038   
00039   //! launches the executable, connecting its stdin and stdout to this comm port
00040   virtual bool open();
00041   
00042   //! sends kill signal to the child process
00043   virtual bool close();
00044   
00045   //! if #command is modified, close current connection (if running) and launch new one
00046   virtual void plistValueChanged(const plist::PrimitiveBase& pl);
00047   
00048   plist::Primitive<std::string> command; //!< shell command
00049   plist::Primitive<std::string> shell; //!< shell name
00050   
00051 protected:
00052   pid_t child; //!< process ID of the child (0 if not launched, -1 if error)
00053   
00054   basic_netbuf<std::ios::char_type> rbuf; //!< reads from child process
00055   basic_netbuf<std::ios::char_type> wbuf; //!< writes to child process
00056   
00057   unsigned int openedCnt; //!< reference count of the number of times we've been opened (i.e. pending close()s)
00058   
00059   enum {
00060     READPIPE=0, //!< pipe() system call returns read end on the first entry, lets make it symbolic so it's more clear
00061     WRITEPIPE=1 //!< pipe() system call returns write end on the second entry, lets make it symbolic so it's more clear
00062   };
00063   
00064   //! waits for child process to exit for t milliseconds, polling status every p millseconds, returns true if no longer running
00065   bool waitChild(unsigned int t, unsigned int p);
00066   
00067   //! returns true if child is still running
00068   bool isChildRunning() const;
00069 
00070   //! holds the class name, set via registration with the CommPort registry
00071   static const std::string autoRegisterExecutableCommPort;
00072 };
00073 
00074 /*! @file
00075  * @brief 
00076  * @author Ethan Tira-Thompson (ejt) (Creator)
00077  */
00078 
00079 #endif

Tekkotsu Hardware Abstraction Layer 5.1CVS
Generated Mon May 9 05:01:38 2016 by Doxygen 1.6.3