mirror of https://github.com/BOINC/boinc.git
Condor interface: various fixes, mostly from Jaime Frey
- XML parser: for parse_string(), malloc the 256KB buffer instead of allocating it on the stack; the latter crashes threads with 32KB stacks. However, do the malloc() only if we've actually seen the start tag (this required a bit of code shuffle). - BOINC GAHP: escape spaces in error msgs
This commit is contained in:
parent
f30097d175
commit
8009a8cecb
|
@ -540,18 +540,9 @@ int XML_PARSER::scan_cdata(char* buf, int len) {
|
|||
}
|
||||
}
|
||||
|
||||
#define MAX_XML_STRING 262144
|
||||
|
||||
// We just parsed "parsed_tag".
|
||||
// If it matches "start_tag", and is followed by a string
|
||||
// and by the matching close tag, return the string in "buf",
|
||||
// and return true.
|
||||
//
|
||||
bool XML_PARSER::parse_str(const char* start_tag, char* buf, int len) {
|
||||
bool eof;
|
||||
char end_tag[TAG_BUF_LEN], tag[TAG_BUF_LEN];
|
||||
|
||||
static inline bool is_empty_string(char* parsed_tag, const char* start_tag) {
|
||||
size_t n = strlen(parsed_tag);
|
||||
char tag[TAG_BUF_LEN];
|
||||
|
||||
// handle the archaic form <tag/>, which means empty string
|
||||
//
|
||||
|
@ -559,14 +550,17 @@ bool XML_PARSER::parse_str(const char* start_tag, char* buf, int len) {
|
|||
strcpy(tag, parsed_tag);
|
||||
tag[n-1] = 0;
|
||||
if (!strcmp(tag, start_tag)) {
|
||||
strcpy(buf, "");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// check for start tag
|
||||
//
|
||||
if (strcmp(parsed_tag, start_tag)) return false;
|
||||
// we've parsed the start tag of a string; parse the string itself.
|
||||
//
|
||||
bool XML_PARSER::parse_str_aux(const char* start_tag, char* buf, int len) {
|
||||
bool eof;
|
||||
char end_tag[TAG_BUF_LEN], tag[TAG_BUF_LEN];
|
||||
|
||||
end_tag[0] = '/';
|
||||
strcpy(end_tag+1, start_tag);
|
||||
|
@ -598,12 +592,37 @@ bool XML_PARSER::parse_str(const char* start_tag, char* buf, int len) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// We just parsed "parsed_tag".
|
||||
// If it matches "start_tag", and is followed by a string
|
||||
// and by the matching close tag, return the string in "buf",
|
||||
// and return true.
|
||||
//
|
||||
bool XML_PARSER::parse_str(const char* start_tag, char* buf, int len) {
|
||||
if (is_empty_string(parsed_tag, start_tag)) {
|
||||
strcpy(buf, "");
|
||||
return true;
|
||||
}
|
||||
if (strcmp(parsed_tag, start_tag)) return false;
|
||||
return parse_str_aux(start_tag, buf, len);
|
||||
}
|
||||
|
||||
#define MAX_XML_STRING 262144
|
||||
|
||||
// same, for std::string
|
||||
//
|
||||
bool XML_PARSER::parse_string(const char* start_tag, string& str) {
|
||||
char buf[MAX_XML_STRING];
|
||||
bool flag = parse_str(start_tag, buf, sizeof(buf));
|
||||
if (!flag) return false;
|
||||
str = buf;
|
||||
return true;
|
||||
if (is_empty_string(parsed_tag, start_tag)) {
|
||||
str = "";
|
||||
return true;
|
||||
}
|
||||
if (strcmp(parsed_tag, start_tag)) return false;
|
||||
char *buf=(char *)malloc(MAX_XML_STRING);
|
||||
bool flag = parse_str_aux(start_tag, buf, MAX_XML_STRING);
|
||||
if (flag) {
|
||||
str = buf;
|
||||
}
|
||||
free(buf);
|
||||
return flag;
|
||||
}
|
||||
|
||||
// Same, for integers
|
||||
|
|
31
lib/parse.h
31
lib/parse.h
|
@ -244,7 +244,10 @@ struct XML_PARSER {
|
|||
strip_whitespace(buf);
|
||||
return retval;
|
||||
}
|
||||
bool parse_str_aux(const char*, char*, int);
|
||||
|
||||
// interface starts here
|
||||
//
|
||||
bool parse_start(const char*);
|
||||
bool parse_str(const char*, char*, int);
|
||||
bool parse_string(const char*, std::string&);
|
||||
|
@ -332,34 +335,6 @@ inline bool parse_double(const char* buf, const char* tag, double& x) {
|
|||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Same, for unsigned long
|
||||
//
|
||||
inline bool parse_ulong(const char* buf, const char* tag, unsigned long& x) {
|
||||
const char* p = strstr(buf, tag);
|
||||
if (!p) return false;
|
||||
errno = 0;
|
||||
unsigned long y = strtoul(p+strlen(tag), NULL, 0);
|
||||
if (errno) return false;
|
||||
x = y;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Same, for unsigned long long
|
||||
//
|
||||
inline bool parse_ulonglong(
|
||||
const char* buf, const char* tag, unsigned long long& x
|
||||
) {
|
||||
const char* p = strstr(buf, tag);
|
||||
if (!p) return false;
|
||||
errno = 0;
|
||||
unsigned long long y = boinc_strtoull(p+strlen(tag), NULL, 0);
|
||||
if (errno) return false;
|
||||
x = y;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern bool parse(char* , char* );
|
||||
extern bool parse_str(const char*, const char*, char*, int);
|
||||
extern bool parse_str(const char* buf, const char* tag, std::string& dest);
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
// test program for XML parser
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
using std::string;
|
||||
|
||||
#include "parse.h"
|
||||
|
||||
|
@ -12,6 +15,7 @@ void parse(FILE* f) {
|
|||
char foo[64];
|
||||
int val;
|
||||
double x;
|
||||
string s;
|
||||
|
||||
strcpy(name, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
|
||||
mf.init_file(f);
|
||||
|
@ -29,8 +33,9 @@ void parse(FILE* f) {
|
|||
if (xp.match_tag("/blah")) {
|
||||
printf("success\n");
|
||||
return;
|
||||
} else if (xp.parse_str("str", name, 33)) {
|
||||
printf("got str: [%s]\n", name);
|
||||
} else if (xp.parse_str("str", name, 64)) {
|
||||
//} else if (xp.parse_string("str", s)) {
|
||||
printf("got str: [%s]\n", s.c_str());
|
||||
} else if (xp.parse_int("int", val)) {
|
||||
printf("got int: %d\n", val);
|
||||
} else if (xp.parse_double("double", x)) {
|
||||
|
|
|
@ -317,7 +317,7 @@ int submit_jobs(
|
|||
error_msg = "";
|
||||
int temp;
|
||||
while (fgets(buf, 256, reply)) {
|
||||
printf("submit_batch reply: %s", buf);
|
||||
//printf("submit_batch reply: %s", buf);
|
||||
if (parse_int(buf, "<batch_id>", temp)) {
|
||||
retval = 0;
|
||||
continue;
|
||||
|
@ -527,7 +527,7 @@ int get_output_file(
|
|||
sprintf(url, "%sget_output.php?cmd=workunit_file&auth_str=%s&wu_name=%s&file_num=%d",
|
||||
project_url, authenticator, job_name, file_num
|
||||
);
|
||||
printf("fetching %s to %s\n", url, dst_path);
|
||||
//printf("fetching %s to %s\n", url, dst_path);
|
||||
int retval = do_http_get(url, dst_path);
|
||||
error_msg = "";
|
||||
if (retval) {
|
||||
|
|
|
@ -87,6 +87,24 @@ int compute_md5(string path, LOCAL_FILE& f) {
|
|||
return md5_file(path.c_str(), f.md5, f.nbytes);
|
||||
}
|
||||
|
||||
const char *escape_str(const string &str)
|
||||
{
|
||||
static string out;
|
||||
out = "";
|
||||
for ( const char *ptr = str.c_str(); *ptr; ptr++ ) {
|
||||
switch ( *ptr ) {
|
||||
case ' ':
|
||||
case '\\':
|
||||
case '\r':
|
||||
case '\n':
|
||||
out += '\\';
|
||||
default:
|
||||
out += *ptr;
|
||||
}
|
||||
}
|
||||
return out.c_str();
|
||||
}
|
||||
|
||||
// Get a list of the input files used by the batch.
|
||||
// Get their MD5s.
|
||||
// See if they're already on the server.
|
||||
|
@ -206,8 +224,8 @@ void handle_submit(COMMAND& c) {
|
|||
project_url, authenticator, req.app_name, NULL, td, error_msg
|
||||
);
|
||||
if (retval) {
|
||||
sprintf(buf, "error getting templates: %d\n", retval);
|
||||
s = string(buf) + error_msg;
|
||||
sprintf(buf, "error\\ getting\\ templates:\\ %d\\ ", retval);
|
||||
s = string(buf) + escape_str(error_msg);
|
||||
c.out = strdup(s.c_str());
|
||||
return;
|
||||
}
|
||||
|
@ -215,22 +233,22 @@ void handle_submit(COMMAND& c) {
|
|||
project_url, authenticator, req.batch_name, req.app_name, req.batch_id, error_msg
|
||||
);
|
||||
if (retval) {
|
||||
sprintf(buf, "error creating batch: %d ", retval);
|
||||
s = string(buf) + error_msg;
|
||||
sprintf(buf, "error\\ creating\\ batch:\\ %d\\ ", retval);
|
||||
s = string(buf) + escape_str(error_msg);
|
||||
c.out = strdup(s.c_str());
|
||||
return;
|
||||
}
|
||||
retval = process_input_files(req, error_msg);
|
||||
if (retval) {
|
||||
sprintf(buf, "error processing input files: %d ", retval);
|
||||
s = string(buf) + error_msg;
|
||||
sprintf(buf, "error\\ processing\\ input\\ files:\\ %d\\ ", retval);
|
||||
s = string(buf) + escape_str(error_msg);
|
||||
c.out = strdup(s.c_str());
|
||||
return;
|
||||
}
|
||||
retval = submit_jobs(project_url, authenticator, req, error_msg);
|
||||
if (retval) {
|
||||
sprintf(buf, "error submitting jobs: %d ", retval);
|
||||
s = string(buf) + error_msg;
|
||||
sprintf(buf, "error\\ submitting\\ jobs:\\ %d\\ ", retval);
|
||||
s = string(buf) + escape_str(error_msg);
|
||||
} else {
|
||||
s = "NULL";
|
||||
}
|
||||
|
@ -254,13 +272,15 @@ void handle_query_batches(COMMAND&c) {
|
|||
project_url, authenticator, c.batch_names, reply, error_msg
|
||||
);
|
||||
if (retval) {
|
||||
sprintf(buf, "error querying batch: %d ", retval);
|
||||
s = string(buf) + error_msg;
|
||||
sprintf(buf, "error\\ querying\\ batch:\\ %d\\ ", retval);
|
||||
s = string(buf) + escape_str(error_msg);
|
||||
} else {
|
||||
s = string("NULL ");
|
||||
sprintf(buf, "%d", (int)reply.jobs.size());
|
||||
s += string(buf);
|
||||
for (unsigned int i=0; i<reply.jobs.size(); i++) {
|
||||
QUERY_BATCH_JOB &j = reply.jobs[i];
|
||||
sprintf(buf, "%s %s ", j.job_name.c_str(), j.status.c_str());
|
||||
sprintf(buf, " %s %s", j.job_name.c_str(), j.status.c_str());
|
||||
s += string(buf);
|
||||
}
|
||||
}
|
||||
|
@ -339,8 +359,8 @@ void handle_fetch_output(COMMAND& c) {
|
|||
project_url, authenticator, NULL, req.job_name, td, error_msg
|
||||
);
|
||||
if (retval) {
|
||||
sprintf(buf, "error getting templates: %d\n", retval);
|
||||
s = string(buf) + error_msg;
|
||||
sprintf(buf, "error\\ getting\\ templates:\\ %d\\ ", retval);
|
||||
s = string(buf) + escape_str(error_msg);
|
||||
c.out = strdup(s.c_str());
|
||||
return;
|
||||
}
|
||||
|
@ -351,8 +371,8 @@ void handle_fetch_output(COMMAND& c) {
|
|||
project_url, authenticator, req.job_name, cjd, error_msg
|
||||
);
|
||||
if (retval) {
|
||||
sprintf(buf, "query_completed_job() returned %d ", retval);
|
||||
s = string(buf) + error_msg;
|
||||
sprintf(buf, "query_completed_job()\\ returned\\ %d\\ ", retval);
|
||||
s = string(buf) + escape_str(error_msg);
|
||||
goto done;
|
||||
}
|
||||
sprintf(buf, " %d %f %f", cjd.exit_status, cjd.elapsed_time, cjd.cpu_time);
|
||||
|
@ -364,7 +384,7 @@ void handle_fetch_output(COMMAND& c) {
|
|||
sprintf(path, "%s/%s", req.dir, req.stderr_filename.c_str());
|
||||
FILE* f = fopen(path, "w");
|
||||
if (!f) {
|
||||
sprintf(buf, "can't open stderr output file %s ", path);
|
||||
sprintf(buf, "can't\\ open\\ stderr\\ output\\ file\\ %s ", path);
|
||||
s = string(buf);
|
||||
goto done;
|
||||
}
|
||||
|
@ -380,13 +400,13 @@ void handle_fetch_output(COMMAND& c) {
|
|||
project_url, authenticator, req.job_name, 0, path, error_msg
|
||||
);
|
||||
if (retval) {
|
||||
sprintf(buf, "get_output_file() returned %d ", retval);
|
||||
s = string(buf) + error_msg;
|
||||
sprintf(buf, "get_output_file()\\ returned\\ %d\\ ", retval);
|
||||
s = string(buf) + escape_str(error_msg);
|
||||
} else {
|
||||
sprintf(buf, "cd %s; unzip temp.zip");
|
||||
retval = system(buf);
|
||||
if (retval) {
|
||||
s = string("unzip failed");
|
||||
s = string("unzip\\ failed");
|
||||
}
|
||||
}
|
||||
} else if (req.fetch_all) {
|
||||
|
@ -396,8 +416,8 @@ void handle_fetch_output(COMMAND& c) {
|
|||
project_url, authenticator, req.job_name, i, path, error_msg
|
||||
);
|
||||
if (retval) {
|
||||
sprintf(buf, "get_output_file() returned %d ", retval);
|
||||
s = string(buf) + error_msg;
|
||||
sprintf(buf, "get_output_file()\\ returned\\ %d\\ ", retval);
|
||||
s = string(buf) + escape_str(error_msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -406,7 +426,7 @@ void handle_fetch_output(COMMAND& c) {
|
|||
char* lname = req.file_descs[i].src;
|
||||
int j = output_file_index(td, lname);
|
||||
if (j < 0) {
|
||||
sprintf(buf, "requested file %s not in template", lname);
|
||||
sprintf(buf, "requested\\ file\\ %s\\ not\\ in\\ template", lname);
|
||||
s = string(buf);
|
||||
goto done;
|
||||
}
|
||||
|
@ -415,8 +435,8 @@ void handle_fetch_output(COMMAND& c) {
|
|||
project_url, authenticator, req.job_name, i, path, error_msg
|
||||
);
|
||||
if (retval) {
|
||||
sprintf(buf, "get_output_file() returned %d ", retval);
|
||||
s = string(buf) + error_msg;
|
||||
sprintf(buf, "get_output_file()\\ returned\\ %d\\ ", retval);
|
||||
s = string(buf) + escape_str(error_msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -438,7 +458,7 @@ void handle_fetch_output(COMMAND& c) {
|
|||
sprintf(buf, "mv %s/%s %s", req.dir, of.src, dst_path);
|
||||
retval = system(buf);
|
||||
if (retval) {
|
||||
s = string("mv failed");
|
||||
s = string("mv\\ failed");
|
||||
}
|
||||
}
|
||||
done:
|
||||
|
@ -464,8 +484,8 @@ void handle_abort_jobs(COMMAND& c) {
|
|||
string s;
|
||||
char buf[256];
|
||||
if (retval) {
|
||||
sprintf(buf, "abort_jobs() returned %d \n", retval);
|
||||
s = string(buf) + error_msg;
|
||||
sprintf(buf, "abort_jobs()\\ returned\\ %d\\ ", retval);
|
||||
s = string(buf) + escape_str(error_msg);
|
||||
} else {
|
||||
s = "NULL";
|
||||
}
|
||||
|
@ -477,8 +497,8 @@ void handle_ping(COMMAND& c) {
|
|||
char buf[256];
|
||||
int retval = ping_server(project_url, error_msg);
|
||||
if (retval) {
|
||||
sprintf(buf, "ping_server returned %d \n", retval);
|
||||
s = string(buf) + error_msg;
|
||||
sprintf(buf, "ping_server\\ returned\\ %d\\ ", retval);
|
||||
s = string(buf) + escape_str(error_msg);
|
||||
} else {
|
||||
s = "NULL";
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue