(file) Return to cli.cpp CVS log (file) (dir) Up to [OMI] / omi / cli

   1 mike  1.1 /*
   2           **==============================================================================
   3           **
   4           ** Open Management Infrastructure (OMI)
   5           **
   6           ** Copyright (c) Microsoft Corporation
   7           ** 
   8           ** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
   9           ** use this file except in compliance with the License. You may obtain a copy 
  10           ** of the License at 
  11           **
  12           **     http://www.apache.org/licenses/LICENSE-2.0 
  13           **
  14           ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15           ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
  16           ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
  17           ** MERCHANTABLITY OR NON-INFRINGEMENT. 
  18           **
  19           ** See the Apache 2 License for the specific language governing permissions 
  20           ** and limitations under the License.
  21           **
  22 mike  1.1 **==============================================================================
  23           */
  24           
  25           #include <climits>
  26           #include <cassert>
  27           #include <cstdlib>
  28           #include <cstdio>
  29           #include <string>
  30           #include <omiclient/client.h>
  31           #include <base/args.h>
  32           #include <base/result.h>
  33           #include <wql/wql.h>
  34           #include <base/strings.h>
  35           #include <base/paths.h>
  36           #include <base/conf.h>
  37           #include <base/env.h>
  38           #include <base/getopt.h>
  39           #include <base/io.h>
  40           #include <base/time.h>
  41           
  42           #define T MI_T
  43 mike  1.1 
  44           #if (MI_CHAR_TYPE == 1)
  45           #define STRF "%s"
  46           #else
  47           #define STRF "%S"
  48           #endif
  49           
  50           using namespace mi;
  51           
  52           const char* arg0;
  53           
  54           struct Options
  55           {
  56               bool help;
  57               bool quiet;
  58               bool suppressResults;
  59               bool trace;
  60               bool shallow;
  61               int repeat;
  62               String assocClass;
  63               String resultClass;
  64 mike  1.1     String role;
  65               String resultRole;
  66               String user;
  67               String password;
  68               Uint64 timeOut;
  69               unsigned int httpport;
  70               unsigned int httpsport;
  71               bool nulls;
  72               String querylang;
  73               String queryexpr;
  74           
  75               Options()
  76               {
  77                   Clear();
  78               }
  79           
  80               void Clear()
  81               {
  82                   help = false;
  83                   quiet = false;
  84                   suppressResults = false;
  85 mike  1.1         trace = false;
  86                   shallow = false;
  87                   repeat = 1;
  88                   assocClass.Clear();
  89                   resultClass.Clear();
  90                   role.Clear();
  91                   resultRole.Clear();
  92                   user.Clear();
  93                   password.Clear();
  94                   timeOut = 90 * 1000 * 1000;
  95                   httpport = CONFIG_HTTPPORT;
  96                   httpsport = CONFIG_HTTPSPORT;
  97                   nulls = false;
  98                   querylang.Clear();
  99                   queryexpr.Clear();
 100               }
 101           };
 102           
 103           static Options opts;
 104           
 105           static FILE* sout = stdout;
 106 mike  1.1 static FILE* serr = stderr;
 107           
 108           PRINTF_FORMAT(1, 2)
 109           static void err(const char* fmt, ...)
 110           {
 111               fprintf(serr, "%s: ", arg0);
 112           
 113               va_list ap;
 114               va_start(ap, fmt);
 115               vfprintf(serr, fmt, ap);
 116               va_end(ap);
 117           
 118               fputc('\n', serr);
 119           }
 120           
 121           static String MakeString(const char* str)
 122           {
 123               String s;
 124               while (*str)
 125                   s += MI_Char(*str++);
 126           
 127 mike  1.1     return s;
 128           }
 129           
 130           static std::string ZToStr(const MI_Char* str)
 131           {
 132               std::string r;
 133           
 134               while (*str)
 135                   r += char(*str++);
 136           
 137               return r;
 138           }
 139           
 140           static int FindConfigFile(char path[MAX_PATH_SIZE])
 141           {
 142               /* Look in current directory */
 143               {
 144                   Strlcpy(path, "./.omiclirc", MAX_PATH_SIZE);
 145           
 146                   if (access(path, R_OK) == 0)
 147                       return 0;
 148 mike  1.1     }
 149           
 150               /* Look in HOME directory */
 151               char* home = Dupenv("HOME");
 152               if (home)
 153               {
 154                   Strlcpy(path, home, MAX_PATH_SIZE);
 155                   Strlcat(path, "/.omiclirc", MAX_PATH_SIZE);
 156           
 157                   if (access(path, R_OK) == 0)
 158                   {
 159                       free(home);
 160                       return 0;
 161                   }
 162                   free(home);
 163               }
 164           
 165               /* Look in system config directory */
 166               {
 167                   Strlcpy(path, GetPath(ID_SYSCONFDIR), MAX_PATH_SIZE);
 168                   Strlcat(path, "/omicli.conf", MAX_PATH_SIZE);
 169 mike  1.1 
 170                   if (access(path, R_OK) == 0)
 171                       return 0;
 172               }
 173           
 174               /* Not found */
 175               return -1;
 176           }
 177           
 178           static int GetConfigFileOptions()
 179           {
 180               char path[MAX_PATH_SIZE];
 181               Conf* conf;
 182           
 183               /* Form the configuration file path (silently ignore if not found) */
 184               if (FindConfigFile(path) != 0)
 185                   return 0;
 186           
 187               /* Open the configuration file */
 188               conf = Conf_Open(path);
 189               if (!conf)
 190 mike  1.1     {
 191                   err("failed to open configuration file: %s", path);
 192                   return 1;
 193               }
 194           
 195               /* For each key=value pair in configuration file */
 196               for (;;)
 197               {
 198                   const char* key;
 199                   const char* value;
 200                   int r = Conf_Read(conf, &key, &value);
 201           
 202                   if (r == -1)
 203                   {
 204                       err("%s: %s\n", path, Conf_Error(conf));
 205                       return 1;
 206                   }
 207           
 208                   if (r == 1)
 209                       break;
 210           
 211 mike  1.1         if (strcmp(key, "httpport") == 0)
 212                   {
 213                       char* end;
 214                       unsigned long x = Strtoul(value, &end, 10);
 215           
 216                       if (*end != '\0' || x > USHRT_MAX)
 217                       {
 218                           err("%s(%u): invalid value for '%s': %s", path, 
 219                               Conf_Line(conf), key, value);
 220                           return 1;
 221                       }
 222           
 223                       opts.httpport = (unsigned short)x;
 224                   }
 225                   else if (strcmp(key, "httpsport") == 0)
 226                   {
 227                       char* end;
 228                       unsigned long x = Strtoul(value, &end, 10);
 229           
 230                       if (*end != '\0' || x > USHRT_MAX)
 231                       {
 232 mike  1.1                 err("%s(%u): invalid value for '%s': %s", path, 
 233                               Conf_Line(conf), key, value);
 234                           return 1;
 235                       }
 236           
 237                       opts.httpsport = (unsigned short)x;
 238                   }
 239                   else if (strcmp(key, "trace") == 0)
 240                   {
 241                       if (Strcasecmp(value, "true") == 0)
 242                       {
 243                           opts.trace = MI_TRUE;
 244                       }
 245                       else if (Strcasecmp(value, "false") == 0)
 246                       {
 247                           opts.trace = MI_FALSE;
 248                       }
 249                       else
 250                       {
 251                           err("%s(%u): invalid value for '%s': %s", path, 
 252                               Conf_Line(conf), key, value);
 253 mike  1.1                 return 1;
 254                       }
 255                   }
 256                   else if (IsNickname(key))
 257                   {
 258                       if (SetPathFromNickname(key, value) != 0)
 259                       {
 260                           err("SetPathFromNickname() failed");
 261                           return 1;
 262                       }
 263                   }
 264                   else
 265                   {
 266                       err("%s(%u): unknown key: %s", path, Conf_Line(conf), key);
 267                       return 1;
 268                   }
 269               }
 270           
 271               /* Close configuration file */
 272               Conf_Close(conf);
 273               return 0;
 274 mike  1.1 }
 275           
 276           static void GetCommandLineDestDirOption(
 277               int* argc_,
 278               const char* argv[])
 279           {
 280               int argc = *argc_;
 281               int i;
 282               const char* destdir = NULL;
 283           
 284               for (i = 1; i < argc; )
 285               {
 286                   if (strcmp(argv[i], "--destdir") == 0)
 287                   {
 288                       if (i + 1 == argc)
 289                           err("missing argument for --destdir option");
 290           
 291                       destdir = argv[i+1];
 292                       memmove((char*)&argv[i], (char*)&argv[i+2], 
 293                           sizeof(char*) * (argc-i-1));
 294                       argc -= 2;
 295 mike  1.1         }
 296                   else if (strncmp(argv[i], "--destdir=", 10) == 0)
 297                   {
 298                       destdir = argv[i] + 10;
 299                       memmove((char*)&argv[i], (char*)&argv[i+1], 
 300                           sizeof(char*) * (argc-i));
 301           
 302                       argc -= 1;
 303                   }
 304                   else
 305                       i++;
 306               }
 307           
 308               if (destdir)
 309               {
 310                   if (SetPath(ID_DESTDIR, destdir) != 0)
 311                       err("failed to set destdir");
 312               }
 313           
 314               *argc_ = argc;
 315           }
 316 mike  1.1 
 317           static int GetCommandLineOptions(
 318               int& argc,
 319               const char* argv[],
 320               Options& options)
 321           {
 322               GetOptState state = GETOPTSTATE_INITIALIZER;
 323               const char* supportedOptions[] =
 324               {
 325                   "-h",
 326                   "-q",
 327                   "-t",
 328                   "-s",
 329                   "-shallow",
 330                   "-n",
 331                   "-R:",
 332                   "-ac:",
 333                   "-rc:",
 334                   "-r:",
 335                   "-rr:",
 336                   "-rc:",
 337 mike  1.1         "-u:",
 338                   "-p:",
 339                   "--prefix:",
 340                   "--libdir:",
 341                   "--bindir:",
 342                   "--localstatedir:",
 343                   "--sysconfdir:",
 344                   "--providerdir:",
 345                   "--certsdir:",
 346                   "--rundir:",
 347                   "--logdir:",
 348                   "--pidfile:",
 349                   "--logfile:",
 350                   "--registerdir:",
 351                   "--socketfile:",
 352                   "--pemfile:",
 353                   "--keyfile:",
 354                   "--agentprogram:",
 355                   "--serverprogram:",
 356                   "--stdout:",
 357                   "--stderr:",
 358 mike  1.1         "--querylang:",
 359                   "--queryexpr:",
 360                   NULL,
 361               };
 362           
 363               for (;;)
 364               {
 365                   int r = GetOpt(&argc, argv, supportedOptions, &state);
 366           
 367                   if (r == 1)
 368                       break;
 369           
 370                   if (r == -1)
 371                   {
 372                       fprintf(serr, "error: %s\n", state.err);
 373                       fprintf(serr, "Try -h for help\n");
 374                       return 1;
 375                   }
 376           
 377                   if (strcmp(state.opt, "-h") == 0)
 378                   {
 379 mike  1.1             options.help = true;
 380                   }
 381                   else if (strcmp(state.opt, "-q") == 0)
 382                   {
 383                       options.quiet = true;
 384                   }
 385                   else if (strcmp(state.opt, "-t") == 0)
 386                   {
 387                       options.trace = true;
 388                   }
 389                   else if (strcmp(state.opt, "-s") == 0)
 390                   {
 391                       options.suppressResults = true;
 392                   }
 393                   else if (strcmp(state.opt, "-shallow") == 0)
 394                   {
 395                       options.shallow = true;
 396                   }
 397                   else if (strcmp(state.opt, "-n") == 0)
 398                   {
 399                       options.nulls = true;
 400 mike  1.1         }
 401                   else if (strcmp(state.opt, "-R") == 0)
 402                   {
 403                       options.repeat = atoi(state.arg);
 404           
 405                       if (options.repeat <= 0)
 406                       {
 407                           err("bad value for -R: %s", state.arg);
 408                           return 1;
 409                       }
 410                   }
 411                   else if (strcmp(state.opt, "-ac") == 0)
 412                   {
 413                       options.assocClass = MakeString(state.arg);
 414                   }
 415                   else if (strcmp(state.opt, "-rc") == 0)
 416                   {
 417                       options.resultClass = MakeString(state.arg);
 418                   }
 419                   else if (strcmp(state.opt, "-r") == 0)
 420                   {
 421 mike  1.1             options.role = MakeString(state.arg);
 422                   }
 423                   else if (strcmp(state.opt, "-rr") == 0)
 424                   {
 425                       options.resultRole = MakeString(state.arg);
 426                   }
 427                   else if (strcmp(state.opt, "-u") == 0)
 428                   {
 429                       options.user = MakeString(state.arg);
 430                   }
 431                   else if (strcmp(state.opt, "-p") == 0)
 432                   {
 433                       options.password = MakeString(state.arg);
 434                   }
 435                   else if (strcmp(state.opt, "--stdout") == 0)
 436                   {
 437                       FILE* os = Fopen(state.arg, "wb");
 438           
 439                       if (!os)
 440                           err("failed to open: %s", state.arg);
 441           
 442 mike  1.1             sout = os;
 443                   }
 444                   else if (strcmp(state.opt, "--stderr") == 0)
 445                   {
 446                       FILE* os = Fopen(state.arg, "wb");
 447           
 448                       if (!os)
 449                           err("failed to open: %s", state.arg);
 450           
 451                       serr = os;
 452                   }
 453                   else if (strcmp(state.opt, "--querylang") == 0)
 454                   {
 455                       options.querylang = MakeString(state.arg);
 456                   }
 457                   else if (strcmp(state.opt, "--queryexpr") == 0)
 458                   {
 459                       options.queryexpr = MakeString(state.arg);
 460                   }
 461                   else if (strncmp(state.opt, "--", 2) == 0 && IsNickname(state.opt+2))
 462                   {
 463 mike  1.1             if (SetPathFromNickname(state.opt+2, state.arg) != 0)
 464                           err("SetPathFromNickname() failed");
 465                   }
 466               }
 467           
 468               return 0;
 469           }
 470           
 471           const char USAGE[] = "\
 472           Usage: %s [OPTIONS] COMMAND ...\n\
 473           \n\
 474           This tool sends requests to the CIM server.\n\
 475           \n\
 476           OPTIONS:\n\
 477               -h                  Print this help message.\n\
 478               -q                  Operate quietly.\n\
 479               -t                  Enable diagnostic tracing.\n\
 480               -R N                Repeat command N times.\n\
 481               -shallow            Use shallow inheritance (see 'ei' command).\n\
 482               -ac CLASSNAME       Association class (see 'a' and 'r' commands).\n\
 483               -rc CLASSNAME       Result class (see 'a' command).\n\
 484 mike  1.1     -r ROLE             Role (see 'a' and 'r' commands).\n\
 485               -rr ROLE            Result role (see 'a' command).\n\
 486               -n                  Show null properties.\n\
 487               -u USERNAME         Username.\n\
 488               -p PASSWORD         User's password.\n\
 489               -id			Send identify request.\n\
 490               --socketfile PATH   Talk to the server server whose socket file resides\n\
 491                                   at the location given by the path argument.\n\
 492               --httpport		Connect on this port instead of default.\n\
 493               --httpsport		Connect on this secure port instead of default.\n\
 494               --querylang         Query language (for 'ei' command).\n\
 495               --queryexpr         Query expression (for 'ei' command).\n\
 496           \n\
 497           COMMANDS:\n\
 498               noop\n\
 499                   Perform a no-op operation.\n\
 500               gi NAMESPACE INSTANCENAME\n\
 501                   Peform a CIM [g]et [i]nstance operation.\n\
 502               ci NAMESPACE NEWINSTANCE\n\
 503                   Peform a CIM [c]create [i]nstance operation.\n\
 504               mi NAMESPACE MODIFIEDINSTANCE\n\
 505 mike  1.1         Peform a CIM [m]odify [i]nstance operation.\n\
 506               di NAMESPACE INSTANCENAME\n\
 507                   Peform a CIM [d]elete [i]nstance operation.\n\
 508               ei [-shallow] NAMESPACE CLASSNAME\n\
 509                   Peform a CIM [e]numerate [i]nstances operation.\n\
 510               iv NAMESPACE INSTANCENAME METHODNAME PARAMETERS\n\
 511                   Peform a CIM extrinisic method [i]nvocation operation.\n\
 512               a [-ac -rc -r -rr ] NAMESPACE INSTANCENAME\n\
 513                   Perform a CIM [a]ssociator instances operation.\n\
 514               r [-ac -r] NAMESPACE INSTANCENAME (references)\n\
 515                   Perform a CIM [r]eference instances operation.\n\
 516               enc INSTANCE\n\
 517                   Attempt to encode and print the given instance representation.\n\
 518               wql NAMESPACE WQLQUERY\n\
 519                   Peform a WQL query operation.\n\
 520           \n";
 521           
 522 mike  1.2 // Find closing brach (assuming *p points to an opening brace).
 523           static const char** FindClosingBrace(const char** p)
 524           {
 525               int nesting = 1;
 526           
 527               if (strcmp(*p, "{") != 0)
 528                   return NULL;
 529           
 530               p++;
 531           
 532               while (*p)
 533               {
 534                   if (strcmp(*p, "{") == 0)
 535                       nesting++;
 536                   else if (strcmp(*p, "}") == 0)
 537                       nesting--;
 538           
 539                   p++;
 540           
 541                   if (nesting == 0)
 542                       return p;
 543 mike  1.2     }
 544           
 545               return NULL;
 546           }
 547           
 548 mike  1.1 // ATTN: support arrays.
 549           static bool ArgsToInstance(
 550               const char**& p, 
 551               const char** end, 
 552               DInstance::MetaType metaType,
 553               bool key,
 554               DInstance& instanceOut)
 555           {
 556               if (p == end)
 557                   return false;
 558           
 559               // Consume opening brace:
 560               if (strcmp(*p++, "{") != 0)
 561                   return false;
 562           
 563               if (p == end)
 564                   return false;
 565           
 566               // Call the 'empty' constructor so that we can use placement operator.
 567               DInstance instance;
 568           
 569 mike  1.1     if (metaType == DInstance::METHOD)
 570               {
 571                   instance = DInstance(T("Parameters"), DInstance::METHOD);
 572               }
 573               else
 574               {
 575                   instance = DInstance(MakeString(*p++), DInstance::CLASS);
 576           
 577                   if (p == end)
 578                       return false;
 579               }
 580           
 581               // Consume name/value pairs:
 582               for (;;)
 583               {
 584                   if (strcmp(*p, "}") == 0)
 585                   {
 586                       p++;
 587                       break;
 588                   }
 589           
 590 mike  1.1         // Get name:
 591                   String name = MakeString(*p++);
 592           
 593                   if (p == end)
 594                       return false;
 595           
 596                   // Get value:
 597                   if (strcmp(*p, "{") == 0)
 598                   {
 599 mike  1.2             const char** q = FindClosingBrace(p);
 600 mike  1.1 
 601 mike  1.2             if (!q || q == end)
 602 mike  1.1                 return false;
 603           
 604                       // Recursively call to obtain reference or embedded instance.
 605 mike  1.2             DInstance tmpInst;
 606           
 607                       if (!ArgsToInstance(p, q, DInstance::CLASS, key, tmpInst))
 608 mike  1.1                 return false;
 609           
 610 mike  1.2             if (!instance.AddInstance(name, tmpInst, false, key))
 611 mike  1.1                 return false;
 612                   }
 613                   else if (strcmp(*p, "[") == 0)
 614                   {
 615                       Array<String> array;
 616 mike  1.2             Array<DInstance> instances;
 617 mike  1.1             p++;
 618           
 619                       // Find closing brace:
 620                       while (*p && strcmp(*p, "]") != 0)
 621                       {
 622 mike  1.2                 if (strcmp(*p, "{") == 0)
 623                           {
 624                               const char** q = FindClosingBrace(p);
 625           
 626                               if (!q || q == end)
 627                                   return false;
 628           
 629                               DInstance tmpInst;
 630           
 631                               if (!ArgsToInstance(p, q, DInstance::CLASS, key, tmpInst))
 632                                   return false;
 633           
 634                               instances.PushBack(tmpInst);
 635                           }
 636                           else
 637                           {
 638                               array.PushBack(MakeString(*p++));
 639                           }
 640 mike  1.1             }
 641           
 642                       // Handle missing closing brace:
 643                       if (p == end)
 644                           return false;
 645           
 646 mike  1.2             if (instances.GetSize())
 647                       {
 648                           if (!instance.AddInstanceA(name, instances, false, key))
 649                               return false;
 650                       }
 651                       else if (array.GetSize())
 652                       {
 653                           if (!instance.AddStringA(name, array, false, key))
 654                               return false;
 655                       }
 656 mike  1.1 
 657                       p++;
 658                   }
 659                   else
 660                   {
 661                       // Get value:
 662                       String value = MakeString(*p++);
 663           
 664                       // Add property:
 665                       if (!instance.AddString(name, value, false, key))
 666                           return false;
 667           
 668                       if (p == end)
 669                           break;
 670                   }
 671               }
 672           
 673               instanceOut = instance;
 674               return true;
 675           }
 676           
 677 mike  1.1 static int NoOp(Client& client, int argc, const char* argv[])
 678           {
 679               MI_UNUSED(argv);
 680           
 681               if (argc != 2)
 682               {
 683                   fprintf(serr, "Usage: %s noop\n\n", arg0);
 684                   return 1;
 685               }
 686           
 687               if (!client.NoOp(opts.timeOut))
 688               {
 689                   err("noop request failed");
 690                   return 1;
 691               }
 692           
 693               if (!opts.quiet)
 694                   fprintf(sout, "got noop response\n");
 695           
 696               return 0;
 697           }
 698 mike  1.1 
 699           static void PrintInstance(const DInstance& inst, bool nulls)
 700           {
 701               inst.Print(sout, 0, nulls);
 702           }
 703           
 704           static int Encode(int argc, const char* argv[])
 705           {
 706               if (argc < 3)
 707               {
 708                   fprintf(serr, "Usage: %s noop CLASSNAME KEYBINDING\n\n", arg0);
 709                   return 1;
 710               }
 711           
 712               DInstance inst;
 713               argc -= 2;
 714               argv += 2;
 715           
 716               if (!ArgsToInstance(argv, argv + argc, DInstance::CLASS, false, inst))
 717               {
 718                   err("invalid instance name specification");
 719 mike  1.1         return 1;
 720               }
 721           
 722               if (!opts.quiet)
 723               {
 724                   PrintInstance(inst, opts.nulls);
 725               }
 726           
 727               return 0;
 728           }
 729           
 730           static MI_Result s_result;
 731           static bool s_done;
 732           
 733           static int EnumerateInstances(Client& client, int argc, const char* argv[])
 734           {
 735               if (argc != 4)
 736               {
 737                   fprintf(serr, "Usage: %s ei NAMESPACE CLASSNAME\n\n", arg0);
 738                   return 1;
 739               }
 740 mike  1.1 
 741               // Default to WQL query language.
 742               if (opts.querylang.GetSize() && opts.queryexpr.GetSize() == 0)
 743               {
 744                   opts.querylang = T("WQL");
 745               }
 746           
 747               // Reject if --querylang option present but not --queryexpr option.
 748               if (opts.querylang.GetSize() && opts.queryexpr.GetSize() == 0)
 749               {
 750                   err("--querylang options requires --queryexpr option");
 751                   return 1;
 752               }
 753           
 754               const String nameSpace = MakeString(argv[2]);
 755               const String className = MakeString(argv[3]);
 756               Array<DInstance> instances;
 757               MI_Result result;
 758               Uint64 msgID = 0;
 759           
 760               s_result = MI_RESULT_OK;
 761 mike  1.1     s_done = false;
 762           
 763               if (!client.EnumerateInstancesAsync(nameSpace, className, !opts.shallow, 
 764                   opts.querylang, opts.queryexpr,  msgID))
 765               {
 766                   err("communication failed (cannot connect/initiate command)");
 767                   return 1;
 768               }
 769           
 770               Uint64 endTime, now;
 771           
 772               if (Time_Now(&now) != MI_RESULT_OK)
 773                   return 3;
 774           
 775               endTime = now + opts.timeOut;
 776           
 777               for (;!s_done && endTime >= now;)
 778               {
 779                   client.Run(1000);
 780           
 781                   if (Time_Now(&now) != MI_RESULT_OK)
 782 mike  1.1             break;
 783               }
 784           
 785               if (!s_done)
 786               {
 787                   err("communication failed (timeout)");
 788                   return 1;
 789               }
 790           
 791               result = s_result;
 792           
 793               if (result != MI_RESULT_OK)
 794               {
 795                   return 2;
 796               }
 797           
 798               return 0;
 799           }
 800           
 801           static int Query(Client& client, int argc, const char* argv[])
 802           {
 803 mike  1.1     // Check arguments
 804               if (argc != 4)
 805               {
 806                   fprintf(serr, "Usage: %s wql NAMESPACE QUERY\n\n", arg0);
 807                   return 1;
 808               }
 809           
 810               // Extract query options.
 811               opts.querylang = T("WQL");
 812               opts.queryexpr = MakeString(argv[3]);
 813           
 814               // Always perform shallow query.
 815               opts.shallow = false;
 816           
 817               // Pre-compile the query (to get className).
 818               std::string className;
 819               {
 820                   WQL* wql = WQL_Parse(opts.queryexpr.Str(), NULL);
 821           
 822                   if (!wql)
 823                   {
 824 mike  1.1             fprintf(serr, "%s : invalid query: %s\n\n", arg0, argv[3]);
 825                       return 1;
 826                   }
 827           
 828                   className = ZToStr(wql->className);
 829                   WQL_Delete(wql);
 830               }
 831           
 832               // Invoke enumerate with these arguments.
 833               const char* args[5];
 834               args[0] = argv[0];
 835               args[1] = "ei";
 836               args[2] = argv[2]; /* namespace */
 837               args[3] = className.c_str();
 838               args[4] = NULL;
 839           
 840               return EnumerateInstances(client, 4, args);
 841           }
 842           
 843           static int GetInstance(Client& client, int argc, const char* argv[])
 844           {
 845 mike  1.1     if (argc < 4)
 846               {
 847                   fprintf(serr, "Usage: %s gi NAMESPACE INSTANCENAME\n\n", arg0);
 848                   return 1;
 849               }
 850           
 851               const String nameSpace = MakeString(argv[2]);
 852           
 853               DInstance instanceName;
 854           
 855               argc -= 3;
 856               argv += 3;
 857               const char** p = argv;
 858               const char** end = p + argc;
 859           
 860               if (!ArgsToInstance(p, end, DInstance::CLASS, true, instanceName))
 861               {
 862                   err("invalid instance name specification");
 863                   return 1;
 864               }
 865           
 866 mike  1.1     if (p != end)
 867               {
 868                   err("extraneous arguments after instance name");
 869                   return 1;
 870               }
 871           
 872               DInstance instance;
 873               MI_Result result;
 874           
 875               if (!client.GetInstance(nameSpace, instanceName, opts.timeOut, instance, 
 876                   result))
 877               {
 878                   err("communication failed");
 879                   return 1;
 880               }
 881           
 882               if (!opts.quiet && result == MI_RESULT_OK)
 883                   PrintInstance(instance, opts.nulls);
 884           
 885               if (result != MI_RESULT_OK)
 886               {
 887 mike  1.1         if (!opts.suppressResults)
 888                       err("result: " STRF , Result_ToString(result));
 889                   return 2;
 890               }
 891           
 892               return 0;
 893           }
 894           
 895           static int CreateInstance(Client& client, int argc, const char* argv[])
 896           {
 897               if (argc < 4)
 898               {
 899                   fprintf(serr, "Usage: %s ci NAMESPACE INSTANCE\n\n", arg0);
 900                   return 1;
 901               }
 902           
 903               const String nameSpace = MakeString(argv[2]);
 904           
 905               DInstance instance;
 906           
 907               argc -= 3;
 908 mike  1.1     argv += 3;
 909               const char** p = argv;
 910               const char** end = p + argc;
 911           
 912               if (!ArgsToInstance(p, end, DInstance::CLASS, true, instance))
 913               {
 914                   err("invalid instanceName name specification");
 915                   return 1;
 916               }
 917           
 918               if (p != end)
 919               {
 920                   err("extraneous arguments after instanceName name");
 921                   return 1;
 922               }
 923           
 924               DInstance instanceName;
 925               MI_Result result;
 926           
 927               if (!client.CreateInstance(nameSpace, instance, opts.timeOut, instanceName, 
 928                   result))
 929 mike  1.1     {
 930                   err("communication failed");
 931                   return 1;
 932               }
 933           
 934               if (!opts.quiet && result == MI_RESULT_OK)
 935                   PrintInstance(instanceName, true);
 936           
 937               if (result != MI_RESULT_OK)
 938               {
 939                   if (!opts.suppressResults)
 940                       err("result: " STRF, Result_ToString(result));
 941                   return 2;
 942               }
 943           
 944               return 0;
 945           }
 946           
 947           static int ModifyInstance(Client& client, int argc, const char* argv[])
 948           {
 949               if (argc < 4)
 950 mike  1.1     {
 951                   fprintf(serr, "Usage: %s mi NAMESPACE INSTANCE\n\n", arg0);
 952                   return 1;
 953               }
 954           
 955               const String nameSpace = MakeString(argv[2]);
 956           
 957               DInstance instance;
 958           
 959               argc -= 3;
 960               argv += 3;
 961               const char** p = argv;
 962               const char** end = p + argc;
 963           
 964               if (!ArgsToInstance(p, end, DInstance::CLASS, true, instance))
 965               {
 966                   err("invalid instanceName name specification");
 967                   return 1;
 968               }
 969           
 970               if (p != end)
 971 mike  1.1     {
 972                   err("extraneous arguments after instanceName name");
 973                   return 1;
 974               }
 975           
 976               MI_Result result;
 977           
 978               if (!client.ModifyInstance(nameSpace, instance, opts.timeOut, result))
 979               {
 980                   err("communication failed");
 981                   return 1;
 982               }
 983           
 984               if (result != MI_RESULT_OK)
 985               {
 986                   if (!opts.suppressResults)
 987                       err("result: " STRF, Result_ToString(result));
 988                   return 2;
 989               }
 990           
 991               return 0;
 992 mike  1.1 }
 993           
 994           static int DeleteInstance(Client& client, int argc, const char* argv[])
 995           {
 996               if (argc < 4)
 997               {
 998                   fprintf(serr, "Usage: %s gi NAMESPACE INSTANCENAME\n\n", arg0);
 999                   return 1;
1000               }
1001           
1002               const String nameSpace = MakeString(argv[2]);
1003           
1004               DInstance instanceName;
1005           
1006               argc -= 3;
1007               argv += 3;
1008               const char** p = argv;
1009               const char** end = p + argc;
1010           
1011               if (!ArgsToInstance(p, end, DInstance::CLASS, true, instanceName))
1012               {
1013 mike  1.1         err("invalid instance name specification");
1014                   return 1;
1015               }
1016           
1017               if (p != end)
1018               {
1019                   err("extraneous arguments after instance name");
1020                   return 1;
1021               }
1022           
1023               DInstance instance;
1024               MI_Result result;
1025           
1026               if (!client.DeleteInstance(nameSpace, instanceName, opts.timeOut, result))
1027               {
1028                   err("communication failed");
1029                   return 1;
1030               }
1031           
1032               if (result != MI_RESULT_OK)
1033               {
1034 mike  1.1         if (!opts.suppressResults)
1035                       err("result: " STRF, Result_ToString(result));
1036                   return 2;
1037               }
1038           
1039               return 0;
1040           }
1041           
1042           static int Associators(Client& client, int argc, const char* argv[])
1043           {
1044               if (argc < 4)
1045               {
1046                   fprintf(serr, "Usage: %s a NAMESPACE INSTANCENAME\n\n", arg0);
1047                   return 1;
1048               }
1049           
1050               const String nameSpace = MakeString(argv[2]);
1051           
1052               DInstance instanceName;
1053           
1054               argc -= 3;
1055 mike  1.1     argv += 3;
1056               const char** p = argv;
1057               const char** end = p + argc;
1058           
1059               if (!ArgsToInstance(p, end, DInstance::CLASS, true, instanceName))
1060               {
1061                   err("invalid instance name specification");
1062                   return 1;
1063               }
1064           
1065               if (p != end)
1066               {
1067                   err("extraneous arguments after instance name");
1068                   return 1;
1069               }
1070           
1071               Array<DInstance> instances;
1072               MI_Result result;
1073           
1074               if (!client.AssociatorInstances(
1075                   nameSpace, 
1076 mike  1.1         instanceName, 
1077                   opts.assocClass,
1078                   opts.resultClass,
1079                   opts.role,
1080                   opts.resultRole,
1081                   opts.timeOut, 
1082                   instances, 
1083                   result))
1084               {
1085                   err("communication failed");
1086                   return 1;
1087               }
1088           
1089               if (!opts.quiet)
1090               {
1091                   for (Uint32 i = 0; i < instances.GetSize(); i++)
1092                       PrintInstance(instances[i], opts.nulls);
1093               }
1094           
1095               if (result != MI_RESULT_OK)
1096               {
1097 mike  1.1         if (!opts.suppressResults)
1098                       err("result: " STRF, Result_ToString(result));
1099                   return 2;
1100               }
1101           
1102               return 0;
1103           }
1104           
1105           static int References(Client& client, int argc, const char* argv[])
1106           {
1107               if (argc < 4)
1108               {
1109                   fprintf(serr, "Usage: %s a NAMESPACE INSTANCENAME\n\n", arg0);
1110                   return 1;
1111               }
1112           
1113               const String nameSpace = MakeString(argv[2]);
1114           
1115               DInstance instanceName;
1116           
1117               argc -= 3;
1118 mike  1.1     argv += 3;
1119               const char** p = argv;
1120               const char** end = p + argc;
1121           
1122               if (!ArgsToInstance(p, end, DInstance::CLASS, true, instanceName))
1123               {
1124                   err("invalid instance name specification");
1125                   return 1;
1126               }
1127           
1128               if (p != end)
1129               {
1130                   err("extraneous arguments after instance name");
1131                   return 1;
1132               }
1133           
1134               Array<DInstance> instances;
1135               MI_Result result;
1136           
1137               if (!client.ReferenceInstances(
1138                   nameSpace, 
1139 mike  1.1         instanceName, 
1140                   opts.assocClass,
1141                   opts.role,
1142                   opts.timeOut, 
1143                   instances, 
1144                   result))
1145               {
1146                   err("communication failed");
1147                   return 1;
1148               }
1149           
1150               if (!opts.quiet)
1151               {
1152                   for (Uint32 i = 0; i < instances.GetSize(); i++)
1153                       PrintInstance(instances[i], opts.nulls);
1154               }
1155           
1156               if (result != MI_RESULT_OK)
1157               {
1158                   if (!opts.suppressResults)
1159                       err("result: " STRF, Result_ToString(result));
1160 mike  1.1         return 2;
1161               }
1162           
1163               return 0;
1164           }
1165           
1166           static int Invoke(Client& client, int argc, const char* argv[])
1167           {
1168               if (argc < 5)
1169               {
1170                   fprintf(serr, 
1171                       "Usage: %s iv NAMESPACE INSTANCENAME METHODNAME PARAMETERS\n\n", 
1172                       arg0);
1173                   return 1;
1174               }
1175           
1176               const String nameSpace = MakeString(argv[2]);
1177           
1178               // Skip over first 3 args:
1179               argc -= 3;
1180               argv += 3;
1181 mike  1.1     const char** p = argv;
1182               const char** end = p + argc;
1183           
1184               // Get instanceName parameter:
1185               DInstance instanceName;
1186               {
1187                   if (!ArgsToInstance(p, end, DInstance::CLASS, true, instanceName))
1188                   {
1189                       err("invalid instance name specification");
1190                       return 1;
1191                   }
1192               }
1193           
1194               // Get methodName parameter:
1195               if (p == end)
1196               {
1197                   err("expected method name");
1198                   return 1;
1199               }
1200           
1201               String methodName = MakeString(*p);
1202 mike  1.1     p++;
1203           
1204               // Get method parameters:
1205               DInstance in(T("Parameters"), DInstance::METHOD);
1206           
1207               if (p != end)
1208               {
1209                   if (!ArgsToInstance(p, end, DInstance::METHOD, true, in))
1210                   {
1211                       err("invalid parameters specification");
1212                       return 1;
1213                   }
1214               }
1215           
1216               // Invoke the method:
1217               DInstance out;
1218               MI_Result result;
1219           
1220               if (!client.Invoke(nameSpace, instanceName, methodName, in, opts.timeOut, 
1221                   out, result))
1222               {
1223 mike  1.1         err("communication failed");
1224                   return 1;
1225               }
1226           
1227               if (!opts.quiet && result == MI_RESULT_OK)
1228                   PrintInstance(out, opts.nulls);
1229           
1230               if (result != MI_RESULT_OK)
1231               {
1232                   if (!opts.suppressResults)
1233                       err("result: " STRF, Result_ToString(result));
1234                   return 2;
1235               }
1236           
1237               return 0;
1238           }
1239           
1240           class CliHandler : public Handler
1241           {
1242           public:
1243           
1244 mike  1.1     /*virtual void HandleConnect();
1245           
1246           
1247               virtual void HandleNoOp(Uint64 msgID);*/
1248               virtual void HandleConnectFailed()
1249               {
1250                   if (!opts.suppressResults)
1251                       err("connect failed...");
1252                   s_result = MI_RESULT_FAILED;
1253                   s_done = true;
1254               }
1255           
1256               virtual void HandleDisconnect()
1257               {
1258                   if (!opts.suppressResults)
1259                       err("disconnected...");
1260                   s_result = MI_RESULT_FAILED;
1261                   s_done = true;
1262               }
1263           
1264               virtual void HandleInstance(Uint64 msgID, const DInstance& instance)
1265 mike  1.1     {
1266                   MI_UNUSED(msgID);
1267           
1268                   if (!opts.quiet)
1269                   {
1270                       PrintInstance(instance, opts.nulls);
1271                   }
1272               }
1273           
1274               virtual void HandleResult(Uint64 msgID, MI_Result result)
1275               {
1276                   MI_UNUSED(msgID);
1277           
1278                   if (result != MI_RESULT_OK)
1279                   {
1280                       if (!opts.suppressResults)
1281                           err("result: " STRF, Result_ToString(result));
1282                   }
1283                   s_result = result;
1284                   s_done = true;
1285               }
1286 mike  1.1 };
1287           
1288           int climain(int argc, const char* argv[])
1289           {
1290               arg0 = argv[0];
1291               const Uint64 CONNECT_TIMEOUT_USEC = 10 * 1000 * 1000;
1292               int r = 0;
1293               Client client( new CliHandler );
1294           
1295               // Setup default stderr and stdout streams:
1296               serr = stderr;
1297               sout = stdout;
1298           
1299               // Initialize options:
1300               opts.Clear();
1301           
1302               // Get the options:
1303               GetCommandLineDestDirOption(&argc, argv);
1304           
1305               // Get configuration file options:
1306               if (GetConfigFileOptions() != 0)
1307 mike  1.1     {
1308                   r = 1;
1309                   goto done;
1310               }
1311           
1312               // Get the options:
1313               if (GetCommandLineOptions(argc, argv, opts) != 0)
1314               {
1315                   r = 1;
1316                   goto done;
1317               }
1318           
1319               // There must be at least 1 argument left:
1320               if (argc < 2)
1321               {
1322                   fprintf(sout, "%s", USAGE);
1323                   r = 1;
1324                   goto done;
1325               }
1326           
1327               // Connect to server:
1328 mike  1.1 
1329               if (strcmp(argv[1], "enc") != 0)
1330               {
1331           #if defined(CONFIG_OS_WINDOWS)
1332                   if (!client.Connect(T("7777"), opts.user, opts.password, CONNECT_TIMEOUT_USEC))
1333           #else
1334                   if (!client.Connect(GetPath(ID_SOCKETFILE), opts.user, opts.password, CONNECT_TIMEOUT_USEC))
1335           #endif
1336                   {
1337           #if defined(CONFIG_OS_WINDOWS)
1338                       err("failed to connect on port 7777");
1339           #else
1340                       err("failed to connect to %s", GetPath(ID_SOCKETFILE));
1341           #endif
1342                       r = 1;
1343                       goto done;
1344                   }
1345               }
1346           
1347               if (strcmp(argv[1], "noop") == 0)
1348               {
1349 mike  1.1         for (int i = 0; i < opts.repeat; i++)
1350                   {
1351                       r = NoOp(client, argc, argv);
1352                       if (r != 0)
1353                           goto done;
1354                   }
1355               }
1356               else if (strcmp(argv[1], "enc") == 0)
1357               {
1358                   r = Encode(argc, argv);
1359                   goto done;
1360               }
1361               else if (strcmp(argv[1], "ei") == 0)
1362               {
1363                   for (int i = 0; i < opts.repeat; i++)
1364                   {
1365                       r = EnumerateInstances(client, argc, argv);
1366                       if (r != 0)
1367                           goto done;
1368                   }
1369               }
1370 mike  1.1     else if (strcmp(argv[1], "id") == 0)
1371               {
1372           	if (argc != 2)
1373           	{
1374           	    fprintf(serr, "Usage: %s id\n\n", arg0);
1375           	    r = 1;
1376                       goto done;
1377           	}
1378           
1379           	const char* args[5];
1380           	args[0]= argv[0];
1381           	args[1]= (char*)"ei";
1382           	args[2]= (char*)"root/omi";
1383           	args[3]= (char*)"OMI_Identify";
1384           	args[4]= NULL;
1385           
1386                   for (int i = 0; i < opts.repeat; i++)
1387                   {
1388                       r = EnumerateInstances(client, 4, args);
1389                       if (r != 0)
1390                           goto done;
1391 mike  1.1         }
1392               }
1393               else if (strcmp(argv[1], "gi") == 0)
1394               {
1395                   for (int i = 0; i < opts.repeat; i++)
1396                   {
1397                       r = GetInstance(client, argc, argv);
1398                       if (r != 0)
1399                           goto done;
1400                   }
1401               }
1402               else if (strcmp(argv[1], "ci") == 0)
1403               {
1404                   for (int i = 0; i < opts.repeat; i++)
1405                   {
1406                       r = CreateInstance(client, argc, argv);
1407                       if (r != 0)
1408                           goto done;
1409                   }
1410               }
1411               else if (strcmp(argv[1], "mi") == 0)
1412 mike  1.1     {
1413                   for (int i = 0; i < opts.repeat; i++)
1414                   {
1415                       r = ModifyInstance(client, argc, argv);
1416                       if (r != 0)
1417                           goto done;
1418                   }
1419               }
1420               else if (strcmp(argv[1], "di") == 0)
1421               {
1422                   for (int i = 0; i < opts.repeat; i++)
1423                   {
1424                       r = DeleteInstance(client, argc, argv);
1425                       if (r != 0)
1426                           goto done;
1427                   }
1428               }
1429               else if (strcmp(argv[1], "iv") == 0)
1430               {
1431                   for (int i = 0; i < opts.repeat; i++)
1432                   {
1433 mike  1.1             r = Invoke(client, argc, argv);
1434                       if (r != 0)
1435                           goto done;
1436                   }
1437               }
1438               else if (strcmp(argv[1], "a") == 0)
1439               {
1440                   for (int i = 0; i < opts.repeat; i++)
1441                   {
1442                       r = Associators(client, argc, argv);
1443                       if (r != 0)
1444                           goto done;
1445                   }
1446               }
1447               else if (strcmp(argv[1], "r") == 0)
1448               {
1449                   for (int i = 0; i < opts.repeat; i++)
1450                   {
1451                       r = References(client, argc, argv);
1452                       if (r != 0)
1453                           goto done;
1454 mike  1.1         }
1455               }
1456               else if (strcmp(argv[1], "wql") == 0)
1457               {
1458                   for (int i = 0; i < opts.repeat; i++)
1459                   {
1460                       r = Query(client, argc, argv);
1461                       if (r != 0)
1462                           goto done;
1463                   }
1464               }
1465               else
1466               {
1467                   err("unknown command: %s", argv[1]);
1468                   r = 1;
1469                   goto done;
1470               }
1471           
1472           done:
1473           
1474               if (sout != stdout)
1475 mike  1.1         fclose(sout);
1476           
1477               if (serr != stdout)
1478                   fclose(serr);
1479           
1480               return r;
1481           }

ViewCVS 0.9.2