(file) Return to agent.c CVS log (file) (dir) Up to [OMI] / omi / agent

  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 <protocol/protocol.h>
 26           #include <base/time.h>
 27           #include <provmgr/provmgr.h>
 28           #include <base/strings.h>
 29           #include <base/args.h>
 30           #include <base/log.h>
 31           #include <base/env.h>
 32           #include <base/paths.h>
 33           #include <base/getopt.h>
 34           #include <sys/types.h>
 35           #include <pwd.h>
 36           #include <grp.h>
 37           
 38           #define T MI_T
 39           
 40           typedef struct _AgentData AgentData;
 41           
 42           struct _AgentData
 43 mike  1.1 {
 44               Protocol*   protocol;
 45               ProvMgr     provmgr;
 46               Selector    selector;
 47           } ;
 48           
 49           typedef struct _Options
 50           {
 51               const char* provDir;
 52               MI_Boolean help;
 53               MI_Uint32   idletimeout;
 54           } 
 55           Options;
 56           
 57           static AgentData  s_data;
 58           
 59           static Options s_opts;
 60           static const char* arg0 = 0;
 61           static const char HELP[] = "\
 62           Usage: %s [OPTIONS]\n\
 63           \n\
 64 mike  1.1 This program starts the OMI agent.\n\
 65           \n\
 66           OPTIONS:\n\
 67               --version           Print version information.\n\
 68               --providerdir       Find providers in this directory.\n\
 69               --loglevel LEVEL    Set the log level (0-4).\n\
 70           \n";
 71           
 72           PRINTF_FORMAT(1, 2)
 73           void FUNCTION_NEVER_RETURNS err(const char* fmt, ...)
 74           {
 75               va_list ap;
 76               memset(&ap, 0, sizeof(ap));
 77           
 78               fprintf(stderr, "%s: ", arg0);
 79           
 80               va_start(ap, fmt);
 81               vfprintf(stderr, fmt, ap);
 82               va_end(ap);
 83           
 84               fputc('\n', stderr);
 85 mike  1.1     exit(1);
 86           }
 87           
 88           static void _ProviderCallback(Message* msg, void* callbackData)
 89           {
 90           
 91               /* forward message to the other side */
 92               /*if (msg->request)
 93                   msg->clientID = msg->request->clientID;*/
 94           
 95               Protocol_Send(s_data.protocol, msg);
 96           }
 97           
 98           /* Called by protocol stack to dispatch an incoming request message */
 99           static MI_Boolean _RequestCallback(
100               Protocol* protocol_,
101               Message* msg,
102               void* data)
103           {
104               //ServerCallbackData* self = (ServerCallbackData*)data;
105               MI_Result r;
106 mike  1.1 
107               MI_UNUSED(protocol_);
108           
109               msg->callback = _ProviderCallback;
110               //msg->callbackData = self;
111           
112               r = ProvMgr_PostMessage(&s_data.provmgr, msg->libraryName, msg);
113               
114               if (MI_RESULT_OK != r)
115               {
116                   PostResultMsg* resp;
117           
118                   resp = PostResultMsg_New( msg->msgID );
119           
120                   if (!resp)
121                       return MI_FALSE;
122           
123                   resp->result = r;
124                   Message_SetRequest(&resp->base,msg);
125                   (*msg->callback)(&resp->base, msg->callbackData);
126           
127 mike  1.1         PostResultMsg_Release(resp);
128               }
129           
130               return MI_TRUE;
131           }
132           
133           static void GetCommandLineDestDirOption(
134               int* argc_,
135               const char* argv[])
136           {
137               int argc = *argc_;
138               int i;
139               const char* destdir = NULL;
140           
141               for (i = 1; i < argc; )
142               {
143                   if (strcmp(argv[i], "--destdir") == 0)
144                   {
145                       if (i + 1 == argc)
146                           err("missing argument for --destdir option");
147           
148 mike  1.1             destdir = argv[i+1];
149                       memmove((char*)&argv[i], (char*)&argv[i+2], 
150                           sizeof(char*) * (argc-i-1));
151                       argc -= 2;
152                   }
153                   else if (strncmp(argv[i], "--destdir=", 10) == 0)
154                   {
155                       destdir = argv[i] + 10;
156                       memmove((char*)&argv[i], (char*)&argv[i+1], 
157                           sizeof(char*) * (argc-i));
158           
159                       argc -= 1;
160                   }
161                   else
162                       i++;
163               }
164           
165               if (destdir)
166               {
167                   if (SetPath(ID_DESTDIR, destdir) != 0)
168                       err("failed to set destdir");
169 mike  1.1     }
170           
171               *argc_ = argc;
172           }
173           
174           static void GetCommandLineOptions(int* argc, const char* argv[])
175           {
176               GetOptState state = GETOPTSTATE_INITIALIZER;
177               const char* opts[] =
178               {
179                   "-h",
180                   "--help",
181                   "-v",
182                   "--version",
183                   "--providerdir:",
184                   "--idletimeout:",
185                   "--loglevel:",
186                   NULL,
187               };
188           
189               for (;;)
190 mike  1.1     {
191                   int r = GetOpt(argc, argv, opts, &state);
192           
193                   if (r == 1)
194                       break;
195           
196                   if (r == -1)
197                       err("%s", state.err);
198           
199                   /* Check for -h option */
200                   if (strcmp(state.opt, "-h") == 0 || strcmp(state.opt, "--help") == 0)
201                   {
202                       s_opts.help = MI_TRUE;
203                   }
204                   else if (strcmp(state.opt, "--version") == 0)
205                   {
206                       printf("%s: %s\n", arg0,
207                           CONFIG_PRODUCT "-" CONFIG_VERSION " - " CONFIG_DATE);
208                       exit(0);
209                   }
210                   else if (strcmp(state.opt, "--providerdir") == 0)
211 mike  1.1         {
212                       s_opts.provDir = state.arg;
213                   }
214                   else if (strcmp(state.opt, "--idletimeout") == 0)
215                   {
216                       char* end;
217                       MI_Uint64 x = Strtoull(state.arg, &end, 10);
218           
219                       if (*end != '\0')
220                           err("bad option argument for --idletimeout: %s", state.arg);
221           
222                       s_opts.idletimeout = x;
223                   }
224                   else if (strcmp(state.opt, "--loglevel") == 0)
225                   {
226                       if (Log_SetLevelFromString(state.arg) != 0)
227                       {
228                           err("bad option argument for %s: %s", state.opt, state.arg);
229                       }
230                   }
231               }
232 mike  1.1 }
233           
234           static void _EventCallback(
235               Protocol* protocol,
236               ProtocolEvent event,
237               void* data)
238           {
239               MI_UNUSED(protocol);
240               MI_UNUSED(event);
241               MI_UNUSED(data);
242           
243               LOGI_CHAR(("disconnected form server; exiting"));
244               exit(0);
245           }
246           
247           static void _ProvMgrCallbackOnIdle(
248               ProvMgr* mgr,
249               void* callbackData)
250           {
251               BinProtocolNotification* notification;
252           
253 mike  1.1     MI_UNUSED(mgr);
254               MI_UNUSED(callbackData);
255           
256               LOGI_CHAR(("sending 'agent-idle' notification to the server"));
257           
258               notification = BinProtocolNotification_New( BinNotificationAgentIdle );
259           
260               if (!notification)
261                   return;
262           
263               Protocol_Send(s_data.protocol, &notification->base);
264           
265               BinProtocolNotification_Release(notification);
266           }
267           
268           int agent_main(int argc, const char* argv[])
269           {
270               MI_Result r;
271               Sock fd;
272               int logfd;
273           
274 mike  1.1     arg0 = argv[0];
275           
276               memset(&s_data, 0, sizeof(s_data));
277           
278               /* Get --destdir option first (other options may depend on it) */
279               GetCommandLineDestDirOption(&argc, argv);
280           
281               /* Extract options */
282               GetCommandLineOptions(&argc, argv);
283           
284               /* Print help */
285               if (s_opts.help)
286               {
287                   fprintf(stderr, HELP, arg0);
288                   exit(1);
289               }
290           
291               /* extract socket number */
292               if (argc < 3)
293               {
294                   LOGE_CHAR(("parameter is missing (fd)"));
295 mike  1.1         exit(1);
296               }
297           
298               fd = Strtol(argv[1], 0, 10);
299               logfd = Strtol(argv[2], 0, 10);
300           
301               /* Attach log file */
302               {
303                   /* Open the log file */
304                   if (Log_OpenFD(logfd) != MI_RESULT_OK)
305                   {
306                       err("failed to attach log file to fd: %d; errno %d", logfd, 
307                           (int)errno);
308                   }
309               }
310           
311               /* selector */
312               {
313                   /* Initialize the network */
314                   Sock_Start();
315           
316 mike  1.1         if(Selector_Init(&s_data.selector) != MI_RESULT_OK)
317                       err("Selector_Init() failed");
318               }
319           
320               /* Create new protocol object */
321               {
322                   r = Protocol_New_From_Socket(
323                       &s_data.protocol,
324                       &s_data.selector,
325                       fd,
326                       MI_FALSE,
327                       _RequestCallback,
328                       0,
329                       _EventCallback,
330                       0);
331           
332                   if (r != MI_RESULT_OK)
333                       err("Protocol_New_Listener() failed");
334               }
335           
336               /* Provider manager */
337 mike  1.1     {
338                   r = ProvMgr_Init(&s_data.provmgr, &s_data.selector, _ProvMgrCallbackOnIdle, &s_data, s_opts.provDir);
339           
340                   if (r != MI_RESULT_OK)
341                       err("ProvMgr_Init() failed");
342               }
343           
344               /* idle timeout */
345               if (s_opts.idletimeout)
346               {
347                   /* convert it to usec */
348                   s_data.provmgr.idleTimeoutUsec = s_opts.idletimeout * 1000000;
349                   LOGI((T("changing idle timeout to %d sec"), (int)s_opts.idletimeout));
350           
351               }
352           
353               /* Log start up message */
354               LOGI((T("agent started; fd %d"), (int)fd));
355           
356               /* Run the protocol object (waiting for new messages) */
357               r = Protocol_Run(s_data.protocol, TIME_NEVER);
358 mike  1.1 
359               if (r != MI_RESULT_OK)
360                   err("Protocol_Run() failed (%d)", (int)r);
361           
362               // Destroy all global objects
363               Selector_RemoveAllHandlers(&s_data.selector);
364               Protocol_Delete(s_data.protocol);
365               Selector_Destroy(&s_data.selector);
366           
367               return 0;
368           }

ViewCVS 0.9.2