#include "ace/OS_NS_stdio.h" #include "ace/OS_NS_fcntl.h" #include "ace/OS_NS_pwd.h" #include "ace/os_include/os_pwd.h" #include "ace/OS_NS_stdlib.h" #include "ace/OS_NS_string.h" #include "ace/OS_NS_unistd.h" #include "ace/OS_NS_pwd.h" #include "ace/Process.h" #include "ace/Log_Msg.h" // Listing 1 code/ch10 class Manager : public ACE_Process { public: Manager (const ACE_TCHAR* program_name) { ACE_TRACE ("Manager::Manager"); ACE_OS::strcpy (programName_, program_name); } int doWork () { ACE_TRACE ("Manager::doWork"); // Spawn the new process; prepare() hook is called first. ACE_Process_Options options; pid_t pid = this->spawn (options); if (pid == ACE_INVALID_PID) ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("spawn")), -1); // Wait forever for my child to exit. if (this->wait () == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("wait")), -1); // Dump whatever happened. this->dumpRun (); return 0; } // Listing 1 private: // Listing 3 code/ch10 int dumpRun () { ACE_TRACE ("Manager::dumpRun"); if (ACE_OS::lseek (this->outputfd_, 0, SEEK_SET) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("lseek")), -1); char buf[1024]; ssize_t length = 0; // Read the contents of the error stream written // by the child and print it out. while ((length = ACE_OS::read (this->outputfd_, buf, sizeof(buf)-1)) > 0) { buf[length] = 0; ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%C\n"), buf)); } ACE_OS::close (this->outputfd_); return 0; } // Listing 3 // Listing 2 code/ch10 // prepare() is inherited from ACE_Process. int prepare (ACE_Process_Options &options) { ACE_TRACE ("Manager::prepare"); options.command_line (ACE_TEXT ("%s 1"), this->programName_); if (this->setStdHandles (options) == -1 || this->setEnvVariable (options) == -1) return -1; #if !defined (ACE_WIN32) && !defined (ACE_LACKS_PWD_FUNCTIONS) return this->setUserID (options); #else return 0; #endif } int setStdHandles (ACE_Process_Options &options) { ACE_TRACE ("Manager::setStdHandles"); ACE_OS::unlink ("output.dat"); this->outputfd_ = ACE_OS::open ("output.dat", O_RDWR | O_CREAT); return options.set_handles (ACE_STDIN, ACE_STDOUT, this->outputfd_); } int setEnvVariable (ACE_Process_Options &options) { ACE_TRACE ("Manager::setEnvVariables"); return options.setenv (ACE_TEXT ("PRIVATE_VAR=/that/seems/to/be/it")); } // Listing 2 #if !defined (ACE_LACKS_PWD_FUNCTIONS) // Listing 10 code/ch10 int setUserID (ACE_Process_Options &options) { ACE_TRACE ("Manager::setUserID"); passwd* pw = ACE_OS::getpwnam ("nobody"); if (pw == 0) return -1; options.seteuid (pw->pw_uid); return 0; } // Listing 10 #endif /* !ACE_LACKS_PWD_FUNCTIONS */ private: ACE_HANDLE outputfd_; ACE_TCHAR programName_[256]; }; // Listing 4 code/ch10 class Slave { public: Slave () { ACE_TRACE ("Slave::Slave"); } int doWork () { ACE_TRACE ("Slave::doWork"); ACE_DEBUG ((LM_INFO, ACE_TEXT ("(%P) started at %T, parent is %d\n"), ACE_OS::getppid ())); this->showWho (); ACE_DEBUG ((LM_INFO, ACE_TEXT ("(%P) the private environment is %s\n"), ACE_OS::getenv ("PRIVATE_VAR"))); ACE_TCHAR str[128]; ACE_OS::sprintf (str, ACE_TEXT ("(%d) Enter your command\n"), static_cast(ACE_OS::getpid ())); ACE_OS::write (ACE_STDOUT, str, ACE_OS::strlen (str)); this->readLine (str); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P) Executed: %C\n"), str)); return 0; } // Listing 4 void showWho () { ACE_TRACE ("Slave::showWho"); #if !defined (ACE_LACKS_PWD_FUNCTIONS) passwd *pw = ::getpwuid (ACE_OS::geteuid ()); ACE_DEBUG ((LM_INFO, ACE_TEXT ("(%P) Running this process as:%s\n"), pw->pw_name)); #endif } ACE_TCHAR* readLine (ACE_TCHAR* str) { ACE_TRACE ("Slave::readLine"); int i = 0; while (true) { ssize_t retval = ACE_OS::read (ACE_STDIN, &str[i], 1); if (retval > 0) { if (str[i] == '\n') { str[++i] = 0; return str; } i++; } else return str; } } }; // Listing 0 code/ch10 int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) { if (argc > 1) // Slave mode { Slave s; return s.doWork (); } // Else, Master mode Manager m (argv[0]); return m.doWork (); } // Listing 0