00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <netcomm/fawkes/client.h>
00024 #include <config/netconf.h>
00025 #include <utils/system/argparser.h>
00026 #include <utils/system/signal.h>
00027
00028 #include <iostream>
00029 #include <cstring>
00030 #include <cstdlib>
00031 #include <cstdio>
00032
00033 using namespace fawkes;
00034
00035
00036
00037 class ConfigChangeWatcherTool : public ConfigurationChangeHandler, public SignalHandler
00038 {
00039 public:
00040
00041
00042
00043
00044
00045 ConfigChangeWatcherTool(Configuration *config, FawkesNetworkClient *c)
00046 {
00047 this->c = c;
00048 this->config = config;
00049 quit = false;
00050 config->add_change_handler(this);
00051 }
00052
00053 virtual void handle_signal(int signal)
00054 {
00055 config->rem_change_handler(this);
00056 quit = true;
00057 }
00058
00059 virtual void config_tag_changed(const char *new_tag)
00060 {
00061 printf("--> New tag loaded: %s\n", new_tag);
00062 }
00063
00064 virtual void config_value_changed(const char *path, bool is_default, int value)
00065 {
00066 printf("%s %-55s| %-8s| %-14i\n", is_default ? "*" : " ", path, "int", value);
00067 }
00068
00069 virtual void config_value_changed(const char *path, bool is_default, unsigned int value)
00070 {
00071 printf("%s %-55s| %-8s| %-14u\n", is_default ? "*" : " ", path, "uint", value);
00072 }
00073
00074 virtual void config_value_changed(const char *path, bool is_default, float value)
00075 {
00076 printf("%s %-55s| %-8s| %-14f\n", is_default ? "*" : " ", path, "float", value);
00077 }
00078
00079 virtual void config_value_changed(const char *path, bool is_default, bool value)
00080 {
00081 printf("%s %-55s| %-8s| %-14s\n", is_default ? "*" : " ", path, "bool", (value ? "true" : "false"));
00082 }
00083
00084 virtual void config_value_changed(const char *path, bool is_default, const char *value)
00085 {
00086 printf("%s %-55s| %-8s| %-14s\n", is_default ? "*" : " ", path, "string", value);
00087 }
00088
00089 virtual void config_comment_changed(const char *path, bool is_default, const char *comment)
00090 {
00091 printf("%s %s: %s\n", is_default ? "C" : "c", path, comment);
00092 }
00093
00094 virtual void config_value_erased(const char *path, bool is_default)
00095 {
00096 printf("%s %-55s| %-8s| %-14s\n", is_default ? "*" : " ", path, "", "ERASED");
00097 }
00098
00099
00100
00101
00102
00103 void
00104 run()
00105 {
00106 while ( ! quit ) {
00107 c->wait(FAWKES_CID_CONFIGMANAGER);
00108 }
00109 }
00110
00111 private:
00112 FawkesNetworkClient *c;
00113 Configuration *config;
00114 bool quit;
00115
00116 };
00117
00118
00119
00120 void
00121 print_header()
00122 {
00123 printf("D %-55s| %-8s| %-14s\n", "Path", "Type", "Value");
00124 printf("--------------------------------------------------------------------------------------\n");
00125 }
00126
00127
00128
00129
00130 void
00131 print_value(Configuration::ValueIterator *i, bool show_comment = false)
00132 {
00133 if ( i->is_float() ) {
00134 printf("%s %-55s| %-8s| %-14f\n", (i->is_default() ? "*" : " "), i->path(), i->type(), i->get_float());
00135 } else if ( i->is_uint() ) {
00136 printf("%s %-55s| %-8s| %-14u\n", (i->is_default() ? "*" : " "), i->path(), "uint", i->get_uint());
00137 } else if ( i->is_int() ) {
00138 printf("%s %-55s| %-8s| %-14i\n", (i->is_default() ? "*" : " "), i->path(), i->type(), i->get_int());
00139 } else if ( i->is_bool() ) {
00140 printf("%s %-55s| %-8s| %-14s\n", (i->is_default() ? "*" : " "), i->path(), i->type(), (i->get_bool() ? "true" : "false"));
00141 } else if ( i->is_string() ) {
00142 printf("%s %-55s| %-8s| %-14s\n", (i->is_default() ? "*" : " "), i->path(), i->type(), i->get_string().c_str());
00143 }
00144
00145 if (show_comment) {
00146 try {
00147 std::string comment = i->get_comment();
00148 if (comment != "") {
00149 printf("C %-55s: %s\n", i->path(), comment.c_str());
00150 }
00151 } catch (Exception &e) {
00152
00153 }
00154 }
00155 }
00156
00157
00158
00159
00160 void
00161 print_line(Configuration::ValueIterator *i, bool show_comment = false)
00162 {
00163 if ( i->is_float() ) {
00164 printf("%-14f\n", i->get_float());
00165 } else if ( i->is_uint() ) {
00166 printf("%-14u\n", i->get_uint());
00167 } else if ( i->is_int() ) {
00168 printf("%-14i\n", i->get_int());
00169 } else if ( i->is_bool() ) {
00170 printf("%-14s\n", (i->get_bool() ? "true" : "false"));
00171 } else if ( i->is_string() ) {
00172 printf("%-14s\n", i->get_string().c_str());
00173 }
00174 }
00175
00176
00177 void
00178 print_usage(const char *program_name)
00179 {
00180 std::cout << "Usage: " << program_name << " [options] <cmd>" << std::endl
00181 << "where cmd is one of the following:" << std::endl << std::endl
00182 << " list" << std::endl
00183 << " List all configuration items" << std::endl << std::endl
00184 << " watch" << std::endl
00185 << " Watch configuration changes" << std::endl << std::endl
00186 << " get <path>" << std::endl
00187 << " Get value for the given path" << std::endl << std::endl
00188 << " set <path> <value> [type]" << std::endl
00189 << " Set value for the given path to the given type and value" << std::endl
00190 << " where type is one of float/uint/int/bool/string. The type" << std::endl
00191 << " is only necessary if you are creating a new value" << std::endl << std::endl
00192 << " set_default <path> <value> [type]" << std::endl
00193 << " Set default value for the given path to the given type and value" << std::endl
00194 << " where type is one of float/uint/int/bool/string. The type" << std::endl
00195 << " is only necessary if you are creating a new value" << std::endl << std::endl
00196 << " set_comment <path> <comment>" << std::endl
00197 << " Set comment for the given path to the given value. The value at" << std::endl
00198 << " the given path must already exist in the host-specific configuration." << std::endl << std::endl
00199 << " set_default_comment <path> <comment>" << std::endl
00200 << " Set default comment for the given path to the given value. The value at" << std::endl
00201 << " the given path must already exist in the default configuration." << std::endl << std::endl
00202 << " erase <path>" << std::endl
00203 << " Erase value for given path from config" << std::endl
00204 << " erase_default <path>" << std::endl
00205 << " Erase default value for given path from config" << std::endl << std::endl
00206 << "and options is none, one or more of the following:" << std::endl << std::endl
00207 << " -c Show comments (only available with list and watch cmd)" << std::endl
00208 << " -a Show all values, even double if default and host-specific " << std::endl
00209 << " values exist (only available with list)" << std::endl
00210 << " -q Quiet. Only show important output, suitable for parsing. " << std::endl
00211 << " (not supported for all commands yet) " << std::endl
00212 << " -r host[:port] Remote host (and optionally port) to connect to\n" << std::endl
00213 << std::endl;
00214 }
00215
00216
00217
00218
00219
00220 int
00221 main(int argc, char **argv)
00222 {
00223 ArgumentParser argp(argc, argv, "+hcar:q");
00224
00225 if ( argp.has_arg("h") ) {
00226 print_usage(argv[0]);
00227 exit(0);
00228 }
00229
00230 std::string host = "localhost";
00231 unsigned short int port = 1910;
00232 if ( argp.has_arg("r") ) {
00233 argp.parse_hostport("r", host, port);
00234 }
00235
00236 bool quiet;
00237 if ( argp.has_arg("q") ) {
00238 quiet = true;
00239 } else {
00240 quiet = false;
00241 }
00242
00243 FawkesNetworkClient *c = new FawkesNetworkClient(host.c_str(), port);
00244 try {
00245 c->connect();
00246 } catch( Exception &e ) {
00247 printf("Could not connect to host: %s\n", host.c_str());
00248 exit(1);
00249 }
00250
00251 NetworkConfiguration *netconf = new NetworkConfiguration(c);
00252
00253 const std::vector< const char* > & args = argp.items();
00254
00255 if ( args.size() == 0) {
00256
00257 printf("Not enough args\n\n");
00258 print_usage(argv[0]);
00259 } else if (strcmp("get", args[0]) == 0) {
00260 if (args.size() == 2) {
00261 if( ! quiet ) {
00262 printf("Requesting value %s\n", args[1]);
00263 }
00264 Configuration::ValueIterator *i = netconf->get_value(args[1]);
00265 if ( i->next() ) {
00266 if( quiet ) {
00267 print_line(i);
00268 } else {
00269 print_header();
00270 print_value(i);
00271 }
00272 } else {
00273 printf("No such value found!\n");
00274 }
00275 delete i;
00276 } else {
00277
00278 printf("You must supply path argument\n");
00279 }
00280 } else if ((strcmp("set", args[0]) == 0) || (strcmp("set_default", args[0]) == 0)) {
00281 bool set_def = (strcmp("set_default", args[0]) == 0);
00282 if (args.size() >= 3) {
00283
00284 printf("Requesting old value for %s\n", args[1]);
00285 Configuration::ValueIterator *i = netconf->get_value(args[1]);
00286 print_header();
00287 printf("OLD:\n");
00288 if ( i->next() ) {
00289 print_line(i);
00290 } else {
00291 printf("Value does not currently exist in configuration.\n");
00292 }
00293
00294 std::string desired_type = "";
00295 if (args.size() == 4) {
00296
00297 desired_type = args[3];
00298 }
00299
00300 if ( (desired_type == "") && ! i->valid()) {
00301 printf("Please specify type\n");
00302 delete i;
00303 } else if ( (desired_type != "") && (i->valid() && (desired_type != i->type())) ) {
00304 printf("The given type '%s' contradicts with type '%s' in config. "
00305 "Erase before setting with new type.\n", desired_type.c_str(), i->type());
00306 delete i;
00307 } else {
00308 if ( i->valid() ) desired_type = i->type();
00309
00310 if ( desired_type == "float" ) {
00311 char *endptr;
00312 float f = strtod(args[2], &endptr);
00313 if ( endptr[0] != 0 ) {
00314 printf("ERROR: '%s' is not a float\n", args[2]);
00315 } else {
00316 if ( ! set_def ) {
00317 netconf->set_float(args[1], f);
00318 } else {
00319 netconf->set_default_float(args[1], f);
00320 }
00321 }
00322 } else if ( (desired_type == "unsigned int") || (desired_type == "uint") ) {
00323 char *endptr;
00324 long int li = strtol(args[2], &endptr, 10);
00325 if ( (endptr[0] != 0) || (li < 0) ) {
00326 printf("ERROR: '%s' is not an unsigned int\n", args[2]);
00327 } else {
00328 if ( ! set_def ) {
00329 netconf->set_uint(args[1], li);
00330 } else {
00331 netconf->set_default_uint(args[1], li);
00332 }
00333 }
00334 } else if ( desired_type == "int" ) {
00335 char *endptr;
00336 long int li = strtol(args[2], &endptr, 10);
00337 if ( endptr[0] != 0 ) {
00338 printf("ERROR: '%s' is not an int\n", args[2]);
00339 } else {
00340 if ( ! set_def ) {
00341 netconf->set_int(args[1], li);
00342 } else {
00343 netconf->set_default_int(args[1], li);
00344 }
00345 }
00346 } else if ( desired_type == "bool" ) {
00347 bool valid = false;
00348 bool b;
00349 if ( strcasecmp("true", args[2]) == 0 ) {
00350 b = true;
00351 valid = true;
00352 } else if ( strcasecmp("false", args[2]) == 0 ) {
00353 b = false;
00354 valid = true;
00355 } else {
00356 printf("ERROR: '%s' is not a boolean.\n", args[2]);
00357 }
00358 if (valid) {
00359 if ( ! set_def ) {
00360 netconf->set_bool(args[1], b);
00361 } else {
00362 netconf->set_default_bool(args[1], b);
00363 }
00364 }
00365 } else if ( desired_type == "string" ) {
00366 if ( ! set_def ) {
00367 netconf->set_string(args[1], args[2]);
00368 } else {
00369 netconf->set_default_string(args[1], args[2]);
00370 }
00371 } else {
00372 printf("Invalid type: %s\n", desired_type.c_str());
00373 }
00374
00375 delete i;
00376
00377 printf("NEW:\n");
00378 i = netconf->get_value(args[1]);
00379 if ( i->next() ) {
00380 print_line(i);
00381 } else {
00382 printf("ERROR: value does not exist\n");
00383 }
00384 delete i;
00385
00386 }
00387 } else {
00388 printf("Usage: %s set <path> <value> [type]\n", argp.program_name());
00389 }
00390 } else if ((strcmp("set_comment", args[0]) == 0) ||
00391 (strcmp("set_default_comment", args[0]) == 0)) {
00392 bool set_def = (strcmp("set_default_comment", args[0]) == 0);
00393 if (args.size() >= 3) {
00394
00395
00396 if ( ! set_def ) {
00397 netconf->set_comment(args[1], args[2]);
00398 } else {
00399 netconf->set_default_comment(args[1], args[2]);
00400 }
00401
00402 } else {
00403 printf("Usage: %s set_(default_)comment <path> <value>\n", argp.program_name());
00404 }
00405 } else if ((strcmp("erase", args[0]) == 0) || (strcmp("erase_default", args[0]) == 0)) {
00406 bool erase_def = (strcmp("erase_default", args[0]) == 0);
00407 if (args.size() == 2) {
00408 printf("Erasing %svalue %s\n", (erase_def ? "default " : ""), args[1]);
00409 bool found = false;
00410 Configuration::ValueIterator *i = netconf->get_value(args[1]);
00411 if ( i->next() ) {
00412 print_header();
00413 print_line(i);
00414 found = true;
00415 } else {
00416 printf("No such value found!\n");
00417 }
00418 delete i;
00419 if ( found ) {
00420 if ( erase_def ) {
00421 netconf->erase_default(args[1]);
00422 } else {
00423 netconf->erase(args[1]);
00424 }
00425 i = netconf->get_value(args[1]);
00426 if ( i->next() ) {
00427 printf("Failed to erase %s (default vs. non-default?)\n", args[1]);
00428 } else {
00429 printf("Successfully erased %s\n", args[1]);
00430 }
00431 delete i;
00432 }
00433 } else {
00434
00435 printf("You must supply path argument\n");
00436 }
00437 } else if (strcmp("watch", args[0]) == 0) {
00438 try {
00439 netconf->set_mirror_mode(true);
00440 } catch (Exception &e) {
00441 e.print_trace();
00442 return -1;
00443 }
00444 print_header();
00445 netconf->lock();
00446 Configuration::ValueIterator *i = netconf->iterator();
00447 while ( i->next() ) {
00448 print_line(i, argp.has_arg("c"));
00449 }
00450 delete i;
00451 netconf->unlock();
00452 printf("------------------------------------------------------------------------------------\n");
00453 printf("Modifications since watching:\n");
00454 printf("------------------------------------------------------------------------------------\n");
00455 ConfigChangeWatcherTool ccwt(netconf, c);
00456 ccwt.run();
00457 } else if (strcmp("list", args[0]) == 0) {
00458 printf("Transmitting config from host... ");
00459 fflush(stdout);
00460 try {
00461 netconf->set_mirror_mode(true);
00462 } catch (Exception &e) {
00463 e.print_trace();
00464 return -1;
00465 }
00466 netconf->lock();
00467 printf("done\n");
00468 print_header();
00469 bool show_comments = argp.has_arg("c");
00470 if (argp.has_arg("a")) {
00471 printf("DEFAULT ENTRIES\n");
00472 Configuration::ValueIterator *i = netconf->iterator_default();
00473 while ( i->next() ) {
00474 print_line(i, show_comments);
00475 }
00476 delete i;
00477 printf("HOST-SPECIFIC ENTRIES\n");
00478 i = netconf->iterator_hostspecific();
00479 while ( i->next() ) {
00480 print_line(i, show_comments);
00481 }
00482 delete i;
00483 } else {
00484 Configuration::ValueIterator *i = netconf->iterator();
00485 while ( i->next() ) {
00486 print_line(i, show_comments);
00487 }
00488 delete i;
00489 }
00490 netconf->unlock();
00491 }
00492
00493 if( ! quiet ) {
00494 printf("Cleaning up... ");
00495 }
00496 fflush(stdout);
00497 delete netconf;
00498 c->disconnect();
00499
00500 delete c;
00501 if( ! quiet ) {
00502 printf("done\n");
00503 }
00504
00505 return 0;
00506 }