aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/mac_crash_logger/llcrashloggermac.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:45:19 -0500
committerJacek Antonelli2008-08-15 23:45:19 -0500
commitb235c59d60472f818a9142c0886b95a0ff4191d7 (patch)
treed323c55587584b19cc43a03f58a178823f12d3cd /linden/indra/mac_crash_logger/llcrashloggermac.cpp
parentSecond Life viewer sources 1.18.5.3 (diff)
downloadmeta-impy-b235c59d60472f818a9142c0886b95a0ff4191d7.zip
meta-impy-b235c59d60472f818a9142c0886b95a0ff4191d7.tar.gz
meta-impy-b235c59d60472f818a9142c0886b95a0ff4191d7.tar.bz2
meta-impy-b235c59d60472f818a9142c0886b95a0ff4191d7.tar.xz
Second Life viewer sources 1.18.6.0-RC
Diffstat (limited to 'linden/indra/mac_crash_logger/llcrashloggermac.cpp')
-rw-r--r--linden/indra/mac_crash_logger/llcrashloggermac.cpp342
1 files changed, 342 insertions, 0 deletions
diff --git a/linden/indra/mac_crash_logger/llcrashloggermac.cpp b/linden/indra/mac_crash_logger/llcrashloggermac.cpp
new file mode 100644
index 0000000..3d8abe5
--- /dev/null
+++ b/linden/indra/mac_crash_logger/llcrashloggermac.cpp
@@ -0,0 +1,342 @@
1/**
2 * @file llcrashloggermac.cpp
3 * @brief Mac OSX crash logger implementation
4 *
5 * $LicenseInfo:firstyear=2003&license=viewergpl$
6 *
7 * Copyright (c) 2003-2007, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception
21 *
22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above,
24 * and agree to abide by those obligations.
25 *
26 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
27 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
28 * COMPLETENESS OR PERFORMANCE.
29 * $/LicenseInfo$
30 */
31
32
33#include "llcrashloggermac.h"
34
35#include <Carbon/Carbon.h>
36#include <iostream>
37#include <sstream>
38
39#include "boost/tokenizer.hpp"
40
41#include "indra_constants.h" // CRASH_BEHAVIOR_ASK, CRASH_SETTING_NAME
42#include "llerror.h"
43#include "llfile.h"
44#include "lltimer.h"
45#include "llstring.h"
46#include "lldir.h"
47#include "llsdserialize.h"
48
49#define MAX_LOADSTRING 100
50const char* const SETTINGS_FILE_HEADER = "version";
51const S32 SETTINGS_FILE_VERSION = 101;
52
53// Windows Message Handlers
54
55BOOL gFirstDialog = TRUE; // Are we currently handling the Send/Don't Send dialog?
56FILE *gDebugFile = NULL;
57
58WindowRef gWindow = NULL;
59EventHandlerRef gEventHandler = NULL;
60LLString gUserNotes = "";
61bool gSendReport = false;
62bool gRememberChoice = false;
63IBNibRef nib = NULL;
64
65OSStatus dialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata)
66{
67 OSStatus result = eventNotHandledErr;
68 OSStatus err;
69 UInt32 evtClass = GetEventClass(event);
70 UInt32 evtKind = GetEventKind(event);
71 if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess))
72 {
73 HICommand cmd;
74 err = GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd);
75
76
77
78 if(err == noErr)
79 {
80 //Get the value of the checkbox
81 ControlID id;
82 ControlRef checkBox = NULL;
83 id.signature = 'remb';
84 id.id = 0;
85 err = GetControlByID(gWindow, &id, &checkBox);
86
87 if(err == noErr)
88 {
89 if(GetControl32BitValue(checkBox) == kControlCheckBoxCheckedValue)
90 {
91 gRememberChoice = true;
92 }
93 else
94 {
95 gRememberChoice = false;
96 }
97 }
98 switch(cmd.commandID)
99 {
100 case kHICommandOK:
101 {
102 char buffer[65535]; /* Flawfinder: ignore */
103 Size size = sizeof(buffer) - 1;
104 ControlRef textField = NULL;
105
106 id.signature = 'text';
107 id.id = 0;
108
109 err = GetControlByID(gWindow, &id, &textField);
110 if(err == noErr)
111 {
112 // Get the user response text
113 err = GetControlData(textField, kControlNoPart, kControlEditTextTextTag, size, (Ptr)buffer, &size);
114 }
115 if(err == noErr)
116 {
117 // Make sure the string is terminated.
118 buffer[size] = 0;
119 gUserNotes = buffer;
120
121 llinfos << buffer << llendl;
122 }
123
124 // Send the report.
125
126 QuitAppModalLoopForWindow(gWindow);
127 gSendReport = true;
128 result = noErr;
129 }
130 break;
131
132 case kHICommandCancel:
133 QuitAppModalLoopForWindow(gWindow);
134 result = noErr;
135 break;
136 }
137 }
138 }
139
140 return(result);
141}
142
143
144LLCrashLoggerMac::LLCrashLoggerMac(void)
145{
146}
147
148LLCrashLoggerMac::~LLCrashLoggerMac(void)
149{
150}
151
152bool LLCrashLoggerMac::init(void)
153{
154 bool ok = LLCrashLogger::init();
155 if(!ok) return false;
156 if(mCrashBehavior != CRASH_BEHAVIOR_ASK) return true;
157
158 // Real UI...
159 OSStatus err;
160
161 err = CreateNibReference(CFSTR("CrashReporter"), &nib);
162
163 if(err == noErr)
164 {
165 err = CreateWindowFromNib(nib, CFSTR("CrashReporter"), &gWindow);
166 }
167
168 if(err == noErr)
169 {
170 // Set focus to the edit text area
171 ControlRef textField = NULL;
172 ControlID id;
173
174 id.signature = 'text';
175 id.id = 0;
176
177 // Don't set err if any of this fails, since it's non-critical.
178 if(GetControlByID(gWindow, &id, &textField) == noErr)
179 {
180 SetKeyboardFocus(gWindow, textField, kControlFocusNextPart);
181 }
182 }
183
184 if(err == noErr)
185 {
186 ShowWindow(gWindow);
187 }
188
189 if(err == noErr)
190 {
191 // Set up an event handler for the window.
192 EventTypeSpec handlerEvents[] =
193 {
194 { kEventClassCommand, kEventCommandProcess }
195 };
196
197 InstallWindowEventHandler(
198 gWindow,
199 NewEventHandlerUPP(dialogHandler),
200 GetEventTypeCount (handlerEvents),
201 handlerEvents,
202 0,
203 &gEventHandler);
204 }
205 return true;
206}
207
208void LLCrashLoggerMac::gatherPlatformSpecificFiles()
209{
210 updateApplication("Gathering hardware information...");
211 char path[MAX_PATH];
212 FSRef folder;
213
214 if(FSFindFolder(kUserDomain, kLogsFolderType, false, &folder) == noErr)
215 {
216 // folder is an FSRef to ~/Library/Logs/
217 if(FSRefMakePath(&folder, (UInt8*)&path, sizeof(path)) == noErr)
218 {
219 struct stat dw_stat;
220 LLString mBuf;
221 bool isLeopard = false;
222 // Try the 10.3 path first...
223 LLString dw_file_name = LLString(path) + LLString("/CrashReporter/Second Life.crash.log");
224 int res = stat(dw_file_name.c_str(), &dw_stat);
225
226 if (res)
227 {
228 // Try the 10.2 one next...
229 dw_file_name = LLString(path) + LLString("/Second Life.crash.log");
230 res = stat(dw_file_name.c_str(), &dw_stat);
231 }
232
233 if(res)
234 {
235 //10.5: Like 10.3+, except it puts the crash time in the file instead of dividing it up
236 //using asterisks. Get a directory listing, search for files starting with second life,
237 //use the last one found.
238 LLString old_file_name, current_file_name, pathname, mask;
239 pathname = LLString(path) + LLString("/CrashReporter/");
240 mask = "Second Life*";
241 while(gDirUtilp->getNextFileInDir(pathname, mask, current_file_name, false))
242 {
243 old_file_name = current_file_name;
244 }
245 if(old_file_name != "")
246 {
247 dw_file_name = pathname + old_file_name;
248 res=stat(dw_file_name.c_str(), &dw_stat);
249 isLeopard = true;
250 }
251 }
252
253 if (!res)
254 {
255 std::ifstream fp(dw_file_name.c_str());
256 std::stringstream str;
257 if(!fp.is_open()) return;
258 str << fp.rdbuf();
259 mBuf = str.str();
260
261 if(!isLeopard)
262 {
263 // Crash logs consist of a number of entries, one per crash.
264 // Each entry is preceeded by "**********" on a line by itself.
265 // We want only the most recent (i.e. last) one.
266 const char *sep = "**********";
267 const char *start = mBuf.c_str();
268 const char *cur = start;
269 const char *temp = strstr(cur, sep);
270
271 while(temp != NULL)
272 {
273 // Skip past the marker we just found
274 cur = temp + strlen(sep); /* Flawfinder: ignore */
275
276 // and try to find another
277 temp = strstr(cur, sep);
278 }
279
280 // If there's more than one entry in the log file, strip all but the last one.
281 if(cur != start)
282 {
283 mBuf.erase(0, cur - start);
284 }
285 }
286 mCrashInfo["CrashLog"] = mBuf;
287 }
288 else
289 {
290 llwarns << "Couldn't find any CrashReporter files..." << llendl;
291 }
292 }
293 }
294}
295
296bool LLCrashLoggerMac::mainLoop()
297{
298 OSStatus err = noErr;
299
300 if(err == noErr && mCrashBehavior == CRASH_BEHAVIOR_ASK)
301 {
302 RunAppModalLoopForWindow(gWindow);
303 }
304 else if (mCrashBehavior == CRASH_BEHAVIOR_ALWAYS_SEND)
305 {
306 gSendReport = true;
307 }
308
309 if(gRememberChoice)
310 {
311 if(gSendReport) saveCrashBehaviorSetting(CRASH_BEHAVIOR_ALWAYS_SEND);
312 else saveCrashBehaviorSetting(CRASH_BEHAVIOR_NEVER_SEND);
313 }
314
315 if(gSendReport)
316 {
317 setUserText(gUserNotes);
318 sendCrashLogs();
319 }
320
321 if(gWindow != NULL)
322 {
323 DisposeWindow(gWindow);
324 }
325
326 if(nib != NULL)
327 {
328 DisposeNibReference(nib);
329 }
330
331 return true;
332}
333
334void LLCrashLoggerMac::updateApplication(LLString message)
335{
336 LLCrashLogger::updateApplication();
337}
338
339bool LLCrashLoggerMac::cleanup()
340{
341 return true;
342}