|
|
| version 1.48.2.18.2.16, 2003/04/08 16:11:54 | version 1.65.8.1, 2005/08/05 13:03:01 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: program executing for different OS-es. | Parser: program executing for different OS-es. |
| Copyright(c) 2000,2001-2003 ArtLebedev Group(http://www.artlebedev.com) | Copyright(c) 2000,2001-2005 ArtLebedev Group(http://www.artlebedev.com) |
| Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) | Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) |
| @todo setrlimit | @todo setrlimit |
| */ | */ |
| static const char* IDENT_EXEC_C="$Date$"; | static const char * const IDENT_EXEC_C="$Date$"; |
| #include "pa_config_includes.h" | #include "pa_config_includes.h" |
| Line 27 static const char* IDENT_EXEC_C="$Date$" | Line 27 static const char* IDENT_EXEC_C="$Date$" |
| /// this func from http://www.ccas.ru/~posp/popov/spawn.htm | /// this func from http://www.ccas.ru/~posp/popov/spawn.htm |
| static DWORD CreateHiddenConsoleProcess(LPCTSTR szCmdLine, | static DWORD CreateHiddenConsoleProcess(LPCTSTR szCmdLine, |
| LPCTSTR szScriptFileSpec, | |
| char *szEnv, | char *szEnv, |
| PROCESS_INFORMATION* ppi, | PROCESS_INFORMATION* ppi, |
| LPHANDLE phInWrite, | LPHANDLE phInWrite, |
| Line 72 static DWORD CreateHiddenConsoleProcess( | Line 73 static DWORD CreateHiddenConsoleProcess( |
| // calculating script's directory | // calculating script's directory |
| char dir[MAX_STRING]; | char dir[MAX_STRING]; |
| strncpy(dir, szCmdLine, MAX_STRING-1); dir[MAX_STRING-1]=0; | strncpy(dir, szScriptFileSpec, MAX_STRING-1); dir[MAX_STRING-1]=0; |
| lsplit(dir,' '); // trim arguments | lsplit(dir,' '); // trim arguments |
| rsplit(dir,'/'); rsplit(dir,'\\'); // trim filename | rsplit(dir,'/'); rsplit(dir,'\\'); // trim filename |
| chdir(dir); | |
| // Create a child process (suspended) | // Create a child process (suspended) |
| fCreated=CreateProcess(NULL, | fCreated=CreateProcess(NULL, |
| Line 132 static const char* buildCommand(const ch | Line 132 static const char* buildCommand(const ch |
| buf[size]=0; | buf[size]=0; |
| if(strncmp(buf, "#!", 2)==0) { | if(strncmp(buf, "#!", 2)==0) { |
| const char* begin=buf+2; | const char* begin=buf+2; |
| if(*begin==' ') // alx: were an old magic for some linux-es | while(*begin==' ') // alx: were an old magic for some linux-es |
| begin++; | begin++; |
| if(char *end=strchr(begin, '\n')) { | if(char *end=strchr(begin, '\n')) { |
| String string(begin, end-begin); | String string(pa_strdup(begin, end-begin)); |
| string << " " << file_spec_cstr; | string << " " << file_spec_cstr; |
| result=string.cstr(); | result=string.cstr(); |
| } | } |
| Line 271 static pid_t execve_piped(const char* fi | Line 271 static pid_t execve_piped(const char* fi |
| static int get_exit_status(int pid) { | static int get_exit_status(int pid) { |
| int status; | int status; |
| if(!waitpid(pid, &status, 0)) | pid_t cid; |
| while ((cid=waitpid(pid, &status, WUNTRACED)) == -1 && errno == EINTR); | |
| if(!cid) | |
| return -1; | return -1; |
| return WIFEXITED(status) ? | return WIFEXITED(status) ? |
| WEXITSTATUS(status) : -2; | WEXITSTATUS(status) : -2; |
| Line 293 static void read_pipe(String& result, in | Line 295 static void read_pipe(String& result, in |
| #ifndef DOXYGEN | #ifndef DOXYGEN |
| struct Append_env_pair_info { | struct Append_env_pair_info { |
| #ifdef WIN32 | #ifdef WIN32 |
| String& string; | String::Body& body; |
| Append_env_pair_info(String& astring): string(astring) {} | Append_env_pair_info(String::Body& abody): body(abody) {} |
| #else | #else |
| char **env_ref; | char **env_ref; |
| #endif | #endif |
| Line 304 struct Append_env_pair_info { | Line 306 struct Append_env_pair_info { |
| static void append_env_pair(HashStringString::key_type key, HashStringString::value_type value, | static void append_env_pair(HashStringString::key_type key, HashStringString::value_type value, |
| Append_env_pair_info *info) { | Append_env_pair_info *info) { |
| #ifdef WIN32 | #ifdef WIN32 |
| info->string << key << "=" << value; | info->body << key << "=" << value; |
| info->string.append_know_length("", 1, String::L_AS_IS); // zero byte | info->body.append_know_length("\1", 1); // placeholder for of zero byte |
| #else | #else |
| StringBody body; | String::Body body; |
| body << key << "=" << value; | body << key << "=" << value.cstr(); |
| *(info->env_ref++)=body.cstrm(); | *(info->env_ref++)=body.cstrm(); |
| #endif | #endif |
| } | } |
| /// @todonow unix part to smart_ptr | |
| PA_exec_result pa_exec( | PA_exec_result pa_exec( |
| bool forced_allow, | bool |
| #if defined(NO_PA_EXEC) || defined(PA_SAFE_MODE) | |
| forced_allow | |
| #endif | |
| , | |
| const String& file_spec, | const String& file_spec, |
| const HashStringString* env, | const HashStringString* env, |
| const ArrayString& argv, | const ArrayString& argv, |
| Line 330 PA_exec_result pa_exec( | Line 335 PA_exec_result pa_exec( |
| "parser execs are disabled [recompile parser without --disable-execs configure option]"); | "parser execs are disabled [recompile parser without --disable-execs configure option]"); |
| #endif | #endif |
| // execve needs non const | |
| char* file_spec_cstr=file_spec.cstrm(String::L_FILE_SPEC); | |
| #ifdef WIN32 | #ifdef WIN32 |
| PROCESS_INFORMATION pi; | PROCESS_INFORMATION pi; |
| HANDLE hInWrite, hOutRead, hErrRead; | HANDLE hInWrite, hOutRead, hErrRead; |
| const char* cmd=buildCommand(file_spec.cstr(String::L_FILE_SPEC), argv); | const char* script_spec_cstr=file_spec.cstr(String::L_FILE_SPEC); |
| char* env_cstr; | const char* cmd=buildCommand(script_spec_cstr, argv); |
| char* env_cstr=0; | |
| if(env) { | if(env) { |
| String string; | String::Body body; |
| Append_env_pair_info info(string); | Append_env_pair_info info(body); |
| env->for_each(append_env_pair, &info); | env->for_each(append_env_pair, &info); |
| env_cstr=info.string.cstrm(String::L_UNSPECIFIED); | env_cstr=info.body.cstrm(); |
| for(char* replacer=env_cstr; *replacer; replacer++) | |
| if(*replacer=='\1') | |
| *replacer=0; | |
| } | } |
| if(DWORD error=CreateHiddenConsoleProcess(cmd, env_cstr, &pi, &hInWrite, &hOutRead, &hErrRead)) { | if(DWORD error=CreateHiddenConsoleProcess(cmd, script_spec_cstr, env_cstr, &pi, &hInWrite, &hOutRead, &hErrRead)) { |
| char szErrorDesc[MAX_STRING]; | char szErrorDesc[MAX_STRING]; |
| const char* param="the file you tried to run"; | const char* param="the file you tried to run"; |
| size_t error_size=FormatMessage( | size_t error_size=FormatMessage( |
| Line 356 PA_exec_result pa_exec( | Line 363 PA_exec_result pa_exec( |
| throw Exception(0, | throw Exception(0, |
| &file_spec, | &file_spec, |
| "exec failed - %s (%ld). Consider adding shbang line (#!x:\\interpreter\\command line)", | "exec failed - %s (%u). Consider adding shbang line (#!x:\\interpreter\\command line)", |
| error_size?szErrorDesc:"<unknown>", (long)error); | error_size?szErrorDesc:"<unknown>", error); |
| } else { | } else { |
| const char* in_cstr=in.cstr(); | const char* in_cstr=in.cstr(); |
| DWORD written_size; | DWORD written_size; |
| Line 383 from http://www.apache.org/websrc/cvsweb | Line 390 from http://www.apache.org/websrc/cvsweb |
| #else | #else |
| // execve needs non const | |
| char* file_spec_cstr=file_spec.cstrm(String::L_FILE_SPEC); | |
| int pipe_write, pipe_read, pipe_err; | int pipe_write, pipe_read, pipe_err; |
| #ifdef PA_SAFE_MODE | #ifdef PA_SAFE_MODE |
| Line 435 from http://www.apache.org/websrc/cvsweb | Line 445 from http://www.apache.org/websrc/cvsweb |
| close(pipe_err); | close(pipe_err); |
| result.status=get_exit_status(pid); // negative may mean "-errno[execl()]" | result.status=get_exit_status(pid); // negative may mean "-errno[execl()]" |
| } else | } else { |
| const char* str=strerror(errno); | |
| throw Exception(0, | throw Exception(0, |
| &file_spec, | &file_spec, |
| "%s error: %s (%d)", pid<0?"fork":"pipe", strerror(errno), errno); | "%s error: %s (%d)", pid<0?"fork":"pipe", str?str:"<unknown>", errno); |
| } | |
| #endif | #endif |
| return result; | return result; |