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 // ATTN: support arrays.
523 static bool ArgsToInstance(
524 const char**& p,
525 const char** end,
526 mike 1.1 DInstance::MetaType metaType,
527 bool key,
528 DInstance& instanceOut)
529 {
530 if (p == end)
531 return false;
532
533 // Consume opening brace:
534 if (strcmp(*p++, "{") != 0)
535 return false;
536
537 if (p == end)
538 return false;
539
540 // Call the 'empty' constructor so that we can use placement operator.
541 DInstance instance;
542
543 if (metaType == DInstance::METHOD)
544 {
545 instance = DInstance(T("Parameters"), DInstance::METHOD);
546 }
547 mike 1.1 else
548 {
549 instance = DInstance(MakeString(*p++), DInstance::CLASS);
550
551 if (p == end)
552 return false;
553 }
554
555 // Consume name/value pairs:
556 for (;;)
557 {
558 if (strcmp(*p, "}") == 0)
559 {
560 p++;
561 break;
562 }
563
564 // Get name:
565 String name = MakeString(*p++);
566
567 if (p == end)
568 mike 1.1 return false;
569
570
571 // Get value:
572 if (strcmp(*p, "{") == 0)
573 {
574 int nesting = 1;
575 const char** q = p;
576 q++;
577
578 // Find closing brace:
579 while (*q)
580 {
581 if (strcmp(*q, "{") == 0)
582 nesting++;
583 else if (strcmp(*q, "}") == 0)
584 nesting--;
585
586 q++;
587
588 if (nesting == 0)
589 mike 1.1 break;
590 }
591
592 // Handle missing closing brace:
593 if (q == end)
594 return false;
595
596 // Recursively call to obtain reference or embedded instance.
597 DInstance tmpInstance;
598 if (!ArgsToInstance(p, q, DInstance::CLASS, key, tmpInstance))
599 {
600 return false;
601 }
602
603 if (!instance.AddInstance(name, tmpInstance, false, key))
604 return false;
605 }
606 else if (strcmp(*p, "[") == 0)
607 {
608 Array<String> array;
609 p++;
610 mike 1.1
611 // Find closing brace:
612 while (*p && strcmp(*p, "]") != 0)
613 {
614 array.PushBack(MakeString(*p++));
615 }
616
617 // Handle missing closing brace:
618 if (p == end)
619 return false;
620
621 if (!instance.AddStringA(name, array, false, key))
622 return false;
623
624 p++;
625 }
626 else
627 {
628 // Get value:
629 String value = MakeString(*p++);
630
631 mike 1.1 // Add property:
632 if (!instance.AddString(name, value, false, key))
633 return false;
634
635 if (p == end)
636 break;
637 }
638 }
639
640 instanceOut = instance;
641 return true;
642 }
643
644 static int NoOp(Client& client, int argc, const char* argv[])
645 {
646 MI_UNUSED(argv);
647
648 if (argc != 2)
649 {
650 fprintf(serr, "Usage: %s noop\n\n", arg0);
651 return 1;
652 mike 1.1 }
653
654 if (!client.NoOp(opts.timeOut))
655 {
656 err("noop request failed");
657 return 1;
658 }
659
660 if (!opts.quiet)
661 fprintf(sout, "got noop response\n");
662
663 return 0;
664 }
665
666 static void PrintInstance(const DInstance& inst, bool nulls)
667 {
668 inst.Print(sout, 0, nulls);
669 }
670
671 static int Encode(int argc, const char* argv[])
672 {
673 mike 1.1 if (argc < 3)
674 {
675 fprintf(serr, "Usage: %s noop CLASSNAME KEYBINDING\n\n", arg0);
676 return 1;
677 }
678
679 DInstance inst;
680 argc -= 2;
681 argv += 2;
682
683 if (!ArgsToInstance(argv, argv + argc, DInstance::CLASS, false, inst))
684 {
685 err("invalid instance name specification");
686 return 1;
687 }
688
689 if (!opts.quiet)
690 {
691 PrintInstance(inst, opts.nulls);
692 }
693
694 mike 1.1 return 0;
695 }
696
697 static MI_Result s_result;
698 static bool s_done;
699
700 static int EnumerateInstances(Client& client, int argc, const char* argv[])
701 {
702 if (argc != 4)
703 {
704 fprintf(serr, "Usage: %s ei NAMESPACE CLASSNAME\n\n", arg0);
705 return 1;
706 }
707
708 // Default to WQL query language.
709 if (opts.querylang.GetSize() && opts.queryexpr.GetSize() == 0)
710 {
711 opts.querylang = T("WQL");
712 }
713
714 // Reject if --querylang option present but not --queryexpr option.
715 mike 1.1 if (opts.querylang.GetSize() && opts.queryexpr.GetSize() == 0)
716 {
717 err("--querylang options requires --queryexpr option");
718 return 1;
719 }
720
721 const String nameSpace = MakeString(argv[2]);
722 const String className = MakeString(argv[3]);
723 Array<DInstance> instances;
724 MI_Result result;
725 Uint64 msgID = 0;
726
727 s_result = MI_RESULT_OK;
728 s_done = false;
729
730 if (!client.EnumerateInstancesAsync(nameSpace, className, !opts.shallow,
731 opts.querylang, opts.queryexpr, msgID))
732 {
733 err("communication failed (cannot connect/initiate command)");
734 return 1;
735 }
736 mike 1.1
737 Uint64 endTime, now;
738
739 if (Time_Now(&now) != MI_RESULT_OK)
740 return 3;
741
742 endTime = now + opts.timeOut;
743
744 for (;!s_done && endTime >= now;)
745 {
746 client.Run(1000);
747
748 if (Time_Now(&now) != MI_RESULT_OK)
749 break;
750 }
751
752 if (!s_done)
753 {
754 err("communication failed (timeout)");
755 return 1;
756 }
757 mike 1.1
758 result = s_result;
759
760 if (result != MI_RESULT_OK)
761 {
762 return 2;
763 }
764
765 return 0;
766 }
767
768 static int Query(Client& client, int argc, const char* argv[])
769 {
770 // Check arguments
771 if (argc != 4)
772 {
773 fprintf(serr, "Usage: %s wql NAMESPACE QUERY\n\n", arg0);
774 return 1;
775 }
776
777 // Extract query options.
778 mike 1.1 opts.querylang = T("WQL");
779 opts.queryexpr = MakeString(argv[3]);
780
781 // Always perform shallow query.
782 opts.shallow = false;
783
784 // Pre-compile the query (to get className).
785 std::string className;
786 {
787 WQL* wql = WQL_Parse(opts.queryexpr.Str(), NULL);
788
789 if (!wql)
790 {
791 fprintf(serr, "%s : invalid query: %s\n\n", arg0, argv[3]);
792 return 1;
793 }
794
795 className = ZToStr(wql->className);
796 WQL_Delete(wql);
797 }
798
799 mike 1.1 // Invoke enumerate with these arguments.
800 const char* args[5];
801 args[0] = argv[0];
802 args[1] = "ei";
803 args[2] = argv[2]; /* namespace */
804 args[3] = className.c_str();
805 args[4] = NULL;
806
807 return EnumerateInstances(client, 4, args);
808 }
809
810 static int GetInstance(Client& client, int argc, const char* argv[])
811 {
812 if (argc < 4)
813 {
814 fprintf(serr, "Usage: %s gi NAMESPACE INSTANCENAME\n\n", arg0);
815 return 1;
816 }
817
818 const String nameSpace = MakeString(argv[2]);
819
820 mike 1.1 DInstance instanceName;
821
822 argc -= 3;
823 argv += 3;
824 const char** p = argv;
825 const char** end = p + argc;
826
827 if (!ArgsToInstance(p, end, DInstance::CLASS, true, instanceName))
828 {
829 err("invalid instance name specification");
830 return 1;
831 }
832
833 if (p != end)
834 {
835 err("extraneous arguments after instance name");
836 return 1;
837 }
838
839 DInstance instance;
840 MI_Result result;
841 mike 1.1
842 if (!client.GetInstance(nameSpace, instanceName, opts.timeOut, instance,
843 result))
844 {
845 err("communication failed");
846 return 1;
847 }
848
849 if (!opts.quiet && result == MI_RESULT_OK)
850 PrintInstance(instance, opts.nulls);
851
852 if (result != MI_RESULT_OK)
853 {
854 if (!opts.suppressResults)
855 err("result: " STRF , Result_ToString(result));
856 return 2;
857 }
858
859 return 0;
860 }
861
862 mike 1.1 static int CreateInstance(Client& client, int argc, const char* argv[])
863 {
864 if (argc < 4)
865 {
866 fprintf(serr, "Usage: %s ci NAMESPACE INSTANCE\n\n", arg0);
867 return 1;
868 }
869
870 const String nameSpace = MakeString(argv[2]);
871
872 DInstance instance;
873
874 argc -= 3;
875 argv += 3;
876 const char** p = argv;
877 const char** end = p + argc;
878
879 if (!ArgsToInstance(p, end, DInstance::CLASS, true, instance))
880 {
881 err("invalid instanceName name specification");
882 return 1;
883 mike 1.1 }
884
885 if (p != end)
886 {
887 err("extraneous arguments after instanceName name");
888 return 1;
889 }
890
891 DInstance instanceName;
892 MI_Result result;
893
894 if (!client.CreateInstance(nameSpace, instance, opts.timeOut, instanceName,
895 result))
896 {
897 err("communication failed");
898 return 1;
899 }
900
901 if (!opts.quiet && result == MI_RESULT_OK)
902 PrintInstance(instanceName, true);
903
904 mike 1.1 if (result != MI_RESULT_OK)
905 {
906 if (!opts.suppressResults)
907 err("result: " STRF, Result_ToString(result));
908 return 2;
909 }
910
911 return 0;
912 }
913
914 static int ModifyInstance(Client& client, int argc, const char* argv[])
915 {
916 if (argc < 4)
917 {
918 fprintf(serr, "Usage: %s mi NAMESPACE INSTANCE\n\n", arg0);
919 return 1;
920 }
921
922 const String nameSpace = MakeString(argv[2]);
923
924 DInstance instance;
925 mike 1.1
926 argc -= 3;
927 argv += 3;
928 const char** p = argv;
929 const char** end = p + argc;
930
931 if (!ArgsToInstance(p, end, DInstance::CLASS, true, instance))
932 {
933 err("invalid instanceName name specification");
934 return 1;
935 }
936
937 if (p != end)
938 {
939 err("extraneous arguments after instanceName name");
940 return 1;
941 }
942
943 MI_Result result;
944
945 if (!client.ModifyInstance(nameSpace, instance, opts.timeOut, result))
946 mike 1.1 {
947 err("communication failed");
948 return 1;
949 }
950
951 if (result != MI_RESULT_OK)
952 {
953 if (!opts.suppressResults)
954 err("result: " STRF, Result_ToString(result));
955 return 2;
956 }
957
958 return 0;
959 }
960
961 static int DeleteInstance(Client& client, int argc, const char* argv[])
962 {
963 if (argc < 4)
964 {
965 fprintf(serr, "Usage: %s gi NAMESPACE INSTANCENAME\n\n", arg0);
966 return 1;
967 mike 1.1 }
968
969 const String nameSpace = MakeString(argv[2]);
970
971 DInstance instanceName;
972
973 argc -= 3;
974 argv += 3;
975 const char** p = argv;
976 const char** end = p + argc;
977
978 if (!ArgsToInstance(p, end, DInstance::CLASS, true, instanceName))
979 {
980 err("invalid instance name specification");
981 return 1;
982 }
983
984 if (p != end)
985 {
986 err("extraneous arguments after instance name");
987 return 1;
988 mike 1.1 }
989
990 DInstance instance;
991 MI_Result result;
992
993 if (!client.DeleteInstance(nameSpace, instanceName, opts.timeOut, result))
994 {
995 err("communication failed");
996 return 1;
997 }
998
999 if (result != MI_RESULT_OK)
1000 {
1001 if (!opts.suppressResults)
1002 err("result: " STRF, Result_ToString(result));
1003 return 2;
1004 }
1005
1006 return 0;
1007 }
1008
1009 mike 1.1 static int Associators(Client& client, int argc, const char* argv[])
1010 {
1011 if (argc < 4)
1012 {
1013 fprintf(serr, "Usage: %s a NAMESPACE INSTANCENAME\n\n", arg0);
1014 return 1;
1015 }
1016
1017 const String nameSpace = MakeString(argv[2]);
1018
1019 DInstance instanceName;
1020
1021 argc -= 3;
1022 argv += 3;
1023 const char** p = argv;
1024 const char** end = p + argc;
1025
1026 if (!ArgsToInstance(p, end, DInstance::CLASS, true, instanceName))
1027 {
1028 err("invalid instance name specification");
1029 return 1;
1030 mike 1.1 }
1031
1032 if (p != end)
1033 {
1034 err("extraneous arguments after instance name");
1035 return 1;
1036 }
1037
1038 Array<DInstance> instances;
1039 MI_Result result;
1040
1041 if (!client.AssociatorInstances(
1042 nameSpace,
1043 instanceName,
1044 opts.assocClass,
1045 opts.resultClass,
1046 opts.role,
1047 opts.resultRole,
1048 opts.timeOut,
1049 instances,
1050 result))
1051 mike 1.1 {
1052 err("communication failed");
1053 return 1;
1054 }
1055
1056 if (!opts.quiet)
1057 {
1058 for (Uint32 i = 0; i < instances.GetSize(); i++)
1059 PrintInstance(instances[i], opts.nulls);
1060 }
1061
1062 if (result != MI_RESULT_OK)
1063 {
1064 if (!opts.suppressResults)
1065 err("result: " STRF, Result_ToString(result));
1066 return 2;
1067 }
1068
1069 return 0;
1070 }
1071
1072 mike 1.1 static int References(Client& client, int argc, const char* argv[])
1073 {
1074 if (argc < 4)
1075 {
1076 fprintf(serr, "Usage: %s a NAMESPACE INSTANCENAME\n\n", arg0);
1077 return 1;
1078 }
1079
1080 const String nameSpace = MakeString(argv[2]);
1081
1082 DInstance instanceName;
1083
1084 argc -= 3;
1085 argv += 3;
1086 const char** p = argv;
1087 const char** end = p + argc;
1088
1089 if (!ArgsToInstance(p, end, DInstance::CLASS, true, instanceName))
1090 {
1091 err("invalid instance name specification");
1092 return 1;
1093 mike 1.1 }
1094
1095 if (p != end)
1096 {
1097 err("extraneous arguments after instance name");
1098 return 1;
1099 }
1100
1101 Array<DInstance> instances;
1102 MI_Result result;
1103
1104 if (!client.ReferenceInstances(
1105 nameSpace,
1106 instanceName,
1107 opts.assocClass,
1108 opts.role,
1109 opts.timeOut,
1110 instances,
1111 result))
1112 {
1113 err("communication failed");
1114 mike 1.1 return 1;
1115 }
1116
1117 if (!opts.quiet)
1118 {
1119 for (Uint32 i = 0; i < instances.GetSize(); i++)
1120 PrintInstance(instances[i], opts.nulls);
1121 }
1122
1123 if (result != MI_RESULT_OK)
1124 {
1125 if (!opts.suppressResults)
1126 err("result: " STRF, Result_ToString(result));
1127 return 2;
1128 }
1129
1130 return 0;
1131 }
1132
1133 static int Invoke(Client& client, int argc, const char* argv[])
1134 {
1135 mike 1.1 if (argc < 5)
1136 {
1137 fprintf(serr,
1138 "Usage: %s iv NAMESPACE INSTANCENAME METHODNAME PARAMETERS\n\n",
1139 arg0);
1140 return 1;
1141 }
1142
1143 const String nameSpace = MakeString(argv[2]);
1144
1145 // Skip over first 3 args:
1146 argc -= 3;
1147 argv += 3;
1148 const char** p = argv;
1149 const char** end = p + argc;
1150
1151 // Get instanceName parameter:
1152 DInstance instanceName;
1153 {
1154 if (!ArgsToInstance(p, end, DInstance::CLASS, true, instanceName))
1155 {
1156 mike 1.1 err("invalid instance name specification");
1157 return 1;
1158 }
1159 }
1160
1161 // Get methodName parameter:
1162 if (p == end)
1163 {
1164 err("expected method name");
1165 return 1;
1166 }
1167
1168 String methodName = MakeString(*p);
1169 p++;
1170
1171 // Get method parameters:
1172 DInstance in(T("Parameters"), DInstance::METHOD);
1173
1174 if (p != end)
1175 {
1176 if (!ArgsToInstance(p, end, DInstance::METHOD, true, in))
1177 mike 1.1 {
1178 err("invalid parameters specification");
1179 return 1;
1180 }
1181 }
1182
1183 // Invoke the method:
1184 DInstance out;
1185 MI_Result result;
1186
1187 if (!client.Invoke(nameSpace, instanceName, methodName, in, opts.timeOut,
1188 out, result))
1189 {
1190 err("communication failed");
1191 return 1;
1192 }
1193
1194 if (!opts.quiet && result == MI_RESULT_OK)
1195 PrintInstance(out, opts.nulls);
1196
1197 if (result != MI_RESULT_OK)
1198 mike 1.1 {
1199 if (!opts.suppressResults)
1200 err("result: " STRF, Result_ToString(result));
1201 return 2;
1202 }
1203
1204 return 0;
1205 }
1206
1207 class CliHandler : public Handler
1208 {
1209 public:
1210
1211 /*virtual void HandleConnect();
1212
1213
1214 virtual void HandleNoOp(Uint64 msgID);*/
1215 virtual void HandleConnectFailed()
1216 {
1217 if (!opts.suppressResults)
1218 err("connect failed...");
1219 mike 1.1 s_result = MI_RESULT_FAILED;
1220 s_done = true;
1221 }
1222
1223 virtual void HandleDisconnect()
1224 {
1225 if (!opts.suppressResults)
1226 err("disconnected...");
1227 s_result = MI_RESULT_FAILED;
1228 s_done = true;
1229 }
1230
1231 virtual void HandleInstance(Uint64 msgID, const DInstance& instance)
1232 {
1233 MI_UNUSED(msgID);
1234
1235 if (!opts.quiet)
1236 {
1237 PrintInstance(instance, opts.nulls);
1238 }
1239 }
1240 mike 1.1
1241 virtual void HandleResult(Uint64 msgID, MI_Result result)
1242 {
1243 MI_UNUSED(msgID);
1244
1245 if (result != MI_RESULT_OK)
1246 {
1247 if (!opts.suppressResults)
1248 err("result: " STRF, Result_ToString(result));
1249 }
1250 s_result = result;
1251 s_done = true;
1252 }
1253 };
1254
1255 int climain(int argc, const char* argv[])
1256 {
1257 arg0 = argv[0];
1258 const Uint64 CONNECT_TIMEOUT_USEC = 10 * 1000 * 1000;
1259 int r = 0;
1260 Client client( new CliHandler );
1261 mike 1.1
1262 // Setup default stderr and stdout streams:
1263 serr = stderr;
1264 sout = stdout;
1265
1266 // Initialize options:
1267 opts.Clear();
1268
1269 // Get the options:
1270 GetCommandLineDestDirOption(&argc, argv);
1271
1272 // Get configuration file options:
1273 if (GetConfigFileOptions() != 0)
1274 {
1275 r = 1;
1276 goto done;
1277 }
1278
1279 // Get the options:
1280 if (GetCommandLineOptions(argc, argv, opts) != 0)
1281 {
1282 mike 1.1 r = 1;
1283 goto done;
1284 }
1285
1286 // There must be at least 1 argument left:
1287 if (argc < 2)
1288 {
1289 fprintf(sout, "%s", USAGE);
1290 r = 1;
1291 goto done;
1292 }
1293
1294 // Connect to server:
1295
1296 if (strcmp(argv[1], "enc") != 0)
1297 {
1298 #if defined(CONFIG_OS_WINDOWS)
1299 if (!client.Connect(T("7777"), opts.user, opts.password, CONNECT_TIMEOUT_USEC))
1300 #else
1301 if (!client.Connect(GetPath(ID_SOCKETFILE), opts.user, opts.password, CONNECT_TIMEOUT_USEC))
1302 #endif
1303 mike 1.1 {
1304 #if defined(CONFIG_OS_WINDOWS)
1305 err("failed to connect on port 7777");
1306 #else
1307 err("failed to connect to %s", GetPath(ID_SOCKETFILE));
1308 #endif
1309 r = 1;
1310 goto done;
1311 }
1312 }
1313
1314 if (strcmp(argv[1], "noop") == 0)
1315 {
1316 for (int i = 0; i < opts.repeat; i++)
1317 {
1318 r = NoOp(client, argc, argv);
1319 if (r != 0)
1320 goto done;
1321 }
1322 }
1323 else if (strcmp(argv[1], "enc") == 0)
1324 mike 1.1 {
1325 r = Encode(argc, argv);
1326 goto done;
1327 }
1328 else if (strcmp(argv[1], "ei") == 0)
1329 {
1330 for (int i = 0; i < opts.repeat; i++)
1331 {
1332 r = EnumerateInstances(client, argc, argv);
1333 if (r != 0)
1334 goto done;
1335 }
1336 }
1337 else if (strcmp(argv[1], "id") == 0)
1338 {
1339 if (argc != 2)
1340 {
1341 fprintf(serr, "Usage: %s id\n\n", arg0);
1342 r = 1;
1343 goto done;
1344 }
1345 mike 1.1
1346 const char* args[5];
1347 args[0]= argv[0];
1348 args[1]= (char*)"ei";
1349 args[2]= (char*)"root/omi";
1350 args[3]= (char*)"OMI_Identify";
1351 args[4]= NULL;
1352
1353 for (int i = 0; i < opts.repeat; i++)
1354 {
1355 r = EnumerateInstances(client, 4, args);
1356 if (r != 0)
1357 goto done;
1358 }
1359 }
1360 else if (strcmp(argv[1], "gi") == 0)
1361 {
1362 for (int i = 0; i < opts.repeat; i++)
1363 {
1364 r = GetInstance(client, argc, argv);
1365 if (r != 0)
1366 mike 1.1 goto done;
1367 }
1368 }
1369 else if (strcmp(argv[1], "ci") == 0)
1370 {
1371 for (int i = 0; i < opts.repeat; i++)
1372 {
1373 r = CreateInstance(client, argc, argv);
1374 if (r != 0)
1375 goto done;
1376 }
1377 }
1378 else if (strcmp(argv[1], "mi") == 0)
1379 {
1380 for (int i = 0; i < opts.repeat; i++)
1381 {
1382 r = ModifyInstance(client, argc, argv);
1383 if (r != 0)
1384 goto done;
1385 }
1386 }
1387 mike 1.1 else if (strcmp(argv[1], "di") == 0)
1388 {
1389 for (int i = 0; i < opts.repeat; i++)
1390 {
1391 r = DeleteInstance(client, argc, argv);
1392 if (r != 0)
1393 goto done;
1394 }
1395 }
1396 else if (strcmp(argv[1], "iv") == 0)
1397 {
1398 for (int i = 0; i < opts.repeat; i++)
1399 {
1400 r = Invoke(client, argc, argv);
1401 if (r != 0)
1402 goto done;
1403 }
1404 }
1405 else if (strcmp(argv[1], "a") == 0)
1406 {
1407 for (int i = 0; i < opts.repeat; i++)
1408 mike 1.1 {
1409 r = Associators(client, argc, argv);
1410 if (r != 0)
1411 goto done;
1412 }
1413 }
1414 else if (strcmp(argv[1], "r") == 0)
1415 {
1416 for (int i = 0; i < opts.repeat; i++)
1417 {
1418 r = References(client, argc, argv);
1419 if (r != 0)
1420 goto done;
1421 }
1422 }
1423 else if (strcmp(argv[1], "wql") == 0)
1424 {
1425 for (int i = 0; i < opts.repeat; i++)
1426 {
1427 r = Query(client, argc, argv);
1428 if (r != 0)
1429 mike 1.1 goto done;
1430 }
1431 }
1432 else
1433 {
1434 err("unknown command: %s", argv[1]);
1435 r = 1;
1436 goto done;
1437 }
1438
1439 done:
1440
1441 if (sout != stdout)
1442 fclose(sout);
1443
1444 if (serr != stdout)
1445 fclose(serr);
1446
1447 return r;
1448 }
|