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 <limits.h>
26 #include <protocol/protocol.h>
27 #include <base/time.h>
28 #include <protocol/wsman.h>
29 #include <provreg/provreg.h>
30 #include <provmgr/provmgr.h>
31 #include <disp/disp.h>
32 #include <base/strings.h>
33 #include <base/args.h>
34 #include <base/dir.h>
35 #include <base/log.h>
36 #include <base/env.h>
37 #include <base/process.h>
38 #include <base/pidfile.h>
39 #include <base/paths.h>
40 #include <base/conf.h>
41 #include <base/user.h>
42 #include <base/getopt.h>
43 mike 1.1
44 #if defined(CONFIG_POSIX)
45 # include <signal.h>
46 # include <sys/wait.h>
47 #endif
48
49 #define T MI_T
50
51 typedef struct _ServerData ServerData;
52
53 typedef enum _ServerTransportType
54 {
55 SRV_PROTOCOL,
56 SRV_WSMAN
57 }
58 ServerTransportType;
59
60 typedef struct _ServerCallbackData
61 {
62 ServerData* data;
63 ServerTransportType type;
64 mike 1.1 }
65 ServerCallbackData;
66
67 struct _ServerData
68 {
69 Disp disp;
70 Protocol* protocol;
71 WSMAN* wsman;
72 Selector selector;
73 MI_Boolean selectorInitialized;
74 MI_Boolean terminated;
75
76 /* pointers to self with different types - one per supported transport */
77 ServerCallbackData protocolData;
78 ServerCallbackData wsmanData;
79 } ;
80
81 typedef struct _Options
82 {
83 MI_Boolean help;
84 MI_Boolean trace;
85 mike 1.1 MI_Boolean terminateByNoop;
86 #if defined(CONFIG_POSIX)
87 MI_Boolean daemonize;
88 MI_Boolean stop;
89 MI_Boolean reloadConfig;
90 #endif
91 /* mostly for unittesting in non-root env */
92 MI_Boolean ignoreAuthentication;
93 MI_Boolean locations;
94 MI_Boolean logstderr;
95 unsigned short httpport;
96 unsigned short httpsport;
97 MI_Uint64 idletimeout;
98 MI_Uint64 livetime;
99 Log_Level logLevel;
100 }
101 Options;
102
103 static Options s_opts;
104
105 static ServerData s_data;
106 mike 1.1
107 static const char* arg0 = 0;
108
109 static const char HELP[] = "\
110 Usage: %s [OPTIONS]\n\
111 \n\
112 This program starts the server.\n\
113 \n\
114 OPTIONS:\n\
115 -h, --help Print this help message.\n\
116 -d Daemonize the server process (POSIX only).\n\
117 -s Stop the server process (POSIX only).\n\
118 -r Re-read configuration by the running server (POSIX only).\n\
119 --httpport PORT HTTP protocol listener port.\n\
120 --httpsport PORT HTTPS protocol listener port.\n\
121 --idletimeout TIMEOUT Idle providers unload timeout (in seconds).\n\
122 -v, --version Print version information.\n\
123 -l, --logstderr Send log output to standard error.\n\
124 --loglevel LEVEL Set logging level to one of the following\n\
125 symbols/numbers: fatal/0, error/1, warning/2,\n\
126 info/3, debug/4 (default 2).\n\
127 mike 1.1 \n";
128
129 PRINTF_FORMAT(1, 2)
130 void FUNCTION_NEVER_RETURNS err(const char* fmt, ...)
131 {
132 va_list ap;
133 memset(&ap, 0, sizeof(ap));
134
135 fprintf(stderr, "%s: ", arg0);
136
137 va_start(ap, fmt);
138 vfprintf(stderr, fmt, ap);
139 va_end(ap);
140
141 /* Write to log as well */
142 va_start(ap, fmt);
143 va_end(ap);
144
145 fputc('\n', stderr);
146 exit(1);
147 }
148 mike 1.1
149 static void _ProviderCallback(Message* msg, void* callbackData)
150 {
151 ServerCallbackData* self = (ServerCallbackData* )callbackData;
152
153 switch ( msg->tag )
154 {
155 case PostResultMsgTag:
156 {
157 const PostResultMsg* rsp = (const PostResultMsg*)msg;
158
159 if (s_opts.trace)
160 {
161 PostResultMsg_Print(rsp, stdout);
162 }
163 }
164 break;
165
166 case PostInstanceMsgTag:
167 {
168 const PostInstanceMsg* rsp = (const PostInstanceMsg*)msg;
169 mike 1.1
170 if (s_opts.trace)
171 {
172 PostInstanceMsg_Print(rsp, stdout);
173 }
174 }
175 break;
176
177 case SubscribeResTag:
178 {
179 const SubscribeRes* rsp = (const SubscribeRes*)msg;
180
181 if (s_opts.trace)
182 {
183 SubscribeRes_Print(rsp, stdout);
184 }
185 }
186 break;
187
188 case NoOpRspTag:
189 break; /* send noop confirmation to the client */
190 mike 1.1
191 default:
192 {
193 LOGF((T("unknown message type: %u"), msg->tag));
194 exit(1);
195 }
196 }
197
198 /* forward message to the other side */
199 if (msg->request)
200 msg->clientID = msg->request->clientID;
201
202 switch (self->type)
203 {
204 case SRV_PROTOCOL:
205 Protocol_Send(self->data->protocol, msg);
206 break;
207
208 case SRV_WSMAN:
209 WSMAN_Send(self->data->wsman, msg);
210 break;
211 mike 1.1
212 default:
213 LOGF((T("unknown transport type: %u"), (int)self->type));
214 exit(1);
215 }
216 }
217
218 /* Called by protocol stack to dispatch an incoming request message */
219 static MI_Boolean _RequestCallback(
220 Protocol* protocol_,
221 Message* msg,
222 void* data)
223 {
224 ServerCallbackData* self = (ServerCallbackData*)data;
225 MI_Result r;
226
227 MI_UNUSED(protocol_);
228
229 if (NoOpReqTag == msg->tag)
230 {
231 NoOpReq* req = (NoOpReq*)msg;
232 mike 1.1 NoOpRsp* rsp;
233
234 if (s_opts.trace)
235 {
236 NoOpReq_Print(req, stdout);
237 }
238
239 /* Send NoOp response back */
240 rsp = NoOpRsp_New(req->base.msgID);
241
242 if (!rsp)
243 err("out of memory");
244
245 rsp->base.clientID = req->base.clientID;
246
247 if (s_opts.trace)
248 {
249 NoOpRsp_Print(rsp, stdout);
250 }
251
252 _ProviderCallback(&rsp->base, self);
253 mike 1.1 NoOpRsp_Release(rsp);
254
255 if (s_opts.terminateByNoop)
256 {
257 s_data.terminated = MI_TRUE;
258 Selector_StopRunning(&s_data.selector);
259 }
260 return MI_TRUE;
261 }
262
263 if (s_opts.trace)
264 {
265 MessagePrint(msg, stdout);
266 }
267
268 msg->callback = _ProviderCallback;
269 msg->callbackData = self;
270
271 r = Disp_HandleRequest(&self->data->disp, msg);
272
273 if (MI_RESULT_OK != r)
274 mike 1.1 {
275 PostResultMsg* resp;
276
277 resp = PostResultMsg_New( msg->msgID );
278
279 if (!resp)
280 return MI_TRUE;
281
282 resp->result = r;
283 Message_SetRequest(&resp->base,msg);
284 (*msg->callback)(&resp->base, msg->callbackData);
285
286 PostResultMsg_Release(resp);
287 }
288
289 return MI_TRUE;
290 }
291
292 static void GetCommandLineDestDirOption(
293 int* argc_,
294 const char* argv[])
295 mike 1.1 {
296 int argc = *argc_;
297 int i;
298 const char* destdir = NULL;
299
300 for (i = 1; i < argc; )
301 {
302 if (strcmp(argv[i], "--destdir") == 0)
303 {
304 if (i + 1 == argc)
305 err("missing argument for --destdir option");
306
307 destdir = argv[i+1];
308 memmove((char*)&argv[i], (char*)&argv[i+2],
309 sizeof(char*) * (argc-i-1));
310 argc -= 2;
311 }
312 else if (strncmp(argv[i], "--destdir=", 10) == 0)
313 {
314 destdir = argv[i] + 10;
315 memmove((char*)&argv[i], (char*)&argv[i+1],
316 mike 1.1 sizeof(char*) * (argc-i));
317
318 argc -= 1;
319 }
320 else
321 i++;
322 }
323
324 if (destdir)
325 {
326 if (SetPath(ID_DESTDIR, destdir) != 0)
327 err("failed to set destdir");
328 }
329
330 *argc_ = argc;
331 }
332
333 static void GetCommandLineOptions(
334 int* argc_,
335 const char* argv[])
336 {
337 mike 1.1 int argc = *argc_;
338 GetOptState state = GETOPTSTATE_INITIALIZER;
339 static const char* opts[] =
340 {
341 "-h",
342 "--help",
343 "-p",
344 "-t",
345 "--stopnoop",
346 "-v",
347 "--version",
348 "-d",
349 "-s",
350 "-r",
351 "--httpport:",
352 "--httpsport:",
353 "--idletimeout:",
354 "--livetime:",
355 "--ignoreAuthentication",
356 "-i",
357 "--prefix:",
358 mike 1.1 "--libdir:",
359 "--bindir:",
360 "--localstatedir:",
361 "--sysconfdir:",
362 "--providerdir:",
363 "--certsdir:",
364 "--rundir:",
365 "--logdir:",
366 "--pidfile:",
367 "--logfile:",
368 "--registerdir:",
369 "--socketfile:",
370 "--pemfile:",
371 "--keyfile:",
372 "--agentprogram:",
373 "--serverprogram:",
374 "--logstderr",
375 "--loglevel:",
376 "-l",
377 NULL,
378 };
379 mike 1.1
380 for (;;)
381 {
382 int r = GetOpt(&argc, argv, opts, &state);
383
384 if (r == 1)
385 break;
386
387 if (r == -1)
388 {
389 fprintf(stderr, "error: %s\n", state.err);
390 exit(1);
391 }
392
393 if (strcmp(state.opt, "-h") == 0 ||
394 strcmp(state.opt, "--help") == 0)
395 {
396 s_opts.help = MI_TRUE;
397 }
398 else if (strcmp(state.opt, "-p") == 0)
399 {
400 mike 1.1 s_opts.locations = MI_TRUE;
401 }
402 else if (strcmp(state.opt, "-t") == 0)
403 {
404 s_opts.trace = MI_TRUE;
405 }
406 else if (strcmp(state.opt, "--stopnoop") == 0)
407 {
408 s_opts.terminateByNoop = MI_TRUE;
409 }
410 else if (strcmp(state.opt, "-v") == 0 ||
411 strcmp(state.opt, "--version") == 0)
412 {
413 printf("%s: %s\n", arg0,
414 CONFIG_PRODUCT "-" CONFIG_VERSION " - " CONFIG_DATE);
415 exit(0);
416 }
417 #if defined(CONFIG_POSIX)
418 else if (strcmp(state.opt, "-d") == 0)
419 {
420 s_opts.daemonize = MI_TRUE;
421 mike 1.1 }
422 else if (strcmp(state.opt, "-s") == 0)
423 {
424 s_opts.stop = MI_TRUE;
425 }
426 else if (strcmp(state.opt, "-r") == 0)
427 {
428 s_opts.reloadConfig = MI_TRUE;
429 }
430 #endif
431 else if (strcmp(state.opt, "--httpport") == 0)
432 {
433 unsigned long x;
434 char* end;
435
436 x = Strtoul(state.arg, &end, 10);
437
438 if (*end != '\0' || x > USHRT_MAX)
439 err("bad option argument for --httpport: %s", state.arg);
440
441 s_opts.httpport = (unsigned short)x;
442 mike 1.1 }
443 else if (strcmp(state.opt, "--httpsport") == 0)
444 {
445 unsigned long x;
446 char* end;
447
448 x = Strtoul(state.arg, &end, 10);
449
450 if (*end != '\0' || x > USHRT_MAX)
451 err("bad option argument for --httpsport: %s", state.arg);
452
453 s_opts.httpsport = (unsigned short)x;
454 }
455 else if (strcmp(state.opt, "--idletimeout") == 0)
456 {
457 char* end;
458 MI_Uint64 x = Strtoull(state.arg, &end, 10);
459
460 if (*end != '\0')
461 err("bad option argument for --idletimeout: %s", state.arg);
462
463 mike 1.1 s_opts.idletimeout = x;
464 }
465 else if (strcmp(state.opt, "--livetime") == 0)
466 {
467 char* end;
468 MI_Uint64 x = Strtoull(state.arg, &end, 10);
469
470 if (*end != '\0')
471 err("bad option argument for --livetime: %s", state.arg);
472
473 s_opts.livetime = x;
474 }
475 else if (strcmp(state.opt, "--ignoreAuthentication") == 0 ||
476 strcmp(state.opt, "-i") == 0)
477 {
478 s_opts.ignoreAuthentication = MI_TRUE;
479 }
480 else if (strcmp(state.opt, "--logstderr") == 0 ||
481 strcmp(state.opt, "-l") == 0)
482 {
483 s_opts.logstderr = MI_TRUE;
484 mike 1.1 }
485 else if (strcmp(state.opt, "--loglevel") == 0)
486 {
487 if (Log_SetLevelFromString(state.arg) != 0)
488 {
489 err("bad option argument for %s: %s", state.opt, state.arg);
490 }
491 }
492 else if (strncmp(state.opt, "--", 2) == 0 && IsNickname(state.opt+2))
493 {
494 if (SetPathFromNickname(state.opt+2, state.arg) != 0)
495 err("SetPathFromNickname() failed");
496 }
497 }
498
499 *argc_ = argc;
500 }
501
502 static void OpenLogFile()
503 {
504 if (s_opts.logstderr)
505 mike 1.1 {
506 if (Log_OpenStdErr() != MI_RESULT_OK)
507 err("failed to open log file to stderr");
508 }
509 else
510 {
511 MI_Char path[MAX_PATH_SIZE];
512 ZStrlcpy(path, GetPath(ID_LOGFILE), MI_COUNT(path));
513
514 /* Open the log file */
515 if (Log_Open(path) != MI_RESULT_OK)
516 err("failed to open log file: %s", path);
517 }
518 }
519
520 #if defined(CONFIG_POSIX)
521 static void _HandleSIGTERM(int sig)
522 {
523 if (sig == SIGTERM && s_data.selectorInitialized)
524 {
525 s_data.terminated = MI_TRUE;
526 mike 1.1 Selector_StopRunning(&s_data.selector);
527 }
528 }
529
530 static void _HandleSIGHUP(int sig)
531 {
532 if (sig == SIGHUP && s_data.selectorInitialized)
533 {
534 Selector_StopRunning(&s_data.selector);
535 }
536 }
537
538 static void _HandleSIGCHLD(int sig)
539 {
540 if (sig == SIGCHLD)
541 {
542 int status = 0;
543 wait(&status);
544 }
545 }
546 #endif
547 mike 1.1
548 static void _PrintPaths()
549 {
550 PrintPaths();
551 }
552
553 static void GetConfigFileOptions()
554 {
555 char path[MAX_PATH_SIZE];
556 Conf* conf;
557
558 /* Form the configuration file path */
559 Strlcpy(path, GetPath(ID_CONFIGFILE), sizeof(path));
560
561 /* Open the configuration file */
562 conf = Conf_Open(path);
563 if (!conf)
564 err("failed to open configuration file: %s", path);
565
566 /* For each key=value pair in configuration file */
567 for (;;)
568 mike 1.1 {
569 const char* key;
570 const char* value;
571 int r = Conf_Read(conf, &key, &value);
572
573 if (r == -1)
574 err("%s: %s\n", path, Conf_Error(conf));
575
576 if (r == 1)
577 break;
578
579 if (strcmp(key, "httpport") == 0)
580 {
581 char* end;
582 unsigned long x = Strtoul(value, &end, 10);
583
584 if (*end != '\0' || x > USHRT_MAX)
585 {
586 err("%s(%u): invalid value for '%s': %s", path,
587 Conf_Line(conf), key, value);
588 }
589 mike 1.1
590 s_opts.httpport = (unsigned short)x;
591 }
592 else if (strcmp(key, "httpsport") == 0)
593 {
594 char* end;
595 unsigned long x = Strtoul(value, &end, 10);
596
597 if (*end != '\0' || x > USHRT_MAX)
598 {
599 err("%s(%u): invalid value for '%s': %s", path,
600 Conf_Line(conf), key, value);
601 }
602
603 s_opts.httpsport = (unsigned short)x;
604 }
605 else if (strcmp(key, "idletimeout") == 0)
606 {
607 char* end;
608 MI_Uint64 x = Strtoull(value, &end, 10);
609
610 mike 1.1 if (*end != '\0')
611 {
612 err("%s(%u): invalid value for '%s': %s", path,
613 Conf_Line(conf), key, value);
614 }
615
616 s_opts.idletimeout = x;
617 }
618 else if (strcmp(key, "livetime") == 0)
619 {
620 char* end;
621 MI_Uint64 x = Strtoull(value, &end, 10);
622
623 if (*end != '\0')
624 {
625 err("%s(%u): invalid value for '%s': %s", path,
626 Conf_Line(conf), key, value);
627 }
628
629 s_opts.livetime = x;
630 }
631 mike 1.1 else if (strcmp(key, "trace") == 0)
632 {
633 if (Strcasecmp(value, "true") == 0)
634 {
635 s_opts.trace = MI_TRUE;
636 }
637 else if (Strcasecmp(value, "false") == 0)
638 {
639 s_opts.trace = MI_FALSE;
640 }
641 else
642 {
643 err("%s(%u): invalid value for '%s': %s", path,
644 Conf_Line(conf), key, value);
645 }
646 }
647 else if (IsNickname(key))
648 {
649 if (SetPathFromNickname(key, value) != 0)
650 err("SetPathFromNickname() failed");
651 }
652 mike 1.1 else
653 {
654 err("%s(%u): unknown key: %s", path, Conf_Line(conf), key);
655 }
656 }
657
658 /* Close configuration file */
659 Conf_Close(conf);
660
661 return;
662 }
663
664 int servermain(int argc, const char* argv[])
665 {
666 MI_Result r;
667 #if defined(CONFIG_POSIX)
668 int pidfile = -1;
669 #endif
670
671 arg0 = argv[0];
672
673 mike 1.1 memset(&s_data, 0, sizeof(s_data));
674
675 /* Set default options */
676 s_opts.httpport = CONFIG_HTTPPORT;
677 s_opts.httpsport = CONFIG_HTTPSPORT;
678 s_opts.idletimeout = 0;
679 s_opts.livetime = 0;
680
681 /* Get --destdir command-line option */
682 GetCommandLineDestDirOption(&argc, argv);
683
684 /* Extract configuration file options */
685 GetConfigFileOptions();
686
687 /* Extract command-line options a second time (to override) */
688 GetCommandLineOptions(&argc, argv);
689
690 /* Open the log file */
691 OpenLogFile();
692
693 /* Print help */
694 mike 1.1 if (s_opts.help)
695 {
696 fprintf(stderr, HELP, arg0);
697 exit(1);
698 }
699
700 /* Print locations of files and directories */
701 if (s_opts.locations)
702 {
703 _PrintPaths();
704 printf("\n");
705 exit(0);
706 }
707
708 #if defined(CONFIG_POSIX)
709 if (s_opts.stop || s_opts.reloadConfig)
710 {
711 if (PIDFile_IsRunning() != 0)
712 err("server is not running\n");
713
714 if (PIDFile_Signal(s_opts.stop ? SIGTERM : SIGHUP) != 0)
715 mike 1.1 err("failed to stop server\n");
716
717 if (s_opts.stop)
718 printf("%s: stopped server\n", arg0);
719 else
720 printf("%s: refreshed server\n", arg0);
721
722 exit(0);
723 }
724 #endif
725
726 #if defined(CONFIG_POSIX)
727
728 if (PIDFile_IsRunning() == 0)
729 err("server is already running\n");
730
731 /* Verify that server is started as root */
732 if (0 != IsRoot() && !s_opts.ignoreAuthentication)
733 {
734 err("expected to run as root");
735 }
736 mike 1.1
737 /* ATTN: unit-test support; should be removed/ifdefed later */
738 if (s_opts.ignoreAuthentication)
739 {
740 IgnoreAuthCalls(1);
741 }
742
743 /* Watch for SIGTERM signals */
744 if (0 != SetSignalHandler(SIGTERM, _HandleSIGTERM) ||
745 0 != SetSignalHandler(SIGHUP, _HandleSIGHUP))
746 err("cannot set sighanlder, erron %d", errno);
747
748
749 /* Watch for SIGCHLD signals */
750 SetSignalHandler(SIGCHLD, _HandleSIGCHLD);
751
752 #endif
753
754 /* Change directory to 'rundir' */
755 if (Chdir(GetPath(ID_RUNDIR)) != 0)
756 err("failed to change directory to: %s", GetPath(ID_RUNDIR));
757 mike 1.1
758 #if defined(CONFIG_POSIX)
759 /* Daemonize */
760 if (s_opts.daemonize && Process_Daemonize() != 0)
761 err("failed to daemonize server process");
762 #endif
763
764 #if defined(CONFIG_POSIX)
765
766 /* Create PID file */
767 if ((pidfile = PIDFile_OpenWrite()) == -1)
768 {
769 LOGF(("failed to create PID file: %s", GetPath(ID_PIDFILE)));
770 exit(1);
771 }
772 #endif
773
774 /* Initialize calback parameters */
775 s_data.protocolData.data = &s_data;
776 s_data.protocolData.type = SRV_PROTOCOL;
777 s_data.wsmanData.data = &s_data;
778 mike 1.1 s_data.wsmanData.type = SRV_WSMAN;
779
780 while (!s_data.terminated)
781 {
782 /* selector */
783 {
784 /* Initialize the network */
785 Sock_Start();
786
787 if(Selector_Init(&s_data.selector) != MI_RESULT_OK)
788 err("Selector_Init() failed");
789
790 s_data.selectorInitialized = MI_TRUE;
791 }
792
793 /* Create the dispatcher object. */
794 {
795 r = Disp_Init(&s_data.disp, &s_data.selector);
796
797 if (r != MI_RESULT_OK)
798 {
799 mike 1.1 LOGF((T("failed to initialize the dispatcher: %u"), r));
800 err("failed to initialize the dispatcher: %u", r);
801 }
802 }
803
804 if (s_opts.idletimeout)
805 {
806 /* convert it to usec */
807 s_data.disp.agentmgr.provmgr.idleTimeoutUsec = s_opts.idletimeout * 1000000;
808 }
809
810 /* wsman server */
811 {
812 r = WSMAN_New_Listener(
813 &s_data.wsman,
814 &s_data.selector,
815 s_opts.httpport,
816 s_opts.httpsport,
817 (WSMANCallback)_RequestCallback, /* ATTN! address callback types! */
818 &s_data.wsmanData);
819
820 mike 1.1 if (r != MI_RESULT_OK)
821 err("WSMAN_New_Listener() failed");
822 }
823
824 /* Set WSMAN options */
825 {
826 WSMAN_Options options = DEFAULT_WSMAN_OPTIONS;
827 options.enableTracing = s_opts.trace;
828 WSMAN_SetOptions(s_data.wsman, &options);
829 }
830
831 /* Create new protocol object */
832 {
833 r = Protocol_New_Listener(&s_data.protocol, &s_data.selector,
834 GetPath(ID_SOCKETFILE), _RequestCallback, &s_data.protocolData);
835
836 if (r != MI_RESULT_OK)
837 err("Protocol_New_Listener() failed");
838 }
839
840 /* Log start up message */
841 mike 1.1 LOGI((T("listening on ports: http %u, https %u"), s_opts.httpport, s_opts.httpsport));
842
843 /* Run the protocol object (waiting for new messages) */
844 r = Protocol_Run(s_data.protocol,
845 (s_opts.livetime ? s_opts.livetime * 1000000 : TIME_NEVER));
846
847 LOGI((T("after run, r %d"), r));
848
849 s_data.selectorInitialized = MI_FALSE;
850
851 if (MI_RESULT_TIME_OUT == r)
852 {
853 LOGI((T("livetime expired; server stopped")));
854 s_data.terminated = MI_TRUE;
855 }
856
857 #if defined(CONFIG_POSIX)
858 if (r == MI_RESULT_OK)
859 {
860 if (s_data.terminated)
861 LOGI((T("server terminated")));
862 mike 1.1 else
863 LOGI((T("re-reading configuration")));
864 }
865 #endif
866
867 // Destroy the dispatcher.
868 Selector_RemoveAllHandlers(&s_data.selector);
869 Disp_Destroy(&s_data.disp);
870 WSMAN_Delete(s_data.wsman);
871 Protocol_Delete(s_data.protocol);
872 Selector_Destroy(&s_data.selector);
873
874 /* Shutdown the network */
875 Sock_Stop();
876 }
877
878 #if defined(CONFIG_POSIX)
879 /* Close PID file */
880 close(pidfile);
881
882 /* Remove PID file */
883 mike 1.1 if (PIDFile_Delete() != 0)
884 LOGW(("failed to remove PID file: %s", GetPath(ID_PIDFILE)));
885 #endif
886
887 /* Log that we are exiting */
888 LOGI((T("server exiting")));
889
890 Log_Close();
891 return 0;
892 }
|