1 krisbash 1.1 #include <stdio.h>
2 #include <signal.h>
3 #include <MI.h>
4 #include <pal/file.h>
5 #include <pal/dir.h>
6 #include <pal/strings.h>
7 #include <pal/cpu.h>
8 #include <pal/format.h>
9 #include <pal/lock.h>
10 #include <pal/sleep.h>
11 #include <pal/strings.h>
12 #include <base/paths.h>
13 #include <wql/wql.h>
14 #include <base/conf.h>
15 #include <base/env.h>
16 #include <base/instance.h>
17 #include <base/log.h>
18 #include <base/result.h>
19 #include <base/strarr.h>
20 #include <base/ptrarray.h>
21
22 krisbash 1.1 static MI_Boolean ArgsToInstance(
23 const MI_Char*** _p,
24 const MI_Char** end,
25 MI_Uint32 metaType,
26 MI_Boolean key,
27 MI_Instance **instanceOut);
28
29 static FILE* sout;
30 static FILE* serr;
31 const MI_Char* arg0;
32 static MI_Operation gop = {0, 0, 0};
33
34 struct Options
35 {
36 MI_Boolean help;
37 MI_Boolean quiet;
38 MI_Boolean summary;
39 MI_Boolean suppressResults;
40 MI_Boolean trace;
41 MI_Boolean shallow;
42 int repeat;
43 krisbash 1.1 const MI_Char *assocClass;
44 const MI_Char *resultClass;
45 const MI_Char *role;
46 const MI_Char *resultRole;
47 const MI_Char *user;
48 const MI_Char *password;
49 MI_Uint64 timeOut;
50 unsigned int httpport;
51 unsigned int httpsport;
52 MI_Boolean nulls;
53 const MI_Char *querylang;
54 const MI_Char *queryexpr;
55 MI_Boolean synchronous;
56 };
57
58 static struct Options opts =
59 { MI_FALSE, MI_FALSE, MI_FALSE, MI_FALSE, MI_FALSE, MI_FALSE, 1, NULL, NULL, NULL, NULL, NULL, NULL, 90 * 1000 * 1000, CONFIG_HTTPPORT, CONFIG_HTTPSPORT, MI_FALSE, MI_T("wql"), NULL, MI_FALSE };
60
61 static void err(const ZChar* fmt, ...)
62 {
63 va_list ap;
64 krisbash 1.1
65 Ftprintf(serr, PAL_T("%T: "), tcs(arg0));
66
67 va_start(ap, fmt);
68 Vftprintf(serr, fmt, ap);
69 va_end(ap);
70
71 Ftprintf(serr, PAL_T("\n"));
72 }
73
74 static MI_Uint64 s_numInstances = 0;
75 static ptrdiff_t s_startTime;
76 static MI_Result s_finalResult = MI_RESULT_FAILED;
77 static ptrdiff_t s_finished = 0;
78
79 static void PrintSummary()
80 {
81 ptrdiff_t now = CPU_GetTimeStamp();
82 MI_Uint64 msec = (now - s_startTime) / 1000;
83 MI_Real64 seconds = (MI_Real64)msec / (MI_Real64)1000.0;
84
85 krisbash 1.1 Tprintf(PAL_T("number of instances: %u\n"), s_numInstances);
86 Tprintf(PAL_T("seconds: %.3lf\n"), seconds);
87 Tprintf(PAL_T("instances per second: %.3lf\n"), s_numInstances / seconds);
88 Tprintf(PAL_T("\n"));
89 }
90
91 static MI_Result Encode(int argc, const MI_Char* argv[])
92 {
93 MI_Instance *inst;
94 if (argc < 3)
95 {
96 Ftprintf(serr, PAL_T("Usage: %s noop CLASSNAME KEYBINDING\n\n"), tcs(arg0));
97 return MI_RESULT_INVALID_PARAMETER;
98 }
99
100 argc -= 2;
101 argv += 2;
102
103 if (!ArgsToInstance(&argv, argv + argc, MI_FLAG_CLASS, MI_FALSE, &inst))
104 {
105 err(PAL_T("invalid instance name specification"));
106 krisbash 1.1 return MI_RESULT_INVALID_PARAMETER;
107 }
108
109 if (!opts.quiet)
110 {
111 Instance_Print(inst, sout, 0, opts.nulls, MI_FALSE);
112 }
113
114 MI_Instance_Delete(inst);
115
116 s_numInstances++;
117
118 return MI_RESULT_OK;
119 }
120
121
122
123 // Find closing brach (assuming *p points to an opening brace).
124 static const MI_Char** FindClosingBrace(const MI_Char** p)
125 {
126 int nesting = 1;
127 krisbash 1.1
128 if (Tcscmp(*p, MI_T("{")) != 0)
129 return NULL;
130
131 p++;
132
133 while (*p)
134 {
135 if (Tcscmp(*p, MI_T("{")) == 0)
136 nesting++;
137 else if (Tcscmp(*p, MI_T("}")) == 0)
138 nesting--;
139
140 p++;
141
142 if (nesting == 0)
143 return p;
144 }
145
146 return NULL;
147 }
148 krisbash 1.1
149 static void MI_MAIN_CALL _DeleteInstance(void* inst)
150 {
151 MI_Instance_Delete((MI_Instance*)inst);
152 }
153
154 static MI_Boolean ArgsToInstance(
155 const MI_Char*** _p,
156 const MI_Char** end,
157 MI_Uint32 metaType,
158 MI_Boolean key,
159 MI_Instance **instanceOut)
160 {
161 MI_Instance *instance;
162 MI_Uint32 keyFlag = 0;
163 const MI_Char **p = *_p;
164
165 if (key)
166 keyFlag = MI_FLAG_KEY;
167
168 if (p == end)
169 krisbash 1.1 return MI_FALSE;
170
171 // Consume opening brace:
172 if (Tcscmp(*p++, MI_T("{")) != 0)
173 return MI_FALSE;
174
175 if (p == end)
176 return MI_FALSE;
177
178
179 if (metaType == MI_FLAG_METHOD)
180 {
181 if (Instance_NewDynamic(&instance, MI_T("Parameters"), MI_FLAG_METHOD, NULL) != MI_RESULT_OK)
182 return MI_FALSE;
183 }
184 else
185 {
186 if (Instance_NewDynamic(&instance, *p++, MI_FLAG_CLASS, NULL) != MI_RESULT_OK)
187 return MI_FALSE;
188
189 if (p == end)
190 krisbash 1.1 {
191 MI_Instance_Delete(instance);
192 return MI_FALSE;
193 }
194 }
195
196 // Consume name/value pairs:
197 for (;;)
198 {
199 const MI_Char *name;
200 if (Tcscmp(*p, MI_T("}")) == 0)
201 {
202 p++;
203 break;
204 }
205
206 // Get name:
207 name = *p++;
208
209 if (p == end)
210 {
211 krisbash 1.1 MI_Instance_Delete(instance);
212 return MI_FALSE;
213 }
214
215 // Get value:
216 if (Tcscmp(*p, MI_T("{")) == 0)
217 {
218 const MI_Char** q = FindClosingBrace(p);
219 MI_Instance *tmpInst;
220 MI_Value value;
221
222 if (!q || q == end)
223 {
224 MI_Instance_Delete(instance);
225 return MI_FALSE;
226 }
227
228 // Recursively call to obtain reference or embedded instance.
229
230 if (!ArgsToInstance(&p, q, MI_FLAG_CLASS, key, &tmpInst))
231 {
232 krisbash 1.1 MI_Instance_Delete(instance);
233 return MI_FALSE;
234 }
235
236 value.instance = tmpInst;
237 if (MI_Instance_AddElement(instance, name, &value, MI_INSTANCE, keyFlag | MI_FLAG_ADOPT) != MI_RESULT_OK)
238 //!instance.AddInstance(name, tmpInst, MI_FALSE, key))
239 {
240 MI_Instance_Delete(tmpInst);
241 MI_Instance_Delete(instance);
242 return MI_FALSE;
243 }
244 }
245 else if (Tcscmp(*p, MI_T("[")) == 0)
246 {
247 MI_Char** strArray = ZArr();
248 PtrArray instanceArray;
249
250 if (strArray == NULL)
251 {
252 MI_Instance_Delete(instance);
253 krisbash 1.1 return MI_FALSE;
254 }
255 if (PtrArray_Construct(&instanceArray, 5, _DeleteInstance) != 0)
256 {
257 ZArrFree(strArray);
258 MI_Instance_Delete(instance);
259 return MI_FALSE;
260 }
261
262 p++;
263
264 // Find closing brace:
265 while (*p && Tcscmp(*p, MI_T("]")) != 0)
266 {
267 if (Tcscmp(*p, MI_T("{")) == 0)
268 {
269 const MI_Char** q = FindClosingBrace(p);
270 MI_Instance *tmpInst = NULL;
271
272 if (!q || q == end)
273 {
274 krisbash 1.1 if (strArray)
275 {
276 #ifdef _PREFAST_
277 #pragma prefast(push)
278 #pragma prefast(disable:26018)
279 #endif
280 ZArrFree(strArray);
281 #ifdef _PREFAST_
282 #pragma prefast(pop)
283 #endif
284 }
285 PtrArray_Destruct(&instanceArray);
286 MI_Instance_Delete(instance);
287 return MI_FALSE;
288 }
289
290 if (!ArgsToInstance(&p, q, MI_FLAG_CLASS, key, &tmpInst))
291 {
292 if (strArray)
293 {
294 #ifdef _PREFAST_
295 krisbash 1.1 #pragma prefast(push)
296 #pragma prefast(disable:26018)
297 #endif
298 ZArrFree(strArray);
299 #ifdef _PREFAST_
300 #pragma prefast(pop)
301 #endif
302 }
303 PtrArray_Destruct(&instanceArray);
304 MI_Instance_Delete(instance);
305 return MI_FALSE;
306 }
307 if (PtrArray_Append(&instanceArray, tmpInst) != 0)
308 {
309 if (strArray)
310 {
311 #ifdef _PREFAST_
312 #pragma prefast(push)
313 #pragma prefast(disable:26018)
314 #endif
315 ZArrFree(strArray);
316 krisbash 1.1 #ifdef _PREFAST_
317 #pragma prefast(pop)
318 #endif
319 }
320 PtrArray_Destruct(&instanceArray);
321 MI_Instance_Delete(instance);
322 MI_Instance_Delete(tmpInst);
323 return MI_FALSE;
324 }
325 }
326 else
327 {
328 MI_Char **_strArray = strArray;
329 ZArrCat(&_strArray, *p++);
330 if (_strArray == NULL)
331 {
332 /* Failed */
333 if (strArray)
334 {
335 #ifdef _PREFAST_
336 #pragma prefast(push)
337 krisbash 1.1 #pragma prefast(disable:26018)
338 #endif
339 ZArrFree(strArray);
340 #ifdef _PREFAST_
341 #pragma prefast(pop)
342 #endif
343 }
344 PtrArray_Destruct(&instanceArray);
345 MI_Instance_Delete(instance);
346 return MI_FALSE;
347 }
348 strArray = _strArray;
349 }
350 }
351
352 // Handle missing closing brace:
353 if (p == end)
354 {
355 if (strArray)
356 {
357 #ifdef _PREFAST_
358 krisbash 1.1 #pragma prefast(push)
359 #pragma prefast(disable:26018)
360 #endif
361 ZArrFree(strArray);
362 #ifdef _PREFAST_
363 #pragma prefast(pop)
364 #endif
365 }
366 PtrArray_Destruct(&instanceArray);
367 MI_Instance_Delete(instance);
368 return MI_FALSE;
369 }
370
371 if (instanceArray.size)
372 {
373 MI_Value value;
374 MI_Uint32 flags = 0;
375 value.instancea.data = (MI_Instance**) instanceArray.data;
376 value.instancea.size = instanceArray.size;
377 if (key)
378 flags = MI_FLAG_KEY;
379 krisbash 1.1
380 if (MI_Instance_AddElement(instance, name, &value, MI_INSTANCEA, flags) != MI_RESULT_OK)
381 {
382 if (strArray)
383 {
384 #ifdef _PREFAST_
385 #pragma prefast(push)
386 #pragma prefast(disable:26018)
387 #endif
388 ZArrFree(strArray);
389 #ifdef _PREFAST_
390 #pragma prefast(pop)
391 #endif
392 }
393 PtrArray_Destruct(&instanceArray);
394 MI_Instance_Delete(instance);
395 return MI_FALSE;
396 }
397 }
398 else
399 {
400 krisbash 1.1 MI_Uint32 arrLength = ZArrLen(strArray);
401 if (arrLength)
402 {
403 MI_Value value;
404 MI_Uint32 flags = 0;
405 value.stringa.data = strArray;
406 value.stringa.size = arrLength;
407 if (key)
408 flags = MI_FLAG_KEY;
409
410 if (MI_Instance_AddElement(instance, name, &value, MI_STRINGA, flags) != MI_RESULT_OK)
411 {
412 if (strArray)
413 {
414 #ifdef _PREFAST_
415 #pragma prefast(push)
416 #pragma prefast(disable:26018)
417 #endif
418 ZArrFree(strArray);
419 #ifdef _PREFAST_
420 #pragma prefast(pop)
421 krisbash 1.1 #endif
422 }
423 PtrArray_Destruct(&instanceArray);
424 MI_Instance_Delete(instance);
425 return MI_FALSE;
426 }
427 }
428 }
429
430 if (strArray)
431 {
432 #ifdef _PREFAST_
433 #pragma prefast(push)
434 #pragma prefast(disable:26018)
435 #endif
436 ZArrFree(strArray);
437 #ifdef _PREFAST_
438 #pragma prefast(pop)
439 #endif
440 }
441 PtrArray_Destruct(&instanceArray);
442 krisbash 1.1 p++;
443 }
444 else
445 {
446 MI_Value value;
447
448 value.string = (MI_Char *)*p++;
449
450 // Add property:
451 if (MI_Instance_AddElement(instance, name, &value, MI_STRING, keyFlag | MI_FLAG_BORROW) != MI_RESULT_OK)
452 {
453 MI_Instance_Delete(instance);
454 return MI_FALSE;
455 }
456
457 if (p == end)
458 break;
459 }
460 }
461
462 *_p = p;
463 krisbash 1.1 *instanceOut = instance;
464 return MI_TRUE;
465 }
466
467 MI_Result CreateOperationOptions(_Inout_ MI_Session *session, _Out_ MI_OperationOptions *options)
468 {
469 MI_Application application;
470 MI_Result miResult;
471 MI_Interval timeoutInterval;
472 MI_Uint64 currentTimeout = opts.timeOut;
473
474
475 miResult = MI_Session_GetApplication(session, &application);
476 if (miResult != MI_RESULT_OK)
477 return miResult;
478
479 miResult = MI_Application_NewOperationOptions(&application, MI_FALSE, options);
480 if (miResult != MI_RESULT_OK)
481 return miResult;
482
483 memset(&timeoutInterval, 0, sizeof(timeoutInterval));
484 krisbash 1.1
485 timeoutInterval.microseconds = currentTimeout%1000000;
486 currentTimeout /= 1000000;
487
488 timeoutInterval.seconds = currentTimeout % 60;
489 currentTimeout /= 60;
490
491 timeoutInterval.minutes = currentTimeout % 60;
492 currentTimeout /= 60;
493
494 timeoutInterval.hours = currentTimeout % 24;
495 currentTimeout /= 24;
496
497 timeoutInterval.days = (MI_Uint32) currentTimeout;
498
499 miResult = MI_OperationOptions_SetTimeout(options, &timeoutInterval);
500 if (miResult != MI_RESULT_OK)
501 {
502 goto cleanup;
503 }
504
505 krisbash 1.1 return miResult;
506
507 cleanup:
508 MI_OperationOptions_Delete(options);
509 memset(options, 0, sizeof(*options));
510 return miResult;
511 }
512
513 void MI_CALL InstanceResults(
514 _In_opt_ MI_Operation *operation,
515 _In_ void *callbackContext,
516 _In_opt_ const MI_Instance *instance,
517 MI_Boolean moreResults,
518 _In_ MI_Result resultCode,
519 _In_opt_z_ const MI_Char *errorString,
520 _In_opt_ const MI_Instance *errorDetails,
521 _In_opt_ MI_Result (MI_CALL * resultAcknowledgement)(_In_ MI_Operation *operation))
522 {
523 if (instance)
524 {
525 s_numInstances++;
526 krisbash 1.1
527 if (!opts.quiet)
528 {
529 Instance_Print(instance, sout, 0, opts.nulls, MI_FALSE);
530 }
531 }
532
533 if (moreResults == MI_FALSE)
534 {
535 if (resultCode != MI_RESULT_OK)
536 {
537 if (!opts.suppressResults)
538 {
539 DEBUG_ASSERT(PAL_FALSE);
540 err(PAL_T("result: %T"), tcs(Result_ToString(resultCode)));
541 if (errorString)
542 {
543 err(PAL_T("result: %T"), tcs(errorString));
544 }
545 if (errorDetails)
546 {
547 krisbash 1.1 Instance_Print(errorDetails, sout, 0, opts.nulls, MI_FALSE);
548 }
549 }
550 }
551 s_finalResult = resultCode;
552 s_finished = 1;
553 CondLock_Broadcast((ptrdiff_t)callbackContext);
554 }
555 }
556
557 void MI_CALL IndicationResult(
558 _In_opt_ MI_Operation *operation,
559 _In_ void *callbackContext,
560 _In_opt_ const MI_Instance *instance,
561 _In_opt_z_ const MI_Char *bookmark,
562 _In_opt_z_ const MI_Char *machineID,
563 MI_Boolean moreResults,
564 _In_ MI_Result resultCode,
565 _In_opt_z_ const MI_Char *errorString,
566 _In_opt_ const MI_Instance *errorDetails,
567 _In_opt_ MI_Result (MI_CALL * resultAcknowledgement)(_In_ MI_Operation *operation))
568 krisbash 1.1 {
569 if (instance)
570 {
571 s_numInstances++;
572
573 if (!opts.quiet)
574 {
575 Ftprintf(sout, PAL_T("Async suscribe. Bookmark: %T; MachineID: %T\n"), tcs(bookmark), tcs(machineID));
576 Instance_Print(instance, sout, 0, opts.nulls, MI_FALSE);
577 }
578 }
579
580 if (moreResults == MI_FALSE)
581 {
582 if (resultCode != MI_RESULT_OK)
583 {
584 if (!opts.suppressResults)
585 {
586 err(PAL_T("result: %T"), tcs(Result_ToString(resultCode)));
587 if (errorString)
588 {
589 krisbash 1.1 err(PAL_T("result: %T"), tcs(errorString));
590 }
591 if (errorDetails)
592 {
593 Instance_Print(errorDetails, sout, 0, opts.nulls, MI_FALSE);
594 }
595 }
596 }
597 s_finalResult = resultCode;
598 s_finished = 1;
599 CondLock_Broadcast((ptrdiff_t)callbackContext);
600 }
601 }
602
603 static MI_Result ConsumeInstanceResults(MI_Operation *miOperation)
604 {
605 MI_Result miResult;
606
607 if (opts.synchronous == MI_TRUE)
608 {
609 MI_Boolean moreResults = MI_FALSE;
610 krisbash 1.1 do
611 {
612 const MI_Instance *miInstanceResult = NULL;
613 MI_Result _miResult;
614 const MI_Char *errorString = NULL;
615 const MI_Instance *errorDetails = NULL;
616
617 _miResult = MI_Operation_GetInstance(miOperation, &miInstanceResult, &moreResults, &miResult, &errorString, &errorDetails);
618 if (_miResult != MI_RESULT_OK)
619 {
620 miResult = _miResult;
621 }
622 if (miInstanceResult)
623 {
624 s_numInstances++;
625
626 if (!opts.quiet)
627 {
628 Instance_Print(miInstanceResult, sout, 0, opts.nulls, MI_FALSE);
629 }
630 }
631 krisbash 1.1
632 if (moreResults == MI_FALSE)
633 {
634 if (miResult != MI_RESULT_OK)
635 {
636 if (!opts.suppressResults)
637 {
638 DEBUG_ASSERT(PAL_FALSE);
639 err(PAL_T("result: %T"), tcs(Result_ToString(miResult)));
640 if (errorString)
641 {
642 err(PAL_T("result: %T"), tcs(errorString));
643 }
644 if (errorDetails)
645 {
646 Instance_Print(errorDetails, sout, 0, opts.nulls, MI_FALSE);
647 }
648 }
649 }
650 s_finalResult = miResult;
651 s_finished = 1;
652 krisbash 1.1 }
653
654 } while ((miResult == MI_RESULT_OK) && (moreResults == MI_TRUE));
655 }
656 else
657 {
658 ptrdiff_t finished;
659 finished = s_finished;
660 while (!finished)
661 {
662 CondLock_Wait((ptrdiff_t)&s_finished, &s_finished, finished, CONDLOCK_DEFAULT_SPINCOUNT);
663 finished = s_finished;
664 }
665 miResult = s_finalResult;
666 }
667
668 return miResult;
669 }
670
671
672 static MI_Result ConsumeIndicationsResults(MI_Operation *miOperation)
673 krisbash 1.1 {
674 MI_Result miResult;
675
676 if (opts.synchronous == MI_TRUE)
677 {
678 MI_Boolean moreResults = MI_FALSE;
679 do
680 {
681 const MI_Instance *miInstanceResult = NULL;
682 MI_Result _miResult;
683 const MI_Char *errorString = NULL;
684 const MI_Instance *errorDetails = NULL;
685 const MI_Char *bookmark;
686 const MI_Char *machineid;
687
688 _miResult = MI_Operation_GetIndication(miOperation, &miInstanceResult, &bookmark, &machineid, &moreResults, &miResult, &errorString, &errorDetails);
689 if (_miResult != MI_RESULT_OK)
690 {
691 miResult = _miResult;
692 }
693
694 krisbash 1.1 if (miInstanceResult)
695 {
696 s_numInstances++;
697
698 if (!opts.quiet)
699 {
700 Ftprintf(sout, PAL_T("Sync subscribe. Bookmark: %T; MachineID: %T\n"), tcs(bookmark), tcs(machineid));
701 Instance_Print(miInstanceResult, sout, 0, opts.nulls, MI_FALSE);
702 }
703 }
704
705 if (moreResults == MI_FALSE)
706 {
707 if (miResult != MI_RESULT_OK)
708 {
709 if (!opts.suppressResults)
710 {
711 err(PAL_T("result: %T"), tcs(Result_ToString(miResult)));
712 if (errorString)
713 {
714 err(PAL_T("result: %T"), tcs(errorString));
715 krisbash 1.1 }
716 if (errorDetails)
717 {
718 Instance_Print(errorDetails, sout, 0, opts.nulls, MI_FALSE);
719 }
720 }
721 }
722 s_finalResult = miResult;
723 s_finished = 1;
724 }
725
726 } while ((miResult == MI_RESULT_OK) && (moreResults == MI_TRUE));
727 }
728 else
729 {
730 ptrdiff_t finished;
731 finished = s_finished;
732 while (!finished)
733 {
734 CondLock_Wait((ptrdiff_t)&s_finished, &s_finished, finished, CONDLOCK_DEFAULT_SPINCOUNT);
735 finished = s_finished;
736 krisbash 1.1 }
737 miResult = s_finalResult;
738 }
739
740 return miResult;
741 }
742
743 void MI_CALL ClassResults(
744 _In_opt_ MI_Operation *operation,
745 _In_ void *callbackContext,
746 _In_opt_ const MI_Class *classObject,
747 MI_Boolean moreResults,
748 _In_ MI_Result resultCode,
749 _In_opt_z_ const MI_Char *errorString,
750 _In_opt_ const MI_Instance *errorDetails,
751 _In_opt_ MI_Result (MI_CALL * resultAcknowledgement)(_In_ MI_Operation *operation))
752 {
753 if (classObject)
754 {
755 s_numInstances++;
756
757 krisbash 1.1 if (!opts.quiet)
758 {
759 MI_Instance *instance;
760 if (Instance_New(&instance, classObject->classDecl, NULL) == MI_RESULT_OK)
761 {
762 Instance_Print(instance, sout, 0, MI_TRUE, MI_TRUE);
763
764 MI_Instance_Delete(instance);
765 }
766 }
767 }
768
769 if (moreResults == MI_FALSE)
770 {
771 if (resultCode != MI_RESULT_OK)
772 {
773 if (!opts.suppressResults)
774 {
775 err(PAL_T("result: %T"), tcs(Result_ToString(resultCode)));
776 if (errorString)
777 {
778 krisbash 1.1 err(PAL_T("result: %T"), tcs(errorString));
779 }
780 if (errorDetails)
781 {
782 Instance_Print(errorDetails, sout, 0, opts.nulls, MI_FALSE);
783 }
784 }
785 }
786 s_finalResult = resultCode;
787 s_finished = 1;
788 CondLock_Broadcast((ptrdiff_t)callbackContext);
789 }
790 }
791
792 static MI_Result ConsumeClassResults(MI_Operation *miOperation)
793 {
794 MI_Result miResult;
795
796 if (opts.synchronous == MI_TRUE)
797 {
798 MI_Boolean moreResults = MI_FALSE;
799 krisbash 1.1 do
800 {
801 const MI_Class *miClassResult = NULL;
802 MI_Result _miResult;
803 const MI_Char *errorString = NULL;
804 const MI_Instance *errorDetails = NULL;
805
806 _miResult = MI_Operation_GetClass(miOperation, &miClassResult, &moreResults, &miResult, &errorString, &errorDetails);
807 if (_miResult != MI_RESULT_OK)
808 {
809 miResult = _miResult;
810 }
811 if (miClassResult)
812 {
813 s_numInstances++;
814
815 if (!opts.quiet)
816 {
817 MI_Instance *instance;
818 if (Instance_New(&instance, miClassResult->classDecl, NULL) == MI_RESULT_OK)
819 {
820 krisbash 1.1 Instance_Print(instance, sout, 0, MI_TRUE, MI_TRUE);
821
822 MI_Instance_Delete(instance);
823 }
824 }
825 }
826
827 if (moreResults == MI_FALSE)
828 {
829 if (miResult != MI_RESULT_OK)
830 {
831 if (!opts.suppressResults)
832 {
833 err(PAL_T("result: %T"), tcs(Result_ToString(miResult)));
834 if (errorString)
835 {
836 err(PAL_T("result: %T"), tcs(errorString));
837 }
838 if (errorDetails)
839 {
840 Instance_Print(errorDetails, sout, 0, opts.nulls, MI_FALSE);
841 krisbash 1.1 }
842 }
843 }
844 s_finalResult = miResult;
845 s_finished = 1;
846 }
847
848 } while ((miResult == MI_RESULT_OK) && (moreResults == MI_TRUE));
849 }
850 else
851 {
852 ptrdiff_t finished;
853 finished = s_finished;
854 while (!finished)
855 {
856 CondLock_Wait((ptrdiff_t)&s_finished, &s_finished, finished, CONDLOCK_DEFAULT_SPINCOUNT);
857 finished = s_finished;
858 }
859 miResult = s_finalResult;
860 }
861
862 krisbash 1.1 return miResult;
863 }
864
865
866 void MI_CALL NoOpResults(
867 _In_opt_ MI_Operation *operation,
868 _In_ void *callbackContext,
869 _In_opt_ const MI_Instance *instance,
870 MI_Boolean moreResults,
871 _In_ MI_Result resultCode,
872 _In_opt_z_ const MI_Char *errorString,
873 _In_opt_ const MI_Instance *errorDetails,
874 _In_opt_ MI_Result (MI_CALL * resultAcknowledgement)(_In_ MI_Operation *operation))
875 {
876 if (instance)
877 {
878 s_numInstances++;
879
880 if (!opts.quiet)
881 {
882 Instance_Print(instance, sout, 0, opts.nulls, MI_FALSE);
883 krisbash 1.1 }
884 }
885
886 if (moreResults == MI_FALSE)
887 {
888 if (resultCode != MI_RESULT_OK)
889 {
890 if (!opts.suppressResults)
891 {
892 err(PAL_T("result: %T"), tcs(Result_ToString(resultCode)));
893 if (errorString)
894 {
895 err(PAL_T("result: %T"), tcs(errorString));
896 }
897 if (errorDetails)
898 {
899 Instance_Print(errorDetails, sout, 0, opts.nulls, MI_FALSE);
900 }
901 }
902 }
903 else
904 krisbash 1.1 {
905 Ftprintf(sout, PAL_T("got noop response\n"));
906
907 }
908 s_finalResult = resultCode;
909 s_finished = 1;
910 CondLock_Broadcast((ptrdiff_t)callbackContext);
911 }
912 }
913
914
915 static MI_Result NoOp(MI_Session *miSession, int argc, const MI_Char* argv [])
916 {
917 MI_Result miResult;
918 MI_Operation miOperation = MI_OPERATION_NULL;
919 MI_OperationCallbacks _callbacks = MI_OPERATIONCALLBACKS_NULL;
920 MI_OperationCallbacks *callbacks = NULL;
921 MI_Uint32 flags = 0;
922
923 MI_UNUSED(argv);
924
925 krisbash 1.1 if (argc != 2)
926 {
927 Ftprintf(serr, MI_T("Usage: %s noop\n\n"), tcs(arg0));
928 return MI_RESULT_INVALID_PARAMETER;
929 }
930
931 if (opts.synchronous == MI_FALSE)
932 {
933 _callbacks.callbackContext = &s_finished;
934 _callbacks.instanceResult = NoOpResults;
935 callbacks = &_callbacks;
936 s_finished = 0;
937 }
938
939
940 MI_Session_TestConnection(miSession, flags, callbacks, &miOperation);
941
942 miResult = ConsumeInstanceResults(&miOperation);
943
944 MI_Operation_Close(&miOperation);
945
946 krisbash 1.1 return miResult;
947 }
948
949 static MI_Result EnumerateInstances(MI_Session *miSession, int argc, const MI_Char* argv[])
950 {
951 MI_Result miResult;
952 MI_OperationOptions miOperationOptions;
953 MI_Operation miOperation = MI_OPERATION_NULL;
954 MI_OperationCallbacks _callbacks = MI_OPERATIONCALLBACKS_NULL;
955 MI_OperationCallbacks *callbacks = NULL;
956 MI_Uint32 flags = 0;
957
958 if (argc != 4)
959 {
960 Ftprintf(serr, MI_T("Usage: %s ei NAMESPACE CLASSNAME\n\n"), tcs(arg0));
961 return MI_RESULT_INVALID_PARAMETER;
962 }
963
964 if (opts.shallow)
965 {
966 flags = MI_OPERATIONFLAGS_POLYMORPHISM_SHALLOW;
967 krisbash 1.1 }
968
969 if (opts.synchronous == MI_FALSE)
970 {
971 _callbacks.callbackContext = &s_finished;
972 _callbacks.instanceResult = InstanceResults;
973 callbacks = &_callbacks;
974 s_finished = 0;
975 }
976
977
978 miResult = CreateOperationOptions(miSession, &miOperationOptions);
979 if (miResult != MI_RESULT_OK)
980 return miResult;
981
982 MI_Session_EnumerateInstances(miSession, flags, &miOperationOptions, argv[2], argv[3], MI_FALSE, callbacks, &miOperation);
983
984 miResult = ConsumeInstanceResults(&miOperation);
985
986 MI_Operation_Close(&miOperation);
987
988 krisbash 1.1 MI_OperationOptions_Delete(&miOperationOptions);
989
990 return miResult;
991 }
992
993 static MI_Result QueryInstances(MI_Session *miSession, int argc, const MI_Char* argv[])
994 {
995 MI_Result miResult;
996 MI_OperationOptions miOperationOptions;
997 MI_Operation miOperation = MI_OPERATION_NULL;
998 MI_OperationCallbacks _callbacks = MI_OPERATIONCALLBACKS_NULL;
999 MI_OperationCallbacks *callbacks = NULL;
1000
1001 if (argc != 4)
1002 {
1003 Ftprintf(serr, MI_T("Usage: %s ei NAMESPACE CLASSNAME\n\n"), tcs(arg0));
1004 return MI_RESULT_INVALID_PARAMETER;
1005 }
1006
1007 if (opts.synchronous == MI_FALSE)
1008 {
1009 krisbash 1.1 _callbacks.callbackContext = &s_finished;
1010 _callbacks.instanceResult = InstanceResults;
1011 callbacks = &_callbacks;
1012 s_finished = 0;
1013 }
1014
1015 miResult = CreateOperationOptions(miSession, &miOperationOptions);
1016 if (miResult != MI_RESULT_OK)
1017 return miResult;
1018
1019 MI_Session_QueryInstances(miSession, 0, &miOperationOptions, argv[2], opts.querylang, opts.queryexpr, callbacks, &miOperation);
1020
1021 miResult = ConsumeInstanceResults(&miOperation);
1022
1023 MI_Operation_Close(&miOperation);
1024
1025 MI_OperationOptions_Delete(&miOperationOptions);
1026
1027 return miResult;
1028 }
1029
1030 krisbash 1.1 static MI_Result Query(MI_Session *miSession, int argc, const MI_Char* argv[])
1031 {
1032 MI_Result miResult;
1033 MI_OperationOptions miOperationOptions;
1034 MI_Operation miOperation = MI_OPERATION_NULL;
1035 MI_OperationCallbacks _callbacks = MI_OPERATIONCALLBACKS_NULL;
1036 MI_OperationCallbacks *callbacks = NULL;
1037 const MI_Char* dialect = NULL;
1038
1039 if (argc != 4)
1040 {
1041 Ftprintf(serr, PAL_T("Usage: %T %T NAMESPACE QUERY\n\n"), tcs(arg0),
1042 tcs(argv[1]));
1043 return MI_RESULT_INVALID_PARAMETER;
1044 }
1045
1046 if (opts.synchronous == MI_FALSE)
1047 {
1048 _callbacks.callbackContext = &s_finished;
1049 _callbacks.instanceResult = InstanceResults;
1050 callbacks = &_callbacks;
1051 krisbash 1.1 s_finished = 0;
1052 }
1053
1054 // Determine query dialect:
1055 if (Tcscmp(argv[1], MI_T("wql")) == 0)
1056 {
1057 dialect = MI_T("WQL");
1058 }
1059 else if (Tcscmp(argv[1], MI_T("cql")) == 0)
1060 {
1061 dialect = MI_T("CQL");
1062 }
1063 else
1064 {
1065 err(MI_T("invalid query dialecdt: %T"), tcs(argv[1]));
1066 }
1067
1068 // Extract query options.
1069 opts.queryexpr = argv[3];
1070
1071 miResult = CreateOperationOptions(miSession, &miOperationOptions);
1072 krisbash 1.1 if (miResult != MI_RESULT_OK)
1073 return miResult;
1074
1075 MI_Session_QueryInstances(miSession, 0, &miOperationOptions, argv[2], dialect, argv[3], callbacks, &miOperation);
1076
1077 miResult = ConsumeInstanceResults(&miOperation);
1078
1079 MI_Operation_Close(&miOperation);
1080
1081 MI_OperationOptions_Delete(&miOperationOptions);
1082
1083 return miResult;
1084 }
1085
1086 static MI_Result GetInstance(MI_Session *miSession, int argc, const MI_Char* argv[])
1087 {
1088 MI_Result miResult;
1089 MI_OperationOptions miOperationOptions;
1090 MI_Operation miOperation = MI_OPERATION_NULL;
1091 MI_OperationCallbacks _callbacks = MI_OPERATIONCALLBACKS_NULL;
1092 MI_OperationCallbacks *callbacks = NULL;
1093 krisbash 1.1 MI_Instance *instance;
1094 const MI_Char *nameSpace;
1095 const MI_Char** p;
1096 const MI_Char** end;
1097
1098 if (argc < 4)
1099 {
1100 Ftprintf(serr, MI_T("Usage: %s gi NAMESPACE INSTANCENAME\n\n"), tcs(arg0));
1101 return MI_RESULT_INVALID_PARAMETER;
1102 }
1103
1104 nameSpace = argv[2];
1105 argc -= 3;
1106 argv += 3;
1107 p = argv;
1108 end = p + argc;
1109
1110 if (!ArgsToInstance(&p, end, MI_FLAG_CLASS, MI_TRUE, &instance))
1111 {
1112 err(MI_T("invalid instance name specification"));
1113 return MI_RESULT_FAILED;
1114 krisbash 1.1 }
1115
1116 if (p != end)
1117 {
1118 err(MI_T("extraneous arguments after instance name"));
1119 return MI_RESULT_INVALID_PARAMETER;
1120 }
1121
1122
1123 if (opts.synchronous == MI_FALSE)
1124 {
1125 _callbacks.callbackContext = &s_finished;
1126 _callbacks.instanceResult = InstanceResults;
1127 callbacks = &_callbacks;
1128 s_finished = 0;
1129 }
1130
1131 miResult = CreateOperationOptions(miSession, &miOperationOptions);
1132 if (miResult != MI_RESULT_OK)
1133 return miResult;
1134
1135 krisbash 1.1 MI_Session_GetInstance(miSession, 0, &miOperationOptions, nameSpace, instance, callbacks, &miOperation);
1136
1137 miResult = ConsumeInstanceResults(&miOperation);
1138
1139 MI_Operation_Close(&miOperation);
1140
1141 MI_Instance_Delete(instance);
1142
1143 MI_OperationOptions_Delete(&miOperationOptions);
1144
1145 return miResult;
1146 }
1147
1148
1149 static MI_Result CreateInstance(MI_Session *miSession, int argc, const MI_Char* argv[])
1150 {
1151 MI_Result miResult;
1152 MI_OperationOptions miOperationOptions;
1153 MI_Operation miOperation = MI_OPERATION_NULL;
1154 MI_OperationCallbacks _callbacks = MI_OPERATIONCALLBACKS_NULL;
1155 MI_OperationCallbacks *callbacks = NULL;
1156 krisbash 1.1 MI_Instance *instance;
1157 const MI_Char *nameSpace;
1158 const MI_Char** p;
1159 const MI_Char** end;
1160
1161 if (argc < 4)
1162 {
1163 Ftprintf(serr, MI_T("Usage: %s ci NAMESPACE INSTANCE\n\n"), tcs(arg0));
1164 return MI_RESULT_INVALID_PARAMETER;
1165 }
1166
1167 nameSpace = argv[2];
1168 argc -= 3;
1169 argv += 3;
1170 p = argv;
1171 end = p + argc;
1172
1173 if (!ArgsToInstance(&p, end, MI_FLAG_CLASS, MI_TRUE, &instance))
1174 {
1175 err(PAL_T("invalid instance name specification"));
1176 return MI_RESULT_FAILED;
1177 krisbash 1.1 }
1178
1179 if (p != end)
1180 {
1181 err(PAL_T("extraneous arguments after instance name"));
1182 return MI_RESULT_INVALID_PARAMETER;
1183 }
1184
1185 if (opts.synchronous == MI_FALSE)
1186 {
1187 _callbacks.callbackContext = &s_finished;
1188 _callbacks.instanceResult = InstanceResults;
1189 callbacks = &_callbacks;
1190 s_finished = 0;
1191 }
1192
1193 miResult = CreateOperationOptions(miSession, &miOperationOptions);
1194 if (miResult != MI_RESULT_OK)
1195 return miResult;
1196
1197 MI_Session_CreateInstance(miSession, 0, &miOperationOptions, nameSpace, instance, callbacks, &miOperation);
1198 krisbash 1.1
1199 miResult = ConsumeInstanceResults(&miOperation);
1200
1201 MI_Operation_Close(&miOperation);
1202
1203 MI_Instance_Delete(instance);
1204
1205 MI_OperationOptions_Delete(&miOperationOptions);
1206
1207 return miResult;
1208
1209 }
1210
1211 static MI_Result ModifyInstance(MI_Session *miSession, int argc, const MI_Char* argv[])
1212 {
1213 MI_Result miResult;
1214 MI_OperationOptions miOperationOptions;
1215 MI_Operation miOperation = MI_OPERATION_NULL;
1216 MI_OperationCallbacks _callbacks = MI_OPERATIONCALLBACKS_NULL;
1217 MI_OperationCallbacks *callbacks = NULL;
1218 MI_Instance *instance;
1219 krisbash 1.1 const MI_Char *nameSpace;
1220 const MI_Char** p;
1221 const MI_Char** end;
1222
1223 if (argc < 4)
1224 {
1225 Ftprintf(serr, MI_T("Usage: %s mi NAMESPACE INSTANCE\n\n"), tcs(arg0));
1226 return MI_RESULT_INVALID_PARAMETER;
1227 }
1228
1229 nameSpace = argv[2];
1230 argc -= 3;
1231 argv += 3;
1232 p = argv;
1233 end = p + argc;
1234
1235 if (!ArgsToInstance(&p, end, MI_FLAG_CLASS, MI_TRUE, &instance))
1236 {
1237 err(PAL_T("invalid instance name specification"));
1238 return MI_RESULT_FAILED;
1239 }
1240 krisbash 1.1
1241 if (p != end)
1242 {
1243 err(PAL_T("extraneous arguments after instance name"));
1244 return MI_RESULT_INVALID_PARAMETER;
1245 }
1246
1247 if (opts.synchronous == MI_FALSE)
1248 {
1249 _callbacks.callbackContext = &s_finished;
1250 _callbacks.instanceResult = InstanceResults;
1251 callbacks = &_callbacks;
1252 s_finished = 0;
1253 }
1254
1255
1256 miResult = CreateOperationOptions(miSession, &miOperationOptions);
1257 if (miResult != MI_RESULT_OK)
1258 return miResult;
1259
1260 MI_Session_ModifyInstance(miSession, 0, &miOperationOptions, nameSpace, instance, callbacks, &miOperation);
1261 krisbash 1.1
1262 miResult = ConsumeInstanceResults(&miOperation);
1263
1264 MI_Operation_Close(&miOperation);
1265
1266 MI_Instance_Delete(instance);
1267
1268 MI_OperationOptions_Delete(&miOperationOptions);
1269
1270 return miResult;
1271
1272 }
1273
1274 static MI_Result DeleteInstance(MI_Session *miSession, int argc, const MI_Char* argv[])
1275 {
1276 MI_Result miResult;
1277 MI_OperationOptions miOperationOptions;
1278 MI_Operation miOperation = MI_OPERATION_NULL;
1279 MI_OperationCallbacks _callbacks = MI_OPERATIONCALLBACKS_NULL;
1280 MI_OperationCallbacks *callbacks = NULL;
1281 MI_Instance *instance;
1282 krisbash 1.1 const MI_Char *nameSpace;
1283 const MI_Char** p;
1284 const MI_Char** end;
1285
1286 if (argc < 4)
1287 {
1288 Ftprintf(serr, MI_T("Usage: %s di NAMESPACE INSTANCE\n\n"), tcs(arg0));
1289 return MI_RESULT_INVALID_PARAMETER;
1290 }
1291
1292 nameSpace = argv[2];
1293 argc -= 3;
1294 argv += 3;
1295 p = argv;
1296 end = p + argc;
1297
1298 if (!ArgsToInstance(&p, end, MI_FLAG_CLASS, MI_TRUE, &instance))
1299 {
1300 err(PAL_T("invalid instance name specification"));
1301 return MI_RESULT_FAILED;
1302 }
1303 krisbash 1.1
1304 if (p != end)
1305 {
1306 err(PAL_T("extraneous arguments after instance name"));
1307 return MI_RESULT_INVALID_PARAMETER;
1308 }
1309
1310 if (opts.synchronous == MI_FALSE)
1311 {
1312 _callbacks.callbackContext = &s_finished;
1313 _callbacks.instanceResult = InstanceResults;
1314 callbacks = &_callbacks;
1315 s_finished = 0;
1316 }
1317
1318
1319 miResult = CreateOperationOptions(miSession, &miOperationOptions);
1320 if (miResult != MI_RESULT_OK)
1321 return miResult;
1322
1323 MI_Session_DeleteInstance(miSession, 0, &miOperationOptions, nameSpace, instance, callbacks, &miOperation);
1324 krisbash 1.1
1325 miResult = ConsumeInstanceResults(&miOperation);
1326
1327 MI_Operation_Close(&miOperation);
1328
1329 MI_Instance_Delete(instance);
1330
1331 MI_OperationOptions_Delete(&miOperationOptions);
1332
1333 return miResult;
1334
1335 }
1336
1337 static MI_Result Associators(MI_Session *miSession, int argc, const MI_Char* argv[])
1338 {
1339 MI_Result miResult;
1340 MI_OperationOptions miOperationOptions;
1341 MI_Operation miOperation = MI_OPERATION_NULL;
1342 MI_OperationCallbacks _callbacks = MI_OPERATIONCALLBACKS_NULL;
1343 MI_OperationCallbacks *callbacks = NULL;
1344 MI_Instance *instance;
1345 krisbash 1.1 const MI_Char *nameSpace;
1346 const MI_Char** p;
1347 const MI_Char** end;
1348
1349 if (argc < 4)
1350 {
1351 Ftprintf(serr, MI_T("Usage: %s a NAMESPACE INSTANCE\n\n"), tcs(arg0));
1352 return MI_RESULT_INVALID_PARAMETER;
1353 }
1354
1355 nameSpace = argv[2];
1356 argc -= 3;
1357 argv += 3;
1358 p = argv;
1359 end = p + argc;
1360
1361 if (!ArgsToInstance(&p, end, MI_FLAG_CLASS, MI_TRUE, &instance))
1362 {
1363 err(PAL_T("invalid instance name specification"));
1364 return MI_RESULT_FAILED;
1365 }
1366 krisbash 1.1
1367 if (p != end)
1368 {
1369 err(PAL_T("extraneous arguments after instance name"));
1370 return MI_RESULT_INVALID_PARAMETER;
1371 }
1372
1373 if (opts.synchronous == MI_FALSE)
1374 {
1375 _callbacks.callbackContext = &s_finished;
1376 _callbacks.instanceResult = InstanceResults;
1377 callbacks = &_callbacks;
1378 s_finished = 0;
1379 }
1380
1381
1382 miResult = CreateOperationOptions(miSession, &miOperationOptions);
1383 if (miResult != MI_RESULT_OK)
1384 return miResult;
1385
1386 MI_Session_AssociatorInstances(miSession, 0, &miOperationOptions, nameSpace, instance, opts.assocClass, opts.resultClass, opts.role, opts.resultRole, MI_FALSE, callbacks, &miOperation);
1387 krisbash 1.1
1388 miResult = ConsumeInstanceResults(&miOperation);
1389
1390 MI_Operation_Close(&miOperation);
1391
1392 MI_Instance_Delete(instance);
1393
1394 MI_OperationOptions_Delete(&miOperationOptions);
1395
1396 return miResult;
1397 }
1398
1399 static MI_Result References(MI_Session *miSession, int argc, const MI_Char* argv[])
1400 {
1401 MI_Result miResult;
1402 MI_OperationOptions miOperationOptions;
1403 MI_Operation miOperation = MI_OPERATION_NULL;
1404 MI_OperationCallbacks _callbacks = MI_OPERATIONCALLBACKS_NULL;
1405 MI_OperationCallbacks *callbacks = NULL;
1406 MI_Instance *instance;
1407 const MI_Char *nameSpace;
1408 krisbash 1.1 const MI_Char** p;
1409 const MI_Char** end;
1410
1411 if (argc < 4)
1412 {
1413 Ftprintf(serr, MI_T("Usage: %T d NAMESPACE INSTANCE\n\n"), tcs(arg0));
1414 return MI_RESULT_INVALID_PARAMETER;
1415 }
1416
1417 nameSpace = argv[2];
1418 argc -= 3;
1419 argv += 3;
1420 p = argv;
1421 end = p + argc;
1422
1423 if (!ArgsToInstance(&p, end, MI_FLAG_CLASS, MI_TRUE, &instance))
1424 {
1425 err(PAL_T("invalid instance name specification"));
1426 return MI_RESULT_FAILED;
1427 }
1428
1429 krisbash 1.1 if (p != end)
1430 {
1431 err(PAL_T("extraneous arguments after instance name"));
1432 return MI_RESULT_INVALID_PARAMETER;
1433 }
1434
1435 if (opts.synchronous == MI_FALSE)
1436 {
1437 _callbacks.callbackContext = &s_finished;
1438 _callbacks.instanceResult = InstanceResults;
1439 callbacks = &_callbacks;
1440 s_finished = 0;
1441 }
1442
1443
1444 miResult = CreateOperationOptions(miSession, &miOperationOptions);
1445 if (miResult != MI_RESULT_OK)
1446 return miResult;
1447
1448 MI_Session_ReferenceInstances(miSession, 0, &miOperationOptions, nameSpace, instance, opts.assocClass, opts.role, MI_FALSE, callbacks, &miOperation);
1449
1450 krisbash 1.1 miResult = ConsumeInstanceResults(&miOperation);
1451
1452 MI_Operation_Close(&miOperation);
1453
1454 MI_Instance_Delete(instance);
1455
1456 MI_OperationOptions_Delete(&miOperationOptions);
1457
1458 return miResult;
1459 }
1460
1461 static MI_Result Invoke(MI_Session *miSession, int argc, const MI_Char* argv[])
1462 {
1463 MI_Result miResult;
1464 MI_OperationOptions miOperationOptions;
1465 MI_Operation miOperation = MI_OPERATION_NULL;
1466 MI_OperationCallbacks _callbacks = MI_OPERATIONCALLBACKS_NULL;
1467 MI_OperationCallbacks *callbacks = NULL;
1468 MI_Instance *instance;
1469 MI_Instance *inParams = NULL;
1470 const MI_Char *nameSpace;
1471 krisbash 1.1 const MI_Char *methodName;
1472 const MI_Char** p;
1473 const MI_Char** end;
1474 MI_Uint32 elementCount = 0;
1475
1476 if (argc < 5)
1477 {
1478 Ftprintf(serr,
1479 PAL_T("Usage: %s iv NAMESPACE INSTANCENAME METHODNAME PARAMETERS\n\n"),
1480 tcs(arg0));
1481 return MI_RESULT_INVALID_PARAMETER;
1482 }
1483
1484 nameSpace = argv[2];
1485 argc -= 3;
1486 argv += 3;
1487 p = argv;
1488 end = p + argc;
1489
1490 if (!ArgsToInstance(&p, end, MI_FLAG_CLASS, MI_TRUE, &instance))
1491 {
1492 krisbash 1.1 err(PAL_T("invalid instance name specification"));
1493 return MI_RESULT_FAILED;
1494 }
1495
1496 if (p == end)
1497 {
1498 err(PAL_T("expected method name"));
1499 return MI_RESULT_INVALID_PARAMETER;
1500 }
1501
1502 methodName = *p;
1503 p++;
1504
1505 if (p != end)
1506 {
1507 if (!ArgsToInstance(&p, end, MI_FLAG_METHOD, MI_TRUE, &inParams))
1508 {
1509 err(PAL_T("invalid instance name specification"));
1510 return MI_RESULT_FAILED;
1511 }
1512 }
1513 krisbash 1.1
1514 if (opts.synchronous == MI_FALSE)
1515 {
1516 _callbacks.callbackContext = &s_finished;
1517 _callbacks.instanceResult = InstanceResults;
1518 callbacks = &_callbacks;
1519 s_finished = 0;
1520 }
1521
1522 if (MI_Instance_GetElementCount(instance, &elementCount) != MI_RESULT_OK)
1523 {
1524 err(PAL_T("Failed to get element count for instance"));
1525 return MI_RESULT_FAILED;
1526 }
1527
1528 miResult = CreateOperationOptions(miSession, &miOperationOptions);
1529 if (miResult != MI_RESULT_OK)
1530 return miResult;
1531
1532 if (elementCount)
1533 {
1534 krisbash 1.1 MI_Session_Invoke(miSession, 0, NULL, nameSpace, instance->classDecl->name, methodName, instance, inParams, callbacks, &miOperation);
1535 }
1536 else
1537 {
1538 /* Static method */
1539 MI_Session_Invoke(miSession, 0, &miOperationOptions, nameSpace, instance->classDecl->name, methodName, NULL, inParams, callbacks, &miOperation);
1540 }
1541
1542 miResult = ConsumeInstanceResults(&miOperation);
1543
1544 MI_Operation_Close(&miOperation);
1545
1546 MI_Instance_Delete(instance);
1547
1548 MI_OperationOptions_Delete(&miOperationOptions);
1549
1550 return miResult;
1551 }
1552
1553 static MI_Result GetClass(MI_Session *miSession, int argc, const MI_Char* argv[])
1554 {
1555 krisbash 1.1 MI_Result miResult;
1556 MI_OperationOptions miOperationOptions;
1557 MI_Operation miOperation = MI_OPERATION_NULL;
1558 MI_OperationCallbacks _callbacks = MI_OPERATIONCALLBACKS_NULL;
1559 MI_OperationCallbacks *callbacks = NULL;
1560 const MI_Char *nameSpace;
1561 const MI_Char *className;
1562
1563 if (argc != 4)
1564 {
1565 Ftprintf(serr, MI_T("Usage: %s gc NAMESPACE CLASSNAME\n\n"), tcs(arg0));
1566 return MI_RESULT_INVALID_PARAMETER;
1567 }
1568
1569 nameSpace = argv[2];
1570 className = argv[3];
1571
1572 if (opts.synchronous == MI_FALSE)
1573 {
1574 _callbacks.callbackContext = &s_finished;
1575 _callbacks.classResult = ClassResults;
1576 krisbash 1.1 callbacks = &_callbacks;
1577 s_finished = 0;
1578 }
1579
1580
1581 miResult = CreateOperationOptions(miSession, &miOperationOptions);
1582 if (miResult != MI_RESULT_OK)
1583 return miResult;
1584
1585 MI_Session_GetClass(miSession, 0, &miOperationOptions, nameSpace, className, callbacks, &miOperation);
1586
1587 miResult = ConsumeClassResults(&miOperation);
1588
1589 MI_Operation_Close(&miOperation);
1590
1591 MI_OperationOptions_Delete(&miOperationOptions);
1592
1593 return miResult;
1594 }
1595
1596 static MI_Result Subscribe(MI_Session *miSession, int argc, const MI_Char* argv[])
1597 krisbash 1.1 {
1598 MI_Result miResult;
1599 MI_OperationOptions miOperationOptions;
1600 MI_Operation miOperation = MI_OPERATION_NULL;
1601 MI_OperationCallbacks _callbacks = MI_OPERATIONCALLBACKS_NULL;
1602 MI_OperationCallbacks *callbacks = NULL;
1603 const MI_Char *nameSpace;
1604
1605 if (argc != 3 || opts.querylang == NULL || opts.queryexpr == NULL)
1606 {
1607 Ftprintf(serr, MI_T("Usage: %s [--querylang 'WQL/CQL' --queryexpr ] sub NAMESPACE\n\n"), tcs(arg0));
1608 return MI_RESULT_INVALID_PARAMETER;
1609 }
1610
1611 if (opts.synchronous == MI_FALSE)
1612 {
1613 _callbacks.callbackContext = &s_finished;
1614 _callbacks.indicationResult = IndicationResult;
1615 callbacks = &_callbacks;
1616 s_finished = 0;
1617 }
1618 krisbash 1.1
1619 nameSpace = argv[2];
1620
1621 miResult = CreateOperationOptions(miSession, &miOperationOptions);
1622 if (miResult != MI_RESULT_OK)
1623 {
1624 Ftprintf(serr, MI_T("Failed to create MI_OperationOptions, error code(%d)\n\n"), miResult);
1625 return miResult;
1626 }
1627
1628 MI_Session_Subscribe(miSession, 0, &miOperationOptions, nameSpace, opts.querylang, opts.queryexpr, NULL, callbacks, &miOperation);
1629
1630 /* Duplicate operation */
1631 memcpy(&gop, &miOperation, sizeof(MI_Operation));
1632
1633 miResult = ConsumeIndicationsResults(&miOperation);
1634
1635 /* Cleanup global operation since it is done */
1636 memset(&gop, 0, sizeof(MI_Operation));
1637
1638 MI_Operation_Close(&miOperation);
1639 krisbash 1.1
1640 MI_OperationOptions_Delete(&miOperationOptions);
1641
1642 return miResult;
1643 }
1644
1645 static MI_Result FindConfigFile(_Pre_writable_size_(PAL_MAX_PATH_SIZE) char path[PAL_MAX_PATH_SIZE])
1646 {
1647 char* home;
1648 /* Look in current directory */
1649 {
1650 Strlcpy(path, "./.omiclirc", PAL_MAX_PATH_SIZE);
1651
1652 if (access(path, R_OK) == 0)
1653 return MI_RESULT_OK;
1654 }
1655
1656 /* Look in HOME directory */
1657 home = Dupenv("HOME");
1658 if (home)
1659 {
1660 krisbash 1.1 Strlcpy(path, home, PAL_MAX_PATH_SIZE);
1661 Strlcat(path, "/.omiclirc", PAL_MAX_PATH_SIZE);
1662
1663 if (access(path, R_OK) == 0)
1664 {
1665 free(home);
1666 return MI_RESULT_OK;
1667 }
1668 free(home);
1669 }
1670
1671 /* Look in system config directory */
1672 {
1673 Strlcpy(path, OMI_GetPath(ID_SYSCONFDIR), PAL_MAX_PATH_SIZE);
1674 Strlcat(path, "/omicli.conf", PAL_MAX_PATH_SIZE);
1675
1676 if (access(path, R_OK) == 0)
1677 return MI_RESULT_OK;
1678 }
1679
1680 /* Not found */
1681 krisbash 1.1 return MI_RESULT_FAILED;
1682 }
1683
1684 static MI_Result GetConfigFileOptions()
1685 {
1686 char path[PAL_MAX_PATH_SIZE];
1687 Conf* conf;
1688 MI_Result miResult = MI_RESULT_OK;
1689
1690 /* Form the configuration file path (silently ignore if not found) */
1691 if (FindConfigFile(path) != 0)
1692 return MI_RESULT_OK;
1693
1694 /* Open the configuration file */
1695 conf = Conf_Open(path);
1696 if (!conf)
1697 {
1698 err(PAL_T("failed to open configuration file: %s"), scs(path));
1699 return MI_RESULT_FAILED;
1700 }
1701
1702 krisbash 1.1 /* For each key=value pair in configuration file */
1703 for (;;)
1704 {
1705 const char* key;
1706 const char* value;
1707 int r = Conf_Read(conf, &key, &value);
1708
1709 if (r == -1)
1710 {
1711 err(PAL_T("%s: %s\n"), scs(path), scs(Conf_Error(conf)));
1712 miResult = MI_RESULT_FAILED;
1713 goto cleanup;
1714 }
1715
1716 if (r == 1)
1717 break;
1718
1719 if (strcmp(key, "httpport") == 0)
1720 {
1721 char* end;
1722 unsigned long x = Strtoul(value, &end, 10);
1723 krisbash 1.1
1724 if (*end != '\0' || x > USHRT_MAX)
1725 {
1726 err(PAL_T("%s(%u): invalid value for '%s': %s"), scs(path),
1727 Conf_Line(conf), scs(key), scs(value));
1728 miResult = MI_RESULT_FAILED;
1729 goto cleanup;
1730 }
1731
1732 opts.httpport = (unsigned short)x;
1733 }
1734 else if (strcmp(key, "httpsport") == 0)
1735 {
1736 char* end;
1737 unsigned long x = Strtoul(value, &end, 10);
1738
1739 if (*end != '\0' || x > USHRT_MAX)
1740 {
1741 err(PAL_T("%s(%u): invalid value for '%s': %s"), scs(path),
1742 Conf_Line(conf), scs(key), scs(value));
1743 miResult = MI_RESULT_FAILED;
1744 krisbash 1.1 goto cleanup;
1745 }
1746
1747 opts.httpsport = (unsigned short)x;
1748 }
1749 else if (strcmp(key, "trace") == 0)
1750 {
1751 if (Strcasecmp(value, "MI_TRUE") == 0)
1752 {
1753 opts.trace = MI_TRUE;
1754 }
1755 else if (Strcasecmp(value, "MI_FALSE") == 0)
1756 {
1757 opts.trace = MI_FALSE;
1758 }
1759 else
1760 {
1761 err(PAL_T("%s(%u): invalid value for '%s': %s"), scs(path),
1762 Conf_Line(conf), scs(key), scs(value));
1763 miResult = MI_RESULT_FAILED;
1764 goto cleanup;
1765 krisbash 1.1 }
1766 }
1767 else if (strcmp(key, "protocolhandler") == 0)
1768 {
1769 /* This is used in the miapi itself */
1770 }
1771 if (strcmp(key, "loglevel") == 0)
1772 {
1773 if (Log_SetLevelFromString(value) != 0)
1774 {
1775 err(PAL_T("%s(%u): invalid value for '%s': %s"), scs(path),
1776 Conf_Line(conf), scs(key), scs(value));
1777 miResult = MI_RESULT_FAILED;
1778 goto cleanup;
1779 }
1780 }
1781 else if (strcmp(key, "logpath") == 0)
1782 {
1783 /* TODO - this is just a test tool? */
1784 }
1785 else if (strcmp(key, "logfile") == 0)
1786 krisbash 1.1 {
1787 /* TODO - this is just a test tool? */
1788 }
1789 else if (IsNickname(key))
1790 {
1791 if (SetPathFromNickname(key, value) != 0)
1792 {
1793 err(PAL_T("SetPathFromNickname() failed"));
1794 miResult = MI_RESULT_FAILED;
1795 goto cleanup;
1796 }
1797 }
1798 else
1799 {
1800 err(PAL_T("%s(%u): unknown key: %s"), scs(path), Conf_Line(conf),
1801 scs(key));
1802 miResult = MI_RESULT_FAILED;
1803 goto cleanup;
1804 }
1805 }
1806
1807 krisbash 1.1 cleanup:
1808 /* Close configuration file */
1809 Conf_Close(conf);
1810 return miResult;
1811 }
1812
1813 static MI_Result GetCommandLineDestDirOption(
1814 int* argc_,
1815 const MI_Char* argv[])
1816 {
1817 int argc = *argc_;
1818 int i;
1819 const MI_Char* destdir = NULL;
1820
1821 for (i = 1; i < argc; )
1822 {
1823 if (Tcscmp(argv[i], MI_T("--destdir")) == 0)
1824 {
1825 if (i + 1 == argc)
1826 {
1827 err(PAL_T("missing argument for --destdir option"));
1828 krisbash 1.1 return MI_RESULT_INVALID_PARAMETER;
1829 }
1830
1831 destdir = argv[i+1];
1832 memmove((char*)&argv[i], (char*)&argv[i+2],
1833 sizeof(char*) * (argc-i-1));
1834 argc -= 2;
1835 }
1836 else if (Tcsncmp(argv[i], MI_T("--destdir="), 10) == 0)
1837 {
1838 destdir = argv[i] + 10;
1839 memmove((char*)&argv[i], (char*)&argv[i+1],
1840 sizeof(char*) * (argc-i));
1841
1842 argc -= 1;
1843 }
1844 else
1845 i++;
1846 }
1847
1848 if (destdir)
1849 krisbash 1.1 {
1850 #if defined(CONFIG_ENABLE_WCHAR)
1851 char _destdir[PAL_MAX_PATH_SIZE];
1852 StrWcslcpy(_destdir, destdir, PAL_MAX_PATH_SIZE);
1853 if (SetPath(ID_DESTDIR, _destdir) != 0)
1854 #else
1855 if (SetPath(ID_DESTDIR, destdir) != 0)
1856 #endif
1857 {
1858 err(PAL_T("failed to set destdir"));
1859 return MI_RESULT_FAILED;
1860 }
1861 }
1862
1863 *argc_ = argc;
1864
1865 return MI_RESULT_OK;
1866 }
1867
1868 #define GETOPTSTATE_INITIALIZER { 0, { '\0' }, NULL, { '\0' } }
1869 #define GETOPT_OPT_SIZE 512
1870 krisbash 1.1 #define GETOPT_ERR_SIZE 512
1871
1872 typedef struct _GetOptState
1873 {
1874 int index;
1875 MI_Char opt[GETOPT_OPT_SIZE];
1876 const MI_Char* arg;
1877 MI_Char err[GETOPT_ERR_SIZE];
1878 }
1879 GetOptState;
1880
1881 static int GetOpt(
1882 int* argc,
1883 const MI_Char* argv[],
1884 const MI_Char* opts[],
1885 GetOptState* state)
1886 {
1887 int i;
1888 int j;
1889
1890 /* Clear state */
1891 krisbash 1.1 state->opt[0] = '\0';
1892 state->arg = NULL;
1893 state->err[0] = '\0';
1894
1895 for (i = state->index; i < *argc; i++)
1896 {
1897 if (argv[i][0] != '-')
1898 {
1899 state->index++;
1900 continue;
1901 }
1902
1903 /* Find option argv[i] */
1904 for (j = 0; opts[j]; j++)
1905 {
1906 MI_Char opt[GETOPT_OPT_SIZE];
1907 size_t n;
1908 int hasArg;
1909
1910 /* Copy option name */
1911 n = Tcslcpy(opt, opts[j], sizeof(opt)/sizeof(opt[0]));
1912 krisbash 1.1
1913 /* If option name too long */
1914 if (n >= sizeof(opt))
1915 {
1916 Tcslcpy(state->err, MI_T("bad parameter"), sizeof(state->err)/sizeof(state->err[0]));
1917 return -1;
1918 }
1919
1920 /* If option name zero-length */
1921 if (n == 0)
1922 {
1923 Tcslcpy(state->err, MI_T("bad parameter"), sizeof(state->err)/sizeof(state->err[0]));
1924 return -1;
1925 }
1926
1927 /* If option has argument */
1928 #ifdef _PREFAST_
1929 #pragma prefast(push)
1930 #pragma prefast(disable:26014)
1931 #endif
1932 if (opt[n-1] == ':')
1933 krisbash 1.1 {
1934 hasArg = 1;
1935 opt[n-1] = '\0';
1936 }
1937 else
1938 hasArg = 0;
1939 #ifdef _PREFAST_
1940 #pragma prefast(pop)
1941 #endif
1942
1943 /* Does argv[i] match this option? */
1944 if (Tcscmp(argv[i], opt) == 0)
1945 {
1946 if (hasArg)
1947 {
1948 if (i + 1 == *argc)
1949 {
1950 Tcslcpy(state->err, MI_T("missing option argument: "),
1951 sizeof(state->err)/sizeof(state->err[0]));
1952 Tcslcat(state->err, opt, sizeof(state->err)/sizeof(state->err[0]));
1953 return -1;
1954 krisbash 1.1 }
1955
1956 Tcslcpy(state->opt, argv[i], sizeof(state->opt)/sizeof(state->opt[0]));
1957 state->arg = argv[i+1];
1958 memmove((void*)&argv[i], (void*)&argv[i+2],
1959 sizeof(char*) * ((*argc) - i - 1));
1960 *argc -= 2;
1961 return 0;
1962 }
1963 else
1964 {
1965 Tcslcpy(state->opt, argv[i], sizeof(state->opt)/sizeof(state->opt[0]));
1966 memmove((void*)&argv[i], (void*)&argv[i+1],
1967 sizeof(char*) * ((*argc) - i));
1968 *argc -= 1;
1969 return 0;
1970 }
1971 }
1972 else if (hasArg &&
1973 Tcsncmp(argv[i], opt, n-1) == 0 && argv[i][n-1] == '=')
1974 {
1975 krisbash 1.1 Tcslcpy(state->opt, argv[i], sizeof(state->opt)/sizeof(state->opt[0]));
1976 state->opt[n-1] = '\0';
1977 state->arg = &argv[i][n];
1978 memmove((void*)&argv[i], (void*)&argv[i+1],
1979 sizeof(char*) * ((*argc) - i));
1980 *argc -= 1;
1981 return 0;
1982 }
1983 }
1984
1985 /* Unknown option */
1986 Tcslcpy(state->err, MI_T("unknown option: "), sizeof(state->err)/sizeof(state->err[0]));
1987 Tcslcat(state->err, argv[i], sizeof(state->err)/sizeof(state->err[0]));
1988 return -1;
1989 }
1990
1991 /* Done */
1992 return 1;
1993 }
1994 static MI_Result GetCommandLineOptions(
1995 int* argc,
1996 krisbash 1.1 const MI_Char* argv[])
1997 {
1998 GetOptState state = GETOPTSTATE_INITIALIZER;
1999 const MI_Char* supportedOptions[] =
2000 {
2001 MI_T("-h"),
2002 MI_T("-q"),
2003 MI_T("-t"),
2004 MI_T("-s"),
2005 MI_T("-shallow"),
2006 MI_T("-synchronous"),
2007 MI_T("-n"),
2008 MI_T("-R:"),
2009 MI_T("-ac:"),
2010 MI_T("-rc:"),
2011 MI_T("-r:"),
2012 MI_T("-rr:"),
2013 MI_T("-rc:"),
2014 MI_T("-u:"),
2015 MI_T("-p:"),
2016 MI_T("-S"),
2017 krisbash 1.1 MI_T("--summary"),
2018 MI_T("--prefix:"),
2019 MI_T("--libdir:"),
2020 MI_T("--bindir:"),
2021 MI_T("--localstatedir:"),
2022 MI_T("--sysconfdir:"),
2023 MI_T("--providerdir:"),
2024 MI_T("--certsdir:"),
2025 MI_T("--rundir:"),
2026 MI_T("--logdir:"),
2027 MI_T("--pidfile:"),
2028 MI_T("--logfile:"),
2029 MI_T("--registerdir:"),
2030 MI_T("--socketfile:"),
2031 MI_T("--pemfile:"),
2032 MI_T("--keyfile:"),
2033 MI_T("--agentprogram:"),
2034 MI_T("--serverprogram:"),
2035 MI_T("--stdout:"),
2036 MI_T("--stderr:"),
2037 MI_T("--querylang:"),
2038 krisbash 1.1 MI_T("--queryexpr:"),
2039 NULL,
2040 };
2041
2042 for (;;)
2043 {
2044 int r = GetOpt(argc, argv, supportedOptions, &state);
2045
2046 if (r == 1)
2047 break;
2048
2049 if (r == -1)
2050 {
2051 Ftprintf(serr, PAL_T("error: %T\n"), tcs(state.err));
2052 Ftprintf(serr, PAL_T("Try -h for help\n"));
2053 return MI_RESULT_INVALID_PARAMETER;
2054 }
2055
2056 if (Tcscmp(state.opt, PAL_T("-h")) == 0)
2057 {
2058 opts.help = MI_TRUE;
2059 krisbash 1.1 }
2060 else if (Tcscmp(state.opt, PAL_T("-q")) == 0)
2061 {
2062 opts.quiet = MI_TRUE;
2063 }
2064 else if (Tcscmp(state.opt, PAL_T("-t")) == 0)
2065 {
2066 opts.trace = MI_TRUE;
2067 }
2068 else if (Tcscmp(state.opt, PAL_T("-s")) == 0)
2069 {
2070 opts.suppressResults = MI_TRUE;
2071 }
2072 else if (Tcscmp(state.opt, PAL_T("-shallow")) == 0)
2073 {
2074 opts.shallow = MI_TRUE;
2075 }
2076 else if (Tcscmp(state.opt, PAL_T("-synchronous")) == 0)
2077 {
2078 opts.synchronous = MI_TRUE;
2079 }
2080 krisbash 1.1 else if (Tcscmp(state.opt, PAL_T("-n")) == 0)
2081 {
2082 opts.nulls = MI_TRUE;
2083 }
2084 else if (Tcscmp(state.opt, PAL_T("-R")) == 0)
2085 {
2086 MI_Char *end;
2087 opts.repeat = Tcstol(state.arg, &end, 10);
2088
2089 if (opts.repeat <= 0)
2090 {
2091 err(PAL_T("bad value for -R: %T"), tcs(state.arg));
2092 return MI_RESULT_INVALID_PARAMETER;
2093 }
2094 }
2095 else if (Tcscmp(state.opt, PAL_T("-ac")) == 0)
2096 {
2097 opts.assocClass = state.arg;
2098 }
2099 else if (Tcscmp(state.opt, PAL_T("-rc")) == 0)
2100 {
2101 krisbash 1.1 opts.resultClass = state.arg;
2102 }
2103 else if (Tcscmp(state.opt, PAL_T("-r")) == 0)
2104 {
2105 opts.role = state.arg;
2106 }
2107 else if (Tcscmp(state.opt, PAL_T("-rr")) == 0)
2108 {
2109 opts.resultRole = state.arg;
2110 }
2111 else if (Tcscmp(state.opt, PAL_T("-u")) == 0)
2112 {
2113 opts.user = state.arg;
2114 }
2115 else if (Tcscmp(state.opt, PAL_T("-p")) == 0)
2116 {
2117 opts.password = state.arg;
2118 }
2119 else if (Tcscmp(state.opt, PAL_T("--stdout")) == 0)
2120 {
2121 FILE* os;
2122 krisbash 1.1 #if defined(_MSC_VER)
2123 FILE* fp;
2124 os = (_wfopen_s(&fp, state.arg, PAL_T("wb")) == 0 ? fp : NULL);
2125 #else
2126 {
2127 #if defined(CONFIG_ENABLE_WCHAR)
2128 char tmp[50];
2129 StrWcslcpy(tmp, state.arg, sizeof(tmp));
2130 os = File_Open(tmp, "wb");
2131 #else
2132 os = File_Open(state.arg, "wb");
2133 #endif
2134 }
2135 #endif
2136
2137 if (!os)
2138 err(PAL_T("failed to open: %T"), tcs(state.arg));
2139
2140 sout = os;
2141 }
2142 else if (Tcscmp(state.opt, PAL_T("--stderr")) == 0)
2143 krisbash 1.1 {
2144 FILE* os;
2145 #if defined(_MSC_VER)
2146 FILE* fp;
2147 os = (_wfopen_s(&fp, state.arg, PAL_T("wb")) == 0 ? fp : NULL);
2148 #else
2149 {
2150 #if defined(CONFIG_ENABLE_WCHAR)
2151 char tmp[50];
2152 StrWcslcpy(tmp, state.arg, sizeof(tmp));
2153 os = File_Open(tmp, "wb");
2154 #else
2155 os = File_Open(state.arg, "wb");
2156 #endif
2157 }
2158 #endif
2159
2160 if (!os)
2161 err(PAL_T("failed to open: %T"), tcs(state.arg));
2162
2163 serr = os;
2164 krisbash 1.1 }
2165 else if (Tcscmp(state.opt, PAL_T("--querylang")) == 0)
2166 {
2167 opts.querylang = state.arg;
2168 }
2169 else if (Tcscmp(state.opt, PAL_T("--queryexpr")) == 0)
2170 {
2171 opts.queryexpr = state.arg;
2172 }
2173 else if (Tcscmp(state.opt, PAL_T("--summary")) == 0 ||
2174 Tcscmp(state.opt, PAL_T("-S")) == 0)
2175 {
2176 opts.summary = MI_TRUE;
2177 }
2178 #if 0
2179 else if (Tcsncmp(state.opt, PAL_T("--"), 2) == 0 && IsNickname(state.opt+2))
2180 {
2181 if (SetPathFromNickname(state.opt+2, state.arg) != 0)
2182 err(PAL_T("SetPathFromNickname() failed"));
2183 }
2184 #endif
2185 krisbash 1.1 }
2186
2187 return MI_RESULT_OK;
2188 }
2189
2190 const MI_Char USAGE[] = MI_T("\
2191 Usage: %T [OPTIONS] COMMAND ...\n\
2192 \n\
2193 This tool sends requests to the CIM server.\n\
2194 \n\
2195 OPTIONS:\n\
2196 -h Print this help message.\n\
2197 -q Operate quietly.\n\
2198 -t Enable diagnostic tracing.\n\
2199 -R N Repeat command N times.\n\
2200 -shallow Use shallow inheritance (see 'ei' command).\n\
2201 -synchronous Executes command in synchronous mode.\n\
2202 -ac CLASSNAME Association class (see 'a' and 'r' commands).\n\
2203 -rc CLASSNAME Result class (see 'a' command).\n\
2204 -r ROLE Role (see 'a' and 'r' commands).\n\
2205 -rr ROLE Result role (see 'a' command).\n\
2206 krisbash 1.1 -n Show null properties.\n\
2207 -u USERNAME Username.\n\
2208 -p PASSWORD User's password.\n\
2209 -id Send identify request.\n\
2210 --socketfile PATH Talk to the server server whose socket file resides\n\
2211 at the location given by the path argument.\n\
2212 --httpport Connect on this port instead of default.\n\
2213 --httpsport Connect on this secure port instead of default.\n\
2214 --querylang Query language (for 'ei', 'sub' command).\n\
2215 --queryexpr Query expression (for 'ei', 'sub' command).\n\
2216 \n\
2217 COMMANDS:\n\
2218 noop\n\
2219 Perform a no-op operation.\n\
2220 gi NAMESPACE INSTANCENAME\n\
2221 Peform a CIM [g]et [i]nstance operation.\n\
2222 ci NAMESPACE NEWINSTANCE\n\
2223 Peform a CIM [c]reate [i]nstance operation.\n\
2224 mi NAMESPACE MODIFIEDINSTANCE\n\
2225 Peform a CIM [m]odify [i]nstance operation.\n\
2226 di NAMESPACE INSTANCENAME\n\
2227 krisbash 1.1 Peform a CIM [d]elete [i]nstance operation.\n\
2228 ei [-shallow] NAMESPACE CLASSNAME\n\
2229 Peform a CIM [e]numerate [i]nstances operation.\n\
2230 iv NAMESPACE INSTANCENAME METHODNAME PARAMETERS\n\
2231 Peform a CIM extrinisic method [i]nvocation operation.\n\
2232 a [-ac -rc -r -rr ] NAMESPACE INSTANCENAME\n\
2233 Perform a CIM [a]ssociator instances operation.\n\
2234 r [-ac -r] NAMESPACE INSTANCENAME (references)\n\
2235 Perform a CIM [r]eference instances operation.\n\
2236 gc NAMESPACE CLASSENAME\n\
2237 Peform a CIM [g]et [c]lass operation.\n\
2238 enc INSTANCE\n\
2239 Attempt to encode and print the given instance representation.\n\
2240 wql NAMESPACE WQLQUERY\n\
2241 Peform a WQL query operation.\n\
2242 cql NAMESPACE CQLQUERY\n\
2243 Peform a CQL query operation.\n\
2244 sub NAMESPACE\n\
2245 Peform a subscribe to indication operation.\n\
2246 \n\
2247 INSTANCENAME and PARAMETERS format:\n\
2248 krisbash 1.1 { class_name property_name property_value property_name property_value }\n\
2249 property_value is either a string value, or can be an INSTANCENAME.\n\
2250 property_value can also be an array taking the form [ property_value property_value ].\n\
2251 \n");
2252
2253 /*
2254 * Signal handler that catch SIGINT signal, the signal
2255 * is triggered by CTRL+C from console; In case of
2256 * SIGINT signal, need to cancel the active operation
2257 * and exit
2258 *
2259 */
2260 void MI_MAIN_CALL SignalHandler(int signo)
2261 {
2262 err(PAL_T("Quit program upon receiving ctrl+c"), signo);
2263 if (gop.ft)
2264 {
2265 if (s_finished == 0)
2266 {
2267 s_finished = 1;
2268 CondLock_Broadcast((ptrdiff_t)(&s_finished));
2269 krisbash 1.1 }
2270
2271 Ftprintf(sout, MI_T("Cancel the operation"));
2272 MI_Operation_Cancel(&gop, MI_REASON_SHUTDOWN);
2273 /* Close opeartion will be hung due to */
2274 /* the operation is not get final result yet */
2275 /* need to enable this code after end to end cancel was completed */
2276 /* MI_Operation_Close(&gop); */
2277 /* Ftprintf(sout, MI_T("Closed the operation")); */
2278 Sleep_Milliseconds(200);
2279 }
2280 exit(1);
2281 }
2282
2283 /*
2284 * Set up signal handler to catch SIGINT signal
2285 *
2286 */
2287 void CatchCtrlC()
2288 {
2289 if (signal(SIGINT, SignalHandler) == SIG_ERR)
2290 krisbash 1.1 err(PAL_T("cannot catch signal: SIGINT\n"));
2291 }
2292
2293 MI_Result climain(int argc, const MI_Char* argv[])
2294 {
2295 MI_Application miApplication = MI_APPLICATION_NULL;
2296 MI_Session miSession = MI_SESSION_NULL;
2297 MI_Result miResult;
2298 MI_DestinationOptions _miDestinationOptions = MI_DESTINATIONOPTIONS_NULL;
2299 MI_DestinationOptions *miDestinationOptions = NULL;
2300 MI_UserCredentials miUserCredentials = {0};
2301
2302 /*Log_OpenStdErr();
2303 Log_SetLevel(LOG_VERBOSE);*/
2304 CatchCtrlC();
2305
2306 // Setup default stderr and stdout streams:
2307 serr = stderr;
2308 sout = stdout;
2309
2310 arg0 = argv[0];
2311 krisbash 1.1
2312 // const MI_Uint64 CONNECT_TIMEOUT_USEC = 10 * 1000 * 1000;
2313
2314 // Get the options:
2315 miResult = GetCommandLineDestDirOption(&argc, argv);
2316 if (miResult != MI_RESULT_OK)
2317 {
2318 return miResult;
2319 }
2320
2321 // Get configuration file options:
2322 miResult = GetConfigFileOptions();
2323 if (miResult != MI_RESULT_OK)
2324 {
2325 return miResult;
2326 }
2327
2328 // Get the options:
2329 miResult = GetCommandLineOptions(&argc, argv);
2330 if (miResult != MI_RESULT_OK)
2331 {
2332 krisbash 1.1 return miResult;
2333 }
2334 // There must be at least 1 argument left:
2335 if (argc < 2)
2336 {
2337 if (argc >= 1)
2338 {
2339 Ftprintf(sout, USAGE, tcs(argv[0]));
2340 if (opts.help)
2341 miResult = MI_RESULT_OK;
2342 else
2343 miResult = MI_RESULT_INVALID_PARAMETER;
2344 }
2345 else
2346 {
2347 Ftprintf(sout, USAGE, tcs(MI_T("omicli")));
2348 miResult = MI_RESULT_INVALID_PARAMETER;
2349 }
2350 return miResult;
2351 }
2352
2353 krisbash 1.1 if (Tcscmp(argv[1], MI_T("enc")) != 0)
2354 {
2355 miResult = MI_Application_Initialize(0, NULL, NULL, &miApplication);
2356 if (miResult != MI_RESULT_OK)
2357 return miResult;
2358 if (opts.user)
2359 {
2360 miDestinationOptions = &_miDestinationOptions;
2361 miResult = MI_Application_NewDestinationOptions(&miApplication, miDestinationOptions);
2362 if (miResult != MI_RESULT_OK)
2363 goto CleanupApplication;
2364
2365 miUserCredentials.authenticationType = MI_AUTH_TYPE_BASIC;
2366 miUserCredentials.credentials.usernamePassword.domain = MI_T("localhost");
2367 miUserCredentials.credentials.usernamePassword.username = opts.user;
2368 miUserCredentials.credentials.usernamePassword.password = opts.password;
2369
2370 miResult = MI_DestinationOptions_AddDestinationCredentials(miDestinationOptions, &miUserCredentials);
2371 if (miResult != MI_RESULT_OK)
2372 goto CleanupApplication;
2373 }
2374 krisbash 1.1
2375 miResult = MI_Application_NewSession(&miApplication, NULL, NULL, miDestinationOptions, NULL, NULL, &miSession);
2376 if (miResult != MI_RESULT_OK)
2377 goto CleanupApplication;
2378
2379 // Remember start time (will calculate total time in PrintSummary()
2380 s_startTime = CPU_GetTimeStamp();
2381 }
2382
2383 if (Tcscmp(argv[1], MI_T("ei")) == 0)
2384 {
2385 int i;
2386 for (i = 0; i < opts.repeat; i++)
2387 {
2388 if (opts.queryexpr)
2389 {
2390 miResult = QueryInstances(&miSession, argc, argv);
2391 if (miResult != MI_RESULT_OK)
2392 goto CleanupSession;
2393 }
2394 else
2395 krisbash 1.1 {
2396 miResult = EnumerateInstances(&miSession, argc, argv);
2397 if (miResult != MI_RESULT_OK)
2398 goto CleanupSession;
2399 }
2400 }
2401 }
2402 else if (Tcscmp(argv[1], MI_T("id")) == 0)
2403 {
2404 const MI_Char* args[5];
2405 int i;
2406
2407 if (argc != 2)
2408 {
2409 Ftprintf(serr, PAL_T("Usage: %T id\n\n"), tcs(arg0));
2410 miResult = MI_RESULT_INVALID_PARAMETER;
2411 goto CleanupSession;
2412 }
2413
2414 args[0]= argv[0];
2415 args[1]= MI_T("ei");
2416 krisbash 1.1 args[2]= MI_T("root/omi");
2417 args[3]= MI_T("OMI_Identify");
2418 args[4]= NULL;
2419
2420 for (i = 0; i < opts.repeat; i++)
2421 {
2422 miResult = EnumerateInstances(&miSession, 4, args);
2423 if (miResult != MI_RESULT_OK)
2424 goto CleanupSession;
2425 }
2426 }
2427 else if (Tcscmp(argv[1], MI_T("wql")) == 0 ||
2428 Tcscmp(argv[1], MI_T("cql")) == 0)
2429 {
2430 int i;
2431 for (i = 0; i < opts.repeat; i++)
2432 {
2433 miResult = Query(&miSession, argc, argv);
2434 if (miResult != MI_RESULT_OK)
2435 goto CleanupSession;
2436 }
2437 krisbash 1.1 }
2438 else if (Tcscmp(argv[1], MI_T("noop")) == 0)
2439 {
2440 int i;
2441 for (i = 0; i < opts.repeat; i++)
2442 {
2443 miResult = NoOp(&miSession, argc, argv);
2444 if (miResult != MI_RESULT_OK)
2445 goto CleanupSession;
2446 }
2447 }
2448 else if (Tcscmp(argv[1], MI_T("enc")) == 0)
2449 {
2450 miResult = Encode(argc, argv);
2451 goto CleanupApplication;
2452 }
2453 else if (Tcscmp(argv[1], MI_T("gi")) == 0)
2454 {
2455 int i;
2456 for (i = 0; i < opts.repeat; i++)
2457 {
2458 krisbash 1.1 miResult = GetInstance(&miSession, argc, argv);
2459 if (miResult != MI_RESULT_OK)
2460 goto CleanupSession;
2461 }
2462 }
2463 else if (Tcscmp(argv[1], MI_T("ci")) == 0)
2464 {
2465 int i;
2466 for (i = 0; i < opts.repeat; i++)
2467 {
2468 miResult = CreateInstance(&miSession, argc, argv);
2469 if (miResult != MI_RESULT_OK)
2470 goto CleanupSession;
2471 }
2472 }
2473 else if (Tcscmp(argv[1], MI_T("mi")) == 0)
2474 {
2475 int i;
2476 for (i = 0; i < opts.repeat; i++)
2477 {
2478 miResult = ModifyInstance(&miSession, argc, argv);
2479 krisbash 1.1 if (miResult != MI_RESULT_OK)
2480 goto CleanupSession;
2481 }
2482 }
2483 else if (Tcscmp(argv[1], MI_T("di")) == 0)
2484 {
2485 int i;
2486 for (i = 0; i < opts.repeat; i++)
2487 {
2488 miResult = DeleteInstance(&miSession, argc, argv);
2489 if (miResult != MI_RESULT_OK)
2490 goto CleanupSession;
2491 }
2492 }
2493 else if (Tcscmp(argv[1], MI_T("iv")) == 0)
2494 {
2495 int i;
2496 for (i = 0; i < opts.repeat; i++)
2497 {
2498 miResult = Invoke(&miSession, argc, argv);
2499 if (miResult != MI_RESULT_OK)
2500 krisbash 1.1 goto CleanupSession;
2501 }
2502 }
2503 else if (Tcscmp(argv[1], MI_T("a")) == 0)
2504 {
2505 int i;
2506 for (i = 0; i < opts.repeat; i++)
2507 {
2508 miResult = Associators(&miSession, argc, argv);
2509 if (miResult != MI_RESULT_OK)
2510 goto CleanupSession;
2511 }
2512 }
2513 else if (Tcscmp(argv[1], MI_T("r")) == 0)
2514 {
2515 int i;
2516 for (i = 0; i < opts.repeat; i++)
2517 {
2518 miResult = References(&miSession, argc, argv);
2519 if (miResult != MI_RESULT_OK)
2520 goto CleanupSession;
2521 krisbash 1.1 }
2522 }
2523 else if (Tcscmp(argv[1], MI_T("gc")) == 0)
2524 {
2525 int i;
2526 for (i = 0; i < opts.repeat; i++)
2527 {
2528 miResult = GetClass(&miSession, argc, argv);
2529 if (miResult != MI_RESULT_OK)
2530 goto CleanupSession;
2531 }
2532 }
2533 else if (Tcscmp(argv[1], MI_T("sub")) == 0)
2534 {
2535 int i;
2536 for (i = 0; i < opts.repeat; i++)
2537 {
2538 miResult = Subscribe(&miSession, argc, argv);
2539 if (miResult != MI_RESULT_OK)
2540 goto CleanupSession;
2541 }
2542 krisbash 1.1 }
2543 else
2544 {
2545 err(PAL_T("unknown command: %T"), tcs(argv[1]));
2546 miResult = MI_RESULT_INVALID_PARAMETER;
2547 goto CleanupSession;
2548 }
2549
2550 if (opts.summary)
2551 PrintSummary();
2552
2553 CleanupSession:
2554 MI_Session_Close(&miSession, NULL, NULL);
2555
2556 CleanupApplication:
2557 if (miDestinationOptions)
2558 MI_DestinationOptions_Delete(miDestinationOptions);
2559
2560 MI_Application_Close(&miApplication);
2561
2562 if (sout != stdout)
2563 krisbash 1.1 fclose(sout);
2564
2565 if (serr != stdout)
2566 fclose(serr);
2567
2568 return miResult;
2569 }
|