3 #include <asm/ptrace.h>
5 #include <lib/base/eerror.h>
6 #include <lib/base/smartptr.h>
7 #include <lib/base/nconfig.h>
8 #include <lib/gdi/grc.h>
9 #include <lib/gdi/gfbdc.h>
11 #include <lib/gdi/sdl.h>
16 /************************************************/
18 #ifdef BUILD_VUPLUS /* ikseong */
19 #define CRASH_EMAILADDR "crashlog"
21 #define CRASH_EMAILADDR "crashlog@dream-multimedia-tv.de"
23 #define STDBUFFER_SIZE 512
24 #define RINGBUFFER_SIZE 16384
25 static char ringbuffer[RINGBUFFER_SIZE];
26 static int ringbuffer_head;
28 static void addToLogbuffer(const char *data, int len)
32 int remaining = RINGBUFFER_SIZE - ringbuffer_head;
37 memcpy(ringbuffer + ringbuffer_head, data, remaining);
40 ringbuffer_head += remaining;
41 if (ringbuffer_head >= RINGBUFFER_SIZE)
46 static std::string getLogBuffer()
48 int begin = ringbuffer_head;
49 while (ringbuffer[begin] == 0)
52 if (begin == RINGBUFFER_SIZE)
54 if (begin == ringbuffer_head)
57 if (begin < ringbuffer_head)
58 return std::string(ringbuffer + begin, ringbuffer_head - begin);
61 return std::string(ringbuffer + begin, RINGBUFFER_SIZE - begin) + std::string(ringbuffer, ringbuffer_head);
65 static void addToLogbuffer(int level, const std::string &log)
67 addToLogbuffer(log.c_str(), log.size());
70 static std::string getConfigFileValue(const char *entry)
72 std::string configfile = "/etc/enigma2/settings";
73 std::string configvalue;
76 ePythonConfigQuery::getConfigValue(entry, configvalue);
77 if (configvalue != "") //we get at least the default value if python is still alive
81 else // get value from enigma2 settings file
83 FILE *f = fopen(configfile.c_str(), "r");
91 if (!fgets(line, 1024, f))
93 if (!strncmp(line, entry, strlen(entry) ))
95 if (strlen(line) && line[strlen(line)-1] == '\r')
96 line[strlen(line)-1] = 0;
97 if (strlen(line) && line[strlen(line)-1] == '\n')
98 line[strlen(line)-1] = 0;
99 std::string tmp = line;
100 int posEqual = tmp.find("=", 0);
101 configvalue = tmp.substr(posEqual+1);
110 static std::string getFileContent(const char *file)
112 std::string filecontent;
116 FILE *f = fopen(file, "r");
124 if (!fgets(line, 1024, f))
126 std::string tmp = line;
127 std::string password;
128 int pwdpos = tmp.find(".password=", 0);
129 if( pwdpos != std::string::npos)
131 filecontent += tmp.substr(0,pwdpos +10);
132 for ( int pos = pwdpos +10; pos < tmp.length()-1; ++pos )
147 static std::string execCommand(char* cmd) {
148 FILE* pipe = popen(cmd, "r");
151 char buffer[STDBUFFER_SIZE];
152 std::string result = "";
155 if(!fgets(buffer,STDBUFFER_SIZE, pipe))
163 extern std::string execCommand();
164 extern std::string getConfigFileValue();
165 extern std::string getFileContent();
166 extern std::string getLogBuffer();
168 #define INFOFILE "/maintainer.info"
170 void bsodFatal(const char *component)
173 sprintf(logfile, "/media/hdd/enigma2_crash_%u.log", (unsigned int)time(0));
174 FILE *f = fopen(logfile, "wb");
176 std::string lines = getLogBuffer();
178 /* find python-tracebacks, and extract " File "-strings */
181 char crash_emailaddr[256] = CRASH_EMAILADDR;
182 char crash_component[256] = "enigma2";
185 snprintf(crash_component, 256, component);
188 while ((start = lines.find("\n File \"", start)) != std::string::npos)
191 size_t end = lines.find("\"", start);
192 if (end == std::string::npos)
194 end = lines.rfind("/", end);
195 /* skip a potential prefix to the path */
196 unsigned int path_prefix = lines.find("/usr/", start);
197 if (path_prefix != std::string::npos && path_prefix < end)
200 if (end == std::string::npos)
202 if (end - start >= (256 - strlen(INFOFILE)))
205 snprintf(filename, 256, "%s%s", lines.substr(start, end - start).c_str(), INFOFILE);
206 FILE *cf = fopen(filename, "r");
209 fgets(crash_emailaddr, sizeof crash_emailaddr, cf);
210 if (*crash_emailaddr && crash_emailaddr[strlen(crash_emailaddr)-1] == '\n')
211 crash_emailaddr[strlen(crash_emailaddr)-1] = 0;
213 fgets(crash_component, sizeof crash_component, cf);
214 if (*crash_component && crash_component[strlen(crash_component)-1] == '\n')
215 crash_component[strlen(crash_component)-1] = 0;
224 char crashtime[STDBUFFER_SIZE];
225 sprintf(crashtime, "%s",ctime(&t));
226 if (strlen(crashtime) && crashtime[strlen(crashtime)-1] == '\n')
227 crashtime[strlen(crashtime)-1] = 0;
228 fprintf(f, "<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?>\n<opendreambox>\n");
229 fprintf(f, "\t<enigma2>\n");
230 fprintf(f, "\t\t<crashdate>%s</crashdate>\n", crashtime);
231 #ifdef ENIGMA2_CHECKOUT_TAG
232 fprintf(f, "\t\t<checkouttag>" ENIGMA2_CHECKOUT_TAG "</checkouttag>\n");
234 fprintf(f, "\t\t<compiledate>" __DATE__ "</compiledate>\n");
236 #ifdef ENIGMA2_CHECKOUT_ROOT
237 fprintf(f, "\t\t<checkoutroot>" ENIGMA2_CHECKOUT_ROOT "</checkoutroot>\n");
239 fprintf(f, "\t\t<contactemail>%s</contactemail>\n", crash_emailaddr);
240 fprintf(f, "\t\t<!-- Please email this crashlog to above address -->\n");
241 std::string activeSkin = getConfigFileValue("config.skin.primary_skin");
242 if (activeSkin != "Error")
244 if (activeSkin == "")
245 activeSkin = "Default Skin";
246 fprintf(f, "\t\t<skin>%s</skin>\n", activeSkin.c_str());
248 fprintf(f, "\t</enigma2>\n");
250 fprintf(f, "\t<image>\n");
251 std::string model = getFileContent("/proc/stb/info/model");
252 if (model != "Error")
254 char modelname[STDBUFFER_SIZE];
255 sprintf(modelname, "%s",model.c_str());
256 if (strlen(modelname) && modelname[strlen(modelname)-1] == '\n')
257 modelname[strlen(modelname)-1] = 0;
258 fprintf(f, "\t\t<dreamboxmodel>%s</dreamboxmodel>\n", modelname);
260 std::string kernel = getFileContent("/proc/cmdline");
261 if (kernel != "Error")
263 char kernelcmd[STDBUFFER_SIZE];
264 sprintf(kernelcmd, "%s",kernel.c_str());
265 if (strlen(kernelcmd) && kernelcmd[strlen(kernelcmd)-1] == '\n')
266 kernelcmd[strlen(kernelcmd)-1] = 0;
267 fprintf(f, "\t\t<kernelcmdline>%s</kernelcmdline>\n", kernelcmd);
269 std::string sendAnonCrashlog = getConfigFileValue("config.plugins.crashlogautosubmit.sendAnonCrashlog");
270 if (sendAnonCrashlog == "False" || sendAnonCrashlog == "false") // defaults to true... default anonymized crashlogs
272 std::string ca = getFileContent("/proc/stb/info/ca");
275 char dreamboxca[STDBUFFER_SIZE];
276 sprintf(dreamboxca, "%s",ca.c_str());
277 if (strlen(dreamboxca) && dreamboxca[strlen(dreamboxca)-1] == '\n')
278 dreamboxca[strlen(dreamboxca)-1] = 0;
279 fprintf(f, "\t\t<dreamboxca>\n\t\t<![CDATA[\n%s\n\t\t]]>\n\t\t</dreamboxca>\n", dreamboxca);
281 std::string settings = getFileContent("/etc/enigma2/settings");
282 if (settings != "Error")
284 fprintf(f, "\t\t<enigma2settings>\n\t\t<![CDATA[\n%s\t\t]]>\n\t\t</enigma2settings>\n", settings.c_str());
287 std::string addNetwork = getConfigFileValue("config.plugins.crashlogautosubmit.addNetwork");
288 if (addNetwork == "True" || addNetwork == "true")
290 std::string nwinterfaces = getFileContent("/etc/network/interfaces");
291 if (nwinterfaces != "Error")
293 fprintf(f, "\t\t<networkinterfaces>\n\t\t<![CDATA[\n%s\t\t]]>\n\t\t</networkinterfaces>\n", nwinterfaces.c_str());
295 std::string dns = getFileContent("/etc/resolv.conf");
298 fprintf(f, "\t\t<dns>\n\t\t<![CDATA[\n%s\t\t]]>\n\t\t</dns>\n", dns.c_str());
300 std::string defaultgw = getFileContent("/etc/default_gw");
301 if (defaultgw != "Error")
303 char gateway[STDBUFFER_SIZE];
304 sprintf(gateway, "%s",defaultgw.c_str());
305 if (strlen(gateway) && gateway[strlen(gateway)-1] == '\n')
306 gateway[strlen(gateway)-1] = 0;
307 fprintf(f, "\t\t<defaultgateway>\n\t\t<![CDATA[\n%s\t\t]]>\n\t\t</defaultgateway>\n", gateway);
310 std::string addWlan = getConfigFileValue("config.plugins.crashlogautosubmit.addWlan");
311 if (addWlan == "True" || addWlan == "true")
313 std::string wpasupplicant = getFileContent("/etc/wpa_supplicant.conf");
314 if (wpasupplicant != "Error")
316 fprintf(f, "\t\t<wpasupplicant>\n\t\t<![CDATA[\n%s\t\t]]>\n\t\t</wpasupplicant>\n", wpasupplicant.c_str());
319 std::string imageversion = getFileContent("/etc/image-version");
320 if (imageversion != "Error")
322 fprintf(f, "\t\t<imageversion>\n\t\t<![CDATA[\n%s\t\t]]>\n\t\t</imageversion>\n", imageversion.c_str());
324 std::string imageissue = getFileContent("/etc/issue.net");
325 if (imageissue != "Error")
327 fprintf(f, "\t\t<imageissue>\n\t\t<![CDATA[\n%s\t\t]]>\n\t\t</imageissue>\n", imageissue.c_str());
329 fprintf(f, "\t</image>\n");
331 fprintf(f, "\t<software>\n");
332 std::string installedplugins = execCommand("ipkg list_installed | grep enigma2");
333 fprintf(f, "\t\t<enigma2software>\n\t\t<![CDATA[\n%s\t\t]]>\n\t\t</enigma2software>\n", installedplugins.c_str());
334 std::string dreambox = execCommand("ipkg list_installed | grep dream");
335 fprintf(f, "\t\t<dreamboxsoftware>\n\t\t<![CDATA[\n%s\t\t]]>\n\t\t</dreamboxsoftware>\n", dreambox.c_str());
336 std::string gstreamer = execCommand("ipkg list_installed | grep gst");
337 fprintf(f, "\t\t<gstreamersoftware>\n\t\t<![CDATA[\n%s\t\t]]>\n\t\t</gstreamersoftware>\n", gstreamer.c_str());
338 fprintf(f, "\t</software>\n");
340 fprintf(f, "\t<crashlogs>\n");
341 std::string buffer = getLogBuffer();
342 fprintf(f, "\t\t<enigma2crashlog>\n\t\t<![CDATA[\n%s\t\t]]>\n\t\t</enigma2crashlog>\n", buffer.c_str());
343 std::string pythonmd5 = execCommand("find /usr/lib/enigma2/python/ -name \"*.py\" | xargs md5sum");
344 fprintf(f, "\t\t<pythonMD5sum>\n\t\t<![CDATA[\n%s\t\t]]>\n\t\t</pythonMD5sum>\n", pythonmd5.c_str());
345 fprintf(f, "\t</crashlogs>\n");
347 fprintf(f, "\n</opendreambox>\n");
354 gSDLDC::getInstance(my_dc);
357 gFBDC::getInstance(my_dc);
363 p.resetClip(eRect(ePoint(0, 0), my_dc->size()));
364 #ifdef ENIGMA2_CHECKOUT_TAG
365 if (ENIGMA2_CHECKOUT_TAG[0] == 'T') /* tagged checkout (release) */
366 p.setBackgroundColor(gRGB(0x0000C0));
367 else if (ENIGMA2_CHECKOUT_TAG[0] == 'D') /* dated checkout (daily experimental build) */
371 unsigned int col = 0;
378 p.setBackgroundColor(gRGB(col));
381 p.setBackgroundColor(gRGB(0x008000));
384 p.setForegroundColor(gRGB(0xFFFFFF));
386 ePtr<gFont> font = new gFont("Regular", 20);
390 eRect usable_area = eRect(100, 70, my_dc->size().width() - 150, 100);
393 #ifdef BUILD_VUPLUS /* ikseong */
394 snprintf(text, 512, "We are really sorry. Your STB encountered "
396 snprintf(text, 512, "We are really sorry. Your Dreambox encountered "
398 "a software problem, and needs to be restarted. "
399 "Please send the logfile created in /hdd/ to %s.\n"
400 #ifdef BUILD_VUPLUS /* ikseong */
401 "Your STB restarts in 10 seconds!\n"
403 "Your Dreambox restarts in 10 seconds!\n"
406 crash_emailaddr, crash_component);
408 p.renderText(usable_area, text, gPainter::RT_WRAP|gPainter::RT_HALIGN_LEFT);
410 usable_area = eRect(100, 170, my_dc->size().width() - 180, my_dc->size().height() - 20);
414 size_t start = std::string::npos + 1;
417 start = lines.rfind('\n', start - 1);
418 if (start == std::string::npos)
425 font = new gFont("Regular", 14);
428 p.renderText(usable_area,
429 lines.substr(start), gPainter::RT_HALIGN_LEFT);
436 #if defined(__MIPSEL__)
437 void oops(const mcontext_t &context, int dumpcode)
439 eDebug("PC: %08lx", (unsigned long)context.pc);
443 eDebugNoNewLine(" %08x", (int)context.gregs[i]);
447 /* this is temporary debug stuff. */
448 if (dumpcode && ((unsigned long)context.pc) > 0x10000) /* not a zero pointer */
450 eDebug("As a final action, i will try to dump a bit of code.");
451 eDebug("I just hope that this won't crash.");
453 eDebugNoNewLine("%08lx:", (unsigned long)context.pc);
454 for (i=0; i<0x20; ++i)
455 eDebugNoNewLine(" %02x", ((unsigned char*)context.pc)[i]);
460 #warning "no oops support!"
461 #define NO_OOPS_SUPPORT
464 void handleFatalSignal(int signum, siginfo_t *si, void *ctx)
466 ucontext_t *uc = (ucontext_t*)ctx;
468 #ifndef NO_OOPS_SUPPORT
469 oops(uc->uc_mcontext, signum == SIGSEGV || signum == SIGABRT);
472 bsodFatal("enigma2, signal");
475 void bsodCatchSignals()
477 struct sigaction act;
478 act.sa_handler = SIG_DFL;
479 act.sa_sigaction = handleFatalSignal;
480 act.sa_flags = SA_RESTART | SA_SIGINFO;
481 if (sigemptyset(&act.sa_mask) == -1)
482 perror("sigemptyset");
484 /* start handling segfaults etc. */
485 sigaction(SIGSEGV, &act, 0);
486 sigaction(SIGILL, &act, 0);
487 sigaction(SIGBUS, &act, 0);
488 sigaction(SIGABRT, &act, 0);
493 logOutput.connect(addToLogbuffer);