VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/SUPSvc.cpp@ 54371

Last change on this file since 54371 was 44529, checked in by vboxsync, 12 years ago

header (C) fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.8 KB
Line 
1/* $Id: SUPSvc.cpp 44529 2013-02-04 15:54:15Z vboxsync $ */
2/** @file
3 * VirtualBox Support Service - Common Code.
4 */
5
6/*
7 * Copyright (C) 2008-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30#define LOG_GROUP LOG_GROUP_SUP
31#include <VBox/log.h>
32#include <iprt/string.h>
33#include <iprt/mem.h>
34#include <iprt/stream.h>
35#include <iprt/getopt.h>
36
37#include "SUPSvcInternal.h"
38
39
40/*******************************************************************************
41* Structures and Typedefs *
42*******************************************************************************/
43/**
44 * Service state.
45 */
46typedef enum SUPSVCSERVICESTATE
47{
48 kSupSvcServiceState_Invalid = 0,
49 kSupSvcServiceState_NotCreated,
50 kSupSvcServiceState_Paused,
51 kSupSvcServiceState_Running,
52 kSupSvcServiceState_End
53} SUPSVCSERVICESTATE;
54
55
56/**
57 * Service descriptor.
58 */
59typedef struct SUPSVCSERVICE
60{
61 /** The service name. */
62 const char *pszName;
63 /** The service state. */
64 SUPSVCSERVICESTATE enmState;
65 /** The instance handle returned by pfnCreate. */
66 void *pvInstance;
67
68 /**
69 * Create the service (don't start it).
70 *
71 * @returns VBox status code, log entry is written on failure.
72 * @param ppvInstance Where to store the instance handle.
73 */
74 DECLCALLBACKMEMBER(int, pfnCreate)(void **ppvInstance);
75
76 /**
77 * Start the service.
78 *
79 * @returns VBox status code, log entry is written on failure.
80 * @param pvInstance The instance handle.
81 */
82 DECLCALLBACKMEMBER(void, pfnStart)(void *pvInstance);
83
84 /**
85 * Attempt to stop a running service.
86 *
87 * This should fail if there are active clients. A stopped service
88 * can be restarted by calling pfnStart.
89 *
90 * @returns VBox status code, log entry is written on failure.
91 * @param pvInstance The instance handle.
92 */
93 DECLCALLBACKMEMBER(int, pfnTryStop)(void *pvInstance);
94
95 /**
96 * Destroy the service, stopping first it if necessary.
97 *
98 * @param pvInstance The instance handle.
99 * @param fRunning Whether the service is running or not.
100 */
101 DECLCALLBACKMEMBER(void, pfnStopAndDestroy)(void *pvInstance, bool fRunning);
102} SUPSVCSERVICE;
103/** Pointer to a service descriptor. */
104typedef SUPSVCSERVICE *PSUPSVCSERVICE;
105/** Pointer to a const service descriptor. */
106typedef SUPSVCSERVICE const *PCSUPSVCSERVICE;
107
108
109
110/*******************************************************************************
111* Global Variables *
112*******************************************************************************/
113static SUPSVCSERVICE g_aServices[] =
114{
115 {
116 "Global",
117 kSupSvcServiceState_NotCreated,
118 NULL,
119 supSvcGlobalCreate,
120 supSvcGlobalStart,
121 supSvcGlobalTryStop,
122 supSvcGlobalStopAndDestroy,
123 }
124#ifdef RT_OS_WINDOWS
125 ,
126 {
127 "Grant",
128 kSupSvcServiceState_NotCreated,
129 NULL,
130 supSvcGrantCreate,
131 supSvcGrantStart,
132 supSvcGrantTryStop,
133 supSvcGrantStopAndDestroy,
134 }
135#endif
136};
137
138
139
140/**
141 * Instantiates and starts the services.
142 *
143 * @returns VBox status code. Done bitching on failure.
144 */
145int supSvcCreateAndStartServices(void)
146{
147 LogFlowFuncEnter();
148
149 /*
150 * Validate that all services are in the NotCreated state.
151 */
152 unsigned i;
153 for (i = 0; i < RT_ELEMENTS(g_aServices); i++)
154 if (g_aServices[i].enmState != kSupSvcServiceState_NotCreated)
155 {
156 supSvcLogError("service %s in state %d, expected state %d (NotCreated)",
157 g_aServices[i].pszName, g_aServices[i].enmState, kSupSvcServiceState_NotCreated);
158 return VERR_WRONG_ORDER;
159 }
160
161 /*
162 * Create all the services, then start them.
163 */
164 int rc = VINF_SUCCESS;
165 for (i = 0; i < RT_ELEMENTS(g_aServices); i++)
166 {
167 void *pvInstance = NULL;
168 int rc = g_aServices[i].pfnCreate(&pvInstance);
169 if (RT_FAILURE(rc))
170 {
171 Log(("supSvcCreateAndStartServices: %s -> %Rrc\n", g_aServices[i].pszName, rc));
172 break;
173 }
174 g_aServices[i].pvInstance = pvInstance;
175 g_aServices[i].enmState = kSupSvcServiceState_Paused;
176 }
177 if (RT_SUCCESS(rc))
178 {
179 for (i = 0; i < RT_ELEMENTS(g_aServices); i++)
180 {
181 g_aServices[i].pfnStart(g_aServices[i].pvInstance);
182 g_aServices[i].enmState = kSupSvcServiceState_Running;
183 }
184 }
185 else
186 {
187 /*
188 * Destroy any services we managed to instantiate.
189 */
190 while (i-- > 0)
191 {
192 g_aServices[i].pfnStopAndDestroy(g_aServices[i].pvInstance, false /* fRunning */);
193 g_aServices[i].pvInstance = NULL;
194 g_aServices[i].enmState = kSupSvcServiceState_NotCreated;
195 }
196 }
197
198 LogFlow(("supSvcCreateAndStartServices: returns %Rrc\n", rc));
199 return rc;
200}
201
202
203/**
204 * Checks if it's possible to stop the services.
205 *
206 * @returns VBox status code, done bitching on failure.
207 */
208int supSvcTryStopServices(void)
209{
210 LogFlowFuncEnter();
211
212 /*
213 * Check that the services are all created and count the running ones.
214 */
215 unsigned i;
216 unsigned cRunning = 0;
217 for (i = 0; i < RT_ELEMENTS(g_aServices); i++)
218 if (g_aServices[i].enmState == kSupSvcServiceState_Running)
219 cRunning++;
220 else if (g_aServices[i].enmState == kSupSvcServiceState_NotCreated)
221 {
222 supSvcLogError("service %s in state %d (NotCreated), expected pause or running",
223 g_aServices[i].pszName, g_aServices[i].enmState, kSupSvcServiceState_NotCreated);
224 return VERR_WRONG_ORDER;
225 }
226 if (!cRunning)
227 return VINF_SUCCESS; /* all stopped, nothing to do. */
228 Assert(cRunning == RT_ELEMENTS(g_aServices)); /* all or nothing */
229
230 /*
231 * Try stop them in reverse of start order.
232 */
233 int rc = VINF_SUCCESS;
234 i = RT_ELEMENTS(g_aServices);
235 while (i-- > 0)
236 {
237 rc = g_aServices[i].pfnTryStop(g_aServices[i].pvInstance);
238 if (RT_FAILURE(rc))
239 {
240 Log(("supSvcTryStopServices: %s -> %Rrc\n", g_aServices[i].pszName, rc));
241 break;
242 }
243 g_aServices[i].enmState = kSupSvcServiceState_Paused;
244 }
245 if (RT_FAILURE(rc))
246 {
247 /* Failed, restart the ones we succeeded in stopping. */
248 while (++i < RT_ELEMENTS(g_aServices))
249 {
250 g_aServices[i].pfnStart(g_aServices[i].pvInstance);
251 g_aServices[i].enmState = kSupSvcServiceState_Running;
252 }
253 }
254 LogFlow(("supSvcTryStopServices: returns %Rrc\n", rc));
255 return rc;
256}
257
258
259/**
260 * Stops and destroys the services.
261 */
262void supSvcStopAndDestroyServices(void)
263{
264 LogFlowFuncEnter();
265
266 /*
267 * Stop and destroy the service in reverse of start order.
268 */
269 unsigned i = RT_ELEMENTS(g_aServices);
270 while (i-- > 0)
271 if (g_aServices[i].enmState != kSupSvcServiceState_NotCreated)
272 {
273 g_aServices[i].pfnStopAndDestroy(g_aServices[i].pvInstance,
274 g_aServices[i].enmState == kSupSvcServiceState_Running);
275 g_aServices[i].pvInstance = NULL;
276 g_aServices[i].enmState = kSupSvcServiceState_NotCreated;
277 }
278
279 LogFlowFuncLeave();
280}
281
282
283
284/**
285 * Logs the message to the appropriate system log.
286 *
287 * In debug builds this will also put it in the debug log.
288 *
289 * @param pszMsg The log string.
290 *
291 * @remarks This may later be replaced by the release logger and callback destination(s).
292 */
293void supSvcLogErrorStr(const char *pszMsg)
294{
295 supSvcOsLogErrorStr(pszMsg);
296 LogRel(("%s\n", pszMsg));
297}
298
299
300/**
301 * Logs the message to the appropriate system log.
302 *
303 * In debug builds this will also put it in the debug log.
304 *
305 * @param pszFormat The log string. No trailing newline.
306 * @param ... Format arguments.
307 *
308 * @todo This should later be replaced by the release logger and callback destination(s).
309 */
310void supSvcLogErrorV(const char *pszFormat, va_list va)
311{
312 if (*pszFormat)
313 {
314 char *pszMsg = NULL;
315 if (RTStrAPrintfV(&pszMsg, pszFormat, va) != -1)
316 {
317 supSvcLogErrorStr(pszMsg);
318 RTStrFree(pszMsg);
319 }
320 else
321 supSvcLogErrorStr(pszFormat);
322 }
323}
324
325
326/**
327 * Logs the error message to the appropriate system log.
328 *
329 * In debug builds this will also put it in the debug log.
330 *
331 * @param pszFormat The log string. No trailing newline.
332 * @param ... Format arguments.
333 *
334 * @todo This should later be replaced by the release logger and callback destination(s).
335 */
336void supSvcLogError(const char *pszFormat, ...)
337{
338 va_list va;
339 va_start(va, pszFormat);
340 supSvcLogErrorV(pszFormat, va);
341 va_end(va);
342}
343
344
345/**
346 * Deals with RTGetOpt failure, bitching in the system log.
347 *
348 * @returns 1
349 * @param pszAction The action name.
350 * @param rc The RTGetOpt return value.
351 * @param argc The argument count.
352 * @param argv The argument vector.
353 * @param iArg The argument index.
354 * @param pValue The value returned by RTGetOpt.
355 */
356int supSvcLogGetOptError(const char *pszAction, int rc, int argc, char **argv, int iArg, PCRTOPTIONUNION pValue)
357{
358 supSvcLogError("%s - RTGetOpt failure, %Rrc (%d): %s",
359 pszAction, rc, rc, iArg < argc ? argv[iArg] : "<null>");
360 return 1;
361}
362
363
364/**
365 * Bitch about too many arguments (after RTGetOpt stops) in the system log.
366 *
367 * @returns 1
368 * @param pszAction The action name.
369 * @param argc The argument count.
370 * @param argv The argument vector.
371 * @param iArg The argument index.
372 */
373int supSvcLogTooManyArgsError(const char *pszAction, int argc, char **argv, int iArg)
374{
375 Assert(iArg < argc);
376 supSvcLogError("%s - Too many arguments: %s", pszAction, argv[iArg]);
377 for ( ; iArg < argc; iArg++)
378 LogRel(("arg#%i: %s\n", iArg, argv[iArg]));
379 return 1;
380}
381
382
383/**
384 * Prints an error message to the screen.
385 *
386 * @param pszFormat The message format string.
387 * @param va Format arguments.
388 */
389void supSvcDisplayErrorV(const char *pszFormat, va_list va)
390{
391 RTStrmPrintf(g_pStdErr, "VBoxSupSvc error: ");
392 RTStrmPrintfV(g_pStdErr, pszFormat, va);
393 Log(("supSvcDisplayErrorV: %s", pszFormat)); /** @todo format it! */
394}
395
396
397/**
398 * Prints an error message to the screen.
399 *
400 * @param pszFormat The message format string.
401 * @param ... Format arguments.
402 */
403void supSvcDisplayError(const char *pszFormat, ...)
404{
405 va_list va;
406 va_start(va, pszFormat);
407 supSvcDisplayErrorV(pszFormat, va);
408 va_end(va);
409}
410
411
412/**
413 * Deals with RTGetOpt failure.
414 *
415 * @returns 1
416 * @param pszAction The action name.
417 * @param rc The RTGetOpt return value.
418 * @param argc The argument count.
419 * @param argv The argument vector.
420 * @param iArg The argument index.
421 * @param pValue The value returned by RTGetOpt.
422 */
423int supSvcDisplayGetOptError(const char *pszAction, int rc, int argc, char **argv, int iArg, PCRTOPTIONUNION pValue)
424{
425 supSvcDisplayError("%s - RTGetOpt failure, %Rrc (%d): %s\n",
426 pszAction, rc, rc, iArg < argc ? argv[iArg] : "<null>");
427 return 1;
428}
429
430
431/**
432 * Bitch about too many arguments (after RTGetOpt stops).
433 *
434 * @returns 1
435 * @param pszAction The action name.
436 * @param argc The argument count.
437 * @param argv The argument vector.
438 * @param iArg The argument index.
439 */
440int supSvcDisplayTooManyArgsError(const char *pszAction, int argc, char **argv, int iArg)
441{
442 Assert(iArg < argc);
443 supSvcDisplayError("%s - Too many arguments: %s\n", pszAction, argv[iArg]);
444 return 1;
445}
446
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette