3 * Copyright 2007, Intel Corporation
5 * This file is part of corewatcher.org
7 * This program file is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; version 2 of the License.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * You should have received a copy of the GNU General Public License
17 * along with this program in a file named COPYING; if not, write to the
18 * Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301 USA
23 * Arjan van de Ven <arjan@linux.intel.com>
24 * William Douglas <william.douglas@intel.com>
34 #include <asm/unistd.h>
35 #include <sys/types.h>
43 #include "corewatcher.h"
48 /* Always pick up the processing_mtx and then the
49 processing_queue_mtx, reverse for setting down */
50 /* Always pick up the gdb_mtx and then the
51 processing_queue_mtx, reverse for setting down */
52 /* Always pick up the processing_mtx and then the
53 gdb_mtx, reverse for setting down */
54 /* so order for pick up should be:
55 processing_mtx -> gdb_mtx -> processing_queue_mtx
56 and the reverse for setting down */
57 static pthread_mutex_t processing_queue_mtx = PTHREAD_MUTEX_INITIALIZER;
58 static char *processing_queue[MAX_PROCESSING_OOPS];
59 static pthread_mutex_t gdb_mtx = PTHREAD_MUTEX_INITIALIZER;
63 static long int get_time(char *filename)
66 if (stat(filename, &st)) {
69 return st.st_mtim.tv_sec;
72 static char *get_build(void)
75 char *line = NULL, *c = NULL, *build = NULL;
78 file = fopen(build_release, "r");
80 line = strdup("Unknown");
85 if (getline(&line, &dummy, file) == -1)
87 if ((c = strstr(line, "BUILD"))) {
89 if (c >= line + strlen(line))
92 /* glibc does things that scare valgrind */
93 /* ignore valgrind error for the line below */
98 c = strchr(build, '\n');
110 line = strdup("Unknown");
115 static char *get_release(void)
121 file = fopen("/etc/issue", "r");
123 line = strdup("Unknown");
127 while (!feof(file)) {
128 if (getline(&line, &dummy, file) == -1)
130 if (strstr(line, "release")) {
133 c = strchr(line, '\n');
144 line = strdup("Unknown");
149 static char *set_wrapped_app(char *line)
151 char *dline = NULL, *app = NULL, *appfile = NULL, *abs_path = NULL;
153 char app_folder[] = "/usr/share/";
159 dline = strdup(line);
161 app = strtok(dline, delim);
163 if (strcmp(app, "--app") == 0) {
164 app = strtok(NULL, delim);
167 app = strtok(NULL, delim);
170 goto cleanup_set_wrapped_app;
171 r = asprintf(&abs_path, "%s%s", app_folder, app);
174 goto cleanup_set_wrapped_app;
175 } else if (((unsigned int)r) != strlen(app_folder) + strlen(app)) {
176 goto cleanup_set_wrapped_app;
179 appfile = find_executable(abs_path);
181 cleanup_set_wrapped_app:
187 static GList *get_core_file_list(char *appfile, char *dump_text)
189 char *txt = NULL, *part = NULL, *c = NULL;
190 char delim[] = " ',`;\n\"";
193 if (!(txt = strdup(dump_text)))
196 part = strtok(txt, delim);
198 if (strstr(part, "/")) {
199 if (!(c = strdup(part)))
201 files = g_list_prepend(files, c);
203 part = strtok(NULL, delim);
205 if ((c = strdup(appfile))) {
206 files = g_list_prepend(files, c);
213 static char *run_cmd(char *cmd)
215 char *line = NULL, *str = NULL;
222 file = popen(cmd, "r");
226 if (getline(&line, &size, file) != -1) {
227 c = strchr(line, '\n');
237 static char *lookup_part(char *check, char *line)
239 char *c = NULL, *c1 = NULL, *c2 = NULL;
244 if (strncmp(check, line, strlen(check)))
246 if (!(c1 = strstr(line, ":")))
249 if (c1 >= line + strlen(line))
251 if (!(c2 = strstr(c1, " ")))
254 if (!(c = strdup(c1)))
259 static int append(char **s, char *e, char *a)
264 if (!s || !(*s) || !e || !a)
268 r = asprintf(s, "%s%s%s", t, a, e);
272 } else if (((unsigned int)r) != strlen(t) + strlen(a) + strlen(e)) {
281 static void build_times(char *cmd, GHashTable *ht_p2p, GHashTable *ht_p2d)
285 char *line = NULL, *dline = NULL, *pack = NULL, *date = NULL;
286 char *nm = NULL, *vr = NULL, *rl = NULL, *c = NULL, *p = NULL;
288 char name[] = "Name";
289 char version[] = "Version";
290 char release[] = "Release";
293 file = popen(cmd, "r");
296 while (!feof(file)) {
297 pack = nm = vr = rl = NULL;
298 if (getline(&line, &size, file) == -1)
300 if (!(nm = lookup_part(name, line)))
302 if (getline(&line, &size, file) == -1)
304 if (!(vr = lookup_part(version, line)))
306 if (getline(&line, &size, file) == -1)
308 if (!(rl = lookup_part(release, line)))
310 ret = asprintf(&pack, "%s-%s-%s", nm, vr, rl);
313 else if (((unsigned int)ret) != strlen(nm) + strlen(vr) + strlen(rl) + 2)
315 /* using p instead of pack to keep freeing the hashtables uniform */
316 if (!(p = g_hash_table_lookup(ht_p2p, pack)))
319 while (!feof(file)) {
321 if (getline(&dline, &size, file) == -1)
323 if (strncmp("*", dline, 1))
325 /* twice to skip the leading '*' */
326 c = strtok(dline, delim);
328 c = strtok(NULL, delim);
331 if (!(date = strdup(c)))
334 for (i = 0; i < 3; i++) {
335 c = strtok(NULL, delim);
336 if (!c) goto cleanup;
337 if ((ret = append(&date, c, " ")) < 0)
340 g_hash_table_insert(ht_p2d, p, date);
359 static char *get_package_info(char *appfile, char *dump_text)
361 GList *l = NULL, *files = NULL, *hfiles = NULL, *tmpl = NULL;
362 GHashTable *ht_f2f = NULL, *ht_f2p = NULL, *ht_p2p = NULL, *ht_p2d = NULL;
363 char *c1 = NULL, *cmd = NULL, *out = NULL;
364 char find_pkg[] = "rpm -qf --queryformat \"%{NAME}-%{VERSION}-%{RELEASE}\" ";
365 char find_date[] = "rpm -qi --changelog";
366 char dev_null[] = "2>/dev/null";
369 if (!(ht_f2f = g_hash_table_new(g_str_hash, g_str_equal)))
371 if (!(ht_f2p = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, free)))
373 if (!(ht_p2p = g_hash_table_new(g_str_hash, g_str_equal)))
375 if (!(ht_p2d = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, free)))
377 if (!(files = get_core_file_list(appfile, dump_text)))
380 /* get files in hash to remove duplicates */
381 for (l = files; l; l = l->next) {
382 if (!g_hash_table_lookup(ht_f2f, l->data))
383 g_hash_table_insert(ht_f2f, l->data, l->data);
386 hfiles = g_hash_table_get_keys(ht_f2f);
388 /* run through files one at a time in case some files don't have packages and it */
389 /* isn't guaranteed we will see the error correspond with the file we are testing */
390 for (l = hfiles; l; l = l->next) {
391 r = asprintf(&cmd, "%s%s %s", find_pkg, (char *)l->data, dev_null);
394 else if (((unsigned int)r) != sizeof(find_pkg) + sizeof((char *)l->data) + sizeof(dev_null) + 1) {
402 if (c1 && strlen(c1) > 0) {
403 g_hash_table_insert(ht_f2p, l->data, c1);
405 g_hash_table_insert(ht_f2p, l->data, NULL);
410 tmpl = g_hash_table_get_values(ht_f2p);
411 for (l = tmpl; l; l = l->next) {
412 if (l->data && !g_hash_table_lookup(ht_p2p, l->data))
413 g_hash_table_insert(ht_p2p, l->data, l->data);
418 tmpl = g_hash_table_get_keys(ht_p2p);
419 cmd = strdup(find_date);
422 for (l = tmpl; l; l = l->next) {
423 append(&cmd, l->data, " ");
427 build_times(cmd, ht_p2p, ht_p2d);
430 if (!(out = strdup("")))
432 for (l = hfiles; l; l = l->next) {
433 if (append(&out, l->data, "") < 0)
436 if (!(c1 = g_hash_table_lookup(ht_f2p, l->data))) {
437 if (append(&out, "\n", "") < 0)
441 if (append(&out, c1, ":") < 0)
444 if (!(c1 = g_hash_table_lookup(ht_p2d, c1))) {
445 if (append(&out, "\n", "") < 0)
449 if (append(&out, c1, ":") < 0)
452 if (append(&out, "\n", "") < 0)
463 g_hash_table_destroy(ht_p2d);
465 g_hash_table_destroy(ht_p2p);
467 g_hash_table_destroy(ht_f2p);
469 g_hash_table_destroy(ht_f2f);
471 g_list_free_full(files, free);
480 static char *signame(int sig)
483 case SIGINT: return "SIGINT";
484 case SIGILL: return "SIGILL";
485 case SIGABRT: return "SIGABRT";
486 case SIGFPE: return "SIGFPE";
487 case SIGSEGV: return "SIGSEGV";
488 case SIGPIPE: return "SIGPIPE";
489 case SIGBUS: return "SIGBUS";
490 default: return strsignal(sig);
495 static char *get_kernel(void)
501 char command[] = "uname -r";
503 file = popen(command, "r");
506 line = strdup("Unknown");
510 ret = getline(&line, &size, file);
511 if (!size || ret <= 0) {
513 line = strdup("Unknown");
518 line[size - 1] = '\0';
524 static char *build_core_header(char *appfile, char *corefile, char * processed_fullpath)
528 char *build = get_build();
529 char *release = get_release();
530 char *kernel = get_kernel();
531 long int time = get_time(corefile);
533 ret = asprintf(&result,
534 "analyzer: corewatcher-gdb\n"
538 "reason: Process %s was killed by signal %d (%s)\n"
546 appfile, sig, signame(sig),
557 result = strdup("Unknown");
563 * Scan core dump in case a wrapper was used
564 * to run the process and get the actual binary name
566 static char *wrapper_scan(char *command)
568 char *line = NULL, *appfile = NULL;
571 file = popen(command, "r");
575 while (!feof(file)) {
579 ret = getline(&line, &size, file);
585 if (strstr(line, "Core was generated by") &&
586 strstr(line, "--app")) {
587 /* attempt to update appfile */
588 appfile = set_wrapped_app(line);
600 * Strip the directories from the path
603 char *strip_directories(char *fullpath)
605 char *dfile = NULL, *c1 = NULL, *c2 = NULL, *r = NULL;
611 dfile = strdup(fullpath);
615 c1 = strtok(dfile, delim);
618 c1 = strtok(NULL, delim);
629 * Move corefile from /tmp to core_folder.
630 * Add extension if given and attempt to create core_folder.
632 int move_core(char *fullpath, char *extension)
634 char *corefn = NULL, newpath[8192];
636 if (!core_folder || !fullpath)
639 if (!(corefn = strip_directories(fullpath))) {
644 if (!mkdir(core_folder, S_IRWXU | S_IRWXG | S_IRWXO)
645 && errno != EEXIST) {
651 snprintf(newpath, 8192, "%s%s.%s", core_folder, corefn, extension);
653 snprintf(newpath, 8192, "%s%s", core_folder, corefn);
656 rename(fullpath, newpath);
662 * Finds the full path for the application that crashed,
663 * and depending on what opted_in was configured as will:
664 * opted_in 2 (always submit) -> move file to core_folder
665 * to be processed further
666 * opted_in 1 (ask user) -> ask user if we should submit
667 * the crash and add to asked_oops hash so we don't get
668 * called again for this corefile
669 * opted_in 0 (don't submit) -> do nothing
671 * Picks up and sets down the asked_mtx.
673 static char *get_appfile(char *fullpath)
675 char *appname = NULL, *appfile = NULL;
680 appname = find_coredump(fullpath);
684 /* don't try and do anything for rpm, gdb or corewatcher crashes */
685 if (!(strcmp(appname, "rpm") && strcmp(appname, "gdb") && strcmp(appname, "corewatcher")))
688 appfile = find_executable(appname);
689 /* appname no longer used, so free it as it was strdup'd */
695 dbus_say_found(fullpath, appfile);
696 move_core(fullpath, "to-process");
697 } else if (opted_in == 1) {
698 char *fp = NULL, *af = NULL;
699 if (!(fp = strdup(fullpath))) {
703 if (!(af = strdup(appfile))) {
708 dbus_ask_permission(fullpath, appfile);
709 /* If we got here the oops wasn't in the hash so add it */
710 pthread_mutex_lock(&core_status.asked_mtx);
711 g_hash_table_insert(core_status.asked_oops, fp, af);
712 pthread_mutex_unlock(&core_status.asked_mtx);
722 * Use GDB to extract backtrace information from corefile
724 static struct oops *extract_core(char *fullpath, char *appfile, char *processed_fullpath)
726 struct oops *oops = NULL;
728 char *command = NULL, *h1 = NULL, *h2 = NULL, *c1 = NULL, *c2 = NULL, *line = NULL, *text = NULL, *at = NULL;
730 char *private = private_report ? "private: yes\n" : "";
732 if (asprintf(&command, "LANG=C gdb --batch -f %s %s -x /var/lib/corewatcher/gdb.command 2> /dev/null", appfile, fullpath) == -1)
735 if ((at = wrapper_scan(command))) {
740 h1 = build_core_header(appfile, fullpath, processed_fullpath);
742 file = popen(command, "r");
744 while (file && !feof(file)) {
749 ret = getline(&line, &size, file);
755 if (strstr(line, "no debugging symbols found")) {
758 if (strstr(line, "reason: ")) {
764 if (asprintf(&c1, "%s%s", c2, line) == -1)
768 /* keep going even if asprintf has errors */
769 ret = asprintf(&c1, "%s", line);
777 if (!(h2 = get_package_info(appfile, c1)))
778 h2 = strdup("Unknown");
780 ret = asprintf(&text,
782 "package-info\n-----\n"
786 "\nbacktrace\n-----\n"
788 h1, h2, private, c1);
795 oops = malloc(sizeof(struct oops));
800 memset(oops, 0, sizeof(struct oops));
801 oops->application = strdup(appfile);
803 oops->filename = strdup(fullpath);
808 * filename is of the form core.XXXX[.blah]
809 * we need to get the pid out as we want
810 * output of the form XXXX[.ext]
812 char *get_core_filename(char *filename, char *ext)
814 char *pid = NULL, *c = NULL, *s = NULL, *detail_filename = NULL;
819 if (!(s = strstr(filename, ".")))
824 /* causes valgrind whining because we copy from middle of a string */
825 if (!(pid = strdup(s)))
828 c = strstr(pid, ".");
834 /* causes valgrind whining because we copy from middle of a string */
835 if ((asprintf(&detail_filename, "%s%s.%s", core_folder, pid, ext)) == -1) {
840 /* causes valgrind whining because we copy from middle of a string */
841 if ((asprintf(&detail_filename, "%s%s", core_folder, pid)) == -1) {
848 return detail_filename;
852 * Write the backtrace from the core file into a text
853 * file named after the pid
855 static void write_core_detail_file(char *filename, char *text)
858 char *detail_filename = NULL;
860 if (!filename || !text)
863 if (!(detail_filename = get_core_filename(filename, "txt")))
866 if ((fd = open(detail_filename, O_WRONLY | O_CREAT | O_TRUNC, 0)) != -1) {
867 if(write(fd, text, strlen(text)) >= 0)
870 unlink(detail_filename);
873 free(detail_filename);
877 * Removes corefile (core.XXXX) from the processing_queue.
879 * Expects the processing_queue_mtx to be held.
881 static void remove_from_processing_queue(void)
883 free(processing_queue[head]);
884 processing_queue[head++] = NULL;
891 * Removes file from processing_oops hash based on pid.
892 * Extracts pid from the fullpath such that
893 * /home/user/core.pid will be tranformed into just the pid.
895 * Expects the lock on the given hash to be held.
897 void remove_pid_from_hash(char *fullpath, GHashTable *ht)
899 char *c1 = NULL, *c2 = NULL;
901 if (!(c1 = strip_directories(fullpath)))
904 if (!(c2 = get_core_filename(c1, NULL))) {
911 g_hash_table_remove(ht, c2);
917 * Common function for processing core
918 * files to generate oops structures
920 static struct oops *process_common(char *fullpath, char *processed_fullpath)
922 struct oops *oops = NULL;
923 char *appname = NULL, *appfile = NULL;
925 if(!(appname = find_coredump(fullpath))) {
929 if (!(appfile = find_executable(appname))) {
935 if (!(oops = extract_core(fullpath, appfile, processed_fullpath))) {
946 * Processes .to-process core files.
947 * Also creates the pid.txt file and adds
948 * the oops struct to the submit queue
950 * Picks up and sets down the gdb_mtx and
951 * picks up and sets down the processing_queue_mtx.
952 * (held at the same time in that order)
953 * Also will pick up and sets down the queued_mtx.
955 static void *process_new(void __unused *vp)
957 struct oops *oops = NULL;
958 char *procfn = NULL, *corefn = NULL, *fullpath = NULL;
960 pthread_mutex_lock(&core_status.processing_mtx);
961 pthread_mutex_lock(&gdb_mtx);
962 pthread_mutex_lock(&processing_queue_mtx);
964 if (!(fullpath = processing_queue[head])) {
965 /* something went quite wrong */
966 pthread_mutex_unlock(&processing_queue_mtx);
967 pthread_mutex_unlock(&gdb_mtx);
968 pthread_mutex_unlock(&core_status.processing_mtx);
972 if (!(corefn = strip_directories(fullpath)))
973 goto clean_process_new;
975 if (!(procfn = replace_name(fullpath, ".to-process", ".processed")))
976 goto clean_process_new;
978 if (!(oops = process_common(fullpath, procfn)))
979 goto clean_process_new;
981 if (!(oops->detail_filename = get_core_filename(corefn, "txt")))
982 goto clean_process_new;
984 if (rename(fullpath, procfn))
985 goto clean_process_new;
987 free(oops->filename);
988 oops->filename = procfn;
990 remove_from_processing_queue();
992 pthread_mutex_unlock(&processing_queue_mtx);
993 pthread_mutex_unlock(&gdb_mtx);
994 pthread_mutex_unlock(&core_status.processing_mtx);
996 write_core_detail_file(corefn, oops->text);
998 pthread_mutex_lock(&core_status.queued_mtx);
999 queue_backtrace(oops);
1000 pthread_mutex_unlock(&core_status.queued_mtx);
1002 /* don't need to free procfn because was set to oops->filename and that gets free'd */
1008 remove_pid_from_hash(fullpath, core_status.processing_oops);
1009 remove_from_processing_queue();
1011 procfn = NULL; /* don't know if oops->filename == procfn so be safe */
1014 pthread_mutex_unlock(&processing_queue_mtx);
1015 pthread_mutex_unlock(&gdb_mtx);
1016 pthread_mutex_unlock(&core_status.processing_mtx);
1021 * Reprocesses .processed core files.
1023 * Picks up and sets down the gdb_mtx.
1024 * Picks up and sets down the processing_queue_mtx.
1025 * (held at the same time in that order)
1026 * Also will pick up and sets down the queued_mtx.
1028 static void *process_old(void __unused *vp)
1030 struct oops *oops = NULL;
1031 char *corefn = NULL, *fullpath = NULL;
1033 pthread_mutex_lock(&gdb_mtx);
1034 pthread_mutex_lock(&processing_queue_mtx);
1036 if (!(fullpath = processing_queue[head])) {
1037 /* something went quite wrong */
1038 pthread_mutex_unlock(&processing_queue_mtx);
1039 pthread_mutex_unlock(&gdb_mtx);
1043 if (!(corefn = strip_directories(fullpath)))
1044 goto clean_process_old;
1046 if (!(oops = process_common(fullpath, fullpath)))
1047 goto clean_process_old;
1049 if (!(oops->detail_filename = get_core_filename(corefn, "txt")))
1050 goto clean_process_old;
1052 remove_from_processing_queue();
1054 pthread_mutex_unlock(&processing_queue_mtx);
1055 pthread_mutex_unlock(&gdb_mtx);
1057 pthread_mutex_lock(&core_status.queued_mtx);
1058 queue_backtrace(oops);
1059 pthread_mutex_unlock(&core_status.queued_mtx);
1066 remove_pid_from_hash(fullpath, core_status.processing_oops);
1067 remove_from_processing_queue();
1070 pthread_mutex_unlock(&processing_queue_mtx);
1071 pthread_mutex_unlock(&gdb_mtx);
1076 * Adds corefile (based on pid) to the processing_oops
1077 * hash table if it is not already there, then
1078 * tries to add to the processing_queue.
1080 * Picks up and sets down the processing_mtx.
1081 * Picks up and sets down the processing_queue_mtx.
1083 static int add_to_processing(char *fullpath)
1085 char *c1 = NULL, *c2 = NULL, *fp = NULL;
1090 if (!(fp = strdup(fullpath)))
1091 goto clean_add_to_processing;
1093 if (!(c1 = get_core_filename(fp, NULL)))
1094 goto clean_add_to_processing;
1096 if (!(c2 = strip_directories(c1)))
1097 goto clean_add_to_processing;
1102 pthread_mutex_lock(&core_status.processing_mtx);
1103 if (g_hash_table_lookup(core_status.processing_oops, c2)) {
1104 pthread_mutex_unlock(&core_status.processing_mtx);
1105 goto clean_add_to_processing;
1108 pthread_mutex_lock(&processing_queue_mtx);
1109 if (processing_queue[tail]) {
1110 pthread_mutex_unlock(&processing_queue_mtx);
1111 pthread_mutex_unlock(&core_status.processing_mtx);
1112 goto clean_add_to_processing;
1115 g_hash_table_insert(core_status.processing_oops, c2, c2);
1116 processing_queue[tail++] = fp;
1120 pthread_mutex_unlock(&processing_queue_mtx);
1121 pthread_mutex_unlock(&core_status.processing_mtx);
1123 clean_add_to_processing:
1131 * Entry for processing new core files.
1133 static void process_corefile(char *fullpath)
1138 r = add_to_processing(fullpath);
1143 if (pthread_create(&thrd, NULL, process_new, NULL))
1144 fprintf(stderr, "Couldn't start up gdb extract core thread\n");
1148 * Entry for processing already seen core files.
1150 static void reprocess_corefile(char *fullpath)
1155 r = add_to_processing(fullpath);
1160 if (pthread_create(&thrd, NULL, process_old, NULL))
1161 fprintf(stderr, "Couldn't start up gdb extract core thread\n");
1164 int scan_corefolders(void __unused *unused)
1167 struct dirent *entry = NULL;
1168 char *fullpath = NULL, *appfile = NULL;
1169 char tmp_folder[] = "/tmp/";
1172 dir = opendir(tmp_folder);
1176 fprintf(stderr, "+ scanning %s...\n", tmp_folder);
1181 entry = readdir(dir);
1182 if (!entry || !entry->d_name)
1184 if (entry->d_name[0] == '.')
1186 if (strncmp(entry->d_name, "core.", 5))
1189 /* matched core.#### where #### is the processes pid */
1190 r = asprintf(&fullpath, "%s%s", tmp_folder, entry->d_name);
1194 } else if (((unsigned int)r) != strlen(tmp_folder) + strlen(entry->d_name)) {
1197 /* already found, waiting for response from user */
1198 pthread_mutex_lock(&core_status.asked_mtx);
1199 if (g_hash_table_lookup(core_status.asked_oops, fullpath)) {
1200 pthread_mutex_unlock(&core_status.asked_mtx);
1203 pthread_mutex_unlock(&core_status.asked_mtx);
1204 fprintf(stderr, "+ Looking at %s\n", fullpath);
1205 appfile = get_appfile(fullpath);
1218 dir = opendir(core_folder);
1222 fprintf(stderr, "+ scanning %s...\n", core_folder);
1227 entry = readdir(dir);
1228 if (!entry || !entry->d_name)
1230 if (entry->d_name[0] == '.')
1232 if (!strstr(entry->d_name, "process"))
1235 r = asprintf(&fullpath, "%s%s", core_folder, entry->d_name);
1239 } else if (((unsigned int)r) != strlen(core_folder) + strlen(entry->d_name)) {
1243 fprintf(stderr, "+ Looking at %s\n", fullpath);
1244 if (strstr(fullpath, "to-process"))
1245 process_corefile(fullpath);
1247 reprocess_corefile(fullpath);