Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / Service_Manager.cpp
blob7862e2312dbc66265ff195eb38174e94e5d5d042
1 #include "ace/Service_Manager.h"
3 #include "ace/Get_Opt.h"
4 #include "ace/Log_Category.h"
5 #include "ace/Service_Repository.h"
6 #include "ace/Service_Config.h"
7 #include "ace/Service_Types.h"
8 #include "ace/Reactor.h"
9 #include "ace/WFMO_Reactor.h"
10 #include "ace/OS_NS_stdio.h"
11 #include "ace/OS_NS_string.h"
13 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
15 ACE_ALLOC_HOOK_DEFINE (ACE_Service_Manager)
17 void
18 ACE_Service_Manager::dump () const
20 #if defined (ACE_HAS_DUMP)
21 ACE_TRACE ("ACE_Service_Manager::dump");
22 #endif /* ACE_HAS_DUMP */
25 // Static variables.
27 u_short ACE_Service_Manager::DEFAULT_PORT_ = 10000;
29 ACE_Service_Manager::ACE_Service_Manager ()
30 : debug_ (false),
31 signum_ (SIGHUP)
33 ACE_TRACE ("ACE_Service_Manager::ACE_Service_Manager");
36 ACE_Service_Manager::~ACE_Service_Manager ()
38 ACE_TRACE ("ACE_Service_Manager::~ACE_Service_Manager");
41 int
42 ACE_Service_Manager::suspend ()
44 ACE_TRACE ("ACE_Service_Manager::suspend");
45 return ACE_Reactor::instance ()->suspend_handler (this);
48 int
49 ACE_Service_Manager::resume ()
51 ACE_TRACE ("ACE_Service_Manager::resume");
52 return ACE_Reactor::instance ()->resume_handler (this);
55 int
56 ACE_Service_Manager::open (const ACE_INET_Addr &sia)
58 ACE_TRACE ("ACE_Service_Manager::open");
60 // Reuse the listening address, even if it's already in use!
61 if (this->acceptor_.open (sia, 1) == -1)
63 return -1;
66 return 0;
69 int
70 ACE_Service_Manager::info (ACE_TCHAR **strp, size_t length) const
72 ACE_TRACE ("ACE_Service_Manager::info");
73 ACE_INET_Addr sa;
74 ACE_TCHAR buf[BUFSIZ];
76 if (this->acceptor_.get_local_addr (sa) == -1)
78 return -1;
81 ACE_OS::snprintf (buf, BUFSIZ,
82 ACE_TEXT ("%d/%s %s"),
83 sa.get_port_number (),
84 ACE_TEXT ("tcp"),
85 ACE_TEXT ("# lists all services in the daemon\n"));
87 if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
89 return -1;
91 else
93 ACE_OS::strsncpy (*strp, buf, length);
96 return static_cast<int> (ACE_OS::strlen (buf));
99 int
100 ACE_Service_Manager::init (int argc, ACE_TCHAR *argv[])
102 ACE_TRACE ("ACE_Service_Manager::init");
103 ACE_INET_Addr local_addr (ACE_Service_Manager::DEFAULT_PORT_);
105 //FUZZ: disable check_for_lack_ACE_OS
106 ACE_Get_Opt getopt (argc, argv, ACE_TEXT ("dp:s:"), 0); // Start at argv[0]
108 for (int c; (c = getopt ()) != -1; )
109 //FUZZ: enable check_for_lack_ACE_OS
110 switch (c)
112 case 'd':
113 this->debug_ = true;
114 break;
115 case 'p':
116 local_addr.set ((u_short) ACE_OS::atoi (getopt.opt_arg ()));
117 break;
118 case 's':
119 this->signum_ = ACE_OS::atoi (getopt.opt_arg ());
120 break;
121 default:
122 break;
125 if (this->get_handle () == ACE_INVALID_HANDLE &&
126 this->open (local_addr) == -1)
128 ACELIB_ERROR_RETURN ((LM_ERROR,
129 ACE_TEXT ("%p\n"),
130 ACE_TEXT ("open")), -1);
132 else if (ACE_Reactor::instance ()->register_handler
133 (this,
134 ACE_Event_Handler::ACCEPT_MASK) == -1)
136 ACELIB_ERROR_RETURN ((LM_ERROR,
137 ACE_TEXT ("registering service with ACE_Reactor\n")),
138 -1);
141 return 0;
145 ACE_Service_Manager::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
147 ACE_TRACE ("ACE_Service_Manager::handle_close");
148 return this->acceptor_.close ();
152 ACE_Service_Manager::fini ()
154 ACE_TRACE ("ACE_Service_Manager::fini");
156 int retv = 0;
158 if (this->get_handle () != ACE_INVALID_HANDLE)
160 retv =
161 ACE_Reactor::instance ()->remove_handler (
162 this,
163 ACE_Event_Handler::ACCEPT_MASK | ACE_Event_Handler::DONT_CALL);
165 this->handle_close (ACE_INVALID_HANDLE,
166 ACE_Event_Handler::NULL_MASK);
169 return retv;
172 ACE_HANDLE
173 ACE_Service_Manager::get_handle () const
175 ACE_TRACE ("ACE_Service_Manager::get_handle");
176 return this->acceptor_.get_handle ();
180 ACE_Service_Manager::handle_signal (int, siginfo_t *, ucontext_t *)
182 return 0;
185 // Determine all the services offered by this daemon and return the
186 // information back to the client.
189 ACE_Service_Manager::list_services ()
191 ACE_TRACE ("ACE_Service_Manager::list_services");
192 ACE_Service_Repository_Iterator sri (*ACE_Service_Repository::instance (), 0);
194 for (const ACE_Service_Type *sr;
195 sri.next (sr) != 0;
196 sri.advance ())
198 ssize_t len = static_cast<ssize_t> (ACE_OS::strlen (sr->name ())) + 11;
199 ACE_TCHAR buf[BUFSIZ];
200 ACE_TCHAR *p = buf + len;
202 ACE_OS::strcpy (buf, sr->name ());
203 ACE_OS::strcat (buf, (sr->active ()) ?
204 ACE_TEXT (" (active) ") :
205 ACE_TEXT (" (paused) "));
207 p[-1] = ' ';
208 p[0] = '\0';
210 len += sr->type ()->info (&p, sizeof buf - len);
212 if (this->debug_)
214 ACELIB_DEBUG ((LM_DEBUG,
215 ACE_TEXT ("len = %d, info = %s%s"),
216 len,
217 buf,
218 buf[len - 1] == '\n' ? ACE_TEXT ("") : ACE_TEXT ("\n")));
221 if (len > 0)
223 ssize_t n = this->client_stream_.send_n (buf, len);
225 if (n <= 0 && errno != EPIPE)
227 ACELIB_ERROR ((LM_ERROR,
228 ACE_TEXT ("%p\n"),
229 ACE_TEXT ("send_n")));
234 return 0;
237 // Trigger a reconfiguration of the Service Configurator via its
238 // svc.conf file.
241 ACE_Service_Manager::reconfigure_services ()
243 ACE_TRACE ("ACE_Service_Manager::reconfigure_services");
245 #if 0
246 // Send ourselves a signal! ACE_OS::kill (ACE_OS::getpid (),
247 // this->signum_);
248 #endif /* 0 */
250 // Flag the main event loop that a reconfiguration should occur.
251 // The next trip through the <ACE_Reactor::run_event_loop> should
252 // pick this up and cause a reconfiguration. Note that we can't
253 // trigger the reconfiguration automatically since that might "pull
254 // the rug" out from underneath the existing services in a
255 // problematic way.
256 ACE_Service_Config::reconfig_occurred ((sig_atomic_t) 1);
257 return static_cast<int> (this->client_stream_.send_n ("done\n",
258 sizeof ("done\n")));
261 // isolate the request-processing code
262 void
263 ACE_Service_Manager::process_request (ACE_TCHAR *request)
265 ACE_TRACE("ACE_Service_Manager::process_request");
266 ACE_TCHAR *p;
268 // Kill trailing newlines.
269 for (p = request;
270 (*p != '\0') && (*p != '\r') && (*p != '\n');
271 p++)
273 continue;
276 *p = '\0';
278 if (ACE_OS::strcmp (request, ACE_TEXT ("help")) == 0)
280 // Return a list of the configured services.
281 this->list_services ();
283 else if (ACE_OS::strcmp (request, ACE_TEXT ("reconfigure") )== 0)
285 // Trigger a reconfiguration by re-reading the local <svc.conf> file.
286 this->reconfigure_services ();
288 else
290 // Just process a single request passed in via the socket
291 // remotely.
292 ACE_Service_Config_Guard guard (ACE_Service_Config::global ());
293 ACE_Service_Config::process_directive (request);
296 // Additional management services may be handled here...
299 // Accept new connection from client and carry out the service they
300 // request.
303 ACE_Service_Manager::handle_input (ACE_HANDLE)
305 ACE_TRACE ("ACE_Service_Manager::handle_input");
307 // Try to find out if the implementation of the reactor that we are
308 // using requires us to reset the event association for the newly
309 // created handle. This is because the newly created handle will
310 // inherit the properties of the listen handle, including its event
311 // associations.
312 bool reset_new_handle =
313 ACE_Reactor::instance ()->uses_event_associations ();
315 if (this->acceptor_.accept (this->client_stream_, // stream
316 0, // remote address
317 0, // timeout
318 1, // restart
319 reset_new_handle // reset new handler
320 ) == -1)
322 return -1;
325 if (this->debug_)
327 ACELIB_DEBUG ((LM_DEBUG,
328 ACE_TEXT ("client_stream fd = %d\n"),
329 this->client_stream_.get_handle ()));
330 ACE_INET_Addr sa;
332 if (this->client_stream_.get_remote_addr (sa) == -1)
334 return -1;
337 ACELIB_DEBUG ((LM_DEBUG,
338 ACE_TEXT ("accepted from host %C at port %d\n"),
339 sa.get_host_name (),
340 sa.get_port_number ()));
343 ACE_TCHAR request[BUFSIZ];
344 ACE_TCHAR* offset = request;
345 ssize_t remaining = sizeof (request);
347 // Read service request from client.
349 ssize_t result;
351 // Keep looping until we actually get the request. Note that Win32
352 // sets the socket into non-blocking mode, so we may need to loop if
353 // the system is heavily loaded. Read bytes into the buffer until a
354 // '\n' or '\r' is found in the buffer, otherwise the buffer
355 // contains an incomplete string.
357 int error;
361 result = client_stream_.recv (offset, remaining);
362 error = errno;
364 if (result == 0 && error != EWOULDBLOCK)
366 remaining = 0;
369 if (result >= 0)
371 if ((remaining -= result) <= 0)
373 ACELIB_DEBUG ((LM_ERROR,
374 ACE_TEXT ("Request buffer overflow.\n")));
375 result = 0;
376 break;
379 offset += result;
380 *offset = 0;
382 if (ACE_OS::strchr (request, '\r') != 0
383 || ACE_OS::strchr (request, '\n') != 0)
385 remaining = 0;
389 while ((result == -1 && error == EWOULDBLOCK) || remaining > 0);
391 switch (result)
393 case -1:
394 if (this->debug_)
396 ACELIB_DEBUG ((LM_ERROR,
397 ACE_TEXT ("%p\n"),
398 ACE_TEXT ("recv")));
401 break;
402 case 0:
403 return 0;
404 /* NOTREACHED */
405 default:
407 ACE_Event_Handler *old_signal_handler = 0;
408 ACE_Reactor::instance ()->register_handler (SIGPIPE,
409 this,
411 &old_signal_handler);
413 this->process_request (request);
415 // Restore existing SIGPIPE handler
416 ACE_Reactor::instance ()->register_handler (SIGPIPE,
417 old_signal_handler);
421 if (this->client_stream_.close () == -1 && this->debug_)
423 ACELIB_DEBUG ((LM_ERROR,
424 ACE_TEXT ("%p\n"),
425 ACE_TEXT ("close")));
428 return 0;
431 ACE_END_VERSIONED_NAMESPACE_DECL