2 * Copyright 2007, Intel Corporation
4 * This file is part of corewatcher.org
6 * This program file is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * You should have received a copy of the GNU General Public License
16 * along with this program in a file named COPYING; if not, write to the
17 * Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
22 * Arjan van de Ven <arjan@linux.intel.com>
33 #include <asm/unistd.h>
35 #include <curl/curl.h>
37 #include "corewatcher.h"
41 * we keep track of 16 checksums of the last submitted oopses; this allows us to
42 * make sure we don't submit the same oops twice (this allows us to not have to do
43 * really expensive things during non-destructive dmesg-scanning)
45 * This also limits the number of oopses we'll submit per session;
46 * it's important that this is bounded to avoid feedback loops
47 * for the scenario where submitting an oopses causes a warning/oops
49 #define MAX_CHECKSUMS 16
50 static unsigned int checksums[MAX_CHECKSUMS];
58 unsigned int checksum;
61 /* we queue up oopses, and then submit in a batch.
62 * This is useful to be able to cancel all submissions, in case
63 * we later find our marker indicating we submitted everything so far already
66 static struct oops *queued_backtraces;
69 /* For communicating details to the applet, we write the
70 * details in a file, and provide the filename to the applet
72 static char *detail_filename;
75 static unsigned int checksum(char *ptr)
77 unsigned int temp = 0;
79 c = (unsigned char *) ptr;
87 void queue_backtrace(char *oops)
93 if (submitted >= MAX_CHECKSUMS-1)
95 /* first, check if we haven't already submitted the oops */
97 for (i = 0; i < submitted; i++) {
98 if (checksums[i] == sum) {
99 printf("Match with oops %i (%x)\n", i, sum);
103 checksums[submitted++] = sum;
105 new = malloc(sizeof(struct oops));
106 memset(new, 0, sizeof(struct oops));
107 new->next = queued_backtraces;
109 new->text = strdup(oops);
110 queued_backtraces = new;
115 void write_detail_file(void)
122 detail_filename = strdup("/tmp/corewatcher.XXXXXX");
123 temp_fileno = mkstemp(detail_filename);
124 if (temp_fileno < 0) {
125 free(detail_filename);
126 detail_filename = NULL;
129 /* regular user must be able to read this detail file to be
130 * useful; there is nothing worth doing if fchmod fails.
132 fchmod(temp_fileno, 0644);
133 tmpf = fdopen(temp_fileno, "w");
134 oops = queued_backtraces;
136 count++; /* Users are not programmers, start at 1 */
137 fprintf(tmpf, "Application failure message %d:\n", count);
138 fprintf(tmpf, "%s", oops->text);
139 fprintf(tmpf, "\n\n");
146 void unlink_detail_file(void)
148 if (detail_filename) {
149 unlink(detail_filename);
150 free(detail_filename);
155 static void print_queue(void)
161 queue = queued_backtraces;
162 queued_backtraces = NULL;
168 printf("Submit text is:\n---[start of oops]---\n%s\n---[end of oops]---\n", oops->text);
178 static void write_logfile(int count)
180 openlog("corewatcher", 0, LOG_KERN);
181 syslog(LOG_WARNING, "Submitted %i coredump signatures to %s", count, submit_url);
185 char result_url[4096];
187 size_t writefunction( void *ptr, size_t size, size_t nmemb, void __attribute((unused)) *stream)
190 c = malloc(size*nmemb + 1);
191 memset(c, 0, size*nmemb + 1);
192 memcpy(c, ptr, size*nmemb);
193 printf("received %s \n", c);
194 c1 = strstr(c, "201 ");
197 c2 = strchr(c1, '\n');
199 strncpy(result_url, c1, 4095);
204 void submit_queue(void)
211 memset(result_url, 0, 4096);
218 queue = queued_backtraces;
219 queued_backtraces = NULL;
224 struct curl_httppost *post = NULL;
225 struct curl_httppost *last = NULL;
228 handle = curl_easy_init();
230 printf("DEBUG SUBMIT URL is %s \n", submit_url);
231 curl_easy_setopt(handle, CURLOPT_URL, submit_url);
233 /* set up the POST data */
234 curl_formadd(&post, &last,
235 CURLFORM_COPYNAME, "backtracedata",
236 CURLFORM_COPYCONTENTS, oops->text, CURLFORM_END);
238 if (allow_distro_to_pass_on) {
239 curl_formadd(&post, &last,
240 CURLFORM_COPYNAME, "pass_on_allowed",
241 CURLFORM_COPYCONTENTS, "yes", CURLFORM_END);
244 curl_easy_setopt(handle, CURLOPT_HTTPPOST, post);
245 curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, writefunction);
246 result = curl_easy_perform(handle);
249 curl_easy_cleanup(handle);
257 if (count && !testmode)
258 write_logfile(count);
261 dbus_say_thanks(result_url);
263 * If we've reached the maximum count, we'll exit the program,
264 * the program won't do any useful work anymore going forward.
266 if (submitted >= MAX_CHECKSUMS-1) {
267 unlink_detail_file();
272 void clear_queue(void)
274 struct oops *oops, *next;
277 queue = queued_backtraces;
278 queued_backtraces = NULL;
290 void ask_permission(void)
292 if (!newoops && !pinged)
296 if (queued_backtraces) {
298 dbus_ask_permission(detail_filename);