1 mike 1.32 //%/////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001 The Open group, BMC Software, Tivoli Systems, IBM
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to
7 // deal in the Software without restriction, including without limitation the
8 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 // sell copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
13 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
14 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
15 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
16 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
18 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
19 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 //
21 //==============================================================================
22 mike 1.32 //
23 // Author: Mike Brasher (mbrasher@bmc.com)
24 //
25 // Modified By: Mike Day (mdday@us.ibm.com)
|
26 mike 1.33 //
|
27 mike 1.32 // Modified By: Karl Schopmeyer (k.schopmeyer@opengroup.org)
28 //
|
29 kumpf 1.34.2.1 // Modified By: Nag Boranna (nagaraja_boranna@hp.com)
30 //
|
31 mike 1.32 //%/////////////////////////////////////////////////////////////////////////////
32
33
34 //////////////////////////////////////////////////////////////////////
35 //
36 // Notes on deamon operation (Unix) and service operation (Win 32):
37 //
38 // To run pegasus as a daemon on Unix platforms, use the -d option:
39 //
40 // cimserver -d
41 //
42 // The -d option has no effect on windows operation.
43 //
44 // To run pegasus as an NT service, there are FOUR different possibilities:
45 //
46 // To INSTALL the Pegasus service,
47 //
48 // cimserver -install
49 //
50 // To REMOVE the Pegasus service,
51 //
52 mike 1.32 // cimserver -remove
53 //
54 // To START the Pegasus service,
55 //
56 // net start cimserver
57 //
58 // To STOP the Pegasus service,
59 //
60 // net stop cimserver
61 //
62 // Alternatively, you can use the windows service manager. Pegasus shows up
63 // in the service database as "Pegasus CIM Object Manager"
64 //
65 // Mike Day, mdday@us.ibm.com
66 //
67 //////////////////////////////////////////////////////////////////////
68
69
70 #include <iostream>
71 #include <cstdlib>
72 #include <Pegasus/Common/FileSystem.h>
73 mike 1.32 #include <Pegasus/Common/Selector.h>
74 #include <Pegasus/Server/CIMServer.h>
75 #include <Pegasus/Common/PegasusVersion.h>
76 #include <Pegasus/Protocol/Handler.h>
77 #include <Pegasus/Common/Logger.h>
78 #include <Pegasus/Common/System.h>
|
79 kumpf 1.34.2.1 #include <Pegasus/Common/Tracer.h>
80 #include <Pegasus/Config/ConfigManager.h>
|
81 mike 1.32 #include <slp/slp.h>
82
83
84
85 #if defined(PEGASUS_OS_TYPE_WINDOWS)
86 # include "cimserver_windows.cpp"
87 #elif defined(PEGASUS_OS_TYPE_UNIX)
88 # include "cimserver_unix.cpp"
89 #else
90 # error "Unsupported platform"
91 #endif
92
93 PEGASUS_USING_PEGASUS;
94 PEGASUS_USING_STD;
95
|
96 kumpf 1.34.2.4 //
97 // The command name.
98 //
|
99 kumpf 1.34.2.1 static const char COMMAND_NAME [] = "cimserver";
100
|
101 kumpf 1.34.2.4 //
102 // The constant defining usage string.
103 //
104 static const char USAGE [] = "Usage: ";
105
|
106 kumpf 1.34.2.1 /**
|
107 kumpf 1.34.2.4 Constants representing the command line options.
|
108 kumpf 1.34.2.1 */
|
109 kumpf 1.34.2.4 static const char OPTION_VERSION = 'v';
110
111 static const char OPTION_HELP = 'h';
112
113 static const char OPTION_HOME = 'D';
114
|
115 kumpf 1.34.2.1
116
|
117 mike 1.32 void GetEnvironmentVariables(
118 const char* arg0,
119 String& pegasusHome)
120 {
121 // Get environment variables:
122
123 const char* tmp = getenv("PEGASUS_HOME");
124
125 if (!tmp)
126 {
127 cerr << arg0 << ": PEGASUS_HOME environment variable undefined" << endl;
128 exit(1);
129 }
130
131 pegasusHome = tmp;
132 FileSystem::translateSlashes(pegasusHome);
133 }
134
135 /** GetOptions function - This function defines the Options Table
|
136 kumpf 1.34.2.1 and sets up the options from that table using the config manager.
|
137 mike 1.32 */
138 void GetOptions(
|
139 kumpf 1.34.2.1 ConfigManager* cm,
|
140 mike 1.32 int& argc,
141 char** argv,
142 const String& pegasusHome)
143 {
|
144 kumpf 1.34.2.1 String currentFile = pegasusHome + "/" + CURRENT_CONFIG_FILE;
145 String plannedFile = pegasusHome + "/" + PLANNED_CONFIG_FILE;
146
147 try
|
148 mike 1.32 {
|
149 kumpf 1.34.2.1 cm->mergeConfigFiles(currentFile, plannedFile);
|
150 mike 1.32
|
151 kumpf 1.34.2.1 cm->mergeCommandLine(argc, argv);
152 }
153 catch (NoSuchFile nsf)
154 {
155 throw nsf;
156 }
157 catch (FileNotReadable fnr)
158 {
159 throw fnr;
160 }
161 catch (CannotRenameFile ftrf)
162 {
163 throw ftrf;
164 }
165 catch (ConfigFileSyntaxError cfse)
166 {
167 throw cfse;
168 }
|
169 kumpf 1.34.2.4 catch(UnrecognizedConfigProperty ucp)
170 {
171 throw ucp;
172 }
173 catch(InvalidPropertyValue ipv)
174 {
175 throw ipv;
176 }
|
177 mike 1.32 }
178
179 /* PrintHelp - This is temporary until we expand the options manager to allow
180 options help to be defined with the OptionRow entries and presented from
181 those entries.
182 */
183 void PrintHelp(const char* arg0)
184 {
|
185 kumpf 1.34.2.1 /**
186 Build the usage string for the config command.
187 */
188 String usage = String (USAGE);
189 usage.append (COMMAND_NAME);
190 usage.append (" [ [ options ] | [ configProperty=value, ... ] ]\n");
191 usage.append (" options\n");
|
192 kumpf 1.34.2.4 usage.append (" -v - displays pegasus version number\n");
193 usage.append (" -h - prints this help message\n");
194 usage.append (" -t - turns tracing on\n");
195 usage.append (" -t - turns on trace of client IO to console\n");
196 usage.append (" -l - turns on trace of client IO to trace file\n");
197 usage.append (" -d - runs pegasus as a daemon\n");
198 usage.append (" -cleanlogs - clears the log files at startup\n");
199 usage.append (" -install - installs pegasus as a Windows NT Service\n");
200 usage.append (" -remove - removes pegasus as a Windows NT Service\n");
201 usage.append (" -slp - registers pegasus as a service with SLP\n\n");
202
203 usage.append (" configProperty=value\n");
204 usage.append (" port=nnnn - sets port number to listen on\n");
205 usage.append (" home=/pegasus/bin - sets pegasus home directory\n");
206 usage.append (" logdir=/pegasus/logs - directory for log files\n");
|
207 kumpf 1.34.2.1
208 cout << endl;
|
209 mike 1.32 cout << PEGASUS_NAME << PEGASUS_VERSION << endl;
210 cout << endl;
|
211 kumpf 1.34.2.1 cout << usage << endl;
|
212 mike 1.32 }
213
|
214 mike 1.33 /////////////////////////////////////////////////////////////////////////
|
215 mike 1.32 // MAIN
216 //////////////////////////////////////////////////////////////////////////
217 int main(int argc, char** argv)
218 {
|
219 kumpf 1.34.2.1 String pegasusHome = String::EMPTY;
220 Boolean pegasusIOTrace = false;
221 Boolean pegasusIOLog = false;
222 String portOption = String::EMPTY;
223 String logsDirectory = String::EMPTY;
224 Boolean useSLP = false;
225 Boolean daemonOption = false;
226
|
227 mike 1.32 // on Windows NT if there are no command-line options, run as a service
228
229 if (argc == 1 )
230 cim_server_service(argc, argv) ;
231
|
232 kumpf 1.34.2.4 // Get help, version and home options
|
233 mike 1.32
|
234 kumpf 1.34.2.4 for (int i = 0; i < argc; )
235 {
236 const char* arg = argv[i];
237
238 // Check for -option
239 if (*arg == '-')
240 {
241 // Get the option
242 const char* option = arg + 1;
243
244 //
245 // Check to see if user asked for the version (-v option):
246 //
247 if (*option == OPTION_VERSION)
248 {
249 cout << PEGASUS_VERSION << endl;
250 exit(0);
251 }
252 //
253 // Check to see if user asked for help (-h option):
254 //
255 kumpf 1.34.2.4 else if (*option == OPTION_HELP)
256 {
257 PrintHelp(argv[0]);
258 exit(0);
259 }
260 else if (*option == OPTION_HOME)
261 {
262 if (i + 1 < argc)
263 {
264 pegasusHome = argv[i + 1];
265 }
266 else
267 {
268 cout << "Missing argument for option -" << option << endl;
269 exit(0);
270 }
271
272 memmove(&argv[i], &argv[i + 2], (argc-i-1) * sizeof(char*));
273 argc -= 2;
274 }
|
275 mike 1.32 }
|
276 kumpf 1.34.2.4 i++;
|
277 mike 1.32 }
|
278 kumpf 1.34.2.4
|
279 mike 1.32 if (pegasusHome.size() == 0)
280 GetEnvironmentVariables(argv[0], pegasusHome);
281
|
282 kumpf 1.34.2.1 //
283 // Get an instance of the Config Manager.
284 //
|
285 mike 1.34.2.3 ConfigManager* configManager = ConfigManager::getInstance();
|
286 mike 1.32
|
287 kumpf 1.34.2.1 //
288 // Get options (from command line and from configuration file); this
|
289 kumpf 1.34.2.4 // removes corresponding options and their arguments from the command
|
290 kumpf 1.34.2.1 // line.
291 //
|
292 mike 1.32 try
293 {
|
294 kumpf 1.34.2.1 GetOptions(configManager, argc, argv, pegasusHome);
|
295 mike 1.32 }
296 catch (Exception& e)
297 {
|
298 kumpf 1.34.2.1 cerr << argv[0] << ": " << e.getMessage() << endl;
299 exit(1);
|
300 mike 1.32 }
301
302
|
303 kumpf 1.34.2.1 try
304 {
305 //
306 // Check to see if we should (can) install as a NT service
307 //
308
|
309 kumpf 1.34.2.4 if (String::equal(configManager->getCurrentValue("install"), "true"))
|
310 kumpf 1.34.2.1 {
311 if( 0 != cimserver_install_nt_service( pegasusHome ))
312 {
313 cout << "\nPegasus installed as NT Service";
314 exit(0);
315 }
316 }
|
317 mike 1.32
|
318 kumpf 1.34.2.1 //
319 // Check to see if we should (can) remove Pegasus as an NT service
320 //
321
|
322 kumpf 1.34.2.4 if (String::equal(configManager->getCurrentValue("remove"), "true"))
|
323 kumpf 1.34.2.1 {
324 if( 0 != cimserver_remove_nt_service() )
325 {
326 cout << "\nPegasus removed as NT Service";
327 exit(0);
328 }
329 }
|
330 mike 1.32
|
331 kumpf 1.34.2.1 //
332 // Check to see if we should Pegasus as a daemon
333 //
334
|
335 kumpf 1.34.2.4 if (String::equal(configManager->getCurrentValue("daemon"), "true"))
|
336 kumpf 1.34.2.1 {
337 daemonOption = true;
338 }
|
339 mike 1.32
|
340 kumpf 1.34.2.1 //
341 // Grab the port option:
342 //
343
344 portOption = configManager->getCurrentValue("port");
345
346 //
347 // Check the trace options and set global variable
348 //
349
|
350 kumpf 1.34.2.4 if (String::equal(configManager->getCurrentValue("trace"), "true"))
|
351 kumpf 1.34.2.1 {
352 Handler::setMessageTrace(true);
353 pegasusIOTrace = true;
354 cout << "Trace Set" << endl;
355 }
356 //
357 // Check the log trace options and set global variable
358 //
359
|
360 kumpf 1.34.2.4 if (String::equal(configManager->getCurrentValue("logtrace"), "true"))
|
361 kumpf 1.34.2.1 {
362 Handler::setMessageLogTrace(true);
363 pegasusIOLog = true;
364 }
|
365 mike 1.32
|
366 kumpf 1.34.2.1 // Get the log file directory definition.
367 // We put String into Cstring because
368 // Directory functions only handle Cstring.
369 // ATTN-KS: create String based directory functions.
370
371 logsDirectory = configManager->getCurrentValue("logdir");
372
373 // Set up the Logger. This does not open the logs
374 // Might be more logical to clean before set.
375 // ATTN: Need tool to completely disable logging.
|
376 kumpf 1.34.2.4
|
377 kumpf 1.34.2.1 Logger::setHomeDirectory(logsDirectory);
378
|
379 kumpf 1.34.2.4 if (String::equal(configManager->getCurrentValue("cleanlogs"), "true"))
|
380 kumpf 1.34.2.1 {
381 Logger::clean(logsDirectory);;
382 }
|
383 mike 1.32
|
384 kumpf 1.34.2.1 // Leave this in until people get familiar with the logs.
385 cout << "Logs Directory = " << logsDirectory << endl;
|
386 mike 1.32
|
387 kumpf 1.34.2.4 if (String::equal(configManager->getCurrentValue("slp"), "true"))
|
388 kumpf 1.34.2.1 {
389 useSLP = true;
390 }
|
391 mike 1.32 }
|
392 kumpf 1.34.2.1 catch (UnrecognizedConfigProperty e)
|
393 mike 1.32 {
|
394 kumpf 1.34.2.1 cout << "Error: " << e.getMessage() << endl;
|
395 mike 1.32 }
396
397 char* address = portOption.allocateCString();
398
399 // Put out startup up message.
400 cout << PEGASUS_NAME << PEGASUS_VERSION <<
401 " on port " << address << endl;
402 cout << "Built " << __DATE__ << " " << __TIME__ << endl;
403 cout <<"Started..."
404 << (pegasusIOTrace ? " Tracing to Display ": " ")
405 << (pegasusIOLog ? " Tracing to Log ": " ")
406 << (useSLP ? " SLP reg. " : " No SLP ")
407 << endl;
408
409 // Put server start message to the logger
410 Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION,
411 "Start $0 $1 port $2 $3 $4",
412 PEGASUS_NAME,
413 PEGASUS_VERSION,
414 address,
415 (pegasusIOTrace ? " Tracing": " "),
416 mike 1.32 (useSLP ? " SLP on " : " SLP off "));
417
|
418 kumpf 1.34.2.1 // do we need to run as a daemon ?
419 if (daemonOption)
420 {
421 if(-1 == cimserver_fork())
422 exit(-1);
423 }
|
424 mike 1.32
425 // try loop to bind the address, and run the server
426 try
427 {
428 slp_client *discovery = new slp_client() ;;
429 String serviceURL;
430 serviceURL.assign("service:cim.pegasus://");
431 String host_name = slp_get_host_name();
432 serviceURL += host_name;
433 serviceURL += ":";
434 serviceURL += address;
435 char *url = serviceURL.allocateCString();
436 // free(host_name);
437
438 Selector selector;
439 CIMServer server(&selector, pegasusHome);
440
441 // bind throws an exception of the bind fails
|
442 mike 1.33 cout << "Binding to " << address << endl;
|
443 mike 1.32 server.bind(address);
444 delete [] address;
445
446 time_t last = 0;
447 while( 1 )
448 {
449 if(useSLP )
450 {
451 if( (time(NULL) - last ) > 60 )
452 {
453 if( discovery != NULL && url != NULL )
454 discovery->srv_reg_all(url,
|
455 kumpf 1.34.2.4 "(namespace=root/cimv2)",
|
456 mike 1.32 "service:cim.pegasus",
457 "DEFAULT",
458 70) ;
459 time(&last);
460 }
461
462 discovery->service_listener();
463 }
464 server.runForever();
465 }
466
|
467 mike 1.34 // This statement is unrechable!
468 //
469 // Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION,
470 // "Normal Termination");
|
471 mike 1.32 }
472 catch(Exception& e)
473 {
474 Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION,
475 "Abnormal Termination $0", e.getMessage());
476
477 PEGASUS_STD(cerr) << "Error: " << e.getMessage() << PEGASUS_STD(endl);
478 }
479
480 return 0;
481 }
|