VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/VBoxClient/logging.cpp@ 95478

Last change on this file since 95478 was 94624, checked in by vboxsync, 3 years ago

Runtime/log: Allow setting a custom output interface for the file destination (for encryption), bugref:9955

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.6 KB
Line 
1/* $Id: logging.cpp 94624 2022-04-19 09:20:51Z vboxsync $ */
2/** @file
3 * VirtualBox Guest Additions - X11 Client.
4 */
5
6/*
7 * Copyright (C) 2006-2022 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
18
19#include <sys/wait.h>
20#include <stdlib.h>
21#include <iprt/buildconfig.h>
22#include <iprt/file.h>
23#include <iprt/process.h>
24#include <iprt/stream.h>
25#include <iprt/system.h>
26#include <VBox/VBoxGuestLib.h>
27#include <package-generated.h>
28#include "VBoxClient.h"
29
30/** Logging parameters. */
31/** @todo Make this configurable later. */
32static PRTLOGGER g_pLoggerRelease = NULL;
33static uint32_t g_cHistory = 10; /* Enable log rotation, 10 files. */
34static uint32_t g_uHistoryFileTime = RT_SEC_1DAY; /* Max 1 day per file. */
35static uint64_t g_uHistoryFileSize = 100 * _1M; /* Max 100MB per file. */
36
37/** Custom log prefix (to be set externally). */
38static char *g_pszCustomLogPrefix;
39
40extern unsigned g_cRespawn;
41extern unsigned g_cVerbosity;
42
43/**
44 * Notifies the desktop environment with a message.
45 *
46 * @param pszMessage Message to notify desktop environment with.
47 */
48int vbclLogNotify(const char *pszMessage)
49{
50 AssertPtrReturn(pszMessage, VERR_INVALID_POINTER);
51
52 int rc = VINF_SUCCESS;
53
54 if (g_cRespawn == 0)
55 {
56 char *pszCommand = RTStrAPrintf2("notify-send \"VBoxClient: %s\"", pszMessage);
57 if (pszCommand)
58 {
59 int status = system(pszCommand);
60
61 RTStrFree(pszCommand);
62
63 if (WEXITSTATUS(status) != 0) /* Utility or extension not available. */
64 {
65 pszCommand = RTStrAPrintf2("xmessage -buttons OK:0 -center \"VBoxClient: %s\"",
66 pszMessage);
67 if (pszCommand)
68 {
69 status = system(pszCommand);
70 if (WEXITSTATUS(status) != 0) /* Utility or extension not available. */
71 {
72 RTPrintf("VBoxClient: %s", pszMessage);
73 }
74
75 RTStrFree(pszCommand);
76 }
77 else
78 rc = VERR_NO_MEMORY;
79 }
80 }
81 else
82 rc = VERR_NO_MEMORY;
83 }
84
85 return rc;
86}
87
88/**
89 * Logs a verbose message.
90 *
91 * @param pszFormat The message text.
92 * @param va Format arguments.
93 */
94static void vbClLogV(const char *pszFormat, va_list va)
95{
96 char *psz = NULL;
97 RTStrAPrintfV(&psz, pszFormat, va);
98 AssertPtrReturnVoid(psz);
99 LogRel(("%s", psz));
100 RTStrFree(psz);
101}
102
103/**
104 * Logs a fatal error, notifies the desktop environment via a message and
105 * exits the application immediately.
106 *
107 * @param pszFormat Format string to log.
108 * @param ... Variable arguments for format string. Optional.
109 */
110void VBClLogFatalError(const char *pszFormat, ...)
111{
112 va_list args;
113 va_start(args, pszFormat);
114 char *psz = NULL;
115 RTStrAPrintfV(&psz, pszFormat, args);
116 va_end(args);
117
118 AssertPtrReturnVoid(psz);
119 LogFunc(("Fatal Error: %s", psz));
120 LogRel(("Fatal Error: %s", psz));
121
122 vbclLogNotify(psz);
123
124 RTStrFree(psz);
125}
126
127/**
128 * Logs an error message to the (release) logging instance.
129 *
130 * @param pszFormat Format string to log.
131 */
132void VBClLogError(const char *pszFormat, ...)
133{
134 va_list args;
135 va_start(args, pszFormat);
136 char *psz = NULL;
137 RTStrAPrintfV(&psz, pszFormat, args);
138 va_end(args);
139
140 AssertPtrReturnVoid(psz);
141 LogFunc(("Error: %s", psz));
142 LogRel(("Error: %s", psz));
143
144 RTStrFree(psz);
145}
146
147/**
148 * Logs an info message to the (release) logging instance.
149 *
150 * @param pszFormat Format string to log.
151 */
152void VBClLogInfo(const char *pszFormat, ...)
153{
154 va_list args;
155 va_start(args, pszFormat);
156 vbClLogV(pszFormat, args);
157 va_end(args);
158}
159
160/**
161 * Displays a verbose message based on the currently
162 * set global verbosity level.
163 *
164 * @param iLevel Minimum log level required to display this message.
165 * @param pszFormat The message text.
166 * @param ... Format arguments.
167 */
168void VBClLogVerbose(unsigned iLevel, const char *pszFormat, ...)
169{
170 if (iLevel <= g_cVerbosity)
171 {
172 va_list va;
173 va_start(va, pszFormat);
174 vbClLogV(pszFormat, va);
175 va_end(va);
176 }
177}
178
179/**
180 * @callback_method_impl{FNRTLOGPHASE, Release logger callback}
181 */
182static DECLCALLBACK(void) vbClLogHeaderFooter(PRTLOGGER pLoggerRelease, RTLOGPHASE enmPhase, PFNRTLOGPHASEMSG pfnLog)
183{
184 /* Some introductory information. */
185 static RTTIMESPEC s_TimeSpec;
186 char szTmp[256];
187 if (enmPhase == RTLOGPHASE_BEGIN)
188 RTTimeNow(&s_TimeSpec);
189 RTTimeSpecToString(&s_TimeSpec, szTmp, sizeof(szTmp));
190
191 switch (enmPhase)
192 {
193 case RTLOGPHASE_BEGIN:
194 {
195 pfnLog(pLoggerRelease,
196 "VBoxClient %s r%s (verbosity: %u) %s (%s %s) release log\n"
197 "Log opened %s\n",
198 RTBldCfgVersion(), RTBldCfgRevisionStr(), g_cVerbosity, VBOX_BUILD_TARGET,
199 __DATE__, __TIME__, szTmp);
200
201 int vrc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, sizeof(szTmp));
202 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
203 pfnLog(pLoggerRelease, "OS Product: %s\n", szTmp);
204 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szTmp, sizeof(szTmp));
205 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
206 pfnLog(pLoggerRelease, "OS Release: %s\n", szTmp);
207 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, szTmp, sizeof(szTmp));
208 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
209 pfnLog(pLoggerRelease, "OS Version: %s\n", szTmp);
210 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_SERVICE_PACK, szTmp, sizeof(szTmp));
211 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
212 pfnLog(pLoggerRelease, "OS Service Pack: %s\n", szTmp);
213
214 /* the package type is interesting for Linux distributions */
215 char szExecName[RTPATH_MAX];
216 char *pszExecName = RTProcGetExecutablePath(szExecName, sizeof(szExecName));
217 pfnLog(pLoggerRelease,
218 "Executable: %s\n"
219 "Process ID: %u\n"
220 "Package type: %s"
221#ifdef VBOX_OSE
222 " (OSE)"
223#endif
224 "\n",
225 pszExecName ? pszExecName : "unknown",
226 RTProcSelf(),
227 VBOX_PACKAGE_STRING);
228 break;
229 }
230
231 case RTLOGPHASE_PREROTATE:
232 pfnLog(pLoggerRelease, "Log rotated - Log started %s\n", szTmp);
233 break;
234
235 case RTLOGPHASE_POSTROTATE:
236 pfnLog(pLoggerRelease, "Log continuation - Log started %s\n", szTmp);
237 break;
238
239 case RTLOGPHASE_END:
240 pfnLog(pLoggerRelease, "End of log file - Log started %s\n", szTmp);
241 break;
242
243 default:
244 /* nothing */
245 break;
246 }
247}
248
249static DECLCALLBACK(size_t) vbClLogPrefixCb(PRTLOGGER pLogger, char *pchBuf, size_t cchBuf, void *pvUser)
250{
251 size_t cbPrefix = 0;
252
253 RT_NOREF(pLogger);
254 RT_NOREF(pvUser);
255
256 if (g_pszCustomLogPrefix)
257 {
258 cbPrefix = RT_MIN(strlen(g_pszCustomLogPrefix), cchBuf);
259 memcpy(pchBuf, g_pszCustomLogPrefix, cbPrefix);
260 }
261
262 return cbPrefix;
263}
264
265/**
266 * Creates the default release logger outputting to the specified file.
267 *
268 * Pass NULL to disabled logging.
269 *
270 * @return IPRT status code.
271 * @param pszLogFile Filename for log output. NULL disables custom handling.
272 */
273int VBClLogCreate(const char *pszLogFile)
274{
275 if (!pszLogFile)
276 return VINF_SUCCESS;
277
278 /* Create release logger (stdout + file). */
279 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
280 RTUINT fFlags = RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME | RTLOGFLAGS_PREFIX_CUSTOM;
281#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
282 fFlags |= RTLOGFLAGS_USECRLF;
283#endif
284 int rc = RTLogCreateEx(&g_pLoggerRelease, "VBOXCLIENT_RELEASE_LOG", fFlags, "all",
285 RT_ELEMENTS(s_apszGroups), s_apszGroups, UINT32_MAX /*cMaxEntriesPerGroup*/,
286 0 /*cBufDescs*/, NULL /*paBufDescs*/, RTLOGDEST_STDOUT | RTLOGDEST_USER,
287 vbClLogHeaderFooter, g_cHistory, g_uHistoryFileSize, g_uHistoryFileTime,
288 NULL /*pOutputIf*/, NULL /*pvOutputIfUser*/,
289 NULL /*pErrInfo*/, "%s", pszLogFile ? pszLogFile : "");
290 if (RT_SUCCESS(rc))
291 {
292 /* register this logger as the release logger */
293 RTLogRelSetDefaultInstance(g_pLoggerRelease);
294
295 rc = RTLogSetCustomPrefixCallback(g_pLoggerRelease, vbClLogPrefixCb, NULL);
296 if (RT_FAILURE(rc))
297 VBClLogError("unable to register custom log prefix callback\n");
298
299 /* Explicitly flush the log in case of VBOXSERVICE_RELEASE_LOG=buffered. */
300 RTLogFlush(g_pLoggerRelease);
301 }
302
303 return rc;
304}
305
306/**
307 * Set custom log prefix.
308 *
309 * @param pszPrefix Custom log prefix string.
310 */
311void VBClLogSetLogPrefix(const char *pszPrefix)
312{
313 g_pszCustomLogPrefix = (char *)pszPrefix;
314}
315
316/**
317 * Destroys the currently active logging instance.
318 */
319void VBClLogDestroy(void)
320{
321 RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
322}
323
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