From 13c2cf2fa8cefbbef2a22df7c56323d77e379bc3 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sun, 20 Feb 2011 23:46:28 +0000 Subject: [PATCH] - wrapper: add optional element in elements; specifies an environment variable assignment; macro-substitute project dir for $PROJECT_DIR. From Carl Christensen svn path=/trunk/boinc/; revision=23076 --- checkin_notes | 9 ++++ samples/wrapper/wrapper.cpp | 89 +++++++++++++++++++++++++++---------- 2 files changed, 74 insertions(+), 24 deletions(-) diff --git a/checkin_notes b/checkin_notes index 4db72f3aaf..ce6bef45d6 100644 --- a/checkin_notes +++ b/checkin_notes @@ -937,3 +937,12 @@ David 19 Feb 2011 samples/wrapper/ wrapper.cpp + +David 19 Feb 2011 + - wrapper: add optional element in elements; + specifies an environment variable assignment; + macro-substitute project dir for $PROJECT_DIR. + From Carl Christensen + + samples/wrapper/ + wrapper.cpp diff --git a/samples/wrapper/wrapper.cpp b/samples/wrapper/wrapper.cpp index 77da9840bd..313f11af3f 100644 --- a/samples/wrapper/wrapper.cpp +++ b/samples/wrapper/wrapper.cpp @@ -63,6 +63,7 @@ struct TASK { string application; string exec_dir; // optional execution directory; macro-substituted for $PROJECT_DIR + vector vsetenv; // vector of strings for environment variables string stdin_filename; string stdout_filename; string stderr_filename; @@ -89,6 +90,8 @@ struct TASK { struct stat last_stat; #endif bool stat_first; + + int parse_wrapper_macros(char* buf, const int len); int parse(XML_PARSER&); bool poll(int& status); int run(int argc, char** argv); @@ -121,19 +124,49 @@ struct TASK { if (frac > 1) return 1; return frac; } + + void set_up_env_vars(char*** env_vars, const int nvars) { + *env_vars = new char*[nvars+1]; + // need one more than the # of vars, for a NULL ptr at the end + memset(*env_vars, 0x00, sizeof(char*) * (nvars+1)); + // get all environment vars for this task + for (int i = 0; i < nvars; i++) { + (*env_vars)[i] = (char*) vsetenv[i].c_str(); + } + } }; vector tasks; APP_INIT_DATA aid; bool graphics = false; +// macro replacement in wrapper strings from job.xml +// for example PROJECT_DIR can be replaced in exec_dir and environment variables +// +int TASK::parse_wrapper_macros(char* buf, const int iLen = 8192) { + char* buf2 = new char[iLen]; + while (1) { + char* p = strstr(buf, "$PROJECT_DIR"); + if (!p) break; + strcpy(buf2, p+strlen("$PROJECT_DIR")); + if (strlen(aid.project_dir) > 0) { + strcpy(p, aid.project_dir); + } else { + strcpy(p, "."); + } + strcat(p, buf2); + } + delete [] buf2; +} + int TASK::parse(XML_PARSER& xp) { - char tag[1024], buf[8192], buf2[8192]; + char tag[1024], buf[8192]; bool is_tag; weight = 1; final_cpu_time = 0; stat_first = true; + while (!xp.get(tag, sizeof(tag), is_tag)) { if (!is_tag) { fprintf(stderr, "%s TASK::parse(): unexpected text %s\n", @@ -146,32 +179,20 @@ int TASK::parse(XML_PARSER& xp) { } else if (xp.parse_string(tag, "application", application)) continue; else if (xp.parse_str(tag, "exec_dir", buf, sizeof(buf))) { - while (1) { - char* p = strstr(buf, "$PROJECT_DIR"); - if (!p) break; - strcpy(buf2, p+strlen("$PROJECT_DIR")); - if (strlen(aid.project_dir) > 0) { - strcpy(p, aid.project_dir); - } else { - strcpy(p, "."); - } - strcat(p, buf2); - } + parse_wrapper_macros(buf, 8192); exec_dir = buf; - //fprintf(stderr, "Found exec_dir = %s\n", exec_dir.c_str()); - continue; + continue; + } + else if (xp.parse_str(tag, "setenv", buf, sizeof(buf))) { + parse_wrapper_macros(buf, 8192); + vsetenv.push_back(buf); + continue; } else if (xp.parse_string(tag, "stdin_filename", stdin_filename)) continue; else if (xp.parse_string(tag, "stdout_filename", stdout_filename)) continue; else if (xp.parse_string(tag, "stderr_filename", stderr_filename)) continue; else if (xp.parse_str(tag, "command_line", buf, sizeof(buf))) { - while (1) { - char* p = strstr(buf, "$PROJECT_DIR"); - if (!p) break; - strcpy(buf2, p+strlen("$PROJECT_DIR")); - strcpy(p, aid.project_dir); - strcat(p, buf2); - } + parse_wrapper_macros(buf, 8192); command_line = buf; continue; } @@ -336,6 +357,14 @@ int TASK::run(int argct, char** argvt) { startup_info.hStdError = win_fopen(STDERR_FILE, "a"); } + // setup environment vars if needed + // + int nvars = vsetenv.size(); + char** env_vars = NULL; + if (nvars > 0) { + set_up_env_vars(&env_vars, nvars); + } + if (!CreateProcess( app_path, (LPSTR)command.c_str(), @@ -343,7 +372,7 @@ int TASK::run(int argct, char** argvt) { NULL, TRUE, // bInheritHandles CREATE_NO_WINDOW|IDLE_PRIORITY_CLASS, - NULL, + (LPVOID) env_vars, exec_dir.empty()?NULL:exec_dir.c_str(), &startup_info, &process_info @@ -353,6 +382,7 @@ int TASK::run(int argct, char** argvt) { fprintf(stderr, "can't run app: %s\n", error_msg); return ERR_EXEC; } + if (env_vars) delete [] env_vars; pid_handle = process_info.hProcess; pid = process_info.dwProcessId; thread_handle = process_info.hThread; @@ -409,10 +439,21 @@ int TASK::run(int argct, char** argvt) { ); #endif } - retval = execv(app_path, argv); + + // setup environment variables (if any) + // + const int nvars = vsetenv.size(); + char** env_vars = NULL; + if (nvars > 0) { + set_up_env_vars(&env_vars, nvars); + retval = execve(app_path, argv, env_vars); + } else { + retval = execv(app_path, argv); + } + if (env_vars) delete [] env_vars; // never really gets here after the execve perror("execv() failed: "); exit(ERR_EXEC); - } + } // pid = 0 i.e. child proc of the fork #endif wall_cpu_time = 0; suspended = false;