Go to the documentation of this file.00001 #include <ros/ros.h>
00002 #include <stdio.h>
00003 #include <dirent.h>
00004 #include <stdlib.h>
00005 #include <vector>
00006 #include <string>
00007 using namespace std;
00008
00009 string g_screen_cmd = "screen";
00010
00011 bool executeCmd(const string & cmd)
00012 {
00013 int ret = system(cmd.c_str());
00014 if(ret != 0) {
00015 perror("executeCmd");
00016 ROS_ERROR("Command \"%s\" returned %d", cmd.c_str(), ret);
00017 return false;
00018 }
00019 return true;
00020 }
00021
00022 class ProgramEntry
00023 {
00024 public:
00025 string name;
00026 vector<string> commands;
00027
00028 void pushToScreen() {
00029 ROS_INFO("Creating screen window for \"%s\"", name.c_str());
00030 if(!executeCmd(g_screen_cmd + " -S ros -X screen -t '" + name + "'"))
00031 return;
00032 for(vector<string>::iterator it = commands.begin(); it != commands.end(); it++) {
00033 ROS_INFO("Pushing command: \"%s\"", it->c_str());
00034 if(!executeCmd(g_screen_cmd + " -p '" + name + "' -S ros -X eval 'stuff \"" + *it + "\"'"))
00035 return;
00036 }
00037 }
00038 };
00039
00040 vector<ProgramEntry> programs;
00041
00042 bool load()
00043 {
00044 ros::NodeHandle nh("~");
00045
00046 XmlRpc::XmlRpcValue xmlRpc;
00047 if(!nh.getParam("programs", xmlRpc)) {
00048 ROS_FATAL("No programs defined.");
00049 return false;
00050 }
00051
00052 if(xmlRpc.getType() != XmlRpc::XmlRpcValue::TypeArray) {
00053 ROS_FATAL("programs param should be a list.");
00054 return false;
00055 }
00056 if(xmlRpc.size() == 0) {
00057 ROS_FATAL("programs list is empty.");
00058 return false;
00059 }
00060
00061 for(int i = 0; i < xmlRpc.size(); i++) {
00062 ProgramEntry pe;
00063
00064 if(xmlRpc[i].getType() != XmlRpc::XmlRpcValue::TypeStruct) {
00065 ROS_FATAL("programs entry %d is not of type string.", i);
00066 return false;
00067 }
00068 pe.name = (string)xmlRpc[i]["name"];
00069 XmlRpc::XmlRpcValue cmds = xmlRpc[i]["commands"];
00070 if(cmds.getType() != XmlRpc::XmlRpcValue::TypeArray) {
00071 ROS_FATAL("commands for %s is not a list", pe.name.c_str());
00072 return false;
00073 }
00074 for(int j = 0; j < cmds.size(); j++) {
00075 pe.commands.push_back((string)cmds[j]);
00076 }
00077
00078 programs.push_back(pe);
00079 }
00080
00081 return true;
00082 }
00083
00084 string getScreenPath()
00085 {
00086 char* user = getenv("USER");
00087 if(!user)
00088 return "";
00089
00090 return string("/var/run/screen/S-") + user;
00091 }
00092
00093 bool screenRunning()
00094 {
00095 string sp = getScreenPath();
00096 if(sp.empty())
00097 return false;
00098
00099 DIR* dir = opendir(sp.c_str());
00100 if(!dir)
00101 return false;
00102 struct dirent* entry;
00103 while( (entry = readdir(dir)) ) {
00104 string dname = entry->d_name;
00105 if(dname.find("ros") != string::npos)
00106 return true;
00107 }
00108 return false;
00109 }
00110
00111 bool byobu_exists()
00112 {
00113 int ret = system("which byobu > /dev/null");
00114 return ret == 0;
00115 }
00116
00117 int main(int argc, char** argv)
00118 {
00119 ros::init(argc, argv, "screenrun");
00120
00121 if(argc > 1) {
00122 if(strcmp(argv[1], "b") == 0) {
00123 if(!byobu_exists()) {
00124 ROS_ERROR("Requested byobu for screen, but cannot find byobu executable. Install byobu for this. Falling back to screen for now.");
00125 } else {
00126 ROS_INFO("Using byobu for screen.");
00127 g_screen_cmd = "byobu";
00128 }
00129 }
00130 }
00131
00132 ros::NodeHandle nh;
00133
00134 if(!load())
00135 return 1;
00136
00137 if(screenRunning()) {
00138 ROS_WARN("Screen \"ros\" already running, reusing this session");
00139 } else {
00140 ROS_INFO("Creating screen \"ros\"");
00141 if(!executeCmd(g_screen_cmd + " -S ros -d -m")) {
00142 ROS_FATAL("failed");
00143 return 1;
00144 }
00145 }
00146
00147 for(vector<ProgramEntry>::iterator it = programs.begin(); it != programs.end(); it++) {
00148 it->pushToScreen();
00149 }
00150
00151 return 0;
00152 }