VirtualBox

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

Last change on this file since 18499 was 11725, checked in by vboxsync, 16 years ago

#3076: Merged in the branch with the alternate driver authentication method. (34468:HEAD)

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

© 2023 Oracle
ContactPrivacy policyTerms of Use