From 2e7c0d973ed28d732ea19762099ed3c55123780e Mon Sep 17 00:00:00 2001
From: Kyle Machulis <qdot@lindenlab.com>
Date: Tue, 20 Nov 2007 23:42:48 +0000
Subject: svn merge -r74104:74124
 svn+ssh://svn/svn/linden/branches/crash-logger-cleanup-merge-6

---
 indra/linux_crash_logger/linux_crash_logger.cpp | 538 +-----------------------
 1 file changed, 6 insertions(+), 532 deletions(-)

(limited to 'indra/linux_crash_logger/linux_crash_logger.cpp')

diff --git a/indra/linux_crash_logger/linux_crash_logger.cpp b/indra/linux_crash_logger/linux_crash_logger.cpp
index a49dfe1b2b..5310093f69 100644
--- a/indra/linux_crash_logger/linux_crash_logger.cpp
+++ b/indra/linux_crash_logger/linux_crash_logger.cpp
@@ -29,542 +29,16 @@
  * $/LicenseInfo$
  */
 
-#include "linden_common.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <curl/curl.h>
-
-#if LL_GTK
-# include "gtk/gtk.h"
-#endif // LL_GTK
-
-#include "indra_constants.h"	// CRASH_BEHAVIOR_ASK
-#include "llerror.h"
-#include "lltimer.h"
-#include "lldir.h"
-
-#include "llstring.h"
-
-
-// These need to be localized.
-static const char dialog_text[] =
-"Second Life appears to have crashed.\n"
-"This crash reporter collects information about your computer's hardware, operating system, and some Second Life logs, which are used for debugging purposes only.\n"
-"Sending crash reports is the best way to help us improve the quality of Second Life.\n"
-"If you continue to experience this problem, please try:\n"
-"- Contacting support by visiting http://www.secondlife.com/support\n"
-"\n"
-"Send crash report?";
-
-static const char dialog_title[] =
-"Second Life Crash Logger";
-
-
-class LLFileEncoder
-{
-public:
-	LLFileEncoder(const char *formname, const char *filename, bool isCrashLog = false);
-
-	BOOL isValid() const { return mIsValid; }
-	LLString encodeURL(const S32 max_length = 0);
-public:
-	BOOL mIsValid;
-	LLString mFilename;
-	LLString mFormname;
-	LLString mBuf;
-};
-
-LLString encode_string(const char *formname, const LLString &str);
-
-LLString gServerResponse;
-BOOL gSendReport = FALSE;
-LLString gUserserver;
-LLString gUserText;
-BOOL gCrashInPreviousExec = FALSE;
-time_t gLaunchTime;
-
-static size_t curl_download_callback(void *data, size_t size, size_t nmemb,
-				     void *user_data)
-{
-	S32 bytes = size * nmemb;
-	char *cdata = (char *) data;
-	for (int i =0; i < bytes; i += 1)
-	{
-		gServerResponse += (cdata[i]);
-	}
-	return bytes;
-}
-
-#if LL_GTK
-static void response_callback (GtkDialog *dialog,
-			       gint       arg1,
-			       gpointer   user_data)
-{
-	gint *response = (gint*)user_data;
-	*response = arg1;
-	gtk_widget_destroy(GTK_WIDGET(dialog));
-	gtk_main_quit();
-}
-#endif // LL_GTK
-
-static BOOL do_ask_dialog(void)
-{
-#if LL_GTK
-	gtk_disable_setlocale();
-	if (!gtk_init_check(NULL, NULL)) {
-		llinfos << "Could not initialize GTK for 'ask to send crash report' dialog; not sending report." << llendl;
-		return FALSE;
-	}
-	
-	GtkWidget *win = NULL;
-	GtkDialogFlags flags = GTK_DIALOG_MODAL;
-	GtkMessageType messagetype = GTK_MESSAGE_QUESTION;
-	GtkButtonsType buttons = GTK_BUTTONS_YES_NO;
-	gint response = GTK_RESPONSE_NONE;
-
-	win = gtk_message_dialog_new(NULL,
-				     flags, messagetype, buttons,
-				     dialog_text);
-	gtk_window_set_type_hint(GTK_WINDOW(win),
-				 GDK_WINDOW_TYPE_HINT_DIALOG);
-	gtk_window_set_title(GTK_WINDOW(win), dialog_title);
-	g_signal_connect (win,
-			  "response", 
-			  G_CALLBACK (response_callback),
-			  &response);
-	gtk_widget_show_all (win);
-	gtk_main();
-
-	return (GTK_RESPONSE_OK == response ||
-		GTK_RESPONSE_YES == response ||
-		GTK_RESPONSE_APPLY == response);
-#else
-	return FALSE;
-#endif // LL_GTK
-}
-
+#include "llcrashloggerlinux.h"
 
 int main(int argc, char **argv)
 {
-	const S32 BT_MAX_SIZE = 100000;			// Maximum size to transmit of the backtrace file
-	const S32 SL_MAX_SIZE = 100000;			// Maximum size of the Second Life log file.
-	int i;
-	S32 crash_behavior = CRASH_BEHAVIOR_ALWAYS_SEND;
-	
-	time(&gLaunchTime);
-	
-	llinfos << "Starting Second Life Viewer Crash Reporter" << llendl;
-	
-	for(i=1; i<argc; i++)
-	{
-		if(!strcmp(argv[i], "-dialog"))
-		{
-			llinfos << "Show the user dialog" << llendl;
-			crash_behavior = CRASH_BEHAVIOR_ASK;
-		}
-		if(!strcmp(argv[i], "-previous"))
-		{
-			gCrashInPreviousExec = TRUE;
-		}
-		if(!strcmp(argv[i], "-user"))
-		{
-			if ((i + 1) < argc)
-			{
-				i++;
-				gUserserver = argv[i];
-				llinfos << "Got userserver " << gUserserver << llendl;
-			}
-		}
-	}
-	
-	if( gCrashInPreviousExec )
-	{
-		llinfos << "Previous execution did not remove SecondLife.exec_marker" << llendl;
-	}
-	
-	if(!gCrashInPreviousExec)
-	{
-		// Wait a while to let the crashed client finish exiting,
-		// freeing up the screen/etc.
-		sleep(5);
-	}
-
-	// *FIX: do some dialog stuff here?
-	if (CRASH_BEHAVIOR_ALWAYS_SEND == crash_behavior)
-	{
-		gSendReport = TRUE;
-	}
-	else if (CRASH_BEHAVIOR_ASK == crash_behavior)
-	{
-		gSendReport = do_ask_dialog();
-	}
-	
-	if(!gSendReport)
-	{
-		// Only send the report if the user agreed to it.
-		llinfos << "User cancelled, not sending report" << llendl;
-
-		return(0);
-	}
-
-	// We assume that all the logs we're looking for reside on the current drive
-	gDirUtilp->initAppDirs("SecondLife");
-
-	// Lots of silly variable, replicated for each log file.
-	LLString db_file_name;
-	LLString sl_file_name;
-	LLString bt_file_name; // stack_trace.log file
-	LLString st_file_name; // stats.log file
-	LLString si_file_name; // settings.xml file
-
-	LLFileEncoder *db_filep = NULL;
-	LLFileEncoder *sl_filep = NULL;
-	LLFileEncoder *st_filep = NULL;
-	LLFileEncoder *bt_filep = NULL;
-	LLFileEncoder *si_filep = NULL;
-
-	///////////////////////////////////
-	//
-	// We do the parsing for the debug_info file first, as that will
-	// give us the location of the SecondLife.log file.
-	//
-
-	// Figure out the filename of the debug log
-	db_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"debug_info.log").c_str();
-	db_filep = new LLFileEncoder("DB", db_file_name.c_str());
-
-	// Get the filename of the SecondLife.log file
-	// *NOTE: These buffer sizes are hardcoded into a scanf() below.
-	char tmp_sl_name[LL_MAX_PATH];
-	tmp_sl_name[0] = '\0';
-	char tmp_space[256];
-	tmp_space[0] = '\0';
-
-	// Look for it in the debug_info.log file
-	if (db_filep->isValid())
-	{
-		// This was originally scanning for "SL Log: %[^\r\n]", which happily skipped to the next line
-		// on debug logs (which don't have anything after "SL Log:" and tried to open a nonsensical filename.
-		sscanf(db_filep->mBuf.c_str(), "SL Log:%255[ ]%1023[^\r\n]", tmp_space, tmp_sl_name);
-	}
-	else
-	{
-		delete db_filep;
-		db_filep = NULL;
-	}
-
-	// If we actually have a legitimate file name, use it.
-	if (gCrashInPreviousExec)
-	{
-		// If we froze, the crash log this time around isn't useful.
-		// Use the old one.
-		sl_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.old");
-	}
-	else if (tmp_sl_name[0])
-	{
-		sl_file_name = tmp_sl_name;
-		llinfos << "Using log file from debug log: " << sl_file_name << llendl;
-	}
-	else
-	{
-		// Figure out the filename of the second life log
-		sl_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.log").c_str();
-	}
-
-	// Now we get the SecondLife.log file if it's there, and recent enough...
-	sl_filep = new LLFileEncoder("SL", sl_file_name.c_str());
-	if (!sl_filep->isValid())
-	{
-		delete sl_filep;
-		sl_filep = NULL;
-	}
-
-	st_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stats.log").c_str();
-	st_filep = new LLFileEncoder("ST", st_file_name.c_str());
-	if (!st_filep->isValid())
-	{
-		delete st_filep;
-		st_filep = NULL;
-	}
-
-	si_file_name = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"settings.xml").c_str();
-	si_filep = new LLFileEncoder("SI", si_file_name.c_str());
-	if (!si_filep->isValid())
-	{
-		delete si_filep;
-		si_filep = NULL;
-	}
-
-	// encode this as if it were a 'Dr Watson' plain-text backtrace
-	bt_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log").c_str();
-	bt_filep = new LLFileEncoder("DW", bt_file_name.c_str());
-	if (!bt_filep->isValid())
-	{
-		delete bt_filep;
-		bt_filep = NULL;
-	}
-
-	LLString post_data;
-	LLString tmp_url_buf;
-
-	// Append the userserver
-	tmp_url_buf = encode_string("USER", gUserserver);
-	post_data += tmp_url_buf;
-	llinfos << "PostData:" << post_data << llendl;
-
-	if (gCrashInPreviousExec)
-	{
-		post_data.append("&");
-		tmp_url_buf = encode_string("EF", "Y");
-		post_data += tmp_url_buf;
-	}
-
-	if (db_filep)
-	{
-		post_data.append("&");
-		tmp_url_buf = db_filep->encodeURL();
-		post_data += tmp_url_buf;
-		llinfos << "Sending DB log file" << llendl;
-	}
-	else
-	{
-		llinfos << "Not sending DB log file" << llendl;
-	}
-
-	if (sl_filep)
-	{
-		post_data.append("&");
-		tmp_url_buf = sl_filep->encodeURL(SL_MAX_SIZE);
-		post_data += tmp_url_buf;
-		llinfos << "Sending SL log file" << llendl;
-	}
-	else
-	{
-		llinfos << "Not sending SL log file" << llendl;
-	}
-
-	if (st_filep)
-	{
-		post_data.append("&");
-		tmp_url_buf = st_filep->encodeURL(SL_MAX_SIZE);
-		post_data += tmp_url_buf;
-		llinfos << "Sending stats log file" << llendl;
-	}
-	else
-	{
-		llinfos << "Not sending stats log file" << llendl;
-	}
-
-	if (bt_filep)
-	{
-		post_data.append("&");
-		tmp_url_buf = bt_filep->encodeURL(BT_MAX_SIZE);
-		post_data += tmp_url_buf;
-		llinfos << "Sending crash log file" << llendl;
-	}
-	else
-	{
-		llinfos << "Not sending crash log file" << llendl;
-	}
-
-	if (si_filep)
-	{
-		post_data.append("&");
-		tmp_url_buf = si_filep->encodeURL();
-		post_data += tmp_url_buf;
-		llinfos << "Sending settings log file" << llendl;
-	}
-	else
-	{
-		llinfos << "Not sending settings.xml file" << llendl;
-	}
-
-	if (gUserText.size())
-	{
-		post_data.append("&");
-		tmp_url_buf = encode_string("UN", gUserText);
-		post_data += tmp_url_buf;
-	}
-
-	delete db_filep;
-	db_filep = NULL;
-	delete sl_filep;
-	sl_filep = NULL;
-	delete bt_filep;
-	bt_filep = NULL;
-
-	// Debugging spam
-#if 0
-	printf("Crash report post data:\n--------\n");
-	printf("%s", post_data.getString());
-	printf("\n--------\n");
-#endif
-	
-	// Send the report.  Yes, it's this easy.
-	{
-		CURL *curl = curl_easy_init();
-
-		curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
-		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &curl_download_callback);
-		curl_easy_setopt(curl, CURLOPT_POST, 1); 
-		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data.c_str()); 
-		curl_easy_setopt(curl, CURLOPT_URL,	"http://secondlife.com/cgi-bin/viewer_crash_reporter2");
-		
-		llinfos << "Connecting to crash report server" << llendl;
-		CURLcode result = curl_easy_perform(curl);
-		
-		curl_easy_cleanup(curl);
-		
-		if(result != CURLE_OK)
-		{
-			llinfos << "Couldn't talk to crash report server" << llendl;
-		}
-		else
-		{
-			llinfos << "Response from crash report server:" << llendl;
-			llinfos << gServerResponse << llendl;			
-		}
-	}
-	
+	LLCrashLoggerLinux app;
+	app.parseCommandOptions(argc, argv);
+	app.init();
+	app.mainLoop();
+	app.cleanup();
 	return 0;
 }
 
-LLFileEncoder::LLFileEncoder(const char *form_name, const char *filename, bool isCrashLog)
-{
-	mFormname = form_name;
-	mFilename = filename;
-	mIsValid = FALSE;
-
-	int res;
-	
-	struct stat stat_data;
-	res = stat(mFilename.c_str(), &stat_data);
-	if (res)
-	{
-		llwarns << "File " << mFilename << " is missing!" << llendl;
-		return;
-	}
-	else
-	{
-		// Debugging spam
-//		llinfos << "File " << mFilename << " is present..." << llendl;
-
-		if(!gCrashInPreviousExec && isCrashLog)
-		{
-			// Make sure the file isn't too old.
-			double age = difftime(gLaunchTime, stat_data.st_mtim.tv_sec);
-
-//			llinfos << "age is " << age << llendl;
 
-			if(age > 60.0)
-			{
-				// The file was last modified more than 60 seconds before the crash reporter was launched.  Assume it's stale.
-				llwarns << "File " << mFilename << " is too old!" << llendl;
-				return;
-			}
-		}
-
-	}
-
-	S32 buf_size = stat_data.st_size;
-	FILE *fp = fopen(mFilename.c_str(), "rb");
-	U8 *buf = new U8[buf_size + 1];
-	size_t nread = fread(buf, 1, buf_size, fp);
-	fclose(fp);
-	buf[nread] = 0;
-
-	mBuf = (char *)buf;
-	
-	if(isCrashLog)
-	{
-		// Crash logs consist of a number of entries, one per crash.
-		// Each entry is preceeded by "**********" on a line by itself.
-		// We want only the most recent (i.e. last) one.
-		const char *sep = "**********";
-		const char *start = mBuf.c_str();
-		const char *cur = start;
-		const char *temp = strstr(cur, sep);
-		
-		while(temp != NULL)
-		{
-			// Skip past the marker we just found
-			cur = temp + strlen(sep);
-			
-			// and try to find another
-			temp = strstr(cur, sep);
-		}
-		
-		// If there's more than one entry in the log file, strip all but the last one.
-		if(cur != start)
-		{
-			mBuf.erase(0, cur - start);
-		}
-	}
-
-	mIsValid = TRUE;
-	delete[] buf;
-}
-
-LLString LLFileEncoder::encodeURL(const S32 max_length)
-{
-	LLString result = mFormname;
-	result.append("=");
-
-	S32 i = 0;
-
-	if (max_length)
-	{
-		if ((S32)mBuf.size() > max_length)
-		{
-			i = mBuf.size() - max_length;
-		}
-	}
-
-#if 0
-	// Plain text version for debugging
-	result.append(mBuf);
-#else
-	// Not using LLString because of bad performance issues
-	S32 buf_size = mBuf.size();
-	S32 url_buf_size = 3*mBuf.size() + 1;
-	char *url_buf = new char[url_buf_size];
-
-	S32 cur_pos = 0;
-	for (; i < buf_size; i++)
-	{
-		sprintf(url_buf + cur_pos, "%%%02x", mBuf[i]);
-		cur_pos += 3;
-	}
-	url_buf[i*3] = 0;
-
-	result.append(url_buf);
-	delete[] url_buf;
-#endif
-	return result;
-}
-
-LLString encode_string(const char *formname, const LLString &str)
-{
-	LLString result = formname;
-	result.append("=");
-	// Not using LLString because of bad performance issues
-	S32 buf_size = str.size();
-	S32 url_buf_size = 3*str.size() + 1;
-	char *url_buf = new char[url_buf_size];
-
-	S32 cur_pos = 0;
-	S32 i;
-	for (i = 0; i < buf_size; i++)
-	{
-		sprintf(url_buf + cur_pos, "%%%02x", str[i]);
-		cur_pos += 3;
-	}
-	url_buf[i*3] = 0;
-
-	result.append(url_buf);
-	delete[] url_buf;
-	return result;
-}
-- 
cgit v1.2.3