diff options
Diffstat (limited to 'crashrep/source/unx/main.cxx')
-rwxr-xr-x | crashrep/source/unx/main.cxx | 1122 |
1 files changed, 1122 insertions, 0 deletions
diff --git a/crashrep/source/unx/main.cxx b/crashrep/source/unx/main.cxx new file mode 100755 index 000000000000..7579de78ec94 --- /dev/null +++ b/crashrep/source/unx/main.cxx @@ -0,0 +1,1122 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include <cstdio> +#include <stdlib.h> +#include <sys/utsname.h> +#include <_version.h> +#include <errno.h> +#include <string> +#include <string.h> +#include <assert.h> + +#include <sys/socket.h> +#include <netdb.h> +#include <unistd.h> +#include <pwd.h> +#include <pthread.h> +#include <limits.h> + +#include <hash_map> +#include <vector> +#include <string> + +#if defined (LINUX) || (FREEBSD) +#include <netinet/in.h> +#endif + +typedef int SOCKET; + +#define closesocket close +#define SOCKET_ERROR -1 + +#ifdef SOLARIS +const char *basename( const char *filename ) +{ + const char *pSlash = strrchr( filename, '/' ); + + return pSlash ? pSlash + 1 : pSlash; +} +#endif + +using namespace std; + +static bool g_bNoUI = false; +static bool g_bSendReport = false; +static bool g_bLoadReport = false; + +static bool g_bDebugMode = false; +static int g_signal = 0; + +static string g_strProductKey; +static string g_strReportServer; +static unsigned short g_uReportPort = 80; +static string g_buildid; +static string g_strDefaultLanguage; +static string g_strXMLFileName; +static string g_strPStackFileName; +static string g_strChecksumFileName; +static string g_strProgramDir; + +static char g_szStackFile[L_tmpnam] = ""; +static char g_szDescriptionFile[2048] = ""; +static char g_szReportFile[2048] = ""; + +#define SO_CRASHREPORT_MAIL "so-report@sun.com" +#define PSTACK_CMD "pstack %d" + +#ifdef LINUX +#define PMAP_CMD "cat /proc/%d/maps" +#else +#define PMAP_CMD "pmap %d" +#endif + +#define REPORT_SERVER (g_strReportServer.c_str()) +#define REPORT_PORT g_uReportPort + +static string getprogramdir() +{ + return g_strProgramDir; +} + +static const char *getlocale() +{ + const char * locale = getenv( "LC_ALL" ); + + if( NULL == locale ) + locale = getenv( "LC_CTYPE" ); + + if( NULL == locale ) + locale = getenv( "LANG" ); + + if( NULL == locale ) + locale = "C"; + + return locale; +} + +static const char *get_home_dir() +{ + struct passwd *ppwd = getpwuid( getuid() ); + + return ppwd ? (ppwd->pw_dir ? ppwd->pw_dir : "/") : "/"; +} + +static string trim_string( const string& rString ) +{ + string temp = rString; + + while ( temp.length() && (temp[0] == ' ' || temp[0] == '\t') ) + temp.erase( 0, 1 ); + + string::size_type len = temp.length(); + + while ( len && (temp[len-1] == ' ' || temp[len-1] == '\t') ) + { + temp.erase( len - 1, 1 ); + len = temp.length(); + } + + return temp; +} + +static string xml_encode( const string &rString ) +{ + string temp = rString; + string::size_type pos = 0; + + // First replace all occurences of '&' because it may occur in further + // encoded chardters too + + for( pos = 0; (pos = temp.find( '&', pos )) != string::npos; pos += 4 ) + temp.replace( pos, 1, "&" ); + + for( pos = 0; (pos = temp.find( '<', pos )) != string::npos; pos += 4 ) + temp.replace( pos, 1, "<" ); + + for( pos = 0; (pos = temp.find( '>', pos )) != string::npos; pos += 4 ) + temp.replace( pos, 1, ">" ); + + return temp; +} + +static size_t fcopy( FILE *fpout, FILE *fpin ) +{ + char buffer[1024]; + size_t nBytes; + size_t nBytesWritten = 0; + + while ( 0 != (nBytes = fread( buffer, 1, sizeof(buffer), fpin )) ) + { + nBytesWritten += fwrite( buffer, 1, nBytes, fpout ); + } + + return nBytesWritten; +} + +/* + writes the report to a temp-file + from which it can be reviewed and sent +*/ + +bool write_report( const hash_map< string, string >& rSettings ) +{ + FILE *fp = fopen( tmpnam( g_szReportFile ), "w" ); + const char *pszUserType = getenv( "STAROFFICE_USERTYPE" ); + + fprintf( fp, + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<!DOCTYPE errormail:errormail PUBLIC \"-//OpenOffice.org//DTD ErrorMail 1.0//EN\" \"errormail.dtd\">\n" + "<errormail:errormail xmlns:errormail=\"http://openoffice.org/2002/errormail\" usertype=\"%s\">\n" + "<reportmail:mail xmlns:reportmail=\"http://openoffice.org/2002/reportmail\" version=\"1.1\" feedback=\"%s\" email=\"%s\">\n" + "<reportmail:title>%s</reportmail:title>\n" + "<reportmail:attachment name=\"description.txt\" media-type=\"text/plain\" class=\"UserComment\"/>\n" + "<reportmail:attachment name=\"stack.txt\" media-type=\"text/plain\" class=\"pstack output\"/>\n" + "</reportmail:mail>\n" + "<officeinfo:officeinfo xmlns:officeinfo=\"http://openoffice.org/2002/officeinfo\" build=\"%s\" platform=\"%s\" language=\"%s\" exceptiontype=\"%d\" product=\"%s\" procpath=\"%s\"/>\n" + , + pszUserType ? xml_encode( pszUserType ).c_str() : "", + xml_encode(rSettings.find( "CONTACT" )->second).c_str(), + xml_encode(rSettings.find( "EMAIL" )->second).c_str(), + xml_encode(rSettings.find( "TITLE" )->second).c_str(), + g_buildid.length() ? xml_encode( g_buildid ).c_str() : "unknown", + _INPATH, + g_strDefaultLanguage.c_str(), + g_signal, + g_strProductKey.length() ? xml_encode(g_strProductKey).c_str() : "unknown", + xml_encode(getprogramdir()).c_str() + ); + + struct utsname info; + + memset( &info, 0, sizeof(info) ); + uname( &info ); + + fprintf( fp, + "<systeminfo:systeminfo xmlns:systeminfo=\"http://openoffice.org/2002/systeminfo\">\n" + "<systeminfo:System name=\"%s\" version=\"%s\" build=\"%s\" locale=\"%s\"/>\n" + , + xml_encode( info.sysname ).c_str(), + xml_encode( info.version ).c_str(), + xml_encode( info.release ).c_str(), + xml_encode( getlocale() ).c_str() + ); + fprintf( fp, "<systeminfo:CPU type=\"%s\"/>\n", xml_encode( info.machine ).c_str() ); + fprintf( fp, "</systeminfo:systeminfo>\n" ); + + FILE *fpxml = fopen( g_strXMLFileName.c_str(), "r" ); + if ( fpxml ) + { + fcopy( fp, fpxml ); + fclose( fpxml ); + } + + FILE *fpchk = fopen( g_strChecksumFileName.c_str(), "r" ); + if ( fpchk ) + { + fcopy( fp, fpchk ); + fclose( fpchk ); + } + + fprintf( fp, "</errormail:errormail>\n" ); + + fclose( fp ); + + return true; +} + + +bool write_description( const hash_map< string, string >& rSettings ) +{ + bool bSuccess = false; + FILE *fp = fopen( tmpnam( g_szDescriptionFile ), "w" ); + + if ( fp ) + { + bSuccess = true; + fprintf( fp, "\xEF\xBB\xBF" ); + fprintf( fp, "%s\n", rSettings.find( "DESCRIPTION" )->second.c_str() ); + fclose( fp ); + } + + return bSuccess; +} + +#if 0 +// unused +static void printSettings( const hash_map<string,string>& rSettings ) +{ + printf( "Settings:\n" ); + for( hash_map<string,string>::const_iterator it = rSettings.begin(); it != rSettings.end(); ++it ) + { + printf( "%s=\"%s\"\n", it->first.c_str(), it->second.c_str() ); + } +} +#endif + +bool save_crash_report( const string& rFileName, const hash_map< string, string >& /*rSettings*/ ) +{ + bool bSuccess = false; + FILE *fpout = fopen( rFileName.c_str(), "w" ); + + if ( fpout ) + { + FILE *fpin = fopen( g_szStackFile, "r" ); + + if ( fpin ) + { + char buf[1024]; + + while (fgets(buf, sizeof(buf), fpin) != NULL) + { + fputs(buf, fpout); + } + + bSuccess = true; + + fclose ( fpin ); + } + + fclose( fpout ); + } + + return bSuccess; +} + +bool SendHTTPRequest( + FILE *fp, + const char *pszServer, + unsigned short uPort = 80, + const char *pszProxyServer = NULL, + unsigned short uProxyPort = 8080 ) +{ + bool success = false; + + struct hostent *hp; + + if ( pszProxyServer ) + hp = gethostbyname( pszProxyServer ); + else + hp = gethostbyname( pszServer ); + + if ( hp ) + { + SOCKET s = socket( AF_INET, SOCK_STREAM, 0 ); + + if ( s ) + { + struct sockaddr_in address; + + memcpy(&(address.sin_addr.s_addr), *(hp->h_addr_list),sizeof(struct in_addr)); + address.sin_family = AF_INET; + + if ( pszProxyServer ) + address.sin_port = ntohs( uProxyPort ); + else + address.sin_port = ntohs( uPort ); + + if ( 0 == connect( s, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) ) + { + fseek( fp, 0, SEEK_END ); + size_t length = ftell( fp ); + fseek( fp, 0, SEEK_SET ); + + char buffer[2048]; + + if ( pszProxyServer ) + sprintf( buffer, + "POST http://%s:%d/soap/servlet/rpcrouter HTTP/1.0\r\n" + "Content-Type: text/xml; charset=\"utf-8\"\r\n" + "Content-Length: %d\r\n" + "SOAPAction: \"\"\r\n\r\n", + pszServer, + uPort, + static_cast<int>(length) + ); + else + sprintf( buffer, + "POST /soap/servlet/rpcrouter HTTP/1.0\r\n" + "Content-Type: text/xml; charset=\"utf-8\"\r\n" + "Content-Length: %d\r\n" + "SOAPAction: \"\"\r\n\r\n", + static_cast<int>(length) + ); + + if ( g_bDebugMode ) + { + printf( "*** Sending HTTP request ***\n\n" ); + printf( buffer ); + } + + if ( SOCKET_ERROR != send( s, buffer, strlen(buffer), 0 ) ) + { + size_t nBytes; + + do + { + nBytes = fread( buffer, 1, sizeof(buffer), fp ); + + if ( nBytes ) + { + if ( g_bDebugMode ) + fwrite( buffer, 1, nBytes, stdout ); + success = SOCKET_ERROR != send( s, buffer, nBytes, 0 ); + } + } while( nBytes && success ); + + if ( success ) + { + if ( g_bDebugMode ) + printf( "*** Receiving HTTP response ***\n\n" ); + + memset( buffer, 0, sizeof(buffer) ); + success = SOCKET_ERROR != recv( s, buffer, sizeof(buffer), 0 ); + if ( success ) + { + char szHTTPSignature[sizeof(buffer)] = ""; + unsigned uHTTPReturnCode = 0; + + sscanf( buffer, "%s %d ", szHTTPSignature, &uHTTPReturnCode ); + success = uHTTPReturnCode == 200; + } + if ( g_bDebugMode ) + do + { + printf( buffer ); + memset( buffer, 0, sizeof(buffer) ); + } while ( 0 < recv( s, buffer, sizeof(buffer), 0 ) ); + } + } + + } + + closesocket( s ); + } + } + + return success; +} + +static void WriteSOAPRequest( FILE *fp ) +{ + fprintf( fp, + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" + "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"\n" + "xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\"\n" + "xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"\n" + "xmlns:rds=\"urn:ReportDataService\"\n" + "xmlns:apache=\"http://xml.apache.org/xml-soap\"\n" + "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" + "<SOAP-ENV:Body>\n" + ); + + fprintf( fp, "<rds:submitReport>\n" ); + fprintf( fp, "<body xsi:type=\"xsd:string\">This is an autogenerated crash report mail.</body>\n" ); + fprintf( fp, "<hash xsi:type=\"apache:Map\">\n" ); + + FILE *fpin = fopen( g_szReportFile, "r" ); + if ( fpin ) + { + fprintf( fp, + "<item>\n" + "<key xsi:type=\"xsd:string\">reportmail.xml</key>\n" + "<value xsi:type=\"xsd:string\"><![CDATA[" ); + fcopy( fp, fpin ); + fprintf( fp, "]]></value></item>\n" ); + fclose( fpin ); + } + + fpin = fopen( g_szDescriptionFile, "r" ); + if ( fpin ) + { + fprintf( fp, + "<item>\n" + "<key xsi:type=\"xsd:string\">description.txt</key>\n" + "<value xsi:type=\"xsd:string\"><![CDATA[" ); + fcopy( fp, fpin ); + fprintf( fp, "]]></value></item>\n" ); + fclose( fpin ); + }; + + fpin = fopen( g_szStackFile, "r" ); + if ( fpin ) + { + fprintf( fp, + "<item>\n" + "<key xsi:type=\"xsd:string\">stack.txt</key>\n" + "<value xsi:type=\"xsd:string\"><![CDATA[" ); + fcopy( fp, fpin ); + fprintf( fp, "]]></value></item>\n" ); + fclose( fpin ); + }; + + fprintf( fp, + "</hash>\n" + "</rds:submitReport>\n" + "</SOAP-ENV:Body>\n" + "</SOAP-ENV:Envelope>\n" + ); +} + +struct RequestParams +{ + bool success; + FILE *fpin; + const char *pServer; + unsigned short uPort; + const char *pProxyServer; + unsigned short uProxyPort; +}; + + +bool send_crash_report( const hash_map< string, string >& rSettings ) +{ + if ( 0 == strcasecmp( rSettings.find( "CONTACT" )->second.c_str(), "true" ) && + !trim_string(rSettings.find( "EMAIL" )->second).length() ) + { + return false; + } + + char *endptr = NULL; + + const char *pProxyServer = rSettings.find( "SERVER" )->second.c_str(); + unsigned short uProxyPort = (unsigned short)strtoul( rSettings.find( "PORT" )->second.c_str(), &endptr, 10 ); + + bool bUseProxy = !strcasecmp( "true", rSettings.find( "USEPROXY" )->second.c_str() ); + + + write_description( rSettings ); + write_report( rSettings ); + + bool bSuccess = false; + + FILE *fptemp = tmpfile(); + if ( fptemp ) + { + WriteSOAPRequest( fptemp ); + fseek( fptemp, 0, SEEK_SET ); + + bSuccess = SendHTTPRequest( + fptemp, + REPORT_SERVER, REPORT_PORT, + bUseProxy ? pProxyServer : NULL, + uProxyPort ? uProxyPort : 8080 + ); + + fclose( fptemp ); + + } + + unlink( g_szDescriptionFile ); + unlink( g_szReportFile ); + + return bSuccess; +} + + +static bool append_file( const char *filename, string& rString ) +{ + char buf[1024]; + bool bSuccess = false; + + FILE *fp = fopen( filename, "r" ); + if ( fp ) + { + bSuccess = true; + while (fgets(buf, sizeof(buf), fp) != NULL) + { + rString.append( buf ); + } + fclose( fp ); + } + + return true; +} + +string crash_get_details( const hash_map< string, string >& rSettings ) +{ + string aRet; + + write_description( rSettings ); + write_report( rSettings ); + + aRet.append( rSettings.find( "TITLE" )->second.c_str() ); + aRet.append( "\n\n" ); + append_file( g_szDescriptionFile, aRet ); + aRet.append( "\n\n-------\n\n" ); + append_file( g_szReportFile, aRet ); + aRet.append( "\n\n-------\n\n" ); + append_file( g_szStackFile, aRet ); + + unlink( g_szDescriptionFile ); + unlink( g_szReportFile ); + + return aRet; +} + + +// ensure validity of program relative paths +static void setup_program_dir( const char* progname ) +{ + char szCanonicProgPath[PATH_MAX]; + + + if ( realpath( progname, szCanonicProgPath ) ) + { + string aDir = szCanonicProgPath; + + size_t pos = aDir.rfind( '/' ); + // FIXME: search PATH if necessary + assert( pos != string::npos ); + + g_strProgramDir = aDir.substr( 0, pos + 1 ); + aDir.erase( pos ); + chdir( aDir.c_str() ); + } +} + +//************************************************************************* + +static long setup_commandline_arguments( int argc, char** argv, int *pSignal ) +{ + long pid = 0; + int signal = 0; + + for ( int n = 1; n < argc; n++ ) + { + if ( 0 == strcmp( argv[n], "-p" ) ) + { + if ( ++n < argc ) + pid = strtol( argv[n], NULL, 0 ); + } + else if ( 0 == strcmp( argv[n], "-s" ) ) + { + if ( ++n < argc ) + signal = strtol( argv[n], NULL, 0 ); + } + else if ( 0 == strcmp( argv[n], "-debug" ) ) + { + g_bDebugMode = true; + } + else if ( 0 == strcmp( argv[n], "-xml" ) ) + { + if ( ++n < argc ) + g_strXMLFileName = argv[n]; + } + else if ( 0 == strcmp( argv[n], "-stack" ) ) + { + if ( ++n < argc ) + g_strPStackFileName = argv[n]; + } + else if ( 0 == strcmp( argv[n], "-chksum" ) ) + { + if ( ++n < argc ) + g_strChecksumFileName = argv[n]; + } + else if ( 0 == strcmp( argv[n], "-noui" ) ) + { + g_bNoUI = true; + } + else if ( 0 == strcmp( argv[n], "-send" ) ) + { + g_bSendReport = true; + } + else if ( 0 == strcmp( argv[n], "-load" ) ) + { + g_bLoadReport = true; + } + else if ( argv[n] && strlen(argv[n]) ) + { + printf( + "\n%s crash_report %s\n\n" \ + "/?, -h[elp] %s\n\n" \ + "%-20s %s\n\n", + "%MSG_CMDLINE_USAGE%", + "%MSG_PARAM_PROCESSID%", + "%MSG_PARAM_HELP_DESCRIPTION%", + "%MSG_PARAM_PROCESSID%", + "%MSG_PARAM_PROCESSID_DESCRIPTION%" + ); + break; + } + } + + *pSignal = signal; + + return pid; +} + +//************************************************************************* + +static bool read_line( FILE *fp, string& rLine ) +{ + char szBuffer[1024]; + bool bSuccess = false; + bool bEOL = false; + string line; + + + while ( !bEOL && fgets( szBuffer, sizeof(szBuffer), fp ) ) + { + int len = strlen(szBuffer); + + bSuccess = true; + + while ( len && szBuffer[len - 1] == '\n' ) + { + szBuffer[--len] = 0; + bEOL = true; + } + + line.append( szBuffer ); + } + + rLine = line; + return bSuccess; +} + +static string get_script_string( const char *pFileName, const char *pKeyName ) +{ + FILE *fp = fopen( pFileName, "r" ); + string retValue; + + if ( fp ) + { + string line; + string section; + + while ( read_line( fp, line ) ) + { + line = trim_string( line ); + + + string::size_type iEqualSign = line.find( '=', 0 ); + + if ( iEqualSign != string::npos ) + { + string keyname = line.substr( 0, iEqualSign ); + keyname = trim_string( keyname ); + + string value = line.substr( iEqualSign + 1, string::npos ); + value = trim_string( value ); + + if ( value.length() && '\"' == value[0] ) + { + value.erase( 0, 1 ); + + string::size_type iQuotes = value.find( '"', 0 ); + + if ( iQuotes != string::npos ) + value.erase( iQuotes ); + } + + if ( 0 == strcasecmp( keyname.c_str(), pKeyName ) ) + { + retValue = value; + break; + } + } + } + + fclose( fp ); + } + + return retValue; +} + +static string get_profile_string( const char *pFileName, const char *pSectionName, const char *pKeyName, const char *pDefault = NULL ) +{ + FILE *fp = fopen( pFileName, "r" ); + string retValue = pDefault ? pDefault : ""; + + if ( fp ) + { + string line; + string section; + + while ( read_line( fp, line ) ) + { + line = trim_string( line ); + + if ( line.length() && line[0] == '[' ) + { + line.erase( 0, 1 ); + string::size_type end = line.find( ']', 0 ); + + if ( string::npos != end ) + section = trim_string( line.substr( 0, end ) ); + } + else + { + + string::size_type iEqualSign = line.find( '=', 0 ); + + if ( iEqualSign != string::npos ) + { + string keyname = line.substr( 0, iEqualSign ); + keyname = trim_string( keyname ); + + string value = line.substr( iEqualSign + 1, string::npos ); + value = trim_string( value ); + + if ( + 0 == strcasecmp( section.c_str(), pSectionName ) && + 0 == strcasecmp( keyname.c_str(), pKeyName ) + ) + { + retValue = value; + break; + } + } + } + } + + fclose( fp ); + } + + return retValue; +} + +static string get_environment_string( const char *pEnvName ) +{ + const char *pEnvValue = getenv( pEnvName ); + + if ( pEnvValue ) + return pEnvValue; + else + return ""; +} + +static string read_from_file( const string& rFileName ) +{ + string content; + FILE *fp = fopen( rFileName.c_str(), "r" ); + + if ( fp ) + { + char buffer[256 + 1]; + size_t nBytesRead; + + while( 0 != ( nBytesRead = fread( buffer, 1, sizeof(buffer) - 1, fp ) ) ) + { + buffer[nBytesRead] = 0; + content += buffer; + } + + fclose( fp ); + } + + return content; +} + +#define RCFILE ".crash_reportrc" +#define XMLFILE ".crash_report_frames" +#define CHKFILE ".crash_report_checksum" +#define LCKFILE ".crash_report_unsent" +#define PRVFILE ".crash_report_preview" + +static void load_crash_data() +{ + g_strXMLFileName = get_home_dir(); + g_strXMLFileName += "/"; + g_strXMLFileName += string(XMLFILE); + + g_strChecksumFileName = get_home_dir(); + g_strChecksumFileName += "/"; + g_strChecksumFileName += string(CHKFILE); +} + +static bool write_crash_data() +{ + bool success = true; + string sFile = get_home_dir(); + + sFile += "/"; + sFile += string(XMLFILE); + + FILE *fp = fopen( sFile.c_str(), "w" ); + + if ( fp ) + { + FILE *fpin = fopen( g_strXMLFileName.c_str(), "r" ); + + if ( fpin ) + { + fcopy( fp, fpin ); + fclose( fpin ); + } + + fclose( fp ); + } + + sFile = get_home_dir(); + + sFile += "/"; + sFile += string(CHKFILE); + + fp = fopen( sFile.c_str(), "w" ); + + if ( fp ) + { + FILE *fpin = fopen( g_strChecksumFileName.c_str(), "r" ); + + if ( fpin ) + { + fcopy( fp, fpin ); + fclose( fpin ); + } + + fclose( fp ); + } + + sFile = get_home_dir(); + + sFile += "/"; + sFile += string(LCKFILE); + + fp = fopen( sFile.c_str(), "w" ); + + if ( fp ) + { + fprintf( fp, "Unsent\n" ); + fclose( fp ); + } + + return success; +} + +#if 0 +// unused +static bool write_settings( const hash_map< string, string >& rSettings ) +{ + bool success = false; + string sRCFile = get_home_dir(); + + sRCFile += "/"; + sRCFile += string(RCFILE); + + FILE *fp = fopen( sRCFile.c_str(), "w" ); + + if ( fp ) + { + fprintf( fp, "[Options]\n" ); + fprintf( fp, "UseProxy=%s\n", rSettings.find( "USEPROXY" )->second.c_str() ); + fprintf( fp, "ProxyServer=%s\n", rSettings.find( "SERVER" )->second.c_str() ); + fprintf( fp, "ProxyPort=%s\n", rSettings.find( "PORT" )->second.c_str() ); + fprintf( fp, "ReturnAddress=%s\n", rSettings.find( "EMAIL" )->second.c_str() ); + fprintf( fp, "AllowContact=%s\n", rSettings.find( "CONTACT" )->second.c_str() ); + fclose( fp ); + } + + return success; +} +#endif + +static void read_settings( hash_map< string, string >& rSettings ) +{ + string sRCFile = get_home_dir(); + + sRCFile += "/"; + sRCFile += string(RCFILE); + + rSettings[ "EMAIL" ] = get_profile_string( sRCFile.c_str(), "Options", "ReturnAddress" ); + rSettings[ "SERVER" ] = get_profile_string( sRCFile.c_str(), "Options", "ProxyServer" ); + rSettings[ "PORT" ] = get_profile_string( sRCFile.c_str(), "Options", "ProxyPort" ); + rSettings[ "USEPROXY" ] = get_profile_string( sRCFile.c_str(), "Options", "UseProxy" ); + rSettings[ "CONTACT" ] = get_profile_string( sRCFile.c_str(), "Options", "AllowContact" ); + rSettings[ "DESCRIPTION" ] = ""; + rSettings[ "TITLE" ] = ""; +} + +static void read_settings_from_environment( hash_map< string, string >& rSettings ) +{ + string strEnv; + + strEnv = get_environment_string( "ERRORREPORT_RETURNADDRESS" ); + if ( strEnv.length() ) + { + rSettings[ "EMAIL" ] = strEnv; + if ( !(rSettings.find( "CONTACT" )->second).length() ) + rSettings[ "CONTACT" ] = "true"; + } + else if ( !(rSettings.find( "CONTACT" )->second).length() ) + rSettings[ "CONTACT" ] = "false"; + + + strEnv = get_environment_string( "ERRORREPORT_HTTPPROXYSERVER" ); + if ( strEnv.length() ) + rSettings[ "SERVER" ] = strEnv; + + strEnv = get_environment_string( "ERRORREPORT_HTTPPROXYPORT" ); + if ( strEnv.length() ) + rSettings[ "PORT" ] = strEnv; + + strEnv = get_environment_string( "ERRORREPORT_HTTPCONNECTIONTYPE" ); + if ( strEnv.length() ) + rSettings[ "USEPROXY" ] = 0 == strcasecmp( strEnv.c_str(), "MANUALPROXY" ) ? "true" : "false"; + + strEnv = get_environment_string( "ERRORREPORT_BODYFILE" ); + if ( strEnv.length() ) + rSettings[ "DESCRIPTION" ] = read_from_file( strEnv ); + + strEnv = get_environment_string( "ERRORREPORT_SUBJECT" ); + if ( strEnv.length() ) + rSettings[ "TITLE" ] = strEnv; +} + +static bool setup_version() +{ + if ( !getenv( "PRODUCTNAME" ) ) + { + string productkey = get_profile_string( "bootstraprc", "Bootstrap", "ProductKey" ); + + g_strProductKey = productkey; + + if ( productkey.length() ) + { + static string productname; + static string productversion; + string::size_type iSpace = productkey.find( ' ', 0 ); + + if ( string::npos != iSpace ) + { + productname = productkey.substr( 0, iSpace ); + productversion = productkey.substr( iSpace + 1, string::npos ); + } + else + productname = productkey; + + productname.insert( 0, "PRODUCTNAME=" ); + putenv( (char *)productname.c_str() ); + + productversion.insert( 0, "PRODUCTVERSION=" ); + putenv( (char *)productversion.c_str() ); + } + } + + g_buildid = get_profile_string( "versionrc", "Version", "BuildId" ); + g_strDefaultLanguage = get_script_string( "instdb.ins", "DefaultLanguage" ); + + g_strReportServer = get_profile_string( "bootstraprc", "ErrorReport", "ErrorReportServer" ); + + string strReportPort = get_profile_string( "bootstraprc", "ErrorReport", "ErrorReportPort", "80" ); + char *endptr = NULL; + unsigned short uReportPort = (unsigned short)strtoul( strReportPort.c_str(), &endptr, 10 ); + g_uReportPort = uReportPort ? uReportPort : 80; + + return 0 != g_strReportServer.length(); +} + +#if 0 +// Use gconftool-2 to determine if gnome accessiblity is enabled +// unused +static bool get_accessibility_state() +{ + bool bAccessible = false; + FILE *fin = popen( "gconftool-2 -g /desktop/gnome/interface/accessibility", "r"); + + if ( fin ) + { + char buffer[sizeof("true")]; + + bAccessible = fgets( buffer, sizeof(buffer), fin ) && 0 == strcmp( buffer, "true" ); + + pclose( fin ); + } + + return bAccessible; +} +#endif + +int main( int argc, char** argv ) +{ + freopen( "/dev/null", "w", stderr ); + + setup_program_dir( argv[0] ); + + // Don't start if accessiblity is enabled or report server is not given + + if ( setup_version() ) + { + /*long pid =*/ setup_commandline_arguments( argc, argv, &g_signal ); + + if ( g_bLoadReport ) + { + load_crash_data(); + } + + if ( g_bSendReport ) + { + hash_map< string, string > aDialogSettings; + + read_settings( aDialogSettings ); + read_settings_from_environment( aDialogSettings ); + + send_crash_report( aDialogSettings ); + } + else + { + hash_map< string, string > aDialogSettings; + + read_settings( aDialogSettings ); + read_settings_from_environment( aDialogSettings ); + + write_crash_data(); + write_report( aDialogSettings ); + + string sPreviewFile = get_home_dir(); + sPreviewFile += "/"; + sPreviewFile += string(PRVFILE); + + FILE *fpout = fopen( sPreviewFile.c_str(), "w+" ); + if ( fpout ) + { + FILE *fpin = fopen( g_szReportFile, "r" ); + if ( fpin ) + { + fcopy( fpout, fpin ); + fclose( fpin ); + } + fclose( fpout ); + } + + unlink( g_szReportFile ); + } + + if ( g_bLoadReport ) + { + unlink( g_strXMLFileName.c_str() ); + unlink( g_strChecksumFileName.c_str() ); + } + + unlink( g_szStackFile ); + + return 0; + } + + return -1; +} |