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
|
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 }
|