+/**
+ * We have a command.
+ *
+ */
+void
+PropsChannel::foundTerminator()
+{
+ const char* cmd = buffer.getData();
+ SG_LOG( SG_IO, SG_INFO, "processing command = \"" << cmd << "\"" );
+
+ ParameterList tokens = simgear::strutils::split( cmd );
+
+ SGPropertyNode* node = globals->get_props()->getNode( path.c_str() );
+
+ try {
+ if (!tokens.empty()) {
+ string command = tokens[0];
+
+ if (command == "ls") {
+ SGPropertyNode* dir = node;
+ if (tokens.size() == 2) {
+ if (tokens[1][0] == '/') {
+ dir = globals->get_props()->getNode( tokens[1].c_str() );
+ } else {
+ string s = path;
+ s += "/";
+ s += tokens[1];
+ dir = globals->get_props()->getNode( s.c_str() );
+ }
+
+ if (dir == 0) {
+ node_not_found_error( tokens[1] );
+ }
+ }
+
+ for (int i = 0; i < dir->nChildren(); i++) {
+ SGPropertyNode * child = dir->getChild(i);
+ string line = child->getDisplayName(true);
+
+ if ( child->nChildren() > 0 ) {
+ line += "/";
+ } else {
+ if (mode == PROMPT) {
+ string value = child->getStringValue();
+ line += " =\t'" + value + "'\t(";
+ line += getValueTypeString( child );
+ line += ")";
+ }
+ }
+
+ line += getTerminator();
+ push( line.c_str() );
+ }
+ } else if ( command == "dump" ) {
+ stringstream buf;
+ if ( tokens.size() <= 1 ) {
+ writeProperties( buf, node );
+ buf << ends; // null terminate the string
+ push( buf.str().c_str() );
+ push( getTerminator() );
+ } else {
+ SGPropertyNode *child = node->getNode( tokens[1].c_str() );
+ if ( child ) {
+ writeProperties ( buf, child );
+ buf << ends; // null terminate the string
+ push( buf.str().c_str() );
+ push( getTerminator() );
+ } else {
+ node_not_found_error( tokens[1] );
+ }
+ }
+ }
+ else if ( command == "cd" ) {
+ if (tokens.size() == 2) {
+ SGPropertyNode* child = node->getNode( tokens[1].c_str() );
+ if ( child ) {
+ node = child;
+ path = node->getPath();
+ } else {
+ node_not_found_error( tokens[1] );
+ }
+ }
+ } else if ( command == "pwd" ) {
+ string pwd = node->getPath();
+ if (pwd.empty()) {
+ pwd = "/";
+ }
+
+ push( pwd.c_str() );
+ push( getTerminator() );
+ } else if ( command == "get" || command == "show" ) {
+ if ( tokens.size() == 2 ) {
+ string tmp;
+ string value = node->getStringValue ( tokens[1].c_str(), "" );
+ if ( mode == PROMPT ) {
+ tmp = tokens[1];
+ tmp += " = '";
+ tmp += value;
+ tmp += "' (";
+ tmp += getValueTypeString(
+ node->getNode( tokens[1].c_str() ) );
+ tmp += ")";
+ } else {
+ tmp = value;
+ }
+ push( tmp.c_str() );
+ push( getTerminator() );
+ }
+ } else if ( command == "set" ) {
+ if ( tokens.size() >= 2 ) {
+ string value, tmp;
+ for (unsigned int i = 2; i < tokens.size(); i++) {
+ if (i > 2)
+ value += " ";
+ value += tokens[i];
+ }
+ node->getNode( tokens[1].c_str(), true )
+ ->setStringValue(value.c_str());
+
+ if ( mode == PROMPT ) {
+ // now fetch and write out the new value as confirmation
+ // of the change
+ value = node->getStringValue ( tokens[1].c_str(), "" );
+ tmp = tokens[1] + " = '" + value + "' (";
+ tmp += getValueTypeString( node->getNode( tokens[1].c_str() ) );
+ tmp += ")";
+ push( tmp.c_str() );
+ push( getTerminator() );
+ }
+ }
+ } else if ( command == "reinit" ) {
+ if ( tokens.size() == 2 ) {
+ string tmp;
+ SGPropertyNode args;
+ for ( unsigned int i = 1; i < tokens.size(); ++i ) {
+ cout << "props: adding subsystem = " << tokens[i] << endl;
+ SGPropertyNode *node = args.getNode("subsystem", i-1, true);
+ node->setStringValue( tokens[i].c_str() );
+ }
+ if ( !globals->get_commands()
+ ->execute( "reinit", &args) )
+ {
+ SG_LOG( SG_NETWORK, SG_ALERT,
+ "Command " << tokens[1] << " failed.");
+ if ( mode == PROMPT ) {
+ tmp += "*failed*";
+ push( tmp.c_str() );
+ push( getTerminator() );
+ }
+ } else {
+ if ( mode == PROMPT ) {
+ tmp += "<completed>";
+ push( tmp.c_str() );
+ push( getTerminator() );
+ }
+ }
+ }
+ } else if ( command == "run" ) {
+ string tmp;
+ if ( tokens.size() >= 2 ) {
+ SGPropertyNode args;
+ if ( tokens[1] == "reinit" ) {
+ for ( unsigned int i = 2; i < tokens.size(); ++i ) {
+ cout << "props: adding subsystem = " << tokens[i]
+ << endl;
+ SGPropertyNode *node
+ = args.getNode("subsystem", i-2, true);
+ node->setStringValue( tokens[i].c_str() );
+ }
+ } else if ( tokens[1] == "set-sea-level-air-temp-degc" ) {
+ for ( unsigned int i = 2; i < tokens.size(); ++i ) {
+ cout << "props: set-sl command = " << tokens[i]
+ << endl;
+ SGPropertyNode *node
+ = args.getNode("temp-degc", i-2, true);
+ node->setStringValue( tokens[i].c_str() );
+ }
+ } else if ( tokens[1] == "set-outside-air-temp-degc" ) {
+ for ( unsigned int i = 2; i < tokens.size(); ++i ) {
+ cout << "props: set-oat command = " << tokens[i]
+ << endl;
+ SGPropertyNode *node
+ = args.getNode("temp-degc", i-2, true);
+ node->setStringValue( tokens[i].c_str() );
+ }
+ } else if ( tokens[1] == "timeofday" ) {
+ for ( unsigned int i = 2; i < tokens.size(); ++i ) {
+ cout << "props: time of day command = " << tokens[i]
+ << endl;
+ SGPropertyNode *node
+ = args.getNode("timeofday", i-2, true);
+ node->setStringValue( tokens[i].c_str() );
+ }
+ } else if ( tokens[1] == "play-audio-message" ) {
+ if ( tokens.size() == 4 ) {
+ cout << "props: play audio message = " << tokens[2]
+ << " " << tokens[3] << endl;
+ SGPropertyNode *node;
+ node = args.getNode("path", 0, true);
+ node->setStringValue( tokens[2].c_str() );
+ node = args.getNode("file", 0, true);
+ node->setStringValue( tokens[3].c_str() );
+ }
+ }
+ if ( !globals->get_commands()
+ ->execute(tokens[1].c_str(), &args) )
+ {
+ SG_LOG( SG_NETWORK, SG_ALERT,
+ "Command " << tokens[1] << " failed.");
+ if ( mode == PROMPT ) {
+ tmp += "*failed*";
+ push( tmp.c_str() );
+ push( getTerminator() );
+ }
+ } else {
+ if ( mode == PROMPT ) {
+ tmp += "<completed>";
+ push( tmp.c_str() );
+ push( getTerminator() );
+ }
+ }
+ } else {
+ if ( mode == PROMPT ) {
+ tmp += "no command specified";
+ push( tmp.c_str() );
+ push( getTerminator() );
+ }
+ }
+ } else if ( command == "quit" || command == "exit" ) {
+ close();
+ shouldDelete();
+ return;
+ } else if ( command == "data" ) {
+ mode = DATA;
+ } else if ( command == "prompt" ) {
+ mode = PROMPT;
+ } else if (callback_map.find(command) != callback_map.end() ) {
+ TelnetCallback t = callback_map[ command ];
+ if (t)
+ (this->*t) (tokens);
+ else
+ error("No matching callback found for command:"+command);
+ }
+ else {
+ const char* msg = "\
+Valid commands are:\r\n\
+\r\n\
+cd <dir> cd to a directory, '..' to move back\r\n\
+data switch to raw data mode\r\n\
+dump dump current state (in xml)\r\n\
+get <var> show the value of a parameter\r\n\
+help show this help message\r\n\
+ls [<dir>] list directory\r\n\
+prompt switch to interactive mode (default)\r\n\
+pwd display your current path\r\n\
+quit terminate connection\r\n\
+run <command> run built in command\r\n\
+set <var> <val> set <var> to a new <val>\r\n\
+subscribe <var> subscribe to property changes \r\n\
+unscubscribe <var> unscubscribe from property changes (var must be the property name/path used by subscribe)\r\n";
+ push( msg );
+ }
+ }
+
+ } catch ( const string& msg ) {
+ string error = "-ERR \"" + msg + "\"";
+ push( error.c_str() );
+ push( getTerminator() );