masterfix DEV300: #i10000# build fix
[LibreOffice.git] / crashrep / source / unx / main.cxx
blob7579de78ec94239e00318b2a0c164b6a4b7d5e91
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
27 #include <cstdio>
28 #include <stdlib.h>
29 #include <sys/utsname.h>
30 #include <_version.h>
31 #include <errno.h>
32 #include <string>
33 #include <string.h>
34 #include <assert.h>
36 #include <sys/socket.h>
37 #include <netdb.h>
38 #include <unistd.h>
39 #include <pwd.h>
40 #include <pthread.h>
41 #include <limits.h>
43 #include <hash_map>
44 #include <vector>
45 #include <string>
47 #if defined (LINUX) || (FREEBSD)
48 #include <netinet/in.h>
49 #endif
51 typedef int SOCKET;
53 #define closesocket close
54 #define SOCKET_ERROR -1
56 #ifdef SOLARIS
57 const char *basename( const char *filename )
59 const char *pSlash = strrchr( filename, '/' );
61 return pSlash ? pSlash + 1 : pSlash;
63 #endif
65 using namespace std;
67 static bool g_bNoUI = false;
68 static bool g_bSendReport = false;
69 static bool g_bLoadReport = false;
71 static bool g_bDebugMode = false;
72 static int g_signal = 0;
74 static string g_strProductKey;
75 static string g_strReportServer;
76 static unsigned short g_uReportPort = 80;
77 static string g_buildid;
78 static string g_strDefaultLanguage;
79 static string g_strXMLFileName;
80 static string g_strPStackFileName;
81 static string g_strChecksumFileName;
82 static string g_strProgramDir;
84 static char g_szStackFile[L_tmpnam] = "";
85 static char g_szDescriptionFile[2048] = "";
86 static char g_szReportFile[2048] = "";
88 #define SO_CRASHREPORT_MAIL "so-report@sun.com"
89 #define PSTACK_CMD "pstack %d"
91 #ifdef LINUX
92 #define PMAP_CMD "cat /proc/%d/maps"
93 #else
94 #define PMAP_CMD "pmap %d"
95 #endif
97 #define REPORT_SERVER (g_strReportServer.c_str())
98 #define REPORT_PORT g_uReportPort
100 static string getprogramdir()
102 return g_strProgramDir;
105 static const char *getlocale()
107 const char * locale = getenv( "LC_ALL" );
109 if( NULL == locale )
110 locale = getenv( "LC_CTYPE" );
112 if( NULL == locale )
113 locale = getenv( "LANG" );
115 if( NULL == locale )
116 locale = "C";
118 return locale;
121 static const char *get_home_dir()
123 struct passwd *ppwd = getpwuid( getuid() );
125 return ppwd ? (ppwd->pw_dir ? ppwd->pw_dir : "/") : "/";
128 static string trim_string( const string& rString )
130 string temp = rString;
132 while ( temp.length() && (temp[0] == ' ' || temp[0] == '\t') )
133 temp.erase( 0, 1 );
135 string::size_type len = temp.length();
137 while ( len && (temp[len-1] == ' ' || temp[len-1] == '\t') )
139 temp.erase( len - 1, 1 );
140 len = temp.length();
143 return temp;
146 static string xml_encode( const string &rString )
148 string temp = rString;
149 string::size_type pos = 0;
151 // First replace all occurences of '&' because it may occur in further
152 // encoded chardters too
154 for( pos = 0; (pos = temp.find( '&', pos )) != string::npos; pos += 4 )
155 temp.replace( pos, 1, "&amp;" );
157 for( pos = 0; (pos = temp.find( '<', pos )) != string::npos; pos += 4 )
158 temp.replace( pos, 1, "&lt;" );
160 for( pos = 0; (pos = temp.find( '>', pos )) != string::npos; pos += 4 )
161 temp.replace( pos, 1, "&gt;" );
163 return temp;
166 static size_t fcopy( FILE *fpout, FILE *fpin )
168 char buffer[1024];
169 size_t nBytes;
170 size_t nBytesWritten = 0;
172 while ( 0 != (nBytes = fread( buffer, 1, sizeof(buffer), fpin )) )
174 nBytesWritten += fwrite( buffer, 1, nBytes, fpout );
177 return nBytesWritten;
181 writes the report to a temp-file
182 from which it can be reviewed and sent
185 bool write_report( const hash_map< string, string >& rSettings )
187 FILE *fp = fopen( tmpnam( g_szReportFile ), "w" );
188 const char *pszUserType = getenv( "STAROFFICE_USERTYPE" );
190 fprintf( fp,
191 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
192 "<!DOCTYPE errormail:errormail PUBLIC \"-//OpenOffice.org//DTD ErrorMail 1.0//EN\" \"errormail.dtd\">\n"
193 "<errormail:errormail xmlns:errormail=\"http://openoffice.org/2002/errormail\" usertype=\"%s\">\n"
194 "<reportmail:mail xmlns:reportmail=\"http://openoffice.org/2002/reportmail\" version=\"1.1\" feedback=\"%s\" email=\"%s\">\n"
195 "<reportmail:title>%s</reportmail:title>\n"
196 "<reportmail:attachment name=\"description.txt\" media-type=\"text/plain\" class=\"UserComment\"/>\n"
197 "<reportmail:attachment name=\"stack.txt\" media-type=\"text/plain\" class=\"pstack output\"/>\n"
198 "</reportmail:mail>\n"
199 "<officeinfo:officeinfo xmlns:officeinfo=\"http://openoffice.org/2002/officeinfo\" build=\"%s\" platform=\"%s\" language=\"%s\" exceptiontype=\"%d\" product=\"%s\" procpath=\"%s\"/>\n"
201 pszUserType ? xml_encode( pszUserType ).c_str() : "",
202 xml_encode(rSettings.find( "CONTACT" )->second).c_str(),
203 xml_encode(rSettings.find( "EMAIL" )->second).c_str(),
204 xml_encode(rSettings.find( "TITLE" )->second).c_str(),
205 g_buildid.length() ? xml_encode( g_buildid ).c_str() : "unknown",
206 _INPATH,
207 g_strDefaultLanguage.c_str(),
208 g_signal,
209 g_strProductKey.length() ? xml_encode(g_strProductKey).c_str() : "unknown",
210 xml_encode(getprogramdir()).c_str()
213 struct utsname info;
215 memset( &info, 0, sizeof(info) );
216 uname( &info );
218 fprintf( fp,
219 "<systeminfo:systeminfo xmlns:systeminfo=\"http://openoffice.org/2002/systeminfo\">\n"
220 "<systeminfo:System name=\"%s\" version=\"%s\" build=\"%s\" locale=\"%s\"/>\n"
222 xml_encode( info.sysname ).c_str(),
223 xml_encode( info.version ).c_str(),
224 xml_encode( info.release ).c_str(),
225 xml_encode( getlocale() ).c_str()
227 fprintf( fp, "<systeminfo:CPU type=\"%s\"/>\n", xml_encode( info.machine ).c_str() );
228 fprintf( fp, "</systeminfo:systeminfo>\n" );
230 FILE *fpxml = fopen( g_strXMLFileName.c_str(), "r" );
231 if ( fpxml )
233 fcopy( fp, fpxml );
234 fclose( fpxml );
237 FILE *fpchk = fopen( g_strChecksumFileName.c_str(), "r" );
238 if ( fpchk )
240 fcopy( fp, fpchk );
241 fclose( fpchk );
244 fprintf( fp, "</errormail:errormail>\n" );
246 fclose( fp );
248 return true;
252 bool write_description( const hash_map< string, string >& rSettings )
254 bool bSuccess = false;
255 FILE *fp = fopen( tmpnam( g_szDescriptionFile ), "w" );
257 if ( fp )
259 bSuccess = true;
260 fprintf( fp, "\xEF\xBB\xBF" );
261 fprintf( fp, "%s\n", rSettings.find( "DESCRIPTION" )->second.c_str() );
262 fclose( fp );
265 return bSuccess;
268 #if 0
269 // unused
270 static void printSettings( const hash_map<string,string>& rSettings )
272 printf( "Settings:\n" );
273 for( hash_map<string,string>::const_iterator it = rSettings.begin(); it != rSettings.end(); ++it )
275 printf( "%s=\"%s\"\n", it->first.c_str(), it->second.c_str() );
278 #endif
280 bool save_crash_report( const string& rFileName, const hash_map< string, string >& /*rSettings*/ )
282 bool bSuccess = false;
283 FILE *fpout = fopen( rFileName.c_str(), "w" );
285 if ( fpout )
287 FILE *fpin = fopen( g_szStackFile, "r" );
289 if ( fpin )
291 char buf[1024];
293 while (fgets(buf, sizeof(buf), fpin) != NULL)
295 fputs(buf, fpout);
298 bSuccess = true;
300 fclose ( fpin );
303 fclose( fpout );
306 return bSuccess;
309 bool SendHTTPRequest(
310 FILE *fp,
311 const char *pszServer,
312 unsigned short uPort = 80,
313 const char *pszProxyServer = NULL,
314 unsigned short uProxyPort = 8080 )
316 bool success = false;
318 struct hostent *hp;
320 if ( pszProxyServer )
321 hp = gethostbyname( pszProxyServer );
322 else
323 hp = gethostbyname( pszServer );
325 if ( hp )
327 SOCKET s = socket( AF_INET, SOCK_STREAM, 0 );
329 if ( s )
331 struct sockaddr_in address;
333 memcpy(&(address.sin_addr.s_addr), *(hp->h_addr_list),sizeof(struct in_addr));
334 address.sin_family = AF_INET;
336 if ( pszProxyServer )
337 address.sin_port = ntohs( uProxyPort );
338 else
339 address.sin_port = ntohs( uPort );
341 if ( 0 == connect( s, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) )
343 fseek( fp, 0, SEEK_END );
344 size_t length = ftell( fp );
345 fseek( fp, 0, SEEK_SET );
347 char buffer[2048];
349 if ( pszProxyServer )
350 sprintf( buffer,
351 "POST http://%s:%d/soap/servlet/rpcrouter HTTP/1.0\r\n"
352 "Content-Type: text/xml; charset=\"utf-8\"\r\n"
353 "Content-Length: %d\r\n"
354 "SOAPAction: \"\"\r\n\r\n",
355 pszServer,
356 uPort,
357 static_cast<int>(length)
359 else
360 sprintf( buffer,
361 "POST /soap/servlet/rpcrouter HTTP/1.0\r\n"
362 "Content-Type: text/xml; charset=\"utf-8\"\r\n"
363 "Content-Length: %d\r\n"
364 "SOAPAction: \"\"\r\n\r\n",
365 static_cast<int>(length)
368 if ( g_bDebugMode )
370 printf( "*** Sending HTTP request ***\n\n" );
371 printf( buffer );
374 if ( SOCKET_ERROR != send( s, buffer, strlen(buffer), 0 ) )
376 size_t nBytes;
380 nBytes = fread( buffer, 1, sizeof(buffer), fp );
382 if ( nBytes )
384 if ( g_bDebugMode )
385 fwrite( buffer, 1, nBytes, stdout );
386 success = SOCKET_ERROR != send( s, buffer, nBytes, 0 );
388 } while( nBytes && success );
390 if ( success )
392 if ( g_bDebugMode )
393 printf( "*** Receiving HTTP response ***\n\n" );
395 memset( buffer, 0, sizeof(buffer) );
396 success = SOCKET_ERROR != recv( s, buffer, sizeof(buffer), 0 );
397 if ( success )
399 char szHTTPSignature[sizeof(buffer)] = "";
400 unsigned uHTTPReturnCode = 0;
402 sscanf( buffer, "%s %d ", szHTTPSignature, &uHTTPReturnCode );
403 success = uHTTPReturnCode == 200;
405 if ( g_bDebugMode )
408 printf( buffer );
409 memset( buffer, 0, sizeof(buffer) );
410 } while ( 0 < recv( s, buffer, sizeof(buffer), 0 ) );
416 closesocket( s );
420 return success;
423 static void WriteSOAPRequest( FILE *fp )
425 fprintf( fp,
426 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
427 "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
428 "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"\n"
429 "xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\"\n"
430 "xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"\n"
431 "xmlns:rds=\"urn:ReportDataService\"\n"
432 "xmlns:apache=\"http://xml.apache.org/xml-soap\"\n"
433 "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
434 "<SOAP-ENV:Body>\n"
437 fprintf( fp, "<rds:submitReport>\n" );
438 fprintf( fp, "<body xsi:type=\"xsd:string\">This is an autogenerated crash report mail.</body>\n" );
439 fprintf( fp, "<hash xsi:type=\"apache:Map\">\n" );
441 FILE *fpin = fopen( g_szReportFile, "r" );
442 if ( fpin )
444 fprintf( fp,
445 "<item>\n"
446 "<key xsi:type=\"xsd:string\">reportmail.xml</key>\n"
447 "<value xsi:type=\"xsd:string\"><![CDATA[" );
448 fcopy( fp, fpin );
449 fprintf( fp, "]]></value></item>\n" );
450 fclose( fpin );
453 fpin = fopen( g_szDescriptionFile, "r" );
454 if ( fpin )
456 fprintf( fp,
457 "<item>\n"
458 "<key xsi:type=\"xsd:string\">description.txt</key>\n"
459 "<value xsi:type=\"xsd:string\"><![CDATA[" );
460 fcopy( fp, fpin );
461 fprintf( fp, "]]></value></item>\n" );
462 fclose( fpin );
465 fpin = fopen( g_szStackFile, "r" );
466 if ( fpin )
468 fprintf( fp,
469 "<item>\n"
470 "<key xsi:type=\"xsd:string\">stack.txt</key>\n"
471 "<value xsi:type=\"xsd:string\"><![CDATA[" );
472 fcopy( fp, fpin );
473 fprintf( fp, "]]></value></item>\n" );
474 fclose( fpin );
477 fprintf( fp,
478 "</hash>\n"
479 "</rds:submitReport>\n"
480 "</SOAP-ENV:Body>\n"
481 "</SOAP-ENV:Envelope>\n"
485 struct RequestParams
487 bool success;
488 FILE *fpin;
489 const char *pServer;
490 unsigned short uPort;
491 const char *pProxyServer;
492 unsigned short uProxyPort;
496 bool send_crash_report( const hash_map< string, string >& rSettings )
498 if ( 0 == strcasecmp( rSettings.find( "CONTACT" )->second.c_str(), "true" ) &&
499 !trim_string(rSettings.find( "EMAIL" )->second).length() )
501 return false;
504 char *endptr = NULL;
506 const char *pProxyServer = rSettings.find( "SERVER" )->second.c_str();
507 unsigned short uProxyPort = (unsigned short)strtoul( rSettings.find( "PORT" )->second.c_str(), &endptr, 10 );
509 bool bUseProxy = !strcasecmp( "true", rSettings.find( "USEPROXY" )->second.c_str() );
512 write_description( rSettings );
513 write_report( rSettings );
515 bool bSuccess = false;
517 FILE *fptemp = tmpfile();
518 if ( fptemp )
520 WriteSOAPRequest( fptemp );
521 fseek( fptemp, 0, SEEK_SET );
523 bSuccess = SendHTTPRequest(
524 fptemp,
525 REPORT_SERVER, REPORT_PORT,
526 bUseProxy ? pProxyServer : NULL,
527 uProxyPort ? uProxyPort : 8080
530 fclose( fptemp );
534 unlink( g_szDescriptionFile );
535 unlink( g_szReportFile );
537 return bSuccess;
541 static bool append_file( const char *filename, string& rString )
543 char buf[1024];
544 bool bSuccess = false;
546 FILE *fp = fopen( filename, "r" );
547 if ( fp )
549 bSuccess = true;
550 while (fgets(buf, sizeof(buf), fp) != NULL)
552 rString.append( buf );
554 fclose( fp );
557 return true;
560 string crash_get_details( const hash_map< string, string >& rSettings )
562 string aRet;
564 write_description( rSettings );
565 write_report( rSettings );
567 aRet.append( rSettings.find( "TITLE" )->second.c_str() );
568 aRet.append( "\n\n" );
569 append_file( g_szDescriptionFile, aRet );
570 aRet.append( "\n\n-------\n\n" );
571 append_file( g_szReportFile, aRet );
572 aRet.append( "\n\n-------\n\n" );
573 append_file( g_szStackFile, aRet );
575 unlink( g_szDescriptionFile );
576 unlink( g_szReportFile );
578 return aRet;
582 // ensure validity of program relative paths
583 static void setup_program_dir( const char* progname )
585 char szCanonicProgPath[PATH_MAX];
588 if ( realpath( progname, szCanonicProgPath ) )
590 string aDir = szCanonicProgPath;
592 size_t pos = aDir.rfind( '/' );
593 // FIXME: search PATH if necessary
594 assert( pos != string::npos );
596 g_strProgramDir = aDir.substr( 0, pos + 1 );
597 aDir.erase( pos );
598 chdir( aDir.c_str() );
602 //*************************************************************************
604 static long setup_commandline_arguments( int argc, char** argv, int *pSignal )
606 long pid = 0;
607 int signal = 0;
609 for ( int n = 1; n < argc; n++ )
611 if ( 0 == strcmp( argv[n], "-p" ) )
613 if ( ++n < argc )
614 pid = strtol( argv[n], NULL, 0 );
616 else if ( 0 == strcmp( argv[n], "-s" ) )
618 if ( ++n < argc )
619 signal = strtol( argv[n], NULL, 0 );
621 else if ( 0 == strcmp( argv[n], "-debug" ) )
623 g_bDebugMode = true;
625 else if ( 0 == strcmp( argv[n], "-xml" ) )
627 if ( ++n < argc )
628 g_strXMLFileName = argv[n];
630 else if ( 0 == strcmp( argv[n], "-stack" ) )
632 if ( ++n < argc )
633 g_strPStackFileName = argv[n];
635 else if ( 0 == strcmp( argv[n], "-chksum" ) )
637 if ( ++n < argc )
638 g_strChecksumFileName = argv[n];
640 else if ( 0 == strcmp( argv[n], "-noui" ) )
642 g_bNoUI = true;
644 else if ( 0 == strcmp( argv[n], "-send" ) )
646 g_bSendReport = true;
648 else if ( 0 == strcmp( argv[n], "-load" ) )
650 g_bLoadReport = true;
652 else if ( argv[n] && strlen(argv[n]) )
654 printf(
655 "\n%s crash_report %s\n\n" \
656 "/?, -h[elp] %s\n\n" \
657 "%-20s %s\n\n",
658 "%MSG_CMDLINE_USAGE%",
659 "%MSG_PARAM_PROCESSID%",
660 "%MSG_PARAM_HELP_DESCRIPTION%",
661 "%MSG_PARAM_PROCESSID%",
662 "%MSG_PARAM_PROCESSID_DESCRIPTION%"
664 break;
668 *pSignal = signal;
670 return pid;
673 //*************************************************************************
675 static bool read_line( FILE *fp, string& rLine )
677 char szBuffer[1024];
678 bool bSuccess = false;
679 bool bEOL = false;
680 string line;
683 while ( !bEOL && fgets( szBuffer, sizeof(szBuffer), fp ) )
685 int len = strlen(szBuffer);
687 bSuccess = true;
689 while ( len && szBuffer[len - 1] == '\n' )
691 szBuffer[--len] = 0;
692 bEOL = true;
695 line.append( szBuffer );
698 rLine = line;
699 return bSuccess;
702 static string get_script_string( const char *pFileName, const char *pKeyName )
704 FILE *fp = fopen( pFileName, "r" );
705 string retValue;
707 if ( fp )
709 string line;
710 string section;
712 while ( read_line( fp, line ) )
714 line = trim_string( line );
717 string::size_type iEqualSign = line.find( '=', 0 );
719 if ( iEqualSign != string::npos )
721 string keyname = line.substr( 0, iEqualSign );
722 keyname = trim_string( keyname );
724 string value = line.substr( iEqualSign + 1, string::npos );
725 value = trim_string( value );
727 if ( value.length() && '\"' == value[0] )
729 value.erase( 0, 1 );
731 string::size_type iQuotes = value.find( '"', 0 );
733 if ( iQuotes != string::npos )
734 value.erase( iQuotes );
737 if ( 0 == strcasecmp( keyname.c_str(), pKeyName ) )
739 retValue = value;
740 break;
745 fclose( fp );
748 return retValue;
751 static string get_profile_string( const char *pFileName, const char *pSectionName, const char *pKeyName, const char *pDefault = NULL )
753 FILE *fp = fopen( pFileName, "r" );
754 string retValue = pDefault ? pDefault : "";
756 if ( fp )
758 string line;
759 string section;
761 while ( read_line( fp, line ) )
763 line = trim_string( line );
765 if ( line.length() && line[0] == '[' )
767 line.erase( 0, 1 );
768 string::size_type end = line.find( ']', 0 );
770 if ( string::npos != end )
771 section = trim_string( line.substr( 0, end ) );
773 else
776 string::size_type iEqualSign = line.find( '=', 0 );
778 if ( iEqualSign != string::npos )
780 string keyname = line.substr( 0, iEqualSign );
781 keyname = trim_string( keyname );
783 string value = line.substr( iEqualSign + 1, string::npos );
784 value = trim_string( value );
786 if (
787 0 == strcasecmp( section.c_str(), pSectionName ) &&
788 0 == strcasecmp( keyname.c_str(), pKeyName )
791 retValue = value;
792 break;
798 fclose( fp );
801 return retValue;
804 static string get_environment_string( const char *pEnvName )
806 const char *pEnvValue = getenv( pEnvName );
808 if ( pEnvValue )
809 return pEnvValue;
810 else
811 return "";
814 static string read_from_file( const string& rFileName )
816 string content;
817 FILE *fp = fopen( rFileName.c_str(), "r" );
819 if ( fp )
821 char buffer[256 + 1];
822 size_t nBytesRead;
824 while( 0 != ( nBytesRead = fread( buffer, 1, sizeof(buffer) - 1, fp ) ) )
826 buffer[nBytesRead] = 0;
827 content += buffer;
830 fclose( fp );
833 return content;
836 #define RCFILE ".crash_reportrc"
837 #define XMLFILE ".crash_report_frames"
838 #define CHKFILE ".crash_report_checksum"
839 #define LCKFILE ".crash_report_unsent"
840 #define PRVFILE ".crash_report_preview"
842 static void load_crash_data()
844 g_strXMLFileName = get_home_dir();
845 g_strXMLFileName += "/";
846 g_strXMLFileName += string(XMLFILE);
848 g_strChecksumFileName = get_home_dir();
849 g_strChecksumFileName += "/";
850 g_strChecksumFileName += string(CHKFILE);
853 static bool write_crash_data()
855 bool success = true;
856 string sFile = get_home_dir();
858 sFile += "/";
859 sFile += string(XMLFILE);
861 FILE *fp = fopen( sFile.c_str(), "w" );
863 if ( fp )
865 FILE *fpin = fopen( g_strXMLFileName.c_str(), "r" );
867 if ( fpin )
869 fcopy( fp, fpin );
870 fclose( fpin );
873 fclose( fp );
876 sFile = get_home_dir();
878 sFile += "/";
879 sFile += string(CHKFILE);
881 fp = fopen( sFile.c_str(), "w" );
883 if ( fp )
885 FILE *fpin = fopen( g_strChecksumFileName.c_str(), "r" );
887 if ( fpin )
889 fcopy( fp, fpin );
890 fclose( fpin );
893 fclose( fp );
896 sFile = get_home_dir();
898 sFile += "/";
899 sFile += string(LCKFILE);
901 fp = fopen( sFile.c_str(), "w" );
903 if ( fp )
905 fprintf( fp, "Unsent\n" );
906 fclose( fp );
909 return success;
912 #if 0
913 // unused
914 static bool write_settings( const hash_map< string, string >& rSettings )
916 bool success = false;
917 string sRCFile = get_home_dir();
919 sRCFile += "/";
920 sRCFile += string(RCFILE);
922 FILE *fp = fopen( sRCFile.c_str(), "w" );
924 if ( fp )
926 fprintf( fp, "[Options]\n" );
927 fprintf( fp, "UseProxy=%s\n", rSettings.find( "USEPROXY" )->second.c_str() );
928 fprintf( fp, "ProxyServer=%s\n", rSettings.find( "SERVER" )->second.c_str() );
929 fprintf( fp, "ProxyPort=%s\n", rSettings.find( "PORT" )->second.c_str() );
930 fprintf( fp, "ReturnAddress=%s\n", rSettings.find( "EMAIL" )->second.c_str() );
931 fprintf( fp, "AllowContact=%s\n", rSettings.find( "CONTACT" )->second.c_str() );
932 fclose( fp );
935 return success;
937 #endif
939 static void read_settings( hash_map< string, string >& rSettings )
941 string sRCFile = get_home_dir();
943 sRCFile += "/";
944 sRCFile += string(RCFILE);
946 rSettings[ "EMAIL" ] = get_profile_string( sRCFile.c_str(), "Options", "ReturnAddress" );
947 rSettings[ "SERVER" ] = get_profile_string( sRCFile.c_str(), "Options", "ProxyServer" );
948 rSettings[ "PORT" ] = get_profile_string( sRCFile.c_str(), "Options", "ProxyPort" );
949 rSettings[ "USEPROXY" ] = get_profile_string( sRCFile.c_str(), "Options", "UseProxy" );
950 rSettings[ "CONTACT" ] = get_profile_string( sRCFile.c_str(), "Options", "AllowContact" );
951 rSettings[ "DESCRIPTION" ] = "";
952 rSettings[ "TITLE" ] = "";
955 static void read_settings_from_environment( hash_map< string, string >& rSettings )
957 string strEnv;
959 strEnv = get_environment_string( "ERRORREPORT_RETURNADDRESS" );
960 if ( strEnv.length() )
962 rSettings[ "EMAIL" ] = strEnv;
963 if ( !(rSettings.find( "CONTACT" )->second).length() )
964 rSettings[ "CONTACT" ] = "true";
966 else if ( !(rSettings.find( "CONTACT" )->second).length() )
967 rSettings[ "CONTACT" ] = "false";
970 strEnv = get_environment_string( "ERRORREPORT_HTTPPROXYSERVER" );
971 if ( strEnv.length() )
972 rSettings[ "SERVER" ] = strEnv;
974 strEnv = get_environment_string( "ERRORREPORT_HTTPPROXYPORT" );
975 if ( strEnv.length() )
976 rSettings[ "PORT" ] = strEnv;
978 strEnv = get_environment_string( "ERRORREPORT_HTTPCONNECTIONTYPE" );
979 if ( strEnv.length() )
980 rSettings[ "USEPROXY" ] = 0 == strcasecmp( strEnv.c_str(), "MANUALPROXY" ) ? "true" : "false";
982 strEnv = get_environment_string( "ERRORREPORT_BODYFILE" );
983 if ( strEnv.length() )
984 rSettings[ "DESCRIPTION" ] = read_from_file( strEnv );
986 strEnv = get_environment_string( "ERRORREPORT_SUBJECT" );
987 if ( strEnv.length() )
988 rSettings[ "TITLE" ] = strEnv;
991 static bool setup_version()
993 if ( !getenv( "PRODUCTNAME" ) )
995 string productkey = get_profile_string( "bootstraprc", "Bootstrap", "ProductKey" );
997 g_strProductKey = productkey;
999 if ( productkey.length() )
1001 static string productname;
1002 static string productversion;
1003 string::size_type iSpace = productkey.find( ' ', 0 );
1005 if ( string::npos != iSpace )
1007 productname = productkey.substr( 0, iSpace );
1008 productversion = productkey.substr( iSpace + 1, string::npos );
1010 else
1011 productname = productkey;
1013 productname.insert( 0, "PRODUCTNAME=" );
1014 putenv( (char *)productname.c_str() );
1016 productversion.insert( 0, "PRODUCTVERSION=" );
1017 putenv( (char *)productversion.c_str() );
1021 g_buildid = get_profile_string( "versionrc", "Version", "BuildId" );
1022 g_strDefaultLanguage = get_script_string( "instdb.ins", "DefaultLanguage" );
1024 g_strReportServer = get_profile_string( "bootstraprc", "ErrorReport", "ErrorReportServer" );
1026 string strReportPort = get_profile_string( "bootstraprc", "ErrorReport", "ErrorReportPort", "80" );
1027 char *endptr = NULL;
1028 unsigned short uReportPort = (unsigned short)strtoul( strReportPort.c_str(), &endptr, 10 );
1029 g_uReportPort = uReportPort ? uReportPort : 80;
1031 return 0 != g_strReportServer.length();
1034 #if 0
1035 // Use gconftool-2 to determine if gnome accessiblity is enabled
1036 // unused
1037 static bool get_accessibility_state()
1039 bool bAccessible = false;
1040 FILE *fin = popen( "gconftool-2 -g /desktop/gnome/interface/accessibility", "r");
1042 if ( fin )
1044 char buffer[sizeof("true")];
1046 bAccessible = fgets( buffer, sizeof(buffer), fin ) && 0 == strcmp( buffer, "true" );
1048 pclose( fin );
1051 return bAccessible;
1053 #endif
1055 int main( int argc, char** argv )
1057 freopen( "/dev/null", "w", stderr );
1059 setup_program_dir( argv[0] );
1061 // Don't start if accessiblity is enabled or report server is not given
1063 if ( setup_version() )
1065 /*long pid =*/ setup_commandline_arguments( argc, argv, &g_signal );
1067 if ( g_bLoadReport )
1069 load_crash_data();
1072 if ( g_bSendReport )
1074 hash_map< string, string > aDialogSettings;
1076 read_settings( aDialogSettings );
1077 read_settings_from_environment( aDialogSettings );
1079 send_crash_report( aDialogSettings );
1081 else
1083 hash_map< string, string > aDialogSettings;
1085 read_settings( aDialogSettings );
1086 read_settings_from_environment( aDialogSettings );
1088 write_crash_data();
1089 write_report( aDialogSettings );
1091 string sPreviewFile = get_home_dir();
1092 sPreviewFile += "/";
1093 sPreviewFile += string(PRVFILE);
1095 FILE *fpout = fopen( sPreviewFile.c_str(), "w+" );
1096 if ( fpout )
1098 FILE *fpin = fopen( g_szReportFile, "r" );
1099 if ( fpin )
1101 fcopy( fpout, fpin );
1102 fclose( fpin );
1104 fclose( fpout );
1107 unlink( g_szReportFile );
1110 if ( g_bLoadReport )
1112 unlink( g_strXMLFileName.c_str() );
1113 unlink( g_strChecksumFileName.c_str() );
1116 unlink( g_szStackFile );
1118 return 0;
1121 return -1;